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 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(); }
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, 64 ); 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; 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) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10) 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 ); }