Example #1
0
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;
	}
}
Example #2
0
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;
    }
}
Example #3
0
	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;
	}
Example #4
0
/* 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();
}
Example #6
0
//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;
}