void SoundManager::update(Camera* p_gameCamera) { m_masterVoice->SetVolume(m_masterVolume,0); updateListener(p_gameCamera); X3DAudioCalculate(m_X3DAudioInstance, &m_listener, &m_music->getEmitter(), X3DAUDIO_CALCULATE_MATRIX, &m_music->getDSPSettings()); IXAudio2SourceVoice* voice = m_music->getSource(); m_left = m_matrixCoefficients[0]; m_right = m_matrixCoefficients[1]; voice->SetOutputMatrix( m_masterVoice, 1, m_destChannels, m_matrixCoefficients); if(!m_music->isPlaying()) m_music->play(); }
bool XAudio2_Output::init(long sampleRate) { if( failed || initialized ) return false; HRESULT hr; // Initialize XAudio2 UINT32 flags = 0; //#ifdef _DEBUG // flags = XAUDIO2_DEBUG_ENGINE; //#endif hr = XAudio2Create( &xaud, flags ); if( hr != S_OK ) { systemMessage( IDS_XAUDIO2_FAILURE, NULL ); failed = true; return false; } freq = sampleRate; // calculate the number of samples per frame first // then multiply it with the size of a sample frame (16 bit * stereo) soundBufferLen = ( freq / 60 ) * 4; // create own buffers to store sound data because it must not be // manipulated while the voice plays from it buffers = (BYTE *)malloc( ( bufferCount + 1 ) * soundBufferLen ); // + 1 because we need one temporary buffer when all others are in use WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof( wfx ) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = freq; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.nChannels * ( wfx.wBitsPerSample / 8 ); wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; // create sound receiver hr = xaud->CreateMasteringVoice( &mVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, theApp.xa2Device, NULL ); if( hr != S_OK ) { systemMessage( IDS_XAUDIO2_CANNOT_CREATE_MASTERINGVOICE, NULL ); failed = true; return false; } // create sound emitter hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, ¬ify ); if( hr != S_OK ) { systemMessage( IDS_XAUDIO2_CANNOT_CREATE_SOURCEVOICE, NULL ); failed = true; return false; } if( theApp.xa2Upmixing ) { // set up stereo upmixing XAUDIO2_DEVICE_DETAILS dd; ZeroMemory( &dd, sizeof( dd ) ); hr = xaud->GetDeviceDetails( 0, &dd ); ASSERT( hr == S_OK ); float *matrix = NULL; matrix = (float*)malloc( sizeof( float ) * 2 * dd.OutputFormat.Format.nChannels ); if( matrix == NULL ) return false; bool matrixAvailable = true; switch( dd.OutputFormat.Format.nChannels ) { case 4: // 4.0 //Speaker \ Left Source Right Source /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Back L*/ matrix[4] = 1.0000f; matrix[5] = 0.0000f; /*Back R*/ matrix[6] = 0.0000f; matrix[7] = 1.0000f; break; case 5: // 5.0 //Speaker \ Left Source Right Source /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*Side L*/ matrix[6] = 1.0000f; matrix[7] = 0.0000f; /*Side R*/ matrix[8] = 0.0000f; matrix[9] = 1.0000f; break; case 6: // 5.1 //Speaker \ Left Source Right Source /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f; /*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f; /*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f; break; case 7: // 6.1 //Speaker \ Left Source Right Source /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f; /*Side L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f; /*Side R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f; /*Back C*/ matrix[12] = 0.7071f; matrix[13] = 0.7071f; break; case 8: // 7.1 //Speaker \ Left Source Right Source /*Front L*/ matrix[0] = 1.0000f; matrix[1] = 0.0000f; /*Front R*/ matrix[2] = 0.0000f; matrix[3] = 1.0000f; /*Front C*/ matrix[4] = 0.7071f; matrix[5] = 0.7071f; /*LFE */ matrix[6] = 0.0000f; matrix[7] = 0.0000f; /*Back L*/ matrix[8] = 1.0000f; matrix[9] = 0.0000f; /*Back R*/ matrix[10] = 0.0000f; matrix[11] = 1.0000f; /*Side L*/ matrix[12] = 1.0000f; matrix[13] = 0.0000f; /*Side R*/ matrix[14] = 0.0000f; matrix[15] = 1.0000f; break; default: matrixAvailable = false; break; } if( matrixAvailable ) { hr = sVoice->SetOutputMatrix( NULL, 2, dd.OutputFormat.Format.nChannels, matrix ); ASSERT( hr == S_OK ); } free( matrix ); matrix = NULL; } hr = sVoice->Start( 0 ); ASSERT( hr == S_OK ); playing = true; currentBuffer = 0; device_changed = false; initialized = true; return true; }
//----------------------------------------------------------------------------- // Perform per-frame update of audio //----------------------------------------------------------------------------- HRESULT UpdateAudio( float fElapsedTime ) { if( !g_audioState.bInitialized ) return S_FALSE; if( g_audioState.nFrameToApply3DAudio == 0 ) { // Calculate listener orientation in x-z plane if( g_audioState.vListenerPos.x != g_audioState.listener.Position.x || g_audioState.vListenerPos.z != g_audioState.listener.Position.z ) { XMVECTOR v1 = XMLoadFloat3( &g_audioState.vListenerPos ); XMVECTOR v2 = XMVectorSet( g_audioState.listener.Position.x, g_audioState.listener.Position.y, g_audioState.listener.Position.z, 0.f ); XMVECTOR vDelta = v1 - v2; g_audioState.fListenerAngle = float( atan2( XMVectorGetX( vDelta ), XMVectorGetZ( vDelta ) ) ); vDelta = XMVectorSetY( vDelta, 0.f ); vDelta = XMVector3Normalize( vDelta ); XMFLOAT3 tmp; XMStoreFloat3( &tmp, vDelta ); g_audioState.listener.OrientFront.x = tmp.x; g_audioState.listener.OrientFront.y = 0.f; g_audioState.listener.OrientFront.z = tmp.z; } if (g_audioState.fUseListenerCone) { g_audioState.listener.pCone = (X3DAUDIO_CONE*)&Listener_DirectionalCone; } else { g_audioState.listener.pCone = nullptr; } if (g_audioState.fUseInnerRadius) { g_audioState.emitter.InnerRadius = 2.0f; g_audioState.emitter.InnerRadiusAngle = X3DAUDIO_PI/4.0f; } else { g_audioState.emitter.InnerRadius = 0.0f; g_audioState.emitter.InnerRadiusAngle = 0.0f; } if( fElapsedTime > 0 ) { XMVECTOR v1 = XMLoadFloat3( &g_audioState.vListenerPos ); XMVECTOR v2 = XMVectorSet( g_audioState.listener.Position.x, g_audioState.listener.Position.y, g_audioState.listener.Position.z, 0 ); XMVECTOR lVelocity = ( v1 - v2 ) / fElapsedTime; g_audioState.listener.Position.x = g_audioState.vListenerPos.x; g_audioState.listener.Position.y = g_audioState.vListenerPos.y; g_audioState.listener.Position.z = g_audioState.vListenerPos.z; XMFLOAT3 tmp; XMStoreFloat3( &tmp, lVelocity ); g_audioState.listener.Velocity.x = tmp.x; g_audioState.listener.Velocity.y = tmp.y; g_audioState.listener.Velocity.z = tmp.z; v1 = XMLoadFloat3( &g_audioState.vEmitterPos ); v2 = XMVectorSet( g_audioState.emitter.Position.x, g_audioState.emitter.Position.y, g_audioState.emitter.Position.z, 0.f ); XMVECTOR eVelocity = ( v1 - v2 ) / fElapsedTime; g_audioState.emitter.Position.x = g_audioState.vEmitterPos.x; g_audioState.emitter.Position.y = g_audioState.vEmitterPos.y; g_audioState.emitter.Position.z = g_audioState.vEmitterPos.z; XMStoreFloat3( &tmp, eVelocity ); g_audioState.emitter.Velocity.x = tmp.x; g_audioState.emitter.Velocity.y = tmp.y; g_audioState.emitter.Velocity.z = tmp.z; } DWORD dwCalcFlags = X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER | X3DAUDIO_CALCULATE_LPF_DIRECT | X3DAUDIO_CALCULATE_LPF_REVERB | X3DAUDIO_CALCULATE_REVERB; if (g_audioState.fUseRedirectToLFE) { // On devices with an LFE channel, allow the mono source data // to be routed to the LFE destination channel. dwCalcFlags |= X3DAUDIO_CALCULATE_REDIRECT_TO_LFE; } X3DAudioCalculate( g_audioState.x3DInstance, &g_audioState.listener, &g_audioState.emitter, dwCalcFlags, &g_audioState.dspSettings ); IXAudio2SourceVoice* voice = g_audioState.pSourceVoice; if( voice ) { // Apply X3DAudio generated DSP settings to XAudio2 voice->SetFrequencyRatio( g_audioState.dspSettings.DopplerFactor ); voice->SetOutputMatrix( g_audioState.pMasteringVoice, INPUTCHANNELS, g_audioState.nChannels, g_audioState.matrixCoefficients ); voice->SetOutputMatrix(g_audioState.pSubmixVoice, 1, 1, &g_audioState.dspSettings.ReverbLevel); XAUDIO2_FILTER_PARAMETERS FilterParametersDirect = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * g_audioState.dspSettings.LPFDirectCoefficient), 1.0f }; // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here voice->SetOutputFilterParameters(g_audioState.pMasteringVoice, &FilterParametersDirect); XAUDIO2_FILTER_PARAMETERS FilterParametersReverb = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * g_audioState.dspSettings.LPFReverbCoefficient), 1.0f }; // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here voice->SetOutputFilterParameters(g_audioState.pSubmixVoice, &FilterParametersReverb); } } g_audioState.nFrameToApply3DAudio++; g_audioState.nFrameToApply3DAudio &= 1; return S_OK; }
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 ); }