HTML5   发布时间:2022-04-27  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了ios – AudioUnit“Sometime”不起作用. “只”发生在6s(可能是6s加,但我还没有测试过)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用AudioUnit进行播放和录制.优选设置是采样率= 48kHz,缓冲持续时间= 0.02

这是播放和录制的渲染回调:

static OSStatus recordingCallBACk(void *inRefCon,AudioUnitRenderActionFlags *ioActionFlags,const Audiotimestamp *intimestamp,UInt32 inBusnumber,UInt32 innumberFrames,AudioBufferList *ioData) {

    IosAudioController *microphone = (__bridge IosAudioController *)inRefCon;

    // render audio into buffer
    OSStatus result = AudioUnitRender(microphone.audioUnit,ioActionFlags,intimestamp,inBusnumber,innumberFrames,microphone.tempBuffer);
    checkStatus(result);
//    kAudioUnitErr_InvalidPropertyValue

    // notify delegate of new buffer list to process
    if ([microphone.datasource respondsToSELEctor:@SELEctor(microphone:hasBufferList:withBufferSize:withnumberOfChAnnels:)])
    {
        [microphone.datasource microphone:microphone
                          hasBufferList:microphone.tempBuffer
                         withBufferSize:innumberFrames
                   withnumberOfChAnnels:microphone.desTinationFormat.mChAnnelsPerFrame];
    }

    return result;
}

/**
 This callBACk is called when the audioUnit needs new data to play through the
 speakers. If you don't have any,just don't write anything in the buffers
 */
static OSStatus playBACkCallBACk(void *inRefCon,AudioBufferList *ioData) {    

    IosAudioController *output = (__bridge IosAudioController *)inRefCon;

    //
    // Try to ask the data source for audio data to fill out the output's
    // buffer list
    //
    if( [output.datasource respondsToSELEctor:@SELEctor(outputShouldUseCircularBuffer:)] ){

        TPCircularBuffer *circularBuffer = [output.datasource outputShouldUseCircularBuffer:output];
        if( !circularBuffer ){
            //            SInt32 *left  = ioData->mBuffers[0].mData;
            //            SInt32 *right = ioData->mBuffers[1].mData;
            //            for(int i = 0; i < innumberFrames; i++ ){
            //                left[  i ] = 0.0f;
            //                right[ i ] = 0.0f;
            //            }
            *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
            return noErr;
        };

        /**
         Thank you Michael Tyson (A Tasty Pixel) for wriTing the TPCircularBuffer,you are amazing!
         */

        // Get the available bytes in the circular buffer
        int32_t availableBytes;
        void *buffer = TPCircularBufferTail(circularBuffer,&availableBytes);
        int32_t amount = 0;
        //        float floatnumber = availableBytes * 0.25 / 48;
        //        float speakernumber = ioData->mBuffers[0].mDataByteSize * 0.25 / 48;

        for (int i=0; i < ioData->mnumberBuffers; i++) {
            AudioBuffer abuffer = ioData->mBuffers[i];

            // Ideally we'd have all the bytes to be copied,but compare it against the available bytes (get min)
            amount = MIN(abuffer.mDataByteSize,availableBytes);

            // copy buffer to audio buffer which gets played after function return
            memcpy(abuffer.mData,buffer,amount);

            // set data size
            abuffer.mDataByteSize = amount;
        }
        // Consume those bytes ( this will internally push the head of the circular buffer )
        TPCircularBufferConsume(circularBuffer,amount);
    }
    else
    {
        //
        // Silence if there is nothing to output
        //
        *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
    }
    return noErr;
}

_tempBuffer配置了4096帧.

以下是我取消分配audioUnit的方法.请注意,由于VoiceProcessingIO单元如果启动,停止并再次启动它可能无法正常工作的错误,我需要每次都处理并初始化它.这是一个已知的问题并发布在这里,但我不记得链接.

if (_tempBuffer != NULL) {
    for(unsigned i = 0; i < _tempBuffer->mnumberBuffers; i++)
    {
        free(_tempBuffer->mBuffers[i].mData);
    }
    free(_tempBuffer);
}
AudioComponenTinstanceDispose(_audioUnit);

