2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
# include "../../idlib/precompiled.h"
# include "../snd_local.h"
idCVar s_skipHardwareSets ( " s_skipHardwareSets " , " 0 " , CVAR_BOOL , " Do all calculation, but skip XA2 calls " ) ;
idCVar s_debugHardware ( " s_debugHardware " , " 0 " , CVAR_BOOL , " Print a message any time a hardware voice changes " ) ;
// The whole system runs at this sample rate
static int SYSTEM_SAMPLE_RATE = 44100 ;
static float ONE_OVER_SYSTEM_SAMPLE_RATE = 1.0f / SYSTEM_SAMPLE_RATE ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idStreamingVoiceContext
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
class idStreamingVoiceContext : public IXAudio2VoiceCallback
{
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
STDMETHOD_ ( void , OnVoiceProcessingPassStart ) ( UINT32 BytesRequired ) { }
STDMETHOD_ ( void , OnVoiceProcessingPassEnd ) ( ) { }
STDMETHOD_ ( void , OnStreamEnd ) ( ) { }
STDMETHOD_ ( void , OnBufferStart ) ( void * pContext )
{
idSoundSystemLocal : : bufferContext_t * bufferContext = ( idSoundSystemLocal : : bufferContext_t * ) pContext ;
2012-11-26 18:58:24 +00:00
bufferContext - > voice - > OnBufferStart ( bufferContext - > sample , bufferContext - > bufferNumber ) ;
}
2012-11-28 15:47:07 +00:00
STDMETHOD_ ( void , OnLoopEnd ) ( void * ) { }
STDMETHOD_ ( void , OnVoiceError ) ( void * , HRESULT hr )
{
idLib : : Warning ( " OnVoiceError( %d ) " , hr ) ;
}
STDMETHOD_ ( void , OnBufferEnd ) ( void * pContext )
{
idSoundSystemLocal : : bufferContext_t * bufferContext = ( idSoundSystemLocal : : bufferContext_t * ) pContext ;
2012-11-26 18:58:24 +00:00
soundSystemLocal . ReleaseStreamBufferContext ( bufferContext ) ;
}
} streamContext ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : idSoundVoice_XAudio2
= = = = = = = = = = = = = = = = = = = = = = = =
*/
idSoundVoice_XAudio2 : : idSoundVoice_XAudio2 ( )
2012-11-28 15:47:07 +00:00
: pSourceVoice ( NULL ) ,
leadinSample ( NULL ) ,
loopingSample ( NULL ) ,
formatTag ( 0 ) ,
numChannels ( 0 ) ,
sampleRate ( 0 ) ,
paused ( true ) ,
hasVUMeter ( false )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : ~ idSoundVoice_XAudio2
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idSoundVoice_XAudio2 : : ~ idSoundVoice_XAudio2 ( )
{
2012-11-26 18:58:24 +00:00
DestroyInternal ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : CompatibleFormat
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundVoice_XAudio2 : : CompatibleFormat ( idSoundSample_XAudio2 * s )
{
if ( pSourceVoice = = NULL )
{
2012-11-26 18:58:24 +00:00
// If this voice has never been allocated, then it's compatible with everything
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : Create
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : Create ( const idSoundSample * leadinSample_ , const idSoundSample * loopingSample_ )
{
if ( IsPlaying ( ) )
{
2012-11-26 18:58:24 +00:00
// This should never hit
Stop ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
leadinSample = ( idSoundSample_XAudio2 * ) leadinSample_ ;
loopingSample = ( idSoundSample_XAudio2 * ) loopingSample_ ;
if ( pSourceVoice ! = NULL & & CompatibleFormat ( leadinSample ) )
{
2012-11-26 18:58:24 +00:00
sampleRate = leadinSample - > format . basic . samplesPerSec ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
DestroyInternal ( ) ;
formatTag = leadinSample - > format . basic . formatTag ;
numChannels = leadinSample - > format . basic . numChannels ;
sampleRate = leadinSample - > format . basic . samplesPerSec ;
2012-11-28 15:47:07 +00:00
soundSystemLocal . hardware . pXAudio2 - > CreateSourceVoice ( & pSourceVoice , ( const WAVEFORMATEX * ) & leadinSample - > format , XAUDIO2_VOICE_USEFILTER , 4.0f , & streamContext ) ;
if ( pSourceVoice = = NULL )
{
2012-11-26 18:58:24 +00:00
// If this hits, then we are most likely passing an invalid sample format, which should have been caught by the loader (and the sample defaulted)
return ;
}
2012-11-28 15:47:07 +00:00
if ( s_debugHardware . GetBool ( ) )
{
if ( loopingSample = = NULL | | loopingSample = = leadinSample )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p created for %s \n " , Sys_Milliseconds ( ) , pSourceVoice , leadinSample ? leadinSample - > GetName ( ) : " <null> " ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p created for %s and %s \n " , Sys_Milliseconds ( ) , pSourceVoice , leadinSample ? leadinSample - > GetName ( ) : " <null> " , loopingSample ? loopingSample - > GetName ( ) : " <null> " ) ;
}
}
}
sourceVoiceRate = sampleRate ;
pSourceVoice - > SetSourceSampleRate ( sampleRate ) ;
pSourceVoice - > SetVolume ( 0.0f ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : DestroyInternal
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : DestroyInternal ( )
{
if ( pSourceVoice ! = NULL )
{
if ( s_debugHardware . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p destroyed \n " , Sys_Milliseconds ( ) , pSourceVoice ) ;
}
pSourceVoice - > DestroyVoice ( ) ;
pSourceVoice = NULL ;
hasVUMeter = false ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : Start
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : Start ( int offsetMS , int ssFlags )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( s_debugHardware . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p starting %s @ %dms \n " , Sys_Milliseconds ( ) , pSourceVoice , leadinSample ? leadinSample - > GetName ( ) : " <null> " , offsetMS ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! leadinSample )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! pSourceVoice )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( leadinSample - > IsDefault ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " Starting defaulted sound sample %s " , leadinSample - > GetName ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool flicker = ( ssFlags & SSF_NO_FLICKER ) = = 0 ;
2012-11-28 15:47:07 +00:00
if ( flicker ! = hasVUMeter )
{
2012-11-26 18:58:24 +00:00
hasVUMeter = flicker ;
2012-11-28 15:47:07 +00:00
if ( flicker )
{
IUnknown * vuMeter = NULL ;
if ( XAudio2CreateVolumeMeter ( & vuMeter , 0 ) = = S_OK )
{
2012-11-26 18:58:24 +00:00
XAUDIO2_EFFECT_DESCRIPTOR descriptor ;
descriptor . InitialState = true ;
descriptor . OutputChannels = leadinSample - > NumChannels ( ) ;
descriptor . pEffect = vuMeter ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
XAUDIO2_EFFECT_CHAIN chain ;
chain . EffectCount = 1 ;
chain . pEffectDescriptors = & descriptor ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pSourceVoice - > SetEffectChain ( & chain ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
vuMeter - > Release ( ) ;
}
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
pSourceVoice - > SetEffectChain ( NULL ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( offsetMS > = 0 ) ;
int offsetSamples = MsecToSamples ( offsetMS , leadinSample - > SampleRate ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( loopingSample = = NULL & & offsetSamples > = leadinSample - > playLength )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RestartAt ( offsetSamples ) ;
Update ( ) ;
UnPause ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : RestartAt
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idSoundVoice_XAudio2 : : RestartAt ( int offsetSamples )
{
2012-11-26 18:58:24 +00:00
offsetSamples & = ~ 127 ;
2012-11-28 15:47:07 +00:00
idSoundSample_XAudio2 * sample = leadinSample ;
if ( offsetSamples > = leadinSample - > playLength )
{
if ( loopingSample ! = NULL )
{
2012-11-26 18:58:24 +00:00
offsetSamples % = loopingSample - > playLength ;
sample = loopingSample ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int previousNumSamples = 0 ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < sample - > buffers . Num ( ) ; i + + )
{
if ( sample - > buffers [ i ] . numSamples > sample - > playBegin + offsetSamples )
{
2012-11-26 18:58:24 +00:00
return SubmitBuffer ( sample , i , sample - > playBegin + offsetSamples - previousNumSamples ) ;
}
previousNumSamples = sample - > buffers [ i ] . numSamples ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : SubmitBuffer
2012-11-28 15:47:07 +00:00
= = = = = = = = = = = = = = = = = = = = = = = =
2012-11-26 18:58:24 +00:00
*/
2012-11-28 15:47:07 +00:00
int idSoundVoice_XAudio2 : : SubmitBuffer ( idSoundSample_XAudio2 * sample , int bufferNumber , int offset )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( sample = = NULL | | ( bufferNumber < 0 ) | | ( bufferNumber > = sample - > buffers . Num ( ) ) )
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
2012-11-28 15:47:07 +00:00
idSoundSystemLocal : : bufferContext_t * bufferContext = soundSystemLocal . ObtainStreamBufferContext ( ) ;
if ( bufferContext = = NULL )
{
2012-11-26 18:58:24 +00:00
idLib : : Warning ( " No free buffer contexts! " ) ;
return 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bufferContext - > voice = this ;
bufferContext - > sample = sample ;
bufferContext - > bufferNumber = bufferNumber ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
XAUDIO2_BUFFER buffer = { 0 } ;
2012-11-28 15:47:07 +00:00
if ( offset > 0 )
{
2012-11-26 18:58:24 +00:00
int previousNumSamples = 0 ;
2012-11-28 15:47:07 +00:00
if ( bufferNumber > 0 )
{
previousNumSamples = sample - > buffers [ bufferNumber - 1 ] . numSamples ;
2012-11-26 18:58:24 +00:00
}
buffer . PlayBegin = offset ;
buffer . PlayLength = sample - > buffers [ bufferNumber ] . numSamples - previousNumSamples - offset ;
}
buffer . AudioBytes = sample - > buffers [ bufferNumber ] . bufferSize ;
2012-11-28 15:47:07 +00:00
buffer . pAudioData = ( BYTE * ) sample - > buffers [ bufferNumber ] . buffer ;
2012-11-26 18:58:24 +00:00
buffer . pContext = bufferContext ;
2012-11-28 15:47:07 +00:00
if ( ( loopingSample = = NULL ) & & ( bufferNumber = = sample - > buffers . Num ( ) - 1 ) )
{
2012-11-26 18:58:24 +00:00
buffer . Flags = XAUDIO2_END_OF_STREAM ;
}
pSourceVoice - > SubmitSourceBuffer ( & buffer ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return buffer . AudioBytes ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : Update
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundVoice_XAudio2 : : Update ( )
{
if ( pSourceVoice = = NULL | | leadinSample = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
XAUDIO2_VOICE_STATE state ;
pSourceVoice - > GetState ( & state ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
const int srcChannels = leadinSample - > NumChannels ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float pLevelMatrix [ MAX_CHANNELS_PER_VOICE * MAX_CHANNELS_PER_VOICE ] = { 0 } ;
CalculateSurround ( srcChannels , pLevelMatrix , 1.0f ) ;
2012-11-28 15:47:07 +00:00
if ( s_skipHardwareSets . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pSourceVoice - > SetOutputMatrix ( soundSystemLocal . hardware . pMasterVoice , srcChannels , dstChannels , pLevelMatrix , OPERATION_SET ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( idMath : : Fabs ( gain ) < = XAUDIO2_MAX_VOLUME_LEVEL ) ;
pSourceVoice - > SetVolume ( gain , OPERATION_SET ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SetSampleRate ( sampleRate , OPERATION_SET ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we don't do this any longer because we pause and unpause explicitly when the soundworld is paused or unpaused
// UnPause();
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : IsPlaying
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idSoundVoice_XAudio2 : : IsPlaying ( )
{
if ( pSourceVoice = = NULL )
{
2012-11-26 18:58:24 +00:00
return false ;
}
XAUDIO2_VOICE_STATE state ;
pSourceVoice - > GetState ( & state ) ;
return ( state . BuffersQueued ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : FlushSourceBuffers
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : FlushSourceBuffers ( )
{
if ( pSourceVoice ! = NULL )
{
2012-11-26 18:58:24 +00:00
pSourceVoice - > FlushSourceBuffers ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : Pause
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : Pause ( )
{
if ( ! pSourceVoice | | paused )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( s_debugHardware . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p pausing %s \n " , Sys_Milliseconds ( ) , pSourceVoice , leadinSample ? leadinSample - > GetName ( ) : " <null> " ) ;
}
pSourceVoice - > Stop ( 0 , OPERATION_SET ) ;
paused = true ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : UnPause
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : UnPause ( )
{
if ( ! pSourceVoice | | ! paused )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( s_debugHardware . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p unpausing %s \n " , Sys_Milliseconds ( ) , pSourceVoice , leadinSample ? leadinSample - > GetName ( ) : " <null> " ) ;
}
pSourceVoice - > Start ( 0 , OPERATION_SET ) ;
paused = false ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : Stop
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : Stop ( )
{
if ( ! pSourceVoice )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
if ( ! paused )
{
if ( s_debugHardware . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " %dms: %p stopping %s \n " , Sys_Milliseconds ( ) , pSourceVoice , leadinSample ? leadinSample - > GetName ( ) : " <null> " ) ;
}
pSourceVoice - > Stop ( 0 , OPERATION_SET ) ;
paused = true ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : GetAmplitude
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idSoundVoice_XAudio2 : : GetAmplitude ( )
{
if ( ! hasVUMeter )
{
2012-11-26 18:58:24 +00:00
return 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float peakLevels [ MAX_CHANNELS_PER_VOICE ] ;
float rmsLevels [ MAX_CHANNELS_PER_VOICE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
XAUDIO2FX_VOLUMEMETER_LEVELS levels ;
levels . ChannelCount = leadinSample - > NumChannels ( ) ;
levels . pPeakLevels = peakLevels ;
levels . pRMSLevels = rmsLevels ;
2012-11-28 15:47:07 +00:00
if ( levels . ChannelCount > MAX_CHANNELS_PER_VOICE )
{
2012-11-26 18:58:24 +00:00
levels . ChannelCount = MAX_CHANNELS_PER_VOICE ;
}
2012-11-28 15:47:07 +00:00
if ( pSourceVoice - > GetEffectParameters ( 0 , & levels , sizeof ( levels ) ) ! = S_OK )
{
2012-11-26 18:58:24 +00:00
return 0.0f ;
}
2012-11-28 15:47:07 +00:00
if ( levels . ChannelCount = = 1 )
{
2012-11-26 18:58:24 +00:00
return rmsLevels [ 0 ] ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float rms = 0.0f ;
2012-11-28 15:47:07 +00:00
for ( uint32 i = 0 ; i < levels . ChannelCount ; i + + )
{
2012-11-26 18:58:24 +00:00
rms + = rmsLevels [ i ] ;
}
2012-11-28 15:47:07 +00:00
return rms / ( float ) levels . ChannelCount ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : ResetSampleRate
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : SetSampleRate ( uint32 newSampleRate , uint32 operationSet )
{
if ( pSourceVoice = = NULL | | leadinSample = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
sampleRate = newSampleRate ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
XAUDIO2_FILTER_PARAMETERS filter ;
filter . Type = LowPassFilter ;
filter . OneOverQ = 1.0f ; // [0.0f, XAUDIO2_MAX_FILTER_ONEOVERQ]
float cutoffFrequency = 1000.0f / Max ( 0.01f , occlusion ) ;
2012-11-28 15:47:07 +00:00
if ( cutoffFrequency * 6.0f > = ( float ) sampleRate )
{
2012-11-26 18:58:24 +00:00
filter . Frequency = XAUDIO2_MAX_FILTER_FREQUENCY ;
2012-11-28 15:47:07 +00:00
}
else
{
filter . Frequency = 2.0f * idMath : : Sin ( idMath : : PI * cutoffFrequency / ( float ) sampleRate ) ;
2012-11-26 18:58:24 +00:00
}
assert ( filter . Frequency > = 0.0f & & filter . Frequency < = XAUDIO2_MAX_FILTER_FREQUENCY ) ;
filter . Frequency = idMath : : ClampFloat ( 0.0f , XAUDIO2_MAX_FILTER_FREQUENCY , filter . Frequency ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
pSourceVoice - > SetFilterParameters ( & filter , operationSet ) ;
2012-11-28 15:47:07 +00:00
float freqRatio = pitch * ( float ) sampleRate / ( float ) sourceVoiceRate ;
2012-11-26 18:58:24 +00:00
assert ( freqRatio > = XAUDIO2_MIN_FREQ_RATIO & & freqRatio < = XAUDIO2_MAX_FREQ_RATIO ) ;
freqRatio = idMath : : ClampFloat ( XAUDIO2_MIN_FREQ_RATIO , XAUDIO2_MAX_FREQ_RATIO , freqRatio ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the value specified for maxFreqRatio is too high for the specified format, the call to CreateSourceVoice will fail
2012-11-28 15:47:07 +00:00
if ( numChannels = = 1 )
{
assert ( freqRatio * ( float ) SYSTEM_SAMPLE_RATE < = XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MONO ) ;
}
else
{
assert ( freqRatio * ( float ) SYSTEM_SAMPLE_RATE < = XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL ) ;
2012-11-26 18:58:24 +00:00
}
pSourceVoice - > SetFrequencyRatio ( freqRatio , operationSet ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSoundVoice_XAudio2 : : OnBufferStart
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idSoundVoice_XAudio2 : : OnBufferStart ( idSoundSample_XAudio2 * sample , int bufferNumber )
{
2012-11-26 18:58:24 +00:00
SetSampleRate ( sample - > SampleRate ( ) , XAUDIO2_COMMIT_NOW ) ;
2012-11-28 15:47:07 +00:00
idSoundSample_XAudio2 * nextSample = sample ;
2012-11-26 18:58:24 +00:00
int nextBuffer = bufferNumber + 1 ;
2012-11-28 15:47:07 +00:00
if ( nextBuffer = = sample - > buffers . Num ( ) )
{
if ( sample = = leadinSample )
{
if ( loopingSample = = NULL )
{
2012-11-26 18:58:24 +00:00
return ;
}
nextSample = loopingSample ;
}
nextBuffer = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
SubmitBuffer ( nextSample , nextBuffer , 0 ) ;
}