void GameAudio::playMusicOnce(MusicTypes musicType)
{
	if (musicRegistrationMap[musicType] == true)
	{
		IXAudio2SourceVoice *sourceVoice = musicMap[musicType];

		XAUDIO2_VOICE_STATE voiceState;
		sourceVoice->GetState(&voiceState);

		if (musicType == ENUM_MUSIC_LEVEL_COMPLETE)
		{
			if (levelCompleteMusicBuffered == false)
			{
				XAUDIO2_BUFFER *proto = musicBufferPrototypeMap[musicType];
				bool ssbSuccess = SUCCEEDED(sourceVoice->SubmitSourceBuffer(proto));
				sourceVoice->Start();
				levelCompleteMusicBuffered = true;
			}
		}

		/// here put the game over music
		else if (musicType == ENUM_MUSIC_GAMEOVER)
		{
			if (gameOverMusicBuffered == false)
			{
				XAUDIO2_BUFFER *proto = musicBufferPrototypeMap[musicType];
				bool ssbSuccess = SUCCEEDED(sourceVoice->SubmitSourceBuffer(proto));
				sourceVoice->Start();
				gameOverMusicBuffered = true;
			}
		}
	}
}
void GameAudio::processPunchSound()
{
	if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_PUNCH] == true)
	{
		Game *game = Game::getSingleton();
		GameStateManager *gsm = game->getGSM();
		SpriteManager *spriteMgr = gsm->getSpriteManager();
		PlayerSprite *player = spriteMgr->getPlayer();

		wstring playerState = player->getCurrentState();

		if (playerState.compare(L"PUNCH_LEFT") == 0 || playerState.compare(L"PUNCH_RIGHT") == 0
			|| playerState.compare(L"PUNCH_BACK") == 0 || playerState.compare(L"PUNCH_FRONT") == 0)
		{
			IXAudio2SourceVoice *punchSound = soundEffectMap[ENUM_SOUND_EFFECT_PUNCH];

			XAUDIO2_VOICE_STATE voiceState;
			punchSound->GetState(&voiceState);

			//// [voiceState.BuffersQueued <= 0] means there are nothing in the buffer
			//// so let's make a new buffer to queue the sound
			if (voiceState.BuffersQueued <= 0)
			{
				XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_PUNCH];
				bool ssbSuccess = SUCCEEDED(punchSound->SubmitSourceBuffer(proto));
				punchSound->Start();
			}
			//// if there is something in the buffer
			else
			{
				/// do nothing
			}
		}
	}
}
void GameAudio::processHealSound()
{
	if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_HEAL] == true)
	{
		Game *game = Game::getSingleton();
		GameStateManager *gsm = game->getGSM();
		SpriteManager *spriteMgr = gsm->getSpriteManager();
		PlayerSprite *player = spriteMgr->getPlayer();

		bool isHealing = player->getIshealing();

		if (isHealing == true)
		{
			IXAudio2SourceVoice *healSound = soundEffectMap[ENUM_SOUND_EFFECT_HEAL];

			XAUDIO2_VOICE_STATE voiceState;
			healSound->GetState(&voiceState);

			//// [voiceState.BuffersQueued <= 0] means there are nothing in the buffer
			//// so let's make a new buffer to queue the sound
			if (voiceState.BuffersQueued <= 0)
			{
				XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_HEAL];
				bool ssbSuccess = SUCCEEDED(healSound->SubmitSourceBuffer(proto));
				healSound->Start();
				//// After all, there will be only one buffer node in the queue always ...
			}
			//// if there is something in the buffer
			else
			{
				/// do nothing
			}
		}
	}
}
Example #4
0
	virtual const char* write_frame( void * buffer, unsigned num_samples, bool wait )
	{
		if ( paused )
		{
			if ( wait ) Sleep( MulDiv( num_samples / nch, 1000, sample_rate ) );
			return 0;
		}

		if ( reopen_count )
		{
			if ( ! --reopen_count )
			{
				const char * err = open( hwnd, sample_rate, nch, max_samples_per_frame, num_frames );
				if ( err )
				{
					reopen_count = 60 * 5;
					return err;
				}
			}
			else
			{
				if ( wait ) Sleep( MulDiv( num_samples / nch, 1000, sample_rate ) );
				return 0;
			}
		}

		for (;;) {
			sVoice->GetState( &vState );
			assert( vState.BuffersQueued <= num_frames );
			if( vState.BuffersQueued < num_frames ) {
				if( vState.BuffersQueued == 0 ) {
					// buffers ran dry
				}
				// there is at least one free buffer
				break;
			} else {
				// wait for one buffer to finish playing
				ResetEvent( notify.hBufferEndEvent );
				WaitForSingleObject( notify.hBufferEndEvent, INFINITE );
			}
		}
		samples_in_buffer[ buffer_write_cursor ] = num_samples / nch;
		XAUDIO2_BUFFER buf = {0};
		unsigned num_bytes = num_samples * 2;
		buf.AudioBytes = num_bytes;
		buf.pAudioData = ( const BYTE * )( sample_buffer + max_samples_per_frame * buffer_write_cursor );
		buf.pContext = this;
		buffer_write_cursor = ( buffer_write_cursor + 1 ) % num_frames;
		memcpy( ( void * ) buf.pAudioData, buffer, num_bytes );
		if( sVoice->SubmitSourceBuffer( &buf ) == S_OK )
		{
			InterlockedIncrement( &buffered_count );
			return 0;
		}

		close();
		reopen_count = 60 * 5;

		return 0;
	}
