void XAudio2_Output::close() { initialized = false; if( sVoice ) { if( playing ) { HRESULT hr = sVoice->Stop( 0 ); ASSERT( hr == S_OK ); } sVoice->DestroyVoice(); sVoice = NULL; } if( buffers ) { free( buffers ); buffers = NULL; } if( mVoice ) { mVoice->DestroyVoice(); mVoice = NULL; } if( xaud ) { xaud->Release(); xaud = NULL; } }
static void XAUDIO2_CloseDevice(_THIS) { if (_this->hidden != NULL) { IXAudio2 *ixa2 = _this->hidden->ixa2; IXAudio2SourceVoice *source = _this->hidden->source; IXAudio2MasteringVoice *mastering = _this->hidden->mastering; if (source != NULL) { source->Stop(); source->FlushSourceBuffers(); source->DestroyVoice(); } if (ixa2 != NULL) { ixa2->StopEngine(); } if (mastering != NULL) { mastering->DestroyVoice(); } if (ixa2 != NULL) { ixa2->Release(); } SDL_free(_this->hidden->mixbuf); if (_this->hidden->semaphore != NULL) { CloseHandle(_this->hidden->semaphore); } SDL_free(_this->hidden); _this->hidden = NULL; } }
void close() { if( sVoice ) { if( !paused ) { sVoice->Stop( 0 ); } sVoice->DestroyVoice(); } if( mVoice ) { mVoice->DestroyVoice(); } if( xaud ) { xaud->Release(); xaud = NULL; } delete [] sample_buffer; sample_buffer = NULL; delete [] samples_in_buffer; samples_in_buffer = NULL; }
/* Loads a sound with the specified id and path */ void XAudioSoundSystem::OnLoadSound(uint32 soundID, const char* szSoundPath) { if(mSounds[soundID] != NULL) return; HRESULT hr = S_OK; char szFullPath[1024]; sprintf_s(szFullPath, 1024, "Data/Win32/%s", szSoundPath); size_t convertedChars = 0; wchar_t wpath[1024]; mbstowcs_s(&convertedChars, wpath, strlen(szFullPath) + 1, szFullPath, _TRUNCATE); // // Read in the wave file // CWaveFile wav; if( FAILED( hr = wav.Open( wpath, NULL, WAVEFILE_READ ) ) ) { wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, wpath ); return; } // Get format of wave file WAVEFORMATEX* pwfx = wav.GetFormat(); // Calculate how many bytes and samples are in the wave DWORD cbWaveSize = wav.GetSize(); // Read the sample data into memory BYTE* pbWaveData = new BYTE[ cbWaveSize ]; if( FAILED( hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) ) { wprintf( L"Failed to read WAV data: %#X\n", hr ); SAFE_DELETE_ARRAY( pbWaveData ); return; } // // Play the wave using a XAudio2SourceVoice // // Create the source voice IXAudio2SourceVoice* pSourceVoice; if( FAILED( hr = mXAudio2->CreateSourceVoice( &pSourceVoice, pwfx ) ) ) { wprintf( L"Error %#X creating source voice\n", hr ); SAFE_DELETE_ARRAY( pbWaveData ); return; } // Submit the wave sample data using an XAUDIO2_BUFFER structure XAUDIO2_BUFFER buffer = {0}; buffer.pAudioData = pbWaveData; buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer buffer.AudioBytes = cbWaveSize; if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) ) { wprintf( L"Error %#X submitting source buffer\n", hr ); pSourceVoice->DestroyVoice(); SAFE_DELETE_ARRAY( pbWaveData ); return; } Sound* pSound = new Sound(); pSound->mVoice = pSourceVoice; pSound->mAudioBuffer = buffer; pSound->mData = pbWaveData; pSound->mStarted = false; mSounds[soundID] = pSound; }
void GameAudio::shutDown() { //// ---- destroy sound effects if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_SHOOT] == true) { IXAudio2SourceVoice* shootSound = soundEffectMap[ENUM_SOUND_EFFECT_SHOOT]; shootSound->DestroyVoice(); XAUDIO2_BUFFER *buffer = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_SHOOT]; delete[] buffer->pAudioData; delete buffer; } if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_MONEY] == true) { IXAudio2SourceVoice* moneySound = soundEffectMap[ENUM_SOUND_EFFECT_MONEY]; moneySound->DestroyVoice(); XAUDIO2_BUFFER *buffer = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_MONEY]; delete[] buffer->pAudioData; delete buffer; } if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_PUNCH] == true) { IXAudio2SourceVoice* punchSound = soundEffectMap[ENUM_SOUND_EFFECT_PUNCH]; punchSound->DestroyVoice(); XAUDIO2_BUFFER *buffer = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_PUNCH]; delete[] buffer->pAudioData; delete buffer; } if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_HEAL] == true) { IXAudio2SourceVoice* healSound = soundEffectMap[ENUM_SOUND_EFFECT_HEAL]; healSound->DestroyVoice(); XAUDIO2_BUFFER *buffer = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_HEAL]; delete[] buffer->pAudioData; delete buffer; } if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_DAMAGE] == true) { IXAudio2SourceVoice* damageSound = soundEffectMap[ENUM_SOUND_EFFECT_DAMAGE]; damageSound->DestroyVoice(); XAUDIO2_BUFFER *buffer = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_DAMAGE]; delete[] buffer->pAudioData; delete buffer; } //// --- destory sound effects complete //// --- destroy musics if (musicRegistrationMap[ENUM_MUSIC_MAIN_THEME] == true) { IXAudio2SourceVoice* mainTheme = musicMap[ENUM_MUSIC_MAIN_THEME]; mainTheme->DestroyVoice(); XAUDIO2_BUFFER *buffer = musicBufferPrototypeMap[ENUM_MUSIC_MAIN_THEME]; delete[] buffer->pAudioData; delete buffer; } if (musicRegistrationMap[ENUM_MUSIC_LEVEL_COMPLETE] == true) { IXAudio2SourceVoice* completeMusic = musicMap[ENUM_MUSIC_LEVEL_COMPLETE]; completeMusic->DestroyVoice(); XAUDIO2_BUFFER *buffer = musicBufferPrototypeMap[ENUM_MUSIC_LEVEL_COMPLETE]; delete[] buffer->pAudioData; delete buffer; } if (musicRegistrationMap[ENUM_MUSIC_INGAME] == true) { IXAudio2SourceVoice* ingameMusic = musicMap[ENUM_MUSIC_INGAME]; ingameMusic->DestroyVoice(); XAUDIO2_BUFFER *buffer = musicBufferPrototypeMap[ENUM_MUSIC_INGAME]; delete[] buffer->pAudioData; delete buffer; } if (musicRegistrationMap[ENUM_MUSIC_GAMEOVER] == true) { IXAudio2SourceVoice* gameoverMusic = musicMap[ENUM_MUSIC_GAMEOVER]; gameoverMusic->DestroyVoice(); XAUDIO2_BUFFER *buffer = musicBufferPrototypeMap[ENUM_MUSIC_GAMEOVER]; delete[] buffer->pAudioData; delete buffer; } //// --- destroy musics complete //// --- put other effects' destructors here ------ masterVoice->DestroyVoice(); xAudio2Engine->Release(); CoUninitialize(); }
//the streaming thread procedure DWORD WINAPI StreamProc(LPVOID pContext) { //required by XAudio2 CoInitializeEx(NULL, COINIT_MULTITHREADED); if(pContext == NULL) { CoUninitialize(); return -1; } StreamContext* sc = (StreamContext*)pContext; //instantiate the voice's callback class StreamingVoiceCallback callback; //load a file for streaming, non-buffered disk reads (no system cacheing) StreamingWave inFile; if(!inFile.load(sc->filename)) { SetEvent(sc->VoiceLoadEvent); CoUninitialize(); return -3; } //create the voice IXAudio2SourceVoice* source = NULL; if(FAILED(XAudio2->CreateSourceVoice(&source, &inFile.waveFormat.Format, 0, 2.0f, &callback))) { SetEvent(sc->VoiceLoadEvent); CoUninitialize(); return -5; } //fill and queue the maximum number of buffers (except the one needed for reading new wave data) bool somethingsWrong = false; XAUDIO2_VOICE_STATE voiceState = {0}; source->GetState(&voiceState); while(voiceState.BuffersQueued < STREAMINGWAVE_BUFFER_COUNT - 1 && !somethingsWrong) { //read and fill the next buffer to present switch(inFile.prepare()) { case StreamingWave::PR_EOF: //if end of file, loop the file read inFile.resetFile(); //intentionally fall-through to loop sound case StreamingWave::PR_SUCCESS: //present the next available buffer inFile.swap(); //submit another buffer source->SubmitSourceBuffer(inFile.buffer()); source->GetState(&voiceState); break; case StreamingWave::PR_FAILURE: somethingsWrong = true; break; } } //return the created voice through the context pointer sc->pVoice = &source; //signal that the voice has prepared for streaming, and ready to start SetEvent(sc->VoiceLoadEvent); //group the events for the Wait function HANDLE Events[2] = {callback.BufferEndEvent, QuitEvent}; bool quitting = false; while(!quitting) { //wait until either the source voice is ready for another buffer, or the abort signal is set DWORD eventFired = WaitForMultipleObjects(2, Events, FALSE, INFINITE); switch(eventFired) { case 0: //buffer ended event for source voice //reset the event manually ResetEvent(Events[0]); //make sure there's a full number of buffers source->GetState(&voiceState); while(voiceState.BuffersQueued < STREAMINGWAVE_BUFFER_COUNT - 1 && !somethingsWrong) { //read and fill the next buffer to present switch(inFile.prepare()) { case StreamingWave::PR_EOF: //if end of file, loop the file read inFile.resetFile(); //intentionally fall-through to loop sound case StreamingWave::PR_SUCCESS: //present the next available buffer inFile.swap(); //submit another buffer source->SubmitSourceBuffer(inFile.buffer()); source->GetState(&voiceState); break; case StreamingWave::PR_FAILURE: somethingsWrong = true; break; } } break; default: //something's wrong... quitting = true; } } //stop and destroy the voice source->Stop(); source->FlushSourceBuffers(); source->DestroyVoice(); //close the streaming wave file; //this is done automatically in the class destructor, //so this is redundant inFile.close(); //cleanup CoUninitialize(); return 0; }
//-------------------------------------------------------------------------------------- // Name: PlayWave // Desc: Plays a wave and blocks until the wave finishes playing //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT PlayWave( IXAudio2* pXaudio2, LPCWSTR szFilename ) { // // Locate the wave file // WCHAR strFilePath[MAX_PATH]; HRESULT hr = FindMediaFileCch( strFilePath, MAX_PATH, szFilename ); if( FAILED( hr ) ) { wprintf( L"Failed to find media file: %s\n", szFilename ); return hr; } // // Read in the wave file // std::unique_ptr<uint8_t[]> waveFile; DirectX::WAVData waveData; if ( FAILED( hr = DirectX::LoadWAVAudioFromFileEx( strFilePath, waveFile, waveData ) ) ) { wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, strFilePath ); return hr; } // // Play the wave using a XAudio2SourceVoice // // Create the source voice IXAudio2SourceVoice* pSourceVoice; if( FAILED( hr = pXaudio2->CreateSourceVoice( &pSourceVoice, waveData.wfx ) ) ) { wprintf( L"Error %#X creating source voice\n", hr ); return hr; } // Submit the wave sample data using an XAUDIO2_BUFFER structure XAUDIO2_BUFFER buffer = {0}; buffer.pAudioData = waveData.startAudio; buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer buffer.AudioBytes = waveData.audioBytes; if ( waveData.loopLength > 0 ) { buffer.LoopBegin = waveData.loopStart; buffer.LoopLength = waveData.loopLength; buffer.LoopCount = 1; // We'll just assume we play the loop twice } #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/ ) if ( waveData.seek ) { XAUDIO2_BUFFER_WMA xwmaBuffer = {0}; xwmaBuffer.pDecodedPacketCumulativeBytes = waveData.seek; xwmaBuffer.PacketCount = waveData.seekCount; if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer, &xwmaBuffer ) ) ) { wprintf( L"Error %#X submitting source buffer (xWMA)\n", hr ); pSourceVoice->DestroyVoice(); return hr; } } #else if ( waveData.seek ) { wprintf( L"This platform does not support xWMA or XMA2\n" ); pSourceVoice->DestroyVoice(); return hr; } #endif else if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) ) { wprintf( L"Error %#X submitting source buffer\n", hr ); pSourceVoice->DestroyVoice(); return hr; } 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; // Wait till the escape key is pressed if( GetAsyncKeyState( VK_ESCAPE ) ) break; Sleep( 10 ); } // Wait till the escape key is released while( GetAsyncKeyState( VK_ESCAPE ) ) Sleep( 10 ); pSourceVoice->DestroyVoice(); return hr; }
//-------------------------------------------------------------------------------------- // Name: PlayWaveFromWaveBank // Desc: Plays a wave and blocks until the wave finishes playing //-------------------------------------------------------------------------------------- _Use_decl_annotations_ HRESULT PlayWaveFromWaveBank( IXAudio2* pXaudio2, WaveBankReader& wb, uint32_t index ) { if ( index >= wb.Count() ) return E_INVALIDARG; uint8_t waveFormat[64]; auto pwfx = reinterpret_cast<WAVEFORMATEX*>( &waveFormat ); HRESULT hr = wb.GetFormat( index, pwfx, 64 ); if ( FAILED(hr) ) return hr; const uint8_t* waveData = nullptr; uint32_t waveSize; hr = wb.GetWaveData( index, &waveData, waveSize ); if ( FAILED(hr) ) return hr; WaveBankReader::Metadata metadata; hr = wb.GetMetadata( index, metadata ); if ( FAILED(hr) ) return hr; // // Play the wave using a XAudio2SourceVoice // // Create the source voice IXAudio2SourceVoice* pSourceVoice; if( FAILED( hr = pXaudio2->CreateSourceVoice( &pSourceVoice, pwfx ) ) ) { wprintf( L"Error %#X creating source voice\n", hr ); return hr; } // Submit the wave sample data using an XAUDIO2_BUFFER structure XAUDIO2_BUFFER buffer = {0}; buffer.pAudioData = waveData; buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer buffer.AudioBytes = waveSize; if ( metadata.loopLength > 0 && metadata.loopLength != metadata.duration ) { buffer.LoopBegin = metadata.loopStart; buffer.LoopLength = metadata.loopLength; buffer.LoopCount = 1; // We'll just assume we play the loop twice } const uint32_t* seekTable; uint32_t seekTableCount; uint32_t tag; hr = wb.GetSeekTable( index, &seekTable, seekTableCount, tag ); if ( seekTable ) { if ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 ) { #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/ ) XAUDIO2_BUFFER_WMA xwmaBuffer = {0}; xwmaBuffer.pDecodedPacketCumulativeBytes = seekTable; xwmaBuffer.PacketCount = seekTableCount; if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer, &xwmaBuffer ) ) ) { wprintf( L"Error %#X submitting source buffer (xWMA)\n", hr ); pSourceVoice->DestroyVoice(); return hr; } #else wprintf( L"This platform does not support xWMA\n" ); pSourceVoice->DestroyVoice(); return hr; #endif } else if ( tag == 0x166 /* WAVE_FORMAT_XMA2 */ ) { wprintf( L"This platform does not support XMA2\n" ); pSourceVoice->DestroyVoice(); return hr; } } else if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) ) { wprintf( L"Error %#X submitting source buffer\n", hr ); pSourceVoice->DestroyVoice(); return hr; } 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; // Wait till the escape key is pressed if( GetAsyncKeyState( VK_ESCAPE ) ) break; Sleep( 10 ); } // Wait till the escape key is released while( GetAsyncKeyState( VK_ESCAPE ) ) Sleep( 10 ); pSourceVoice->DestroyVoice(); return hr; }