【问题标题】:AudioUnit noise if there is no output buffer没有输出缓冲区时的 AudioUnit 噪声
【发布时间】:2018-05-03 08:42:22
【问题描述】:

我正在尝试播放通过套接字从远程服务器接收到的 pcm 音频。这是我之前的问题link。这很好用,因为我使用循环缓冲区始终输入传入缓冲区。

但是我有一个问题,如果我没有为我的输出提供缓冲区,则会产生巨大的噪音。当我开始使用 AudioOutputUnitStart(_audioUnit) 并且没有缓冲区可以播放时,就会发生这种情况。

我怀疑我必须在下面的 OutputRenderCallback 函数中解决这个问题,或者我可能需要做其他事情:

static OSStatus OutputRenderCallback(void                        *inRefCon,
                                     AudioUnitRenderActionFlags  *ioActionFlags,
                                     const AudioTimeStamp        *inTimeStamp,
                                     UInt32                      inBusNumber,
                                     UInt32                      inNumberFrames,
                                     AudioBufferList             *ioData){


    Test *output = (__bridge Test*)inRefCon;


    TPCircularBuffer *circularBuffer = [output outputShouldUseCircularBuffer];
    if( !circularBuffer ){
        SInt32 *left  = (SInt32*)ioData->mBuffers[0].mData;
        for(int i = 0; i < inNumberFrames; i++ ){
            left[  i ] = 0.0f;
        }
        return noErr;
    };

    int32_t bytesToCopy = ioData->mBuffers[0].mDataByteSize;
    SInt16* outputBuffer = ioData->mBuffers[0].mData;

    uint32_t availableBytes;
    SInt16 *sourceBuffer = TPCircularBufferTail(circularBuffer, &availableBytes);

    int32_t amount = MIN(bytesToCopy,availableBytes);
    memcpy(outputBuffer, sourceBuffer, amount);

    TPCircularBufferConsume(circularBuffer,amount);

    return noErr;
}

非常感谢您的帮助。谢谢。

【问题讨论】:

    标签: ios macos audiounit circular-buffer


    【解决方案1】:

    音频单元回调要求您始终将请求数量的样本放入 AudioBufferList 缓冲区。如果数量(来自可用的循环缓冲区)较少,则您的代码不会这样做。

    所以总是在输出缓冲区中放一些东西,就像你的代码在没有循环缓冲区时所做的那样。

    顺便说一句:调用方法:

    [output outputShouldUseCircularBuffer]
    

    回调内部违反了 Apple 的实时音频规则。

    【讨论】:

    • 谢谢@hotpaw2。你的评论帮助我解决了噪音。很抱歉,我也不明白如何调用您建议的违反 Apple 实时音频规则的方法。正如您在我的代码中看到的,我使用它来访问我的循环缓冲区。
    【解决方案2】:

    我正在发布我的答案,以防其他人与我在同一点上绊倒。我是目标 c 的新手,所以如果有人有更好的解决方案。我欢迎任何建议。

    正如@hotpaw2 建议的那样,AudioBufferList 需要提供样本,在我的情况下,当我的 circularBuffer 里面什么都没有时。我必须将帧设置为 0.0f

    来提供 AudioBufferList
    static OSStatus OutputRenderCallback(void                        *inRefCon,
                                     AudioUnitRenderActionFlags  *ioActionFlags,
                                     const AudioTimeStamp        *inTimeStamp,
                                     UInt32                      inBusNumber,
                                     UInt32                      inNumberFrames,
                                     AudioBufferList             *ioData){
    
    Test *output = (__bridge Test*)inRefCon;
    
    TPCircularBuffer *circularBuffer = [output outputShouldUseCircularBuffer];
    
    int32_t bytesToCopy = ioData->mBuffers[0].mDataByteSize;
    SInt16* outputBuffer = ioData->mBuffers[0].mData;
    
    uint32_t availableBytes;
    SInt16 *sourceBuffer = TPCircularBufferTail(circularBuffer, &availableBytes);
    
    int32_t amount = MIN(bytesToCopy,availableBytes);
    
    if (amount>0) {
            memcpy(outputBuffer, sourceBuffer, amount);
            TPCircularBufferConsume(circularBuffer,amount);
    }
    else{
    
        SInt32 *left  = (SInt32*)ioData->mBuffers[0].mData;
        for(int i = 0; i < inNumberFrames; i++ ){
            left[  i ] = 0.0f;
        }
        return noErr;
    
    }
    
    return noErr; }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多