iOS使用AudioUnit/AudioQueue实现耳返功能

作者: magicMushroom | 来源:发表于2017-05-30 15:28 被阅读664次

    首先理清思路
    我这边使用AudioUnit录音,AudioQueue播放
    1、创建AudioUnit对象,并初始化设置参数等
    2、创建AudioQueue对象,初始化并设置参数
    3、在AudioUnit回调方法中获取到采集到的数据,并将获取到的数据喂给AudioQueue的容器中,并给它播放

    思路是不是很清晰了😆

    需理解的重点
    1、AudioQueue播放是从2-3个(最好3个)AudioQueueBufferRef类型的缓存中不停地读取的。

    代码开始
    1、使用AVAudioSession获取音频录制播放权限,并激活

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

    [[AVAudioSession sharedInstance] setActive:YES error:nil];

    2、创建AudioUnit
    AudioComponentInstanceNew(_audioComponment, &_audioUint);

    3、设置AudioUint

    AudioUnitSetProperty(_audioUint,

                         kAudioOutputUnitProperty_EnableIO,
                         kAudioUnitScope_Input,
                         1,
                         &flagOne,
                         sizeof(flagOne));
    

    AudioUnitSetProperty(_audioUint, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &asbd, sizeof(asbd));

    AudioUnitSetProperty(_audioUint, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, sizeof(cb));

    4、初始化/Start
    AudioUnitInitialize(_audioUint);
    AudioOutputUnitStart(_audioUint);

    5、创建AudioQueue实例
    AudioQueueNewOutput(&_asbd, BufferCallback, (__bridge void * _Nullable)(self), nil, nil, 0, &_audioQueue);

    6、初始化音频缓冲区,这3个音频缓冲区地址不会改变,往里面填数据的时候,只是里面的数据变化而已(官方文档表明地址不可改变)
    //初始化音频缓冲区
    for (int i = 0; i < 3; i++) {
    //创建buffer
    result = AudioQueueAllocateBuffer(_audioQueue, 2048, &_audioQueueBuffers[i]);
    if (result != noErr) {
    NSLog(@"creat AudioQueue fail");
    }
    //初始化
    memset(_audioQueueBuffers[i]->mAudioData, 0, 2048);
    }

    7、AudioUnit回调中处理数据
    AudioUnitRender(vc->_audioUint, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);使用该函数来讲数据填充到我们创建的bufferList中
    便于后续处理
    void *data = malloc(bufferList.mBuffers[0].mDataByteSize);
    memcpy(data, bufferList.mBuffers[0].mData, bufferList.mBuffers[0].mDataByteSize);
    //play
    AudioQueueBufferRef audioBuffer = NULL;
    if (vc->_index == 2) {
    vc->_index = 0;
    }
    audioBuffer = vc->_audioQueueBuffers[vc->_index];
    vc->_index ++;
    audioBuffer->mAudioDataByteSize = bufferList.mBuffers[0].mDataByteSize;
    memset(audioBuffer->mAudioData, 0, bufferList.mBuffers[0].mDataByteSize);
    memcpy(audioBuffer->mAudioData, data, bufferList.mBuffers[0].mDataByteSize);
    //将数据压入AudioQueue播放缓存中
    AudioQueueEnqueueBuffer(vc->_audioQueue, audioBuffer, 0, NULL);
    free(data);

    8、至于AudioQueue的回调,该demo中没什么用,但是有个坑,我之前AudioQueue创建好,没有使用AudioQueueEnqueueBuffer填充数据,该回调方法就不会走,我莫名其妙了好久。

    demo的话:链接: https://pan.baidu.com/s/1hsmSY3a 密码: 1631

    相关文章

      网友评论

      本文标题:iOS使用AudioUnit/AudioQueue实现耳返功能

      本文链接:https://www.haomeiwen.com/subject/krjrfxtx.html