0

I am trying to implement playing pcm audio received from remote server via socket. Here was my previous question link. This works fine as I use circular buffer to always feed in the incoming buffer.

However I have a problem that there is a huge noise sound that is being produced if I have no buffer supplied to my output. This happens when I begin to use AudioOutputUnitStart(_audioUnit) and when there is no buffer to play.

I suspect I have to fix this in my OutputRenderCallback function below or may be there is something else I need to do :

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;
}

I highly appreciate you help.Thanks.

Bill P
  • 3,622
  • 10
  • 20
  • 32
akaiz
  • 131
  • 11

2 Answers2

2

An audio unit callback requires that you always put the requested amount of samples in the AudioBufferList buffers. Your code does not do that if the amount (from that available circular buffer) is less.

So put something in the output buffer always, as your code does if there is no circular buffer.

BTW: calling a method:

[output outputShouldUseCircularBuffer]

inside a callback is a violation of Apple's rules for real-time audio.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • Thanks @hotpaw2 . Your comment helped me fix the noise. I am sorry I also didn't understand what I can do with the calling of the method which you suggested violates Apple's rules for real-time audio. As you can see in my code I use it to access my circular buffer. – akaiz May 04 '18 at 07:14
1

I am posting my answer incase someone else stumbles at the same point as I was. I am new to objective c so incase someone has a better solution. I do welcome any suggestions.

As @hotpaw2 suggested the AudioBufferList needs to be feed with samples and in my case when my circularBuffer had nothing inside of it. I had to feed the AudioBufferList with frames being set to 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; }
akaiz
  • 131
  • 11