CoreAudio AudioQueue PCM 速度快且不稳定

Posted

技术标签:

【中文标题】CoreAudio AudioQueue PCM 速度快且不稳定【英文标题】:CoreAudio AudioQueue PCM is fast and choppy 【发布时间】:2015-12-15 02:21:17 【问题描述】:

我根本无法弄清楚这个问题。下面代码中的音频播放速度非常快且断断续续。 SO上还有另一个类似的问题,但它适用于可变比特率并且不适用。

其他站点上的一些可能的答案(直接设置每个数据包的帧数)不再有效,并给出 aq -50 错误代码。

这是来自合成器代码库,源音频是 44,100 Hz 的 8:24 线性 PCM,非交错。将帧 (4096) 设置为采样率 (44100Hz) 似乎可以解决断断续续的问题,但音频生成后端无法跟上,因此它会停止每个数据包。

有什么解决办法吗?对于我的生活,我无法弄清楚是什么导致它运行得如此之快。

static const int kNumBuffers = 3;
typedef struct CoreAudio_audiodriver

    A2_audiodriver              ad;
    AudioQueueRef               queue;
    AudioQueueBufferRef         buffer[kNumBuffers];
    AudiostreamBasicDescription desc;
 CoreAudio_audiodriver;

/* CoreAudio render thread callback */
static void coreaudio_process(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)

    A2_audiodriver *driver = (A2_audiodriver *)inUserData;
    CoreAudio_audiodriver * cad = (CoreAudio_audiodriver *)inUserData;
    A2_config * config = driver->driver.config;
    int c, i;

    int frames = 4096 /* samples */;

    if( driver->Process )
    
        driver->Process(driver, 4096 /* samples */); // loads 4096 samples into internal buffers
    

    /* copy and interleave internal buffers to queue */
    for ( i = 0; i < frames; i++ )
    
        for ( c = 0; c < 2 /* channels */; c++ )
        
            ((int32_t *)inBuffer->mAudioData)[i + c] = driver->buffers[c][i];
        
    
    inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;

    AudioQueueEnqueueBuffer(cad->queue, inBuffer, 0, NULL);


static int coreaudiod_Open(A2_driver *driver)

    CoreAudio_audiodriver * drv         = (CoreAudio_audiodriver *)driver;
    A2_config * config                  = drv->ad.driver.config;
    AudioStreamBasicDescription * desc  = &drv->desc;
    OSStatus err;
    int c, i;

    /* set up stream description */
    desc->mSampleRate        = (Float64)config->samplerate;
    desc->mFormatID          = kAudioFormatLinearPCM;
    desc->mFormatFlags       = kAudioFormatFlagIsSignedInteger;

    desc->mFramesPerPacket   = 1;
    desc->mChannelsPerFrame  = 2 /* channels */;

    /* packet -> frame -> channel -> data */
    desc->mBytesPerFrame     = desc->mChannelsPerFrame * sizeof(int32_t);
    desc->mBytesPerPacket    = desc->mBytesPerFrame * desc->mFramesPerPacket;
    desc->mBitsPerChannel    = 24; /* 8:24 PCM */

    /* set up queue */
    err = AudioQueueNewOutput(
                        desc,               // data format
                        coreaudio_process,  // callback
                        driver,             // data passed to callback
                        NULL,               // internal run loop
                        kCFRunLoopCommonModes, // kCFRunLoopCommonMode
                        0,                  // reserved by Apple
                        &drv->queue         // queue output
                    );

    for ( i = 0; i < kNumBuffers; i++ )
    
        /* internal buffer */
        err = AudioQueueAllocateBuffer(
                            drv->queue,
                            desc->mBytesPerPacket * 4096 /* samples */,
                            &drv->buffer[i]
                        );

        /* start callback polling */
        drv->buffer[i]->mAudioDataByteSize = drv->buffer[i]->mAudioDataBytesCapacity;
        err = AudioQueueEnqueueBuffer(drv->queue, drv->buffer[i], 0, NULL);
    

    err = AudioQueueStart(drv->queue, NULL);

    return 1;

【问题讨论】:

【参考方案1】:

您可能正在应用的主 UI 线程中处理音频队列回调。如果你阻塞这个线程太久(通过花费太多做合成、UI 或 drawRects 等),AQ 回调将不会被及时调用。因此,音频输出会下溢且声音断断续续。

【讨论】:

谢谢。我将如何确定回调在哪个线程中运行(这是一个控制台应用程序,所以没有运行 UI,但可能是合成。我认为 AudioQueues 在单独的 CFRunLoop 上运行。

以上是关于CoreAudio AudioQueue PCM 速度快且不稳定的主要内容,如果未能解决你的问题,请参考以下文章

CoreAudio AudioQueue 回调函数从未调用过,没有报错

ios 使用audioQueue 录音以及播放 (pcm)

使用 AudioQueue 播放 PCM 音频流音量低

如何将 FFMPEG AV_CODEC_ID_PCM_S16BE 音频数据馈送到 AudioQueue

CoreAudio基础概念

如何在不冻结 GUI 的情况下让 AudioQueue 播放?