Example #5
0
	bool Audio::AddAudioFile(const char* i_AudioPath, bool bLoop, float i_InitialVolume)
	{
		WAVEFORMATEXTENSIBLE wfx = { 0 };
		XAUDIO2_BUFFER buffer = { 0 };

		// Open the file
		HANDLE hFile = CreateFile(
			i_AudioPath,
			GENERIC_READ,
			FILE_SHARE_READ,
			NULL,
			OPEN_EXISTING,
			0,
			NULL);


		SetFilePointer(hFile, 0, NULL, FILE_BEGIN);

		DWORD dwChunkSize;
		DWORD dwChunkPosition;
		//check the file type, should be fourccWAVE or 'XWMA'
		FindChunk(hFile, fourccRIFF, dwChunkSize, dwChunkPosition);
		DWORD filetype;
		ReadChunkData(hFile, &filetype, sizeof(DWORD), dwChunkPosition);
		if (filetype != fourccWAVE)
			return false;

		FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition);
		ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);

		//fill out the audio data buffer with the contents of the fourccDATA chunk
		FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition);
		BYTE * pDataBuffer = new BYTE[dwChunkSize];
		ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition);

		buffer.AudioBytes = dwChunkSize;  //buffer containing audio data
		buffer.pAudioData = pDataBuffer;  //size of the audio buffer in bytes
		buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer
		if (bLoop)
		{
			buffer.LoopLength = 0;
			buffer.LoopCount = XAUDIO2_LOOP_INFINITE;
		}

		HRESULT hr;
		IXAudio2SourceVoice* pSourceVoice;
		if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx)))
			return false;

		if (FAILED(hr = pSourceVoice->SubmitSourceBuffer(&buffer)))
			return false;

		pSourceVoice->SetVolume(i_InitialVolume);

		s_SourceVoices.push_back(pSourceVoice);
		s_AudioBuffers.push_back(buffer);
	}
Example #6
0
void StreamingVoiceContext2_7::SubmitBuffer(PBYTE buf_data)
{
	XAUDIO2_BUFFER buf = {};
	buf.AudioBytes = BUFFER_SIZE_BYTES;
	buf.pContext = buf_data;
	buf.pAudioData = buf_data;

	m_source_voice->SubmitSourceBuffer(&buf);
}
Example #7
0
void XAudio2_Output::write(u16 * finalWave, int length)
{
	if( !initialized || failed ) return;

	while( true ) {
		if ( device_changed ) {
			close();
			if (!init(freq)) return;
		}

		sVoice->GetState( &vState );

		ASSERT( vState.BuffersQueued <= bufferCount );

		if( vState.BuffersQueued < bufferCount ) {
			if( vState.BuffersQueued == 0 ) {
				// buffers ran dry
				if( systemVerbose & VERBOSE_SOUNDOUTPUT ) {
					static unsigned int i = 0;
					log( "XAudio2: Buffers were not refilled fast enough (i=%i)\n", i++ );
				}
			}
			// there is at least one free buffer
			break;
		} else {
			// the maximum number of buffers is currently queued
			if( synchronize && !speedup && !theApp.throttle ) {
				// wait for one buffer to finish playing
				if (WaitForSingleObject( notify.hBufferEndEvent, 10000 ) == WAIT_TIMEOUT) {
					device_changed = true;
				}
			} else {
				// drop current audio frame
				return;
			}
		}
	}

	// copy & protect the audio data in own memory area while playing it
	CopyMemory( &buffers[ currentBuffer * soundBufferLen ], finalWave, soundBufferLen );

	buf.AudioBytes = soundBufferLen;
	buf.pAudioData = &buffers[ currentBuffer * soundBufferLen ];

	currentBuffer++;
	currentBuffer %= ( bufferCount + 1 ); // + 1 because we need one temporary buffer

	HRESULT hr = sVoice->SubmitSourceBuffer( &buf ); // send buffer to queue
	ASSERT( hr == S_OK );
}
Example #8
0
	HRESULT SubmitBuffer()
	{
		// Ensure we do have a valid voice
		if (this->SourceVoice == nullptr)
		{
			return E_FAIL;
		}

		MxMixSamples(this->buffer, this->bufferLength / 4);

		XAUDIO2_BUFFER buf = { 0 };
		buf.AudioBytes = this->bufferLength;
		buf.pAudioData = (const BYTE *) this->buffer;

		return SourceVoice->SubmitSourceBuffer(&buf);
	}
