【发布时间】:2015-05-21 15:11:29
【问题描述】:
我正在使用音频队列来播放音频文件。我需要在最后一个缓冲区完成时精确计时。 我需要在播放完最后一个缓冲区后不迟于 150ms-200ms 通知一个函数...
通过回调方法我知道有多少缓冲区入队
我知道缓冲区大小,我知道最后一个缓冲区填充了多少字节。
首先我初始化了一些缓冲区,最后用音频数据填充缓冲区,然后将它们排入队列。当音频队列需要填充缓冲区时,它会调用回调并用数据填充缓冲区。
当没有更多可用的音频数据时,音频队列会向我发送最后一个空缓冲区,所以我用我拥有的任何数据填充它:
if (sharedCache.numberOfToTalPackets>0)
{
if (currentlyReadingBufferIndex==[sharedCache.baseAudioCache count]-1) {
inBuffer->mAudioDataByteSize = (UInt32)bytesFilled;
lastEnqueudBufferSize=bytesFilled;
err=AudioQueueEnqueueBuffer(inAQ,inBuffer,(UInt32)packetsFilled,packetDescs);
if (err) {
[self failWithErrorCode:err customError:AP_AUDIO_QUEUE_ENQUEUE_FAILED];
}
printf("if that was the last free packet description, then enqueue the buffer\n");
//go to the next item on keepbuffer array
isBufferFilled=YES;
[self incrementBufferUsedCount];
return;
}
}
当音频队列通过回调请求更多数据并且我没有更多数据时,我开始对缓冲区进行倒计时。如果缓冲区计数为零,这意味着飞行中只剩下一个缓冲区要播放,播放完成的那一刻我会尝试停止音频队列。
-(void)decrementBufferUsedCount
{
if (buffersUsed>0) {
buffersUsed--;
printf("buffer on the queue %i\n",buffersUsed);
if (buffersUsed==0) {
NSLog(@"playback is finished\n");
// end playback
isPlayBackDone=YES;
double sampleRate = dataFormat.mSampleRate;
double bufferDuration = lastEnqueudBufferSize/ sampleRate;
double estimatedTimeNeded=bufferDuration*1;
[self performSelector:@selector(stopPlayer) withObject:nil afterDelay:estimatedTimeNeded];
}
}
}
-(void)stopPlayer
{
@synchronized(self)
{
state=AP_STOPPING;
}
err=AudioQueueStop(queue, TRUE);
if (err) {
[self failWithErrorCode:err customError:AP_AUDIO_QUEUE_STOP_FAILED];
}
else
{
@synchronized(self)
{
state=AP_STOPPED;
NSLog(@"Stopped\n");
}
但是,我似乎无法在这里获得准确的时间。上面的代码提前停止播放器。
如果我也很早就关注音频剪辑
double bufferDuration = XMAQDefaultBufSize/ sampleRate;
double estimatedTimeNeded=bufferDuration*1;
如果将1 增加到2,因为缓冲区大小很大,我会遇到一些延迟,目前看来1.5 是最佳值,但我不明白为什么lastEnqueudBufferSize/ sampleRate 不工作
音频文件和缓冲区的详细信息:
Audio file has 22050 sample rate
#define kNumberPlaybackBuffers 4
#define kAQDefaultBufSize 16384
it is a vbr file format with no bitrate information available
【问题讨论】:
-
你试过我下面贴的方法了吗?您可以准确预测最后一个样本何时离开扬声器。
标签: ios objective-c core-audio audioqueue audioqueueservices