void XAudio2_Output::setThrottle( unsigned short throttle ) { if( !initialized || failed ) return; if( throttle == 0 ) throttle = 100; HRESULT hr = sVoice->SetFrequencyRatio( (float)throttle / 100.0f ); ASSERT( hr == S_OK ); }
virtual const char* open( void * hwnd, unsigned sample_rate, unsigned nch, unsigned max_samples_per_frame, unsigned num_frames ) { this->hwnd = hwnd; this->sample_rate = sample_rate; this->nch = nch; this->max_samples_per_frame = max_samples_per_frame; this->num_frames = num_frames; #ifdef HAVE_KS_HEADERS WAVEFORMATEXTENSIBLE wfx; wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx.Format.nChannels = nch; //1; wfx.Format.nSamplesPerSec = sample_rate; wfx.Format.nBlockAlign = 2 * nch; //2; wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; wfx.Format.wBitsPerSample = 16; wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX); wfx.Samples.wValidBitsPerSample = 16; wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfx.dwChannelMask = nch == 2 ? KSAUDIO_SPEAKER_STEREO : KSAUDIO_SPEAKER_MONO; #else WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = nch; //1; wfx.nSamplesPerSec = sample_rate; wfx.nBlockAlign = 2 * nch; //2; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.wBitsPerSample = 16; wfx.cbSize = 0; #endif HRESULT hr = XAudio2Create( &xaud, 0 ); if (FAILED(hr)) return "Creating XAudio2 interface"; hr = xaud->CreateMasteringVoice( &mVoice, nch, sample_rate, 0, NULL, NULL ); if (FAILED(hr)) return "Creating XAudio2 mastering voice"; hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, ¬ify ); if (FAILED(hr)) return "Creating XAudio2 source voice"; hr = sVoice->Start( 0 ); if (FAILED(hr)) return "Starting XAudio2 voice"; hr = sVoice->SetFrequencyRatio((float)1.0f); if (FAILED(hr)) return "Setting XAudio2 voice frequency ratio"; buffered_count = 0; buffer_read_cursor = 0; buffer_write_cursor = 0; samples_played = 0; sample_buffer = new int16_t[ max_samples_per_frame * num_frames ]; samples_in_buffer = new UINT64[ num_frames ]; memset( samples_in_buffer, 0, sizeof( UINT64 ) * num_frames ); return NULL; }
virtual const char* set_ratio( double ratio ) { if ( FAILED( sVoice->SetFrequencyRatio( ratio ) ) ) return "setting ratio"; return 0; }
//----------------------------------------------------------------------------- // 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 ); }