void GameAudio::playMusicRepeat(MusicTypes musicType)
{
	if (musicRegistrationMap[musicType] == true)
	{
		IXAudio2SourceVoice *sourceVoice = musicMap[musicType];

		XAUDIO2_VOICE_STATE voiceState;
		sourceVoice->GetState(&voiceState);

		if (voiceState.BuffersQueued <= 0)
		{
			XAUDIO2_BUFFER *proto = musicBufferPrototypeMap[musicType];
			bool ssbSuccess = SUCCEEDED(sourceVoice->SubmitSourceBuffer(proto));
			sourceVoice->Start();
		}
	}
}
void GameAudio::processMoneySound()
{
	if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_MONEY] == true)
	{
		if (moneySoundSignal == true)
		{
			IXAudio2SourceVoice *moneySound = soundEffectMap[ENUM_SOUND_EFFECT_MONEY];

			XAUDIO2_VOICE_STATE voiceState;
			moneySound->GetState(&voiceState);

			XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_MONEY];
			bool ssbSuccess = SUCCEEDED(moneySound->SubmitSourceBuffer(proto));
			moneySound->Start();

			moneySoundSignal = false;
		}
	}
}
Example #11
0
static void
XAUDIO2_PlayDevice(_THIS)
{
    XAUDIO2_BUFFER buffer;
    Uint8 *mixbuf = _this->hidden->mixbuf;
    Uint8 *nextbuf = _this->hidden->nextbuf;
    const int mixlen = _this->hidden->mixlen;
    IXAudio2SourceVoice *source = _this->hidden->source;
    HRESULT result = S_OK;

    if (!_this->enabled) { /* shutting down? */
        return;
    }

    /* Submit the next filled buffer */
    SDL_zero(buffer);
    buffer.AudioBytes = mixlen;
    buffer.pAudioData = nextbuf;
    buffer.pContext = _this;
	buffer.LoopCount = 1;

    if (nextbuf == mixbuf) {
        nextbuf += mixlen;
    } else {
        nextbuf = mixbuf;
    }
    _this->hidden->nextbuf = nextbuf;

    result = source->SubmitSourceBuffer(&buffer);
    if (result == XAUDIO2_E_DEVICE_INVALIDATED) {
        /* !!! FIXME: possibly disconnected or temporary lost. Recover? */
    }

    if (result != S_OK) {  /* uhoh, panic! */
         source->FlushSourceBuffers();
         _this->enabled = 0;
    }
}
Example #12
0
void XAudio2Streamer::Stream( void const *pSamples )
{
    // Verify buffer availability
    XAUDIO2_VOICE_STATE xa2vs;
    m_pXAudio2SourceVoice->GetState( &xa2vs );
    if( xa2vs.BuffersQueued == m_count )
        return;

    // Copy samples to buffer
    Sample *pBuffer( &m_samples[ m_index * m_size ] );
    using std::memcpy;
    memcpy( pBuffer, pSamples, m_size );

    // Submit buffer to voice
    XAUDIO2_BUFFER xa2b = {};
    xa2b.AudioBytes = UINT32( m_size );
    xa2b.pAudioData = pBuffer;
    if( FAILED( m_pXAudio2SourceVoice->SubmitSourceBuffer( &xa2b ) ) )
        return;

    // Select next buffer
    m_index = ( m_index + 1 ) % m_count;
}
Example #13
0
void WaveBank::Impl::Play( int index )
{
    if ( mStreaming )
    {
        DebugTrace( "ERROR: One-shots can only be created from an in-memory wave bank\n");
        throw std::exception( "WaveBank::Play" );
    }

    if ( index < 0 || uint32_t(index) >= mReader.Count() )
    {
        DebugTrace( "WARNING: Index %d not found in wave bank with only %u entries, one-shot not triggered\n", index, mReader.Count() );
        return;
    }

    if ( !mPrepared )
    {
        mReader.WaitOnPrepare();
        mPrepared = true;
    }

    char wfxbuff[64];
    auto wfx = reinterpret_cast<WAVEFORMATEX*>( wfxbuff );
    HRESULT hr = mReader.GetFormat( index, wfx, 64 );
    ThrowIfFailed( hr );

    IXAudio2SourceVoice* voice = nullptr;
    mEngine->AllocateVoice( wfx, SoundEffectInstance_Default, true, &voice );

    if ( !voice )
        return;

    hr = voice->Start( 0 );
    ThrowIfFailed( hr );

    XAUDIO2_BUFFER buffer;
    memset( &buffer, 0, sizeof(buffer) );

    hr = mReader.GetWaveData( index, &buffer.pAudioData, buffer.AudioBytes );
    ThrowIfFailed( hr );

    WaveBankReader::Metadata metadata;
    hr = mReader.GetMetadata( index, metadata );
    ThrowIfFailed( hr );

    buffer.Flags = XAUDIO2_END_OF_STREAM;
    buffer.pContext = this;

#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8)

    XAUDIO2_BUFFER_WMA wmaBuffer;
    memset( &wmaBuffer, 0, sizeof(wmaBuffer) );

    uint32_t tag;
    hr = mReader.GetSeekTable( index, &wmaBuffer.pDecodedPacketCumulativeBytes, wmaBuffer.PacketCount, tag );
    ThrowIfFailed( hr );

    if ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 )
    {
        hr = voice->SubmitSourceBuffer( &buffer, &wmaBuffer );
    }
    else
