我最近使用AudioUnits在Mac上设计了一个Sound录音机。它的设计表现就像一个视频安全系统,连续录制,带有用于播放浏览的功率级图形显示。 我注意到每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