雾聪
2024-03-29 9ba0dbd98bf69c830dfcfde8f109a400cb65e4e5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
 * Copyright FunASR (https://github.com/alibaba-damo-academy/FunASR). All Rights
 * Reserved. MIT License  (https://opensource.org/licenses/MIT)
 */
 
//
//  AudioRecorder.m
//  paraformer_online
//
//  Created by 邱威 on 2023/6/6.
//
 
#import "AudioRecorder.h"
 
 
 
@implementation AudioRecorder
 
- (id)init
{
    self = [super init];
    if (self) {
 
        self.sampleRate = kDefaultSampleRate;
 
        //设置录音 初始化录音参数
        [self setupAudioFormat:kAudioFormatLinearPCM SampleRate:(int)self.sampleRate];
 
    }
    return self;
}
//设置录音 初始化录音参数
- (void)setupAudioFormat:(UInt32)inFormatID SampleRate:(int)sampeleRate
{
 
    memset(&audioFormat, 0, sizeof(audioFormat));
 
    audioFormat.mSampleRate = sampeleRate;//采样率
    audioFormat.mChannelsPerFrame = 1;//单声道
 
    audioFormat.mFormatID = inFormatID;//采集pcm 格式
    audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
    audioFormat.mBitsPerChannel = 16;//每个通道采集2个byte
    audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame = (audioFormat.mBitsPerChannel / 8) * audioFormat.mChannelsPerFrame;
    audioFormat.mFramesPerPacket = 1;
 
}
 
//回调函数 不断采集声音。
void inputHandler(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime,UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc)
{
 
    AudioRecorder *recorder = (__bridge AudioRecorder*)inUserData;
 
    int k = 0;
    if (inBuffer->mAudioDataByteSize > 0) {
//        NSLog(@"size: %d", inBuffer->mAudioDataByteSize);
        memcpy(recorder->data+recorder->offset,inBuffer->mAudioData,inBuffer->mAudioDataByteSize);//通过recorder->offset 偏移把语音数据存入recorder->data
 
        recorder->offset+=inBuffer->mAudioDataByteSize;//记录语音数据的大小
 
        k = recorder->offset/kBufferByteSize;//计算语音数据有多个960个字节语音
 
        for(int i = 0; i <k; i++)
        {
 
            NSData *SpeechData = [[NSData alloc]initWithBytes:recorder->data+i*kBufferByteSize length:kBufferByteSize];//把recorder->data 数据以960个字节分切放入 传出的数组中。
            [[NSNotificationCenter defaultCenter] postNotificationName:RECORDER_NOTIFICATION_CALLBACK_NAME object:SpeechData];
            if (recorder.inputBlock) {
                recorder.inputBlock(SpeechData);
            }
        }
 
//        NSLog(@"sampleRate: %lu", (unsigned long)recorder->_sampleRate);
        memcpy(recorder->data,recorder->data+k*kBufferByteSize,recorder->offset-(k*kBufferByteSize));//把剩下的语音数据放入原来的数组中
 
        recorder->offset-=(k*kBufferByteSize);//计算剩下的语音数据大小
 
 
    }
 
    if (recorder.isRecording) {
 
        AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
 
    }
 
}
//开始录音
-(void)start
{
    NSError *error = nil;
 
    //录音的设置和初始化
    BOOL ret = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
    if (!ret) {
        return;
    }
 
    //启用audio session
    ret = [[AVAudioSession sharedInstance] setActive:YES error:&error];
    if (!ret)
    {
        return;
    }
 
 
    //初始化缓冲语音数据数组
    memset(data,0,kDataSize); // 清空
    offset = 0;
    audioFormat.mSampleRate = self.sampleRate;
    //初始化音频输入队列
    AudioQueueNewInput(&audioFormat, inputHandler, (__bridge void *)(self), NULL, NULL, 0, &_audioQueue);
 
    int bufferByteSize = kBufferByteSize; //设定采集一帧960个字节
 
    //创建缓冲器
    for (int i = 0; i < kNumberAudioQueueBuffers; ++i){
        AudioQueueAllocateBuffer(_audioQueue, bufferByteSize, &_audioBuffers[i]);
        AudioQueueEnqueueBuffer(_audioQueue, _audioBuffers[i], 0, NULL);
    }
 
    //开始录音
    AudioQueueStart(_audioQueue, NULL);
    self.isRecording = YES;
}
 
//结束录音
-(void)stop
{
    if (self.isRecording) {
        self.isRecording = NO;
        AudioQueueStop(_audioQueue, true);
        AudioQueueDispose(_audioQueue, true);
        [[AVAudioSession sharedInstance] setActive:NO error:nil];
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];
    }
}
 
@end