#endif
    {
        hr = voice->SubmitSourceBuffer( &buffer, nullptr );
    }
    if ( FAILED(hr) )
    {
        DebugTrace( "ERROR: WaveBank failed (%08X) when submitting buffer:\n", hr );
        DebugTrace( "\tFormat Tag %u, %u channels, %u-bit, %u Hz, %u bytes\n", wfx->wFormatTag, 
                    wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec, metadata.lengthBytes );
        throw std::exception( "SubmitSourceBuffer" );
    }

    InterlockedIncrement( &mOneShots );
}
//--------------------------------------------------------------------------------------
// 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;
}
//--------------------------------------------------------------------------------------
// 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;
}
void GameAudio::processShootSound()
{
	if (soundEffectRegistrationMap[ENUM_SOUND_EFFECT_SHOOT] == true)
	{
		Game *game = Game::getSingleton();
		GameStateManager *gsm = game->getGSM();
		SpriteManager *spriteMgr = gsm->getSpriteManager();
		/*if (moneySoundSignal == true)
		{
			IXAudio2SourceVoice *moneySound = soundEffectMap[ENUM_SOUND_EFFECT_MONEY];

			XAUDIO2_VOICE_STATE voiceState;
			moneySound->GetState(&voiceState);

			XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_MONEY];
			bool ssbSuccess = SUCCEEDED(moneySound->SubmitSourceBuffer(proto));
			moneySound->Start();

			moneySoundSignal = false;
		}
		*/
		if (shootSoundSignal == true)
		{
			IXAudio2SourceVoice *shootSound = soundEffectMap[ENUM_SOUND_EFFECT_SHOOT];

			XAUDIO2_VOICE_STATE voiceState;
			shootSound->GetState(&voiceState);

			XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_SHOOT];
			bool ssbSuccess = SUCCEEDED(shootSound->SubmitSourceBuffer(proto));
			shootSound->Start();

			shootSoundSignal = false;
		}

		/*
		list<Bot*>::iterator botIt = spriteMgr->getBotsIterator();
		list<Bot*>::iterator endBotIt = spriteMgr->getEndOfBotsIterator();
		while (botIt != endBotIt)
		{
		Bot *bot = (*botIt);
		wstring botCurState = bot->getCurrentState();
		if (botCurState.compare(L"SHOOT_LEFT") == 0 || botCurState.compare(L"SHOOT_RIGHT") == 0
		|| botCurState.compare(L"SHOOT_BACK") == 0 || botCurState.compare(L"SHOOT_FRONT") == 0)
		{
		IXAudio2SourceVoice *shootSound = soundEffectMap[ENUM_SOUND_EFFECT_SHOOT];

		XAUDIO2_VOICE_STATE voiceState;
		shootSound->GetState(&voiceState);

		if (voiceState.BuffersQueued <= 0)
		{
		XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_SHOOT];
		bool ssbSuccess = SUCCEEDED(shootSound->SubmitSourceBuffer(proto));
		shootSound->Start();
		}
		}
		botIt++;
		}

		PlayerSprite *player = spriteMgr->getPlayer();
		wstring playerState = player->getCurrentState();
		if (playerState.compare(L"SHOOT_LEFT") == 0 || playerState.compare(L"SHOOT_RIGHT") == 0
		|| playerState.compare(L"SHOOT_BACK") == 0 || playerState.compare(L"SHOOT_FRONT") == 0)
		{
		IXAudio2SourceVoice *shootSound = soundEffectMap[ENUM_SOUND_EFFECT_SHOOT];

		XAUDIO2_VOICE_STATE voiceState;
		shootSound->GetState(&voiceState);

		//// [voiceState.BuffersQueued <= 0] means there are nothing in the buffer
		//// so let's make a new buffer to queue the sound
		if (voiceState.BuffersQueued <= 0)
		{
		XAUDIO2_BUFFER *proto = audioBufferPrototypeMap[ENUM_SOUND_EFFECT_SHOOT];
		bool ssbSuccess = SUCCEEDED(shootSound->SubmitSourceBuffer(proto));
		shootSound->Start();
		}
		//// if there is something in the buffer
		else
		{
		/// do nothing
		}
		}
		*/
		
	}
}
Example #17
0
HRESULT WMA::OnSample(DWORD dwOutputNum, QWORD cnsSampleTime, QWORD cnsSampleDuration, DWORD dwFlags, INSSBuffer *pSample)
{
    if( !m_bOpen ) {
        if(m_hRespondEvent) {
            SetEvent(m_hRespondEvent);
        }
        return S_OK;
    }

    if( m_bEOF ) {
        SetEvent(m_hRespondEvent);
        return S_OK;
    }

    /*BYTE* pBuf;
    DWORD dwLen;
    if(!pSample)
    	return E_FAIL;


    HRESULT hr = pSample->GetBuffer(&pBuf);
    if(FAILED(hr))
    	return E_FAIL;

    hr = pSample->GetLength(&dwLen);
    if(FAILED(hr))
    	return E_FAIL;

    //Expand the decoding buffer if it's needed
    if((m_nWritePtr + dwLen) > m_nBufferSize) {
    	uint32_t nNewBufferSize = m_nWritePtr + dwLen + DECODING_BUFFER_ERROR;
    	uint8_t* pNewBuffer = new uint8_t[nNewBufferSize];
    	memcpy( pNewBuffer, m_pBuffer, m_nWritePtr );
    	if(m_pBuffer) {
    		delete [] m_pBuffer;
    		m_pBuffer = 0;
    	}

    	m_pBuffer = pNewBuffer;
    	m_nBufferSize = nNewBufferSize;
    }

    memcpy(m_pBuffer + m_nWritePtr, pBuf, dwLen);
    m_nWritePtr += dwLen;

    if(m_nWritePtr >= m_nTargetPtr)
    {
    	SetEvent(m_hRespondEvent);
    	EnterCriticalSection(&m_csTerm);
    	WaitForSingleObject(m_hWaitEvent, INFINITE);
    	LeaveCriticalSection(&m_csTerm); //this should be happening when shit gets poped of the stack probably?
    }*/

    BYTE* pBuf;
    //BYTE* leakyBuffer;
    DWORD dwLen;
    if(!pSample)
        return E_FAIL;

    HRESULT hr = pSample->GetBuffer(&pBuf);
    if(FAILED(hr))
        return E_FAIL;

    hr = pSample->GetLength(&dwLen);
    if(FAILED(hr))
        return E_FAIL;

    //leakyBuffer = new BYTE[dwLen];
    XAUDIO2_VOICE_STATE state;
    for(; ; )
    {
        mSourceVoice->GetState( &state );
        if( state.BuffersQueued < MAX_BUFFER_COUNT ) {
            break;
        }
        //std::cout << "Blocking..." << std::cout;
        WaitForSingleObject( mVoiceCallback.hBufferEndEvent, INFINITE );
    }

    memcpy(&(mDecodedBuffers[mCurrentBuffer * mMaxBufferSize]), pBuf, dwLen);
    //memcpy( leakyBuffer, pBuf, dwLen );

    XAUDIO2_BUFFER buffer = {0};
    buffer.AudioBytes = dwLen;
    //buffer.Flags = XAUDIO2_END_OF_STREAM;
    buffer.Flags = 0;
    //buffer.pAudioData = leakyBuffer;
    buffer.pAudioData = &(mDecodedBuffers[mCurrentBuffer * mMaxBufferSize]);
    mSourceVoice->SubmitSourceBuffer( &buffer );

    mCurrentTime = cnsSampleTime + cnsSampleDuration;
    mCurrentBuffer++;
    mCurrentBuffer %= MAX_BUFFER_COUNT;

    //probably not an awesome way to do this, since we're dropping audio -- use a ring buffer?
    //uint32_t copyLen = dwLen;
    //std::cout << dwLen << std::endl;
    //if(m_nWritePtr + copyLen > mMaxBufferSize) {
    //	copyLen = mMaxBufferSize - m_nWritePtr;
    //}

    /*memcpy(&(mDecodedBuffers[mCurrentBuffer * mMaxBufferSize]) + m_nWritePtr, pBuf, copyLen);
    m_nWritePtr += dwLen;

    if( m_nWritePtr >= mMaxBufferSize ) {
    	//std::cout << "Starting Buffer Queue" << std::endl;


    	//std::cout << "Actually Queuing Buffer" << std::endl;

    	XAUDIO2_BUFFER buffer = {0};
    	buffer.AudioBytes = m_nWritePtr;
    	//buffer.Flags = XAUDIO2_END_OF_STREAM;
    	buffer.Flags = 0;
    	buffer.pAudioData = &(mDecodedBuffers[mCurrentBuffer * mMaxBufferSize]);
    	mSourceVoice->SubmitSourceBuffer( &buffer );

    	XAUDIO2_VOICE_STATE state;
    	for(; ; )
    	{
    		mSourceVoice->GetState( &state );
    		if( state.BuffersQueued < MAX_BUFFER_COUNT ) {
    			break;
    		}
    		//std::cout << "Blocking..." << std::cout;
    		WaitForSingleObject( mVoiceCallback.hBufferEndEvent, INFINITE );
    	}
    	//std::cout << "Continuing" << std::endl;

    	mCurrentBuffer++;
    	mCurrentBuffer %= MAX_BUFFER_COUNT;
    	m_nWritePtr = 0;
    }*/

    //XAUDIO2_VOICE_STATE state;
    //mSourceVoice->GetState( &state );
    std::cout << cnsSampleTime << std::endl;


    return S_OK;
}
Example #18
0
void WaveBank::Impl::Play(int index, float volume, float pitch, float pan)
{
    assert(volume >= -XAUDIO2_MAX_VOLUME_LEVEL && volume <= XAUDIO2_MAX_VOLUME_LEVEL);
    assert(pitch >= -1.f && pitch <= 1.f);
    assert(pan >= -1.f && pan <= 1.f);

    if (mStreaming)
    {
        DebugTrace("ERROR: One-shots can only be created from an in-memory wave bank\n");
        throw std::exception("WaveBank::Play");
    }

    if (index < 0 || uint32_t(index) >= mReader.Count())
    {
        DebugTrace("WARNING: Index %d not found in wave bank with only %u entries, one-shot not triggered\n", index, mReader.Count());
        return;
    }

    if (!mPrepared)
    {
        mReader.WaitOnPrepare();
        mPrepared = true;
    }

    char wfxbuff[64] = {};
    auto wfx = reinterpret_cast<WAVEFORMATEX*>(wfxbuff);
    HRESULT hr = mReader.GetFormat(index, wfx, sizeof(wfxbuff));
    ThrowIfFailed(hr);

    IXAudio2SourceVoice* voice = nullptr;
    mEngine->AllocateVoice(wfx, SoundEffectInstance_Default, true, &voice);

    if (!voice)
        return;

    if (volume != 1.f)
    {
        hr = voice->SetVolume(volume);
        ThrowIfFailed(hr);
    }

    if (pitch != 0.f)
    {
        float fr = XAudio2SemitonesToFrequencyRatio(pitch * 12.f);

        hr = voice->SetFrequencyRatio(fr);
        ThrowIfFailed(hr);
    }

    if (pan != 0.f)
    {
        float matrix[16];
        if (ComputePan(pan, wfx->nChannels, matrix))
        {
            hr = voice->SetOutputMatrix(nullptr, wfx->nChannels, mEngine->GetOutputChannels(), matrix);
            ThrowIfFailed(hr);
        }
    }

    hr = voice->Start(0);
    ThrowIfFailed(hr);

    XAUDIO2_BUFFER buffer = {};
    hr = mReader.GetWaveData(index, &buffer.pAudioData, buffer.AudioBytes);
    ThrowIfFailed(hr);

    WaveBankReader::Metadata metadata;
    hr = mReader.GetMetadata(index, metadata);
    ThrowIfFailed(hr);

    buffer.Flags = XAUDIO2_END_OF_STREAM;
    buffer.pContext = this;

#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10)

    XAUDIO2_BUFFER_WMA wmaBuffer = {};

    uint32_t tag;
    hr = mReader.GetSeekTable(index, &wmaBuffer.pDecodedPacketCumulativeBytes, wmaBuffer.PacketCount, tag);
    ThrowIfFailed(hr);

    if (tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3)
    {
        hr = voice->SubmitSourceBuffer(&buffer, &wmaBuffer);
    }
    else
    #endif
    {
        hr = voice->SubmitSourceBuffer(&buffer, nullptr);
    }
    if (FAILED(hr))
    {
        DebugTrace("ERROR: WaveBank failed (%08X) when submitting buffer:\n", hr);
        DebugTrace("\tFormat Tag %u, %u channels, %u-bit, %u Hz, %u bytes\n", wfx->wFormatTag,
                   wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec, metadata.lengthBytes);
        throw std::exception("SubmitSourceBuffer");
    }

    InterlockedIncrement(&mOneShots);
}
void Sound::playSoundEffect(SoundEffect effect, X3DAUDIO_EMITTER* emit)
{
	IXAudio2SourceVoice* voice = getSFXVoice();

	voice->FlushSourceBuffers();
	
	switch (effect) {
	case SFX_LASER:
		{
			voice->SubmitSourceBuffer(laserBufferDetails, laserWMABuffer);
			break;
		}
	case SFX_CRASH:
		{
			voice->SubmitSourceBuffer(crashBufferDetails, crashWMABuffer);
			break;
		}
	case SFX_BOOST:
		{
			voice->SubmitSourceBuffer(boostBufferDetails, boostWMABuffer);
			break;
		}
	case SFX_DROPMINE:
		{
			voice->SubmitSourceBuffer(dropmineBufferDetails, dropmineWMABuffer);
			break;
		}
	case SFX_SCREAM:
		{
			// Now pick one of the three screams randomly
			int choice = std::rand() % 3;


			voice->SetVolume(2.0f);
			switch (choice) {
				case 0:	voice->SubmitSourceBuffer(scream1BufferDetails, scream1WMABuffer);
					break;
				case 1:	voice->SubmitSourceBuffer(scream2BufferDetails, scream2WMABuffer);
					break;
				case 2:	voice->SubmitSourceBuffer(scream3BufferDetails, scream3WMABuffer);
					break;
				default:
					voice->SubmitSourceBuffer(scream1BufferDetails, scream1WMABuffer);
			}

			break;
		}
	case SFX_CAREXPLODE:
		{
			voice->SetVolume(2.0f);
			voice->SubmitSourceBuffer(carexplodeBufferDetails, carexplodeWMABuffer);
			break;
		}
	case SFX_EXPLOSION:
		{
			voice->SubmitSourceBuffer(explosionBufferDetails, explosionWMABuffer);
			break;
		}
	case SFX_BEEP:
		{
			voice->SubmitSourceBuffer(beepBufferDetails, beepWMABuffer);
			break;
		}
	case SFX_ROCKETLAUNCH:
		{
			voice->SubmitSourceBuffer(rocketlaunchBufferDetails, rocketlaunchWMABuffer);
			break;
		}
	case SFX_PICKUP:
		{
			voice->SetVolume(2.0f);
			voice->SubmitSourceBuffer(pickupBufferDetails, pickupWMABuffer);
			break;
		}
	case SFX_SELECT:
		{
			voice->SubmitSourceBuffer(selectBufferDetails, selectWMABuffer);
			break;
		}
	case SFX_SHOTGUN:
		{
			voice->SetVolume(2.5f);
			voice->SubmitSourceBuffer(shotgunBufferDetails, shotgunWMABuffer);
			break;
		}
	case SFX_TAKENLEAD:
		{
			voice->SubmitSourceBuffer(takenleadBufferDetails, takenleadWMABuffer);
			break;
		}
	case SFX_LOSTLEAD:
		{
			voice->SubmitSourceBuffer(lostleadBufferDetails, lostleadWMABuffer);
			break;
		}
	case SFX_NOAMMO:
		{
			voice->SubmitSourceBuffer(noammoBufferDetails, noammoWMABuffer);
			break;
		}
	case SFX_ONE:
		{
			voice->SubmitSourceBuffer(oneBufferDetails, oneWMABuffer);
			break;
		}
	case SFX_TWO:
		{
			voice->SubmitSourceBuffer(twoBufferDetails, twoWMABuffer);
			break;
		}
	case SFX_THREE:
		{
			voice->SubmitSourceBuffer(threeBufferDetails, threeWMABuffer);
			break;
		}
	default:
		break;
	}




	X3DAudioCalculate(audio3DHandle, &listener, emit,
		X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER | X3DAUDIO_CALCULATE_LPF_DIRECT,
		&dspSettings);
	
	voice->SetOutputMatrix(smSFX, 1, details.OutputFormat.Format.nChannels, dspSettings.pMatrixCoefficients);
	voice->SetFrequencyRatio(dspSettings.DopplerFactor);

	XAUDIO2_FILTER_PARAMETERS filterParameters = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * dspSettings.LPFDirectCoefficient), 1.0f };
	voice->SetFilterParameters(&filterParameters);
	
	voice->Start();
}
Example #20
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;
}
Example #21
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;
}	
Example #22
0
void PlayAudioFile(char* audioFile)
{
	// Open the file
	HANDLE hFile = CreateFile(
		audioFile,
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		0,
		NULL );


	// Set file pointer to the begining of file
	SetFilePointer( hFile, 0, NULL, FILE_BEGIN );

	DWORD dwChunkSize;
	DWORD dwChunkPosition;

	//check the file type, should be fourccWAVE or 'XWMA'
	FindChunk(hFile,fourccRIFF,dwChunkSize, dwChunkPosition );
	DWORD filetype;
	ReadChunkData(hFile,&filetype,sizeof(DWORD),dwChunkPosition);
	if (filetype != fourccWAVE)
	{
		MessageBox(NULL, "File type was not WAVE", "Error", 0);
	}

	WAVEFORMATEXTENSIBLE wfx = {0};
	FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition );
	ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );

	//fill out the audio data buffer with the contents of the fourccDATA chunk
	FindChunk(hFile,fourccDATA,dwChunkSize, dwChunkPosition );
	BYTE * pDataBuffer = new BYTE[dwChunkSize];
	ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition);

	XAUDIO2_BUFFER buffer = {0};
	buffer.AudioBytes = dwChunkSize;  //size of the audio buffer in bytes
	buffer.pAudioData = pDataBuffer;  //buffer containing audio data
	buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer

	// This line is needed for OS oldder Windows 8
	CoInitializeEx(NULL, COINIT_MULTITHREADED);

	// Create an instance of XAudio2 engine
	IXAudio2* pXAudio2 = NULL;
	HRESULT hr = XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
	if (FAILED(hr))
	{
		MessageBox(NULL, "Failed to create XAudio2 engine instance", "Error", 0);
	}

	// Create a mastering voice
	IXAudio2MasteringVoice* pMasterVoice	= NULL;	
	hr = pXAudio2->CreateMasteringVoice(&pMasterVoice);
	if ( FAILED(hr) )
	{
		MessageBox(NULL, "Failed to create mastering voice", "Error", 0);
	}

	// Create a source voice
	IXAudio2SourceVoice* pSourceVoice  = NULL;
	hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx);
	if(FAILED(hr))
	{
		MessageBox(NULL, "Create source voice failed", "Error", 0);
	}

	// Sub mit source buffer
	hr = pSourceVoice->SubmitSourceBuffer(&buffer);
	if(FAILED(hr))
	{
		MessageBox(NULL, "Submit to source buffer failed", "Error", 0);
	}

	// Play
	hr = pSourceVoice->Start(0);
	if(FAILED(hr))
	{
		MessageBox(NULL, "Play sound failed", "Error", 0);
	}
}