2013-08-28 1 views
1

Я написал небольшую звуковую библиотеку с PortAudio в Linux. Это для маленькой игры, поэтому есть много маленьких звуков, когда происходят разные вещи. Я открываю поток для каждого wav-файла для воспроизведения, вызывая Pa_OpenStream(). В linux этот вызов занимает в среднем около 10 мс. Однако в Windows это обычно занимает от 40 до 70 мс. И что еще хуже, первый вызов занимает 1,3 секунды. Затем по истечении этого времени он снова займет 1,3 секунды. Я не смог найти ничего последовательного в том, почему он висит, за исключением того, что это происходит каждый первый звонок. Окно на самом деле отлично работает на Wine.Как эффективно использовать PortAudio Pa_OpenStream() в Windows?

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

Вот моя игра функция:

int play(const char * sN) 
{ 
    float threshold = .01f; 

    char * soundName = (char*)sN; 
    float g = glfwGetTime(); 
    updatePlayer(); 
    float g2 = glfwGetTime(); 
    if (g2-g > threshold) printf("updatePlayer: %f/", g2 - g); 
    if (!paused && (int)streams.size() < maxStreams && !mute) 
    { 
     streamStr * ss = new streamStr; 

     g = glfwGetTime(); 
     if (g-g2 > threshold) printf("new stream: %f/", g - g2); 
     PaError err; 

     sfData * sdata = getData(soundName); 
     ss->sfd = sdata; 

     g2 = glfwGetTime(); 
     if (g2-g > threshold)printf("getData: %f/", g2 - g); 
     err = Pa_OpenStream(&(ss->stream), 0, &sdata->outputParameters, sdata->sfInfo.samplerate, paFramesPerBufferUnspecified, paNoFlag, PaCallback, ss); 
     if (err) 
     { 
      printf("PortAudio error opening output: %s\n", Pa_GetErrorText(err)); 
      delete ss; 
      return 1; 
     } 

    g = glfwGetTime(); 
    if (g-g2 > threshold) 
    printf("Pa_OpenStream: %f/", g - g2); 

     Pa_StartStream(ss->stream); 

    g2 = glfwGetTime(); 
    if (g2-g > threshold)printf("Pa_StartStream: %f/", g2 - g); 
     addStreams(ss); 

    g = glfwGetTime(); 
    if (g-g2 > threshold)printf("addStreams: %f", g - g2); 
     //Pa_SetStreamFinishedCallback(ss, finishedCallback); 
     printf("\n"); 
    } 
    return 0; 
} 

ответ

2

ИДК, почему это занимает так долго (потому что я не знаю, окна), но я могу сказать, что вы собираетесь об этом неправильный путь. В частности, вы не должны делать никаких ожиданий относительно открытия нового потока. Например, я ожидал бы аналогичных проблем (хотя и в гораздо меньшей степени) в OS X.

Правильная реализация заключалась бы в том, чтобы всегда открывать поток, играть в тишину. Затем, когда вам нужно воспроизвести звук, вы можете сразу воспроизвести его. Для наилучшей задержки вы должны предварительно загрузить первые несколько буферов из файла, чтобы вам не нужно было обращаться к диску при запуске воспроизведения. Я не знаю, какие точные накладные расходы на Windows для открытия потока (я уверен, что это зависит от API), но в некоторых версиях OS X это огромный (все ядро ​​переключается в режим превентивного режима, если нет раньше был звук).

Тем не менее, 1,3 секунды безумны. Я рекомендую просить в списке рассылки. Обязательно скажите, какой хост-API вы используете, потому что вы не сказали этого здесь, и для Windows это имеет значение. Кроме того, какая версия окон.

+0

Интересно, спасибо. В этом есть смысл. Я посмотрю дальше и уточню свои выводы. –

+2

Другой вариант - открыть поток во время инициализации, как было предложено, а затем запустить и остановить поток при воспроизведении звука. Преимуществом этого подхода будет возможность для потока получить резервные копии с данными молчания, которые вы передаете ему (добавлена ​​латентность). Недостатком является латентность, возникающая потоком потока PortAudio создает, когда поток запущен и остановлен. – trukvl

+0

Я никогда не обращал внимания на то, сколько времени требуется для открытия потока, хотя я скажу, что заметил, что приложения могут запускаться в Windows довольно необычно долго. Я должен буду заметить в будущем. – trukvl

0

Чтобы минимизировать задержку запуска для этого прецедента (т. Е. Ожидая, что StartStream() даст минимальную задержку запуска), вы должны использовать флаг потока paPrimeOutputBuffersUsingStreamCallback. В противном случае начальные буферы будут равны нулю, а время, необходимое для того, чтобы звук попал в ЦАП, будет включать в себя разметку длины буфера нулей (которая будет составлять около 80 мс в Windows WMME или DirectSound с настройками ПА по умолчанию).

+0

Это интересный флаг, спасибо за указание на это. Но это не должно вызывать вышеупомянутую задержку на окнах.Поток, запрашивающий поток, полностью остановлен, есть не только латентность звука. –

+0

Я согласен, что это не причина долгой задержки. Если весь поток остановлен, скорее всего, это проблема с драйвером или подсистемой Windows. Можете ли вы определить, какой системный вызов PortAudio остановлен внутри? –

 Смежные вопросы

  • Нет связанных вопросов^_^