Глюки возникают при чтении данных с использованием ExtAudioFile в сочетании с циклическим буфером
Я пытаюсь обработать аудиоданные, которые читаются с использованием ExtAudioFile
, Однако, когда я пытаюсь поместить эти данные в кольцевой буфер, я слышу несколько глюков.
В приведенном ниже примере кода я передаю данные из "inBuffer" непосредственно в "outBuffer" (оба типа TPCircularBuffer
Майкл Тайсон). Оба буфера имеют размер 10 х numberOfFrames * sizeof(float)
, Формат потока клиента - моно с выборками с плавающей точкой.
Почему я слышу эти глюки, даже не обрабатывая никаких данных? Без кругового буфера звуковые потоки хорошо. Что я не прав или будет другой подход лучше?
static OSStatus recordingCallback(
void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData){
PlayAudioFile* player = (__bridge PlayAudioFile*)inRefCon;
Info *info = (Info *)player.info;
ExtAudioFileRead(info->extAudioFile, &inNumberFrames, info->inputBuffer);
if (inNumberFrames == 0) {
ExtAudioFileSeek(info->extAudioFile, 0);
}
// Put data in circular buffer
TPCircularBufferProduceBytes(info->inBuffer, info->inputBuffer->mBuffers[0].mData, info->inputBuffer->mBuffers[0].mDataByteSize);
UInt32 frameSize = inNumberFrames*sizeof(float);
if (info->inBuffer->fillCount >= frameSize) {
int32_t availableBytes;
float *tail = TPCircularBufferTail(info->inBuffer, &availableBytes);
if (availableBytes > frameSize){
memcpy(info->tempBuffer, tail, frameSize);
TPCircularBufferConsume(info->inBuffer, frameSize);
// Currently, data is not processed but just put to the output buffer
TPCircularBufferProduceBytes(info->outBuffer, info->tempBuffer, frameSize);
}
}
return noErr;
}
static OSStatus renderCallback(
void* inRefCon,
AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList* ioData){
PlayAudioFile* player = (__bridge PlayAudioFile*)inRefCon;
Info *info = (Info *)play.info;
for (int i=0; i < ioData->mNumberBuffers; i++) {
AudioBuffer buffer = ioData->mBuffers[i];
if (info->outBuffer->fillCount > ioData->mBuffers[0].mDataByteSize) {
int32_t availableBytes;
float *tail = TPCircularBufferTail(info->outBuffer, &availableBytes);
memcpy(buffer.mData, tail, buffer.mDataByteSize);
TPCircularBufferConsume(info->outBuffer, buffer.mDataByteSize);
/* Messaging is not used for this example
// Notify delegate
if ([player.delegate respondsToSelector:@selector(player:audioBuffer:bufferSize:)])
{
[player.delegate player:player
audioBuffer:buffer.mData
bufferSize:inNumberFrames];
}
*/
}
else {
memset((char*)ioData->mBuffers[i].mData, 0, ioData->mBuffers[i].mDataByteSize * info->clientFormat.mBytesPerFrame);
}
}
return noErr;
}
Редактировать На основе приведенного ниже ответа я изменил код, выделив и освободив память вне функций обратного вызова и увеличив размер кольцевых буферов. К сожалению, звук все еще хуже, чем без кольцевых буферов. Может ли быть еще одна причина для этих глюков?
1 ответ
Выделение или освобождение памяти не должно выполняться внутри звуковых обратных вызовов. Также не следует отправлять сообщения Objective C.
Обратный вызов рендеринга должен всегда помещать данные в буферы списка буферов. Но в вашем коде отсутствует инструкция else для этого. Попробуйте больший кольцевой буфер и убедитесь, что он достаточно предварительно заполнен перед запуском обратных вызовов рендеринга.