Torque3D Documentation / _generateds / sfxFMODVoice.cpp

sfxFMODVoice.cpp

Engine/source/sfx/fmod/sfxFMODVoice.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 "platform/platform.h"
 25#include "sfx/fmod/sfxFMODVoice.h"
 26
 27#include "sfx/fmod/sfxFMODBuffer.h"
 28#include "sfx/fmod/sfxFMODDevice.h"
 29#include "core/tAlgorithm.h"
 30
 31
 32SFXFMODVoice* SFXFMODVoice::create( SFXFMODDevice *device,
 33                                    SFXFMODBuffer *buffer )
 34{
 35   AssertFatal( device, "SFXFMODVoice::create() - Got null device!" );
 36   AssertFatal( buffer, "SFXFMODVoice::create() - Got null buffer!" );
 37
 38   return new SFXFMODVoice( device, buffer );
 39}
 40
 41SFXFMODVoice::SFXFMODVoice(   SFXFMODDevice *device, 
 42                              SFXFMODBuffer *buffer )
 43   :  Parent( buffer ),
 44      mDevice( device ),
 45      mChannel( NULL )
 46{
 47   AssertFatal( device, "SFXFMODVoice::SFXFMODVoice() - No device assigned!" );
 48   AssertFatal( buffer, "SFXFMODVoice::SFXFMODVoice() - No buffer assigned!" );
 49   AssertFatal( _getBuffer()->mSound != NULL, "SFXFMODVoice::SFXFMODVoice() - No sound assigned!" );
 50}
 51
 52SFXFMODVoice::~SFXFMODVoice()
 53{
 54   _stop();
 55}
 56
 57SFXStatus SFXFMODVoice::_status() const
 58{
 59   if( mChannel )
 60   {
 61      FMOD_BOOL isTrue = false;
 62      SFXFMODDevice::smFunc->FMOD_Channel_GetPaused( mChannel, &isTrue );
 63      if ( isTrue )
 64         return SFXStatusPaused;
 65
 66      SFXFMODDevice::smFunc->FMOD_Channel_IsPlaying( mChannel, &isTrue );
 67      if ( isTrue )
 68         return SFXStatusPlaying;
 69   }
 70   
 71   SFXFMODDevice::smFunc->FMOD_Channel_Stop( mChannel );
 72   mChannel = NULL;
 73
 74   return SFXStatusStopped;
 75}
 76
 77void SFXFMODVoice::_play()
 78{
 79   if( !mChannel )
 80      _assignChannel();
 81
 82   SFXFMODDevice::smFunc->FMOD_Channel_SetPaused( mChannel, false );
 83}
 84
 85void SFXFMODVoice::_pause()
 86{
 87   if( mChannel )
 88      SFXFMODDevice::smFunc->FMOD_Channel_SetPaused( mChannel, true );
 89}
 90
 91void SFXFMODVoice::_stop()
 92{
 93   if( mChannel )
 94      SFXFMODDevice::smFunc->FMOD_Channel_Stop(mChannel);
 95      
 96   mChannel = NULL;
 97}
 98
 99void SFXFMODVoice::_seek( U32 sample )
