如果没有输出缓冲区

时间:2018-05-03 08:42:22

标签: ios macos audiounit circular-buffer

我正在尝试通过套接字实现播放从远程服务器接收的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;

}

我非常感谢你的帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

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

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

BTW:调用方法:

[output outputShouldUseCircularBuffer]
回调中的内容违反了Apple的实时音频规则。

答案 1 :(得分:0)

我发布了我的回答,因为其他人偶然发现和我一样。我是客观的新手,因此有人有更好的解决方案。我欢迎任何建议。

由于@ hotpaw2建议AudioBufferList需要提供样本,在我的情况下,我的circularBuffer里面没有任何东西。我必须将AudioBufferList的帧设置为0.0f

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; }
相关问题