2016-04-14 4 views
1

Я делаю воспроизведение с использованием основного звука (OS X, 10.11.4 Beta, более старый mac mini), используя простой выходной аудиоустройство, настроенное для ввода и вывода (хотя все мои проблемы, похоже, с выходом). Это потоковый источник звука из розетки/интернет-подачи в очередь без блокировки, которая затем подается на выход AU. Я получаю аудиопакеты, которые, по-видимому, являются результатом обратного вызова рендеринга AU, который не прерывается с помощью основного звука с перерывами.
Адрес graph. Перед этим разделом было ~ 10 секунд безупречного звука.Опытные аудиопоходы с воспроизведением/воспроизведением основного звука OS X

черный: аудио дискретизации, простой синусоидальной волны

синий: стены Продолжительность часы рендеринга обратного вызова (OutputProc) в мс, указать от диаграммы выше ~ 120 мс

оранжевый: размер очереди беззамочные (playback_buf) в образцах/1000, чтобы уместить его в графике хорошо

оси х: время в мс

Все вошли в OutputProc, так что, если не вызывается, то ничто не регистрируется, но инструмент изображая будет соединить точки периоды. В буфере всегда достаточно образцов. Кажется, что от ~ 22475 мс до ~ 22780 мс OutputProc вызывается только один раз на 22640. У этого есть длительное время настенных часов в этом конкретном случае, но, похоже, связано с преимущественным преимуществом. Позже в диапазоне от 22800 до 23000 все еще остаются отсева, но OutputProc не длится дольше, чем обычно, и, конечно же, не переполняет окно реального времени (~ 6 мс здесь ... Частота кадров HW составляет 96 кГц). Итак, я думаю, что это какой-то другой поток, который как-то упреждает. Я бы ожидал, что основной аудиопоток будет иметь очень высокий приоритет. У меня есть несколько дополнительных входов/выходов asio сокета, идущих параллельно (например, boost :: asio :: io_service io_service), но я бы ожидал, что всегда будет потерять приоритет для основного звука. Если у вас есть какие-то указатели на настоящую проблему ... это всегда приветствуется ... но я могу добиться прогресса, если я просто смогу узнать, какие потоки выполняются в те моменты, когда они интересны? Есть ли что-то в Xcode, которое сообщает мне историю планировщика или историю потоков, возможно, для ядра процессора? OutputProc, если это помогает:

OSStatus AudioStream::OutputProc(void *inRefCon, 
           AudioUnitRenderActionFlags *ioActionFlags, 
           const AudioTimeStamp *TimeStamp, 
           UInt32 inBusNumber, 
           UInt32 inNumberFrames, 
           AudioBufferList *ioData) 
{ 
    AudioStream *This = (AudioStream *) inRefCon; 

    playback_cb_dur_log.StartTime(); 

    static bool first_call = true; 
    if (first_call) 
    { 
     std::cout << TIME(timer) << " playback starting\n"; 
     This->playback_state = PLAYBACK_ACTIVE; 
     first_call = false; 
    } 

    int playback_buf_avail = (int) This->playback_buf.read_available(); 
    playback_buf_size_log.AddPoint(playback_buf_avail/1000.); 
    if (playback_buf_avail >= This->playback_buf_thresh) 
    { 
     std::cout << TIME() << " audio, thresh: " << This->playback_buf_thresh << ", buf_size: " << playback_buf_avail << std::endl; 
     // new threshold just one frame of data 
     This->playback_buf_thresh = This->frames_total; 
     for(int i = 0; i < This->num_channels; i++) 
     { 
      float *temp = (float *) ioData->mBuffers[i].mData; 
      This->playback_buf.pop(temp, inNumberFrames); 
      playback_sample_log.AddData(ioData->mBuffers[i].mData, inNumberFrames, This->chan_params.sample_rate); 
     } 
    } 
    else 
    { 
     std::cout << TIME() << " silence, thresh: " << This->playback_buf_thresh << ", buf_size: " << This->playback_buf.read_available() << std::endl; 
     for(int i = 0; i < This->num_channels; i++) 
     { 
      memset(ioData->mBuffers[i].mData, 0, inNumberFrames * sizeof(Float32)); 
      playback_sample_log.AddData(ioData->mBuffers[i].mData, inNumberFrames, This->chan_params.sample_rate); 
     } 
    } 


    playback_cb_dur_log.StopAndCaptureTime(); 

    return noErr; 
} 
+0

Я никогда не сталкивался с нарастающими настенными часами длительностью CoreAudio, вызывая обратные вызовы или прерывистые системные вызовы OutputProc. Обратный поток - это режим реального времени и таймер. Если поток производителей не обеспечивает своевременную доставку данных, он не ждет: тишина - это то, что вы получаете. Я полагаю, что проблема должна быть в другом месте. Что это за строка: 'if (playback_buf_avail> = This-> playback_buf_thresh)' и какой механизм обновляет структуру данных _This_ data? – user3078414

ответ

1

Ваш механизм регистрации может быть вмешательство в режиме реального времени поток. Все, любой вызов, который может блокировать или управлять памятью (например, создание строки или файл ввода-вывода ввода-вывода), может вызвать выпадения и другие сбои в обратных вызовах Audio Unit.

Если это так, вы можете попробовать набивать ваши штампы времени в блокировочном кольцевом протоколе FIFO и делать любой файл ввода-вывода в другом потоке.

+0

Да, это была хотя бы часть проблемы. Мне также пришлось удалить инструкции std :: cout, а также как протоколирование, так и инструкции cout из функции получения сокетов, которая является продюсером, добавляющим к play_buf (который является boost :: lockfree :: spsc_queue). Благодаря! – Chris