Я просто не могу понять эту проблему. Звук из приведенного ниже кода играет очень быстро и прерывно. Есть еще одна проблема с 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;
}
Спасибо. Как бы я определил, в какой поток работает обратный вызов (это консольное приложение, поэтому никакой пользовательский интерфейс не работает, но, вероятно, синтез. Я думал, что AudioQueues запускается на отдельном CFRunLoop. –
Какой поток может сделать хороший отдельный вопрос. – hotpaw2