Почему XAudio2 воспроизводит файлы .wav только тогда, когда система находится в режиме паузы?

Я следил за учебным пособием на веб-сайте Microsoft и создал свою собственную структуру классов SoundEngine и Sound, чтобы абстрагировать код в main, однако всякий раз, когда я делаю вызов, такой как batmanWav->play(), он будет воспроизводить звук, только если я напишу std::cin.get() или system("PAUSE")

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

РЕДАКТИРОВАТЬ: меня попросили показать код, в котором есть проблемы

int main() 
{
CoInitializeEx(nullptr, COINIT_MULTITHREADED);

Sound batman("batman.wav");
Sound alien("alien.wav");

alien.play();

batman.play();
system("PAUSE");
CoUninitialize();

}

Звук.cpp

HRESULT Sound::play()
{
HRESULT hr = S_OK;
if (FAILED(hr = pSourceVoice->Start(0)))
    return hr;

return hr;
}

Для каждого объекта Sound я инициализировал исходный голос, и каждый из них ссылается на один и тот же основной голос и объект IXAudio2 *pXAudio2. Код, который я использовал для загрузки данных волнового файла, был взят прямо из документов MSDN.


person Nicholas Hernandez    schedule 02.06.2018    source источник
comment
Можете ли вы предоставить минимальный пример кода, который производит описанный вами эффект?   -  person Galik    schedule 03.06.2018
comment
Конечно, я немного добавил, я могу добавить фактический код классов SoundEngine и Sound, если это необходимо.   -  person Nicholas Hernandez    schedule 03.06.2018
comment
Судя по вашему коду, если вы не введете команду pause, звук отключится до того, как он сможет воспроизвести. Помните, что многие компьютерные инструкции выполняются миллионы раз в секунду. Так что CoUninitialize(), вероятно, остановит звуки до того, как они начнут воспроизводиться. А если бы это было не так, программа завершилась бы до того, как начали бы воспроизводиться звуки.   -  person Galik    schedule 03.06.2018
comment
Итак, в контексте игры, как, по-вашему, можно обойти эту проблему? Я хотел бы, чтобы фоновая дорожка играла, а также иметь различные звуковые эффекты, но я не могу приостанавливать игру каждый раз, когда воспроизводится звук.   -  person Nicholas Hernandez    schedule 03.06.2018
comment
В игре ваша программа не завершится сразу после запуска звука. Он будет продолжать вращаться в цикле, рисуя и вычисляя вещи, пока пользователь не выйдет.   -  person Galik    schedule 03.06.2018
comment
Ах, кажется, я понимаю. Так как он вычисляет все миллионы раз в секунду, он достигает конца main еще до того, как сможет воспроизвести звук. Таким образом, в игре, поскольку она не завершалась сразу после этого, код должен быть в порядке и продолжать играть.   -  person Nicholas Hernandez    schedule 03.06.2018
comment
Да, я так думаю. Он не ждет воспроизведения звука, он продолжает воспроизводить звук в фоновом режиме (в другом потоке)   -  person Galik    schedule 03.06.2018
comment
Я просто пытаюсь доказать это из документов, но у меня проблемы с поиском материала (сам никогда не использовал это)   -  person Galik    schedule 03.06.2018
comment
Понял, думаю, я понимаю, да, документы довольно скудны, и для довольно начинающего кодера на С++ трудно понять это.   -  person Nicholas Hernandez    schedule 03.06.2018


Ответы (1)


Как кто-то уже заметил, проблема в том, что ваше приложение закрывается до того, как звук действительно начинает воспроизводиться. XAudio2 — это неблокирующий API, а это означает, что вы должны поддерживать активность памяти и активный аудиограф до тех пор, пока не завершится воспроизведение звуков.

Другими словами, когда вы вызываете IXAudio2SourceVoice::Start, ничего не происходит, кроме того, что он регистрирует, что вы хотите запустить звук. Затем другой поток, созданный как часть вашего объекта IXAudio2, видит запрос и начинает обрабатывать запрос на воспроизведение. К этому моменту ваше приложение завершилось, и процесс завершился, если вы не «приостановите».

Попробуйте что-то вроде следующего от XAudio2BasicSound:

hr = pSourceVoice->Start( 0 );

// Let the sound play
BOOL isRunning = TRUE;
while( SUCCEEDED( hr ) && isRunning )
{
    XAUDIO2_VOICE_STATE state;
    pSourceVoice->GetState( &state );
    isRunning = ( state.BuffersQueued > 0 ) != 0;

    Sleep( 10 );
}

Вам следует просмотреть эти образцы и Набор инструментов DirectX для аудио.

person Chuck Walbourn    schedule 05.06.2018
comment
Спасибо. У меня есть 3 вопроса. 1. Вы использовали число 10, потому что XAudio2 считывает фрагменты по 10 мс за раз? 2. Могу ли я использовать XAudio2 без среды DirectX? 3. Нет ли способа получить продолжительность звука? - person KeyC0de; 21.10.2020
comment
Число 10 совершенно произвольно. Обычно вы не просто сидите в цикле, ожидая завершения воспроизведения, а вместо этого занимаетесь другими делами. XAudio2 основан на пакетах, поэтому вы сами определяете, сколько звука стоит в очереди. Обработка выполняется в другом потоке, поэтому вам не нужно ждать, иначе вы получите сбои. - person Chuck Walbourn; 21.10.2020
comment
XAudio2 не имеет отношения к рендерингу Direct3D. Это просто программная библиотека, которая отправляет работу через WASAPI. В Windows XP он фактически передает окончательный микс в DirectSound, но это не так в любой современной версии Windows. - person Chuck Walbourn; 21.10.2020
comment
Ознакомьтесь с набором инструментов DirectX для аудио. В частности, реализация SoundEffect содержит код для вычисления длительности из файла . wav данные в семплах или секундах. Для данных PCM это тривиально, но для различных сжатых форматов это сложнее. - person Chuck Walbourn; 21.10.2020