/** * 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 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