AudioQueue吃了我的缓冲液(它首先15毫秒) [英] AudioQueue ate my buffer (first 15 milliseconds of it)

查看:253
本文介绍了AudioQueue吃了我的缓冲液(它首先15毫秒)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编程产生音频。我听到我的缓冲区之间的沉默差距。当我勾我的电话一个范围,我看到每个缓冲区的前几个样品丢失,并在他们的地方是沉默。这种沉默的长度几乎没什么可高达20毫秒变化。

我首先想到的是我原来的回调函数需要太多的时间。我用最短的一个可能取代它 - 它遍地重新renqueues相同的缓冲区。我观察到相同的行为。

  AudioQueueRef水溶液;
AudioQueueBufferRef aq_buffer;
AudioStreamBasicDescription ASBD;无效aq_callback(无效* aqData,AudioQueueRef inAQ,AudioQueueBufferRef inBuffer){
    OSStatus S = AudioQueueEnqueueBuffer(水溶液,aq_buffer,0,NULL);
}无效aq_init(无效){
    OSStatus S;    asbd.mSampleRate = AUDIO_SAMPLES_PER_S;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    asbd.mBytesPerPacket = 1;
    asbd.mFramesPerPacket = 1;
    asbd.mBytesPerFrame = 1;
    asbd.mChannelsPerFrame = 1;
    asbd.mBitsPerChannel = 8;
    asbd.mReserved = 0;
    INT PPM_PACKETS_PER_SECOND = 50;
    //一个缓冲区是只要一PPM帧
    INT BUFFER_SIZE_BYTES = asbd.mSampleRate / PPM_PACKETS_PER_SECOND * asbd.mBytesPerFrame;    S = AudioQueueNewOutput(安培; ASBD,aq_callback,NULL,CFRunLoopGetCurrent(),kCFRunLoopCommonModes,0,&放大器;水溶液);
    S = AudioQueueAllocateBuffer(AQ,BUFFER_SIZE_BYTES,&安培; aq_buffer);    //把样品中的缓冲
    buffer_data(my_data,aq_buffer);    S = AudioQueueStart(水溶液,NULL);
    S = AudioQueueEnqueueBuffer(水溶液,aq_buffer,0,NULL);
}


解决方案

我不熟悉iPhone的音频API,但它似乎是类似于其他的一般的地方,你会排队超过一个缓冲,这样当该系统处理完第一缓冲器,它可立即开始处理下一个缓冲区,同时正在执行1号缓冲液中完成回调(因为它已经被排队)。

是这样的:

  AudioQueueRef水溶液;
AudioQueueBufferRef aq_buffer [2];
AudioStreamBasicDescription ASBD;无效aq_callback(无效* aqData,AudioQueueRef inAQ,AudioQueueBufferRef inBuffer){
    //注意回调告诉我们哪个缓冲器已经完成,因此所有
    //我们所要做的就是排队它备份
    OSStatus S = AudioQueueEnqueueBuffer(水溶液,inBuffer,0,NULL);
}无效aq_init(无效){
    OSStatus S;    asbd.mSampleRate = AUDIO_SAMPLES_PER_S;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    asbd.mBytesPerPacket = 1;
    asbd.mFramesPerPacket = 1;
    asbd.mBytesPerFrame = 1;
    asbd.mChannelsPerFrame = 1;
    asbd.mBitsPerChannel = 8;
    asbd.mReserved = 0;
    INT PPM_PACKETS_PER_SECOND = 50;
    //一个缓冲区是只要一PPM帧
    INT BUFFER_SIZE_BYTES = asbd.mSampleRate / PPM_PACKETS_PER_SECOND * asbd.mBytesPerFrame;    S = AudioQueueNewOutput(安培; ASBD,aq_callback,NULL,CFRunLoopGetCurrent(),kCFRunLoopCommonModes,0,&放大器;水溶液);
    S = AudioQueueAllocateBuffer(水溶液,BUFFER_SIZE_BYTES,&放大器; aq_buffer [0]);
    S = AudioQueueAllocateBuffer(水溶液,BUFFER_SIZE_BYTES,&放大器; aq_buffer [1]);    //把样品中的缓冲 - 填写两个缓冲区
    buffer_data(my_data,aq_buffer [0]);
    buffer_data(my_data,aq_buffer [1]);    S = AudioQueueStart(水溶液,NULL);
    S = AudioQueueEnqueueBuffer(水溶液,aq_buffer [0],0,NULL);
    S = AudioQueueEnqueueBuffer(水溶液,aq_buffer [1],0,NULL);
}

