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 } } } }
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; }
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); }
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); }
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 ); }
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; } } }
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; } }
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; }
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 } } */ } }
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; }
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(); }
//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; }
/* 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 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); } }