2015-12-15 4 views
0

Я просто не могу понять эту проблему. Звук из приведенного ниже кода играет очень быстро и прерывно. Есть еще одна проблема с SO, которая аналогична, но для переменной битрейта и неприменима.CoreAudio AudioQueue PCM быстрый и прерывистый

Некоторые возможные ответы на других сайтах (прямое количество кадров в пакете) больше не работают и дают код ошибки aq -50.

Это из базы данных синтезатора, исходный аудиосигнал - 8:24 Линейный PCM с частотой 44,100 Гц, без чередования. Установка кадров (4096) на частоту дискретизации (44100 Гц), по-видимому, устраняет прерывистость, но бэкэнда генерации звука не может идти в ногу, поэтому он ломает каждый пакет.

Любые решения? Для жизни я не могу понять, что заставляет это работать так быстро.

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

Возможно, вы обращаетесь с обратным вызовом звуковой очереди в основной поток пользовательского интерфейса приложения. Если вы слишком долго блокируете этот поток (тратя слишком много времени на выполнение синтеза, пользовательского интерфейса или drawRects и т. Д.), Обратный вызов AQ не будет вызван вовремя. Таким образом, аудиовыход будет истощаться и звучать нестабильно.

+0

Спасибо. Как бы я определил, в какой поток работает обратный вызов (это консольное приложение, поэтому никакой пользовательский интерфейс не работает, но, вероятно, синтез. Я думал, что AudioQueues запускается на отдельном CFRunLoop. –

+0

Какой поток может сделать хороший отдельный вопрос. – hotpaw2