AudioUnit шум, если нет выходного буфера - PullRequest
0 голосов
/ 03 мая 2018

Я пытаюсь реализовать воспроизведение звука PCM, полученного от удаленного сервера через сокет. Вот мой предыдущий вопрос ссылка . Это прекрасно работает, так как я использую круговой буфер для постоянной подачи во входящий буфер.

Однако у меня проблема в том, что из-за громкого шума издается выходной буфер. Это происходит, когда я начинаю использовать 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 голосов
/ 04 мая 2018

Я отправляю свой ответ, если кто-то другой спотыкается в той же точке, что и я. Я новичок в цели c, так что если у кого-то есть лучшее решение. Я приветствую любые предложения.

Как подсказал @ hotpaw2, AudioBufferList должен быть снабжен сэмплами, и в моем случае, когда в моем циркулярном буфере ничего не было. Мне пришлось кормить 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; }
0 голосов
/ 04 мая 2018

Обратный вызов аудиоустройства требует, чтобы вы всегда помещали запрошенное количество выборок в буферы AudioBufferList. Ваш код не делает этого, если количество (из этого доступного циклического буфера) меньше.

Поэтому всегда помещайте что-либо в выходной буфер, как это делает ваш код, если круговой буфер отсутствует.

Кстати: вызов метода:

[output outputShouldUseCircularBuffer]

внутри обратного вызова является нарушением правил Apple для аудио в реальном времени.

...