100{
101   if( !mChannel )
102      _assignChannel();
103
104   SFXFMODDevice::smFunc->FMOD_Channel_SetPosition
105      ( mChannel, sample, FMOD_TIMEUNIT_PCM );
106}
107
108bool SFXFMODVoice::_assignChannel()
109{
110   AssertFatal( _getBuffer()->mSound != NULL, "SFXFMODVoice::_assignChannel() - No sound assigned!" );
111
112   // we start playing it now in the paused state, so that we can immediately set attributes that
113   // depend on having a channel (position, volume, etc).  According to the FMod docs
114   // it is ok to do this.
115   bool success = SFXFMODDevice::smFunc->FMOD_System_PlaySound(
116      SFXFMODDevice::smSystem, 
117      FMOD_CHANNEL_FREE, 
118      _getBuffer()->mSound, 
119      true, 
120      &mChannel ) == FMOD_OK;
121      
122   if( success )
123   {
124      SFXFMODDevice::smFunc->FMOD_Channel_SetMode( mChannel, mMode );
125      SFXFMODDevice::smFunc->FMOD_Channel_SetLoopCount( mChannel, mMode & FMOD_LOOP_NORMAL ? -1 : 0 );
126
127      if( mSetFlags.test( SET_Velocity ) )
128         SFXFMODDevice::smFunc->FMOD_Channel_Set3DAttributes( mChannel, ( const FMOD_VECTOR* ) NULL, &mVelocity );
129      if( mSetFlags.test( SET_MinMaxDistance ) )
130         SFXFMODDevice::smFunc->FMOD_Channel_Set3DMinMaxDistance(mChannel, mMinDistance, mMaxDistance);
131      if( mSetFlags.test( SET_Transform ) )
132      {
133         SFXFMODDevice::smFunc->FMOD_Channel_Set3DAttributes( mChannel, &mPosition, ( const FMOD_VECTOR* ) NULL );
134         SFXFMODDevice::smFunc->FMOD_Channel_Set3DConeOrientation( mChannel, &mDirection );
135      }
136      if( mSetFlags.test( SET_Volume ) )
137         SFXFMODDevice::smFunc->FMOD_Channel_SetVolume(mChannel, mVolume);
138      if( mSetFlags.test( SET_Pitch ) )
139         SFXFMODDevice::smFunc->FMOD_Channel_SetFrequency( mChannel, mFrequency );
140      if( mSetFlags.test( SET_Cone ) )
141         SFXFMODDevice::smFunc->FMOD_Channel_Set3DConeSettings( 
142            mChannel, 
143            mConeInnerAngle,
144            mConeOuterAngle,
145            mConeOuterVolume );
146      if( mSetFlags.test( SET_Priority ) )
147         SFXFMODDevice::smFunc->FMOD_Channel_SetPriority( mChannel, TorquePriorityToFMODPriority( mPriority ) );
148      if( mSetFlags.test( SET_Reverb ) )
149         SFXFMODDevice::smFunc->FMOD_Channel_SetReverbProperties( mChannel, &mReverb );
150   }
151   
152   return success;
153}
154
155U32 SFXFMODVoice::_tell() const
156{
157   if( !mChannel )
158      return 0;
159
160   U32 pos;
161   SFXFMODDevice::smFunc->FMOD_Channel_GetPosition( mChannel, &pos, ( FMOD_TIMEUNIT ) FMOD_TIMEUNIT_PCMBYTES );
162   return _getBuffer()->getSamplePos( pos );
163}
164
165void SFXFMODVoice::setMinMaxDistance( F32 min, F32 max )
166{
167   if ( !( _getBuffer()->mMode & FMOD_3D ) )
168      return;
169      
170   mMinDistance = min;
171   mMaxDistance = max;
172   
173   mSetFlags.set( SET_MinMaxDistance );
174
175   if( mChannel )
176      SFXFMODDevice::smFunc->FMOD_Channel_Set3DMinMaxDistance(mChannel, mMinDistance, mMaxDistance);
177}
178
179void SFXFMODVoice::play( bool looping )
180{
181   if( mBuffer->isStreaming() )
182      looping = true;
183   
184   mMode = mDevice->get3dRollOffMode();
185   mMode |= (looping ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
186
187   Parent::play( looping );
188}
189
190void SFXFMODVoice::setVelocity( const VectorF& velocity )
191{
192   if( !( _getBuffer()->mMode & FMOD_3D ) )
193      return;
194
195   // Note we have to do a handedness swap; see the 
196   // listener update code in SFXFMODDevice for details.
197   mVelocity.x = velocity.x;
198   mVelocity.y = velocity.z;
199   mVelocity.z = velocity.y;
200   
201   mSetFlags.set( SET_Velocity );
202
203   if( mChannel )
204      SFXFMODDevice::smFunc->FMOD_Channel_Set3DAttributes( mChannel, ( const FMOD_VECTOR* ) NULL, &mVelocity );
205}
206
207void SFXFMODVoice::setTransform( const MatrixF& transform )
208{
209   if ( !( _getBuffer()->mMode & FMOD_3D ) )
210      return;
211
212   transform.getColumn( 3, (Point3F*)&mPosition );
213   transform.getColumn( 1, (Point3F*)&mDirection );
214
215   // Note we have to do a handedness swap; see the 
216   // listener update code in SFXFMODDevice for details.
217   swap( mPosition.y, mPosition.z );
218   swap( mDirection.y, mDirection.z );
219   
220   mSetFlags.set( SET_Transform );
221
222   if( mChannel )
223   {
224      // This can fail safe, so don't assert if it fails.
225      SFXFMODDevice::smFunc->FMOD_Channel_Set3DAttributes( mChannel, &mPosition, ( const FMOD_VECTOR* ) NULL );
226      SFXFMODDevice::smFunc->FMOD_Channel_Set3DConeOrientation( mChannel, &mDirection );
227   }
228}
229
230void SFXFMODVoice::setVolume( F32 volume )
231{
232   mVolume = volume;
233   mSetFlags.set( SET_Volume );
234   
235   if( mChannel )
236      SFXFMODDevice::smFunc->FMOD_Channel_SetVolume( mChannel, volume );
237}
238
239void SFXFMODVoice::setPriority( F32 priority )
240{
241   mPriority = priority;
242   mSetFlags.set( SET_Priority );
243   
244   if( mChannel )
245      SFXFMODDevice::smFunc->FMOD_Channel_SetPriority( mChannel, TorquePriorityToFMODPriority( priority ) );
246}
247
248void SFXFMODVoice::setPitch( F32 pitch )
249{
250   // if we do not know the frequency, we cannot change the pitch
251   F32 frequency = _getBuffer()->getFormat().getSamplesPerSecond();
252   if ( frequency == 0 )
253      return;
254      
255   mFrequency = frequency * pitch;
256   
257   mSetFlags.set( SET_Pitch );
258
259   // Scale the original frequency by the pitch factor.
260   if( mChannel )
261      SFXFMODDevice::smFunc->FMOD_Channel_SetFrequency(mChannel, mFrequency);
262}
263
264void SFXFMODVoice::setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume )
265{
266   mConeInnerAngle = innerAngle;
267   mConeOuterAngle = outerAngle;
268   mConeOuterVolume = outerVolume;
269   
270   mSetFlags.set( SET_Cone );
271
272   if( mChannel )
273      SFXFMODDevice::smFunc->FMOD_Channel_Set3DConeSettings( 
274         mChannel, 
275         mConeInnerAngle,
276         mConeOuterAngle,
277         mConeOuterVolume );
278}
279
280void SFXFMODVoice::setReverb( const SFXSoundReverbProperties& reverb )
281{
282   dMemset( &mReverb, 0, sizeof( mReverb ) );
283   
284   mReverb.Direct                = reverb.mDirect;
285   mReverb.Room                  = reverb.mRoom;
286   mReverb.Flags                 = reverb.mFlags;
287   
288   mSetFlags.set( SET_Reverb );
289   
290   if( mChannel )
291      SFXFMODDevice::smFunc->FMOD_Channel_SetReverbProperties( mChannel, &mReverb );
292}
293
294bool SFXFMODVoice::isVirtual() const
295{
296   if( mChannel )
297   {
298      FMOD_BOOL result;
299      SFXFMODDevice::smFunc->FMOD_Channel_IsVirtual( mChannel, &result );
300      return result;
301   }
302   else
303      return false;
304}
305