音视频开发——iOS音频录制(六)

来源:互联网 发布:淘宝店铺转化率低 编辑:程序博客网 时间:2024/06/06 00:44

iOS音视频开发相关文章:

音视频开发——概述(一)

音视频开发——流媒体数据传输RTSP(二)

音视频开发——流媒体数据传输RTP(三)

音视频开发——ffmpeg解码(四)

音视频开发——音频流解码播放(五)

音视频开发——iOS音频录制(六)


一、使用Audio Queues录制音频


输入端连接的是设备的外部音频硬件部分,比如麦克风。输出端采用回调函数的方式,操作录制的音频数据。


标准的录音流程是六步,但写出一个可用的例子并没有这么复杂,三步就能实现:

1. 初始化操作,设置音频格式、建立audio queue的队列、新建几个buffer(通常是三个)并塞到队列中

- (instancetype)init {    self = [super init];    if (self) {        _audioDescription.mSampleRate = kDefaultSampleRate;        _audioDescription.mFormatID = kAudioFormatLinearPCM;        _audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;        _audioDescription.mFramesPerPacket = 1;        _audioDescription.mChannelsPerFrame = 1;        _audioDescription.mBitsPerChannel = 16;        _audioDescription.mBytesPerPacket = (_audioDescription.mBitsPerChannel / 8) * _audioDescription.mChannelsPerFrame;        _audioDescription.mBytesPerFrame = _audioDescription.mBytesPerPacket;                AudioQueueNewInput(&_audioDescription, AQInputCallback, (__bridge void *)self, NULL, kCFRunLoopCommonModes, 0, &_audioQueue);                //计算估算的缓存区大小        int frames = (int)ceil(kDefaultBufferDurationSeconds * _audioDescription.mSampleRate); //返回大于或者等于指定表达式的最小整数        int bufferSize = frames *_audioDescription.mBytesPerFrame;  //缓冲区大小在这里设置,这个很重要,在这里设置的缓冲区有多大,那么在回调函数的时候得到的inbuffer的大小就是多大。                for (int i = 0; i < QUEUE_BUFFER_SIZE; i ++) {            AudioQueueAllocateBuffer(_audioQueue, bufferSize, &_audioQueueBuffers[i]);            AudioQueueEnqueueBuffer(_audioQueue, _audioQueueBuffers[i], 0, NULL);        }                _recordFile = fopen("/Users/XCHF-ios/Documents/phone.pcm", "w");    }    return self;}

2. 启动audio queue

- (void)startRecord {    //    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//    [[AVAudioSession sharedInstance] setActive:YES error:nil];        OSStatus status = AudioQueueStart(_audioQueue, NULL);    if (status  != noErr) {        NSLog(@"AudioQueueStart Error: %d", status);    }}
3. 音频输出回调,输出的buffer使用后,再将该buffer塞到audio queue队列中

static void AQInputCallback (                             void * __nullable               inUserData,                             AudioQueueRef                   inAQ,                             AudioQueueBufferRef             inBuffer,                             const AudioTimeStamp *          inStartTime,                             UInt32                          inNumberPacketDescriptions,                             const AudioStreamPacketDescription * __nullable inPacketDescs) {    PCMAudioRecorder *recorder = (__bridge PCMAudioRecorder *)inUserData;    if (inBuffer->mAudioDataByteSize > 0) {        [recorder processAudioBuffer:inBuffer];    }}

- (void)processAudioBuffer:(AudioQueueBufferRef)buffer {    NSLog(@"processAudioData :%u",buffer->mAudioDataByteSize);    fwrite(buffer->mAudioData, 1, buffer->mAudioDataByteSize, _recordFile);    AudioQueueEnqueueBuffer(_audioQueue, buffer, 0, NULL);}

二、AVAudioRecorder录制本地音频

AVAudioRecorder的用法比Audio Queue简单一些,但只能录制音频保存在本地。在使用时,只需要对其进行初始化的设置,就能开始录制。

- (AVAudioRecorder *)audioRecorder {    if (!_audioRecorder) {        NSURL *url = [self getSavePath];   //音频的保存路径        NSDictionary *setting = [self getAudioSetting];  //音频的参数设置        NSError *error;        _audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:setting error:&error];        _audioRecorder.delegate = self;        _audioRecorder.meteringEnabled = YES;        if (error) {            NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);            return nil;        }    }    return _audioRecorder;}

demo下载:iOS音频操作





1 0