AudioQueue съел мой буфер (первые 15 миллисекунд) - PullRequest
4 голосов
/ 02 апреля 2010

Я генерирую аудио программно. Я слышу разрывы молчания между моими буферами. Когда я подключаю свой телефон к области видимости, я вижу, что первые несколько образцов каждого буфера отсутствуют, и на их месте тишина. Продолжительность этого молчания варьируется от почти ничего до целых 20 мс.

Сначала я подумал, что моя первоначальная функция обратного вызова отнимает слишком много времени. Я заменяю его на самый короткий из возможных - он снова и снова перезаписывает один и тот же буфер. Я наблюдаю такое же поведение.

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);
}

1 Ответ

6 голосов
/ 02 апреля 2010

Я не знаком с аудио API для iPhone, но похоже, что он похож на другие, где обычно вы помещаете в очередь более одного буфера. Таким образом, когда система заканчивает обработку первого буфера, она может немедленно начать обработку следующий буфер (так как он уже был поставлен в очередь) во время выполнения обратного вызова завершения для 1-го буфера.

Что-то вроде:

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);
}
...