此配置适用于6,6及更早版本的设备.但是在6s(可能是6s)出现了问题.有些时候,(那些错误确实非常烦人.我讨厌它.对我来说,它在20次测试中发生了6-7次),仍有传入和传出的数据来自IoUnit,但根本没有声音.
它似乎永远不会发生在第一次测试,所以我猜它可能是IoUnit的内存问题,我仍然不知道如何解决这个问题.

任何建议将不胜感激.

updatE

我忘了展示我如何配置AudioUnit

// Describe audio component
    AudioComponentDescription desc;
    desc.componentType = kAudioUnitType_Output;
    desc.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
    desc.componentFlags = 0;
    desc.componentFlagsmask = 0;
    desc.componentManufacturer = kAudioUnitManufacturer_Apple;

    // Get component
    AudioComponent inputComponent = AudioComponentFindNext(NULL,&desc);

    // Get audio units
    status = AudioComponenTinstanceNew(inputComponent,&_audioUnit);
    checkStatus(status);

    // Enable IO for recording
    UInt32 flag = 1;
    status = AudioUnitSetProperty(_audioUnit,kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Input,kInputBus,&flag,sizeof(flag));
    checkStatus(status);

    // Enable IO for playBACk
    status = AudioUnitSetProperty(_audioUnit,kAudioUnitScope_Output,kOutputBus,sizeof(flag));
    checkStatus(status);

    // Apply format
    status = AudioUnitSetProperty(_audioUnit,kAudioUnitProperty_StreamFormat,&_desTinationFormat,sizeof(self.desTinationFormat));
    checkStatus(status);
    status = AudioUnitSetProperty(_audioUnit,sizeof(self.desTinationFormat));
    checkStatus(status);


    // Set input callBACk
    AURenderCallBACkStruct callBACkStruct;
    callBACkStruct.inputProc = recordingCallBACk;
    callBACkStruct.inputProcRefCon = (__bridge void * _NullablE)(self);
    status = AudioUnitSetProperty(_audioUnit,kAudioOutputUnitProperty_SeTinputCallBACk,kAudioUnitScope_Global,&callBACkStruct,sizeof(callBACkStruct));
    checkStatus(status);

    // Set output callBACk
    callBACkStruct.inputProc = playBACkCallBACk;
    callBACkStruct.inputProcRefCon = (__bridge void * _NullablE)(self);
    status = AudioUnitSetProperty(_audioUnit,kAudioUnitProperty_SetRenderCallBACk,sizeof(callBACkStruct));
    checkStatus(status);

    // Disable buffer alLOCATIOn for the recorder (optional - do this if we want to pass in our own)
    flag = 0;
    status = AudioUnitSetProperty(_audioUnit,kAudioUnitProperty_ShouldAllocateBuffer,sizeof(flag));

    [self configureMicrophoneBufferList];

    // Initialise
    status = AudioUniTinitialize(_audioUnit);

解决方法

3件事可能是问题:

对于静(在下溢期间),您可能希望尝试使用0的innumberFrames填充缓冲区,而不是未@L_944_70@地返回它们.

在音频回调中,Apple DTS不推荐使用任何Objective C消息(您的respondsToSELEctor:call).

在音频处理确实停止之前,您不应释放缓冲区或调用AudioComponenTinstanceDispose.由于音频单元在另一个实时线程中运行,因此它们不会(获取线程或cpu时间)真正停止,直到您的应用程序进行停止音频呼叫后的一段时间.我会等几秒钟,当然不会在延迟时间之后调用(重新)初始化或(重新)启动.

大佬总结

以上是大佬教程为你收集整理的ios – AudioUnit“Sometime”不起作用. “只”发生在6s(可能是6s加,但我还没有测试过)全部内容,希望文章能够帮你解决ios – AudioUnit“Sometime”不起作用. “只”发生在6s(可能是6s加,但我还没有测试过)所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。