Torque3D Documentation / _generateds / sfxDSDevice.cpp

sfxDSDevice.cpp

Engine/source/sfx/dsound/sfxDSDevice.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/dsound/sfxDSDevice.h"
 25#include "sfx/dsound/sfxDSBuffer.h"
 26#include "sfx/dsound/sfxDSVoice.h"
 27#include "platformWin32/platformWin32.h"
 28#include "core/util/safeRelease.h"
 29#include "platform/async/asyncUpdate.h"
 30#include "console/console.h"
 31
 32
 33SFXDSDevice::SFXDSDevice(  SFXProvider* provider, 
 34                           DSoundFNTable *dsFnTbl,
 35                           GUID* guid, 
 36                           String name,
 37                           bool useHardware,
 38                           S32 maxBuffers )
 39   :  SFXDevice( name, provider, useHardware, maxBuffers ),
 40      mDSound( NULL ),
 41      mPrimaryBuffer( NULL ),
 42      mListener( NULL ),
 43      mDSoundTbl( dsFnTbl ),
 44      mGUID( guid )
 45{
 46}
 47
 48bool SFXDSDevice::_init()
 49{
 50   HRESULT hr = mDSoundTbl->DirectSoundCreate8( mGUID, &mDSound, NULL );   
 51   if ( FAILED( hr ) || !mDSound )
 52   {
 53      Con::errorf( "SFXDSDevice::SFXDSDevice() - DirectSoundCreate8 failed" );
 54      return false;
 55   }
 56
 57   hr = mDSound->SetCooperativeLevel( getWin32WindowHandle(), DSSCL_PRIORITY );
 58   if ( FAILED( hr ) )
 59   {
 60      Con::errorf( "SFXDSDevice::SFXDSDevice() - SetCooperativeLevel failed" );
 61      return false;
 62   }
 63
 64   // Get the primary buffer.
 65   DSBUFFERDESC dsbd;   
 66   dMemset( &dsbd, 0, sizeof( DSBUFFERDESC ) ); 
 67   dsbd.dwSize = sizeof( DSBUFFERDESC );
 68   dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
 69   hr = mDSound->CreateSoundBuffer( &dsbd, &mPrimaryBuffer, NULL );
 70   if ( FAILED( hr ) )
 71   {
 72      Con::errorf( "SFXDSDevice::SFXDSDevice - Creating primary sound buffer failed" );
 73      return false;
 74   }
 75
 76   // Set the format and bitrate on the primary buffer.
 77   S32 frequency = Con::getIntVariable( "$pref::SFX::frequency", 44100 );
 78   S32 bitrate = Con::getIntVariable( "$pref::SFX::bitrate", 32 );
 79
 80   WAVEFORMATEX wfx;
 81   dMemset( &wfx, 0, sizeof( WAVEFORMATEX ) ); 
 82   wfx.wFormatTag = WAVE_FORMAT_PCM; 
 83   wfx.nChannels = 2; 
 84   wfx.nSamplesPerSec = frequency;
 85   wfx.wBitsPerSample = bitrate; 
 86   wfx.nBlockAlign = ( wfx.nChannels * wfx.wBitsPerSample ) / 8;
 87   wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; 
 88   hr = mPrimaryBuffer->SetFormat( &wfx );
 89   if( FAILED( hr ) )
 90   {
 91      Con::errorf( "SFXDSDevice::SFXDSDevice() - Setting format of primary buffer failed" );
 92      return false;
 93   }
 94
 95   // Grab the 3d listener.
 96   hr = mPrimaryBuffer->QueryInterface( IID_IDirectSound3DListener8, (LPVOID*)&mListener );
 97   if ( FAILED( hr ) )
 98   {
 99      Con::errorf( "SFXDSDevice::SFXDevice() - Querying the listener interface failed!" );
100      mListener = NULL;
101   }
102
103   mCaps.dwSize = sizeof( DSCAPS );
104   mDSound->GetCaps( &mCaps );
105
106   // If the device reports no hardware buffers then
107   // we have no choice but to disable hardware.
108   if ( mCaps.dwMaxHw3DAllBuffers == 0 )
109      mUseHardware = false;
110
111   // If mMaxBuffers is negative then use the caps
112   // to decide on a good maximum value... or set 8.
113   if ( mMaxBuffers < 0 )
114      mMaxBuffers = getMax( mCaps.dwMaxHw3DAllBuffers, 8 );
115
116   // Start the stream thread.
117
118   if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
119   {
120      SFXInternal::gUpdateThread =
121         new AsyncUpdateThread( "DirectSound Update Thread", SFXInternal::gBufferUpdateList );
122      SFXInternal::gUpdateThread->start();
123   }
124
125   return true;
126}
127
128SFXDSDevice::~SFXDSDevice()
129{
130   // And release our resources.
131   SAFE_RELEASE( mListener );
132   SAFE_RELEASE( mPrimaryBuffer );
133   SAFE_RELEASE( mDSound );
134}
135
136SFXBuffer* SFXDSDevice::createBuffer( const ThreadSafeRef< SFXStream>& stream, SFXDescription* description )
137{
138   AssertFatal( stream, "SFXDSDevice::createBuffer() - Got null stream!" );
139   AssertFatal( description, "SFXDSDevice::createBuffer() - Got null description!" );
140
141   SFXDSBuffer* buffer = SFXDSBuffer::create(   mDSound, 
142                                                stream,
143                                                description, 
144                                                mUseHardware );
145
146   if( buffer )
147      _addBuffer( buffer );
148
149   return buffer;
150}
151
152SFXVoice* SFXDSDevice::createVoice( bool is3D, SFXBuffer *buffer )
153{
154   // Don't bother going any further if we've 
155   // exceeded the maximum voices.
156   if ( mVoices.size() >= mMaxBuffers )
157      return NULL;
158
159   AssertFatal( buffer, "SFXDSDevice::createVoice() - Got null buffer!" );
160
161   SFXDSBuffer* dsBuffer = dynamic_cast<SFXDSBuffer*>( buffer );
162   AssertFatal( dsBuffer, "SFXDSDevice::createVoice() - Got bad buffer!" );
163
164   SFXDSVoice* voice = SFXDSVoice::create( this, dsBuffer );
165   if ( !voice )
166      return NULL;
167
168   _addVoice( voice );
169   return voice;
170}
171
172void SFXDSDevice::_commitDeferred()
173{
174   if( mListener )
175      mListener->CommitDeferredSettings();
176}
177
178void SFXDSDevice::update()
179{
180   Parent::update();
181
182   // Apply the deferred settings that changed between updates.
183   mListener->CommitDeferredSettings();
184}
185
186void SFXDSDevice::setListener( U32 index, const SFXListenerProperties& listener )
187{
188   // Get the transform from the listener.
189   const MatrixF& transform = listener.getTransform();
190   Point3F pos, dir, up;
191   transform.getColumn( 3, &pos );
192   transform.getColumn( 1, &dir );
193   transform.getColumn( 2, &up );
194
195   // And the velocity...
196   const VectorF& velocity = listener.getVelocity();
197
198   // Finally, set it all to DSound!
199   mListener->SetPosition( pos.x, pos.z, pos.y, DS3D_DEFERRED );
200   mListener->SetOrientation( dir.x, dir.z, dir.y, up.x, up.z, up.y, DS3D_DEFERRED );
201   mListener->SetVelocity( velocity.x, velocity.z, velocity.y, DS3D_DEFERRED );
202}
203
204void SFXDSDevice::setDistanceModel( SFXDistanceModel model )
205{
206   switch( model )
207   {
208   case SFXDistanceModelLinear:
209      Con::errorf( "SFXDSDevice::setDistanceModel - 'linear' distance attenuation not supported by DirectSound" );
210      break;
211
212   case SFXDistanceModelLogarithmic:
213      break; // Nothing to do.
214
215   default:
216      AssertWarn( false, "SFXDSDevice::setDistanceModel() - model not implemented" );
217   }
218}
219
220void SFXDSDevice::setDopplerFactor( F32 factor )
221{
222   if( mListener )
223      mListener->SetDopplerFactor( factor, DS3D_DEFERRED ); // Committed in update.
224}
225
226void SFXDSDevice::setRolloffFactor( F32 factor )
227{
228   if( mListener )
229      mListener->SetRolloffFactor( factor, DS3D_DEFERRED ); // Committed in update.
230}
231