Недавно я разработал звукозапись на Mac с помощью AudioUnits. Он был разработан так, чтобы вести себя как система видеонаблюдения, непрерывно записываясь с графическим дисплеем уровней мощности для просмотра в режиме просмотра. Я заметил, что каждые 85 минут искажения появляются в течение 3 минут. После дня устранения кажется, что обнаружение звука, которое происходит перед обратным вызовом, называется циклическим буфером, и функция audioUnitRender вызывающего вызова извлекает из этого буфера, но с немного меньшей скоростью, что в конечном итоге приводит к тому, что внутренняя запись буфера обтекает и захватывает с чтением audioUnitRender. Тест на дуплексную операцию показывает, что время ожидания увеличивается, и через 85 минут вы слышите около 200-300 мс задержки, и шум начинается, когда кадр буфера визуализации имеет комбинацию сегментов буфера в конце и начале буфера, то есть в длинных и коротких латентных периодах. поскольку указатели дрейфуют, шум исчезает, и вы слышите чистый звук с оригинальной короткой задержкой, затем он снова повторяется через 85 минут. Даже при обработке обратного вызова с низким воздействием это все еще происходит. Я видел несколько сообщений о латентности, но никто из них не видел, кто-нибудь видел это?AudioUnit (Mac) Нарушение внутреннего буфера AudioUnitRender
OSX 10.9.5, Xcode 6.1.1 детали код: -
//modes 1=playback, 2=record, 3=both
AudioComponentDescription outputcd = {0}; // 10.6 version
outputcd.componentType = kAudioUnitType_Output;
outputcd.componentSubType = kAudioUnitSubType_HALOutput; //allows duplex
outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponent comp = AudioComponentFindNext (NULL, &outputcd);
if (comp == NULL) {printf ("can't get output unit");exit (-1);}
CheckError (AudioComponentInstanceNew(comp, au),"Couldn't open component for outputUnit");
//tell input bus that its's input, tell output it's an output
if(mode==1 || mode==3) r=[self setAudioMode:*au :0];//play
if(mode==2 || mode==3) r=[self setAudioMode:*au :1];//rec
// register render callback
if(mode==1 || mode==3) [self setCallBack:*au :0];
if(mode==2 || mode==3) [self setCallBack:*au :1];
// if(mode==2 || mode==3) [self setAllocBuffer:*au];
// get default stream, change amt of channels
AudioStreamBasicDescription audioFormat;
UInt32 k=sizeof(audioFormat);
r= AudioUnitGetProperty(*au,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&audioFormat,
&k);
audioFormat.mChannelsPerFrame=1;
r= AudioUnitSetProperty(*au,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
1,
&audioFormat,
k);
//start
CheckError (AudioUnitInitialize(outputUnit),"Couldn't initialize output unit");
//record callback
OSStatus RecProc(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
myView * mv2=(__bridge myView*)inRefCon;
AudioBuffer buffer,buffer2;
OSStatus status;
buffer.mDataByteSize = inNumberFrames *4 ;// buffer size
buffer.mNumberChannels = 1; // one channel
buffer.mData =mv2->rdata;
buffer2.mDataByteSize = inNumberFrames *4 ;// buffer size
buffer2.mNumberChannels = 1; // one channel
buffer2.mData =mv2->rdata2;
AudioBufferList bufferList;
bufferList.mNumberBuffers = 2;
bufferList.mBuffers[0] = buffer;
bufferList.mBuffers[1] = buffer2;
status = AudioUnitRender(mv2->outputUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
[mv2 recproc :mv->rdata :mv->rdata2 :inNumberFrames];
return noErr;
}
Ошибка или ошибка может возникнуть в вашей настройке частоты дискретизации, внутри вашей функции обратного вызова звукового блока или в коде ввода файлов, который вы не показывали. – hotpaw2
Думаю, я все это устранил. моя первая мысль о том, что это были мои процедуры сжатия adpcm, но мне посчастливилось засвидетельствовать эту проблему (требуется много терпения, чтобы ждать около 85 минут) с уменьшенной версией, без сжатия, без архивации, просто воспроизводя записанные (с наушниками). также обратите внимание на изменения латентности, и когда возникает проблема, вы слышите удлиненную задержку вместе с оригинальной копией с задержкой в 20 мс. то длинная латентная копия и искажение исчезают, а звук чист, пока не повторится 85 минут спустя. – kirkgcm
продолжение: - в этих последних замечаниях намекает, что проблема с внутренним круговым буфером. Я бы выбрал несколько кадров так часто, чтобы избежать этого, я знал, как это сделать. возможно, отсутствующий вызов audiounitrender (или добавление дополнительного) за обратный вызов сделал бы это, но я не уверен. надеялся, что кто-то знает, что внутреннее будет скрывать детали сцены об этом. Как я действительно верю в звуковой драйвер (kext) – kirkgcm