Torque3D Documentation / _generateds / sfxXAudioDevice.cpp

sfxXAudioDevice.cpp

Engine/source/sfx/xaudio/sfxXAudioDevice.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "sfx/xaudio/sfxXAudioDevice.h"
 25#include "platform/async/asyncUpdate.h"
 26#include "core/stringTable.h"
 27#include "console/console.h"
 28#include "core/util/safeRelease.h"
 29#include "core/tAlgorithm.h"
 30#include "platform/profiler.h"
 31
 32
 33SFXXAudioDevice::SFXXAudioDevice(   SFXProvider* provider, 
 34                                    const String& name,
 35                                    IXAudio2 *xaudio,
 36                                    U32 deviceIndex,
 37                                    U32 speakerChannelMask,
 38                                    U32 maxBuffers )
 39   :  Parent( name, provider, false, maxBuffers ),
 40      mXAudio( xaudio ),
 41      mMasterVoice( NULL )
 42{
 43   dMemset( &mListener, 0, sizeof( mListener ) );
 44
 45   // If mMaxBuffers is negative then use some default value.
 46   // to decide on a good maximum value... or set 8.
 47   //
 48   // TODO: We should change the terminology to voices!
 49   if ( mMaxBuffers < 0 )
 50      mMaxBuffers = 64;
 51
 52   // Create the mastering voice.
 53   HRESULT hr = mXAudio->CreateMasteringVoice(  &mMasterVoice, 
 54                                                XAUDIO2_DEFAULT_CHANNELS,
 55                                                XAUDIO2_DEFAULT_SAMPLERATE, 
 56                                                0, 
 57                                                deviceIndex, 
 58                                                NULL );
 59   if ( FAILED( hr ) || !mMasterVoice )
 60   {
 61      Con::errorf( "SFXXAudioDevice - Failed creating master voice!" );
 62      return;
 63   }
 64
 65   mMasterVoice->GetVoiceDetails( &mMasterVoiceDetails );
 66
 67   // Init X3DAudio.
 68   X3DAudioInitialize(  speakerChannelMask, 
 69                        X3DAUDIO_SPEED_OF_SOUND, 
 70                        mX3DAudio );
 71
 72   // Start the update thread.
 73
 74   if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
 75   {
 76      SFXInternal::gUpdateThread = new AsyncUpdateThread
 77         ( "XAudio Update Thread", SFXInternal::gBufferUpdateList );
 78      SFXInternal::gUpdateThread->start();
 79   }
 80}
 81
 82
 83SFXXAudioDevice::~SFXXAudioDevice()
 84{
 85   _releaseAllResources();
 86
 87   if ( mMasterVoice )
 88   {
 89      mMasterVoice->DestroyVoice();
 90      mMasterVoice = NULL;
 91   }
 92
 93   // Kill the engine.
 94   SAFE_RELEASE( mXAudio );
 95}
 96
 97
 98SFXBuffer* SFXXAudioDevice::createBuffer( const ThreadSafeRef< SFXStream>& stream, SFXDescription* description )
 99{
100   SFXXAudioBuffer* buffer = SFXXAudioBuffer::create( stream, description );
101   if ( !buffer )
102      return NULL;
103
104   _addBuffer( buffer );
105   return buffer;
106}
107
108SFXVoice* SFXXAudioDevice::createVoice( bool is3D, SFXBuffer *buffer )
109{
110   // Don't bother going any further if we've 
111   // exceeded the maximum voices.
112   if ( mVoices.size() >= mMaxBuffers )
113      return NULL;
114
115   AssertFatal( buffer, "SFXXAudioDevice::createVoice() - Got null buffer!" );
116
117   SFXXAudioBuffer* xaBuffer = dynamic_cast<SFXXAudioBuffer*>( buffer );
118   AssertFatal( xaBuffer, "SFXXAudioDevice::createVoice() - Got bad buffer!" );
119
120   SFXXAudioVoice* voice = SFXXAudioVoice::create( mXAudio, is3D, xaBuffer );
121   if ( !voice )
122      return NULL;
123
124   voice->mXAudioDevice = this;
125
126   _addVoice( voice );
127   return voice;
128}
129
130void SFXXAudioDevice::_setOutputMatrix( SFXXAudioVoice *voice )
131{
132   X3DAUDIO_DSP_SETTINGS dspSettings = {0};
133   FLOAT32 matrix[12] = { 0 };
134   dspSettings.DstChannelCount = mMasterVoiceDetails.InputChannels;
135   dspSettings.pMatrixCoefficients = matrix;
136
137   const X3DAUDIO_EMITTER &emitter = voice->getEmitter();
138   dspSettings.SrcChannelCount = emitter.ChannelCount;
139
140   // Calculate the output volumes and doppler.
141   X3DAudioCalculate(   mX3DAudio, 
142                        &mListener, 
143                        &emitter, 
144                        X3DAUDIO_CALCULATE_MATRIX | 
145                        X3DAUDIO_CALCULATE_DOPPLER,
146                        &dspSettings );
147
148   voice->mXAudioVoice->SetOutputMatrix(   mMasterVoice, 
149                                           dspSettings.SrcChannelCount, 
150                                           dspSettings.DstChannelCount, 
151                                           dspSettings.pMatrixCoefficients,
152                                           4321 );
153
154   voice->mXAudioVoice->SetFrequencyRatio(   dspSettings.DopplerFactor * voice->mPitch, 
155                                             4321 );
156
157   // Commit the changes.
158   mXAudio->CommitChanges( 4321 );
159}
160
161void SFXXAudioDevice::update()
162{
163   PROFILE_SCOPE( SFXXAudioDevice_Update );
164
165   Parent::update();
166
167   X3DAUDIO_DSP_SETTINGS dspSettings = {0};
168   FLOAT32 matrix[12] = { 0 };
169   dspSettings.DstChannelCount = mMasterVoiceDetails.InputChannels;
170   dspSettings.pMatrixCoefficients = matrix;
171
172   dspSettings.DopplerFactor = mDopplerFactor;
173
174   // Now update the volume and frequency of 
175   // all the active 3D voices.
176   VoiceVector::iterator voice = mVoices.begin();
177   for ( ; voice != mVoices.end(); voice++ )
178   {
179      SFXXAudioVoice* xaVoice = ( SFXXAudioVoice* ) *voice;
180
181      // Skip 2D or stopped voices.
182      if (  !xaVoice->is3D() ||
183            xaVoice->getStatus() != SFXStatusPlaying )
184         continue;
185
186      const X3DAUDIO_EMITTER &emitter = xaVoice->getEmitter();
187      dspSettings.SrcChannelCount = emitter.ChannelCount;
188
189      // Calculate the output volumes and doppler.
190      X3DAudioCalculate(   mX3DAudio, 
191                           &mListener, 
192                           &emitter, 
193                           X3DAUDIO_CALCULATE_MATRIX | 
194                           X3DAUDIO_CALCULATE_DOPPLER, 
195                           &dspSettings );
196
197      xaVoice->mXAudioVoice->SetOutputMatrix(   mMasterVoice, 
198                                                dspSettings.SrcChannelCount, 
199                                                dspSettings.DstChannelCount, 
200                                                dspSettings.pMatrixCoefficients,
201                                                4321 ) ;
202
203      xaVoice->mXAudioVoice->SetFrequencyRatio( dspSettings.DopplerFactor * xaVoice->mPitch, 
204                                                4321 );
205   }
206
207   // Commit the changes.
208   mXAudio->CommitChanges( 4321 );
209}
210
211void SFXXAudioDevice::setListener( U32 index, const SFXListenerProperties& listener )
212{
213   // Get the transform from the listener.
214   const MatrixF& transform = listener.getTransform();
215   transform.getColumn( 3, (Point3F*)&mListener.Position );
216   transform.getColumn( 1, (Point3F*)&mListener.OrientFront );
217   transform.getColumn( 2, (Point3F*)&mListener.OrientTop );
218
219   // And the velocity...
220   const VectorF& velocity = listener.getVelocity();
221   mListener.Velocity.x = velocity.x;
222   mListener.Velocity.y = velocity.y;
223   mListener.Velocity.z = velocity.z;
224
225   // XAudio and Torque use opposite handedness, so
226   // flip the z coord to account for that.
227   mListener.Position.z    *= -1.0f;
228   mListener.OrientFront.z *= -1.0f;
229   mListener.OrientTop.z   *= -1.0f;
230   mListener.Velocity.z    *= -1.0f;
231}
232
233void SFXXAudioDevice::setDistanceModel( SFXDistanceModel model )
234{
235   mDistanceModel = model;
236}
237
238void SFXXAudioDevice::setDopplerFactor( F32 factor )
239{
240   mDopplerFactor = factor;
241}
242
243void SFXXAudioDevice::setRolloffFactor( F32 factor )
244{
245   mRolloffFactor = factor;
246}
247