Я написал небольшую библиотеку для воспроизведения звука с помощью PortAudio в Linux. Это для маленькой игры, поэтому, когда происходят разные вещи, звучит много маленьких звуков. Я открываю поток для каждого файла wav для воспроизведения, вызывая Pa_OpenStream (). В Linux этот вызов занимает в среднем около 10 мс. Однако в Windows это обычно занимает от 40 до 70 мс. И что еще хуже, первый звонок занимает 1,3 секунды. Затем после этого иногда это займет 1,3 секунды. Я не смог найти ничего последовательного в том, почему он зависает, за исключением того, что это происходит при каждом первом звонке. На самом деле сборка Windows работает на Wine.
Я предполагаю, что это связано с различиями в базовом звуковом 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;
}
ИДК, почему так долго (потому что я не знаю окон), но я могу сказать, что вы идете по этому поводу неправильно. В частности, вы не должны делать никаких временных ожиданий по поводу открытия нового потока. Например, я ожидал бы подобных проблем (хотя и в гораздо меньшей степени) на OS X.
Правильной реализацией было бы всегда иметь открытый поток, воспроизводящий тишину. Затем, когда вам нужно воспроизвести звук, вы можете воспроизвести его прямо сейчас. Для максимальной задержки вы должны предварительно загрузить несколько первых буферов из файла, чтобы вам не требовался доступ к диску при запуске воспроизведения. Я не знаю, какие именно издержки на окнах для открытия потока (я уверен, что это зависит от API), но в некоторых версиях OS X это огромный (все ядро переключается в режим вытеснения, если до этого не было звука).
Тем не менее, 1,3 секунды безумие. Я рекомендую спросить в списке рассылки. Обязательно укажите, какой хост-API вы используете, потому что вы этого не сказали, а для Windows это важно. Также какая версия windows.
Чтобы минимизировать задержку запуска для этого варианта использования (т.е. ожидая, что StartStream () выдаст минимальную задержку запуска), вы должны использовать флаг потока paPrimeOutputBuffersUsingStreamCallback. В противном случае начальные буферы будут равны нулю, и время, необходимое для попадания звука на ЦАП, будет включать в себя воспроизведение нулевой длины буфера (которая будет около 80 мс в Windows WMME или DirectSound с настройками PA по умолчанию).