I am generating audio programmatically. I hear gaps of silence between my buffers. When I hook my phone to a scope, I see that the first few samples of each buffer are missing, and in their place is silence. The length of this silence varies from almost nothing to as much as 20 ms.

My first thought is that my original callback function takes too much time. I replace it with the shortest one possible--it re-renqueues the same buffer over and over. I observe the same behavior.

AudioQueueRef aq;
AudioQueueBufferRef aq_buffer;
AudioStreamBasicDescription asbd;

void aq_callback (void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
    OSStatus s = AudioQueueEnqueueBuffer(aq, aq_buffer, 0, NULL);
}

void aq_init(void) {
    OSStatus s;

    asbd.mSampleRate = AUDIO_SAMPLES_PER_S;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
    asbd.mBytesPerPacket = 1;
    asbd.mFramesPerPacket = 1; 
    asbd.mBytesPerFrame = 1;
    asbd.mChannelsPerFrame = 1;
    asbd.mBitsPerChannel = 8;
    asbd.mReserved = 0;


    int PPM_PACKETS_PER_SECOND = 50;
    // one buffer is as long as one PPM frame
    int BUFFER_SIZE_BYTES = asbd.mSampleRate/PPM_PACKETS_PER_SECOND*asbd.mBytesPerFrame;

    s = AudioQueueNewOutput(&asbd, aq_callback, NULL, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &aq);
    s = AudioQueueAllocateBuffer(aq, BUFFER_SIZE_BYTES, &aq_buffer);

    // put samples in the buffer
    buffer_data(my_data, aq_buffer);

    s = AudioQueueStart(aq, NULL);
    s = AudioQueueEnqueueBuffer(aq, aq_buffer, 0, NULL);
}

解决方案

I'm not familiar with the iPhone audio APIs but it appears to be similar to other ones where generally you would queue up more than one buffer, This way when the system is finished processing the first buffer, it can immediately start processing the next buffer (since it's already been queued up) while the completion callback on the 1st buffer is being executed.

Something like:

AudioQueueRef aq;
AudioQueueBufferRef aq_buffer[2];
AudioStreamBasicDescription asbd;

void aq_callback (void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
    // note that the callback tells us which buffer has been completed, so all
    //  we have to do is queue it back up
    OSStatus s = AudioQueueEnqueueBuffer(aq, inBuffer, 0, NULL);
}

void aq_init(void) {
    OSStatus s;

    asbd.mSampleRate = AUDIO_SAMPLES_PER_S;
    asbd.mFormatID = kAudioFormatLinearPCM;
    asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
    asbd.mBytesPerPacket = 1;
    asbd.mFramesPerPacket = 1; 
    asbd.mBytesPerFrame = 1;
    asbd.mChannelsPerFrame = 1;
    asbd.mBitsPerChannel = 8;
    asbd.mReserved = 0;


    int PPM_PACKETS_PER_SECOND = 50;
    // one buffer is as long as one PPM frame
    int BUFFER_SIZE_BYTES = asbd.mSampleRate/PPM_PACKETS_PER_SECOND*asbd.mBytesPerFrame;

    s = AudioQueueNewOutput(&asbd, aq_callback, NULL, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &aq);
    s = AudioQueueAllocateBuffer(aq, BUFFER_SIZE_BYTES, &aq_buffer[0]);
    s = AudioQueueAllocateBuffer(aq, BUFFER_SIZE_BYTES, &aq_buffer[1]);

    // put samples in the buffer - fill both buffers
    buffer_data(my_data, aq_buffer[0]);
    buffer_data(my_data, aq_buffer[1]);

    s = AudioQueueStart(aq, NULL);
    s = AudioQueueEnqueueBuffer(aq, aq_buffer[0], 0, NULL);
    s = AudioQueueEnqueueBuffer(aq, aq_buffer[1], 0, NULL);
}

这篇关于AudioQueue吃了我的缓冲液(它首先15毫秒)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