Torque3D Documentation / _generateds / sfxDescription.cpp

sfxDescription.cpp

Engine/source/sfx/sfxDescription.cpp

More...

Classes:

Public Functions

ConsoleDocClass(AudioDescription , "@brief Allows legacy <a href="/coding/class/classaudiodescription/">AudioDescription</a> datablocks <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be treated as <a href="/coding/class/classsfxdescription/">SFXDescription</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxMisc\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
ConsoleDocClass(SFXDescription , "@brief A description <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> how <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> sound should be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">played.\n\n</a>" "SFXDescriptions are used by the sound system <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collect all parameters needed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given " "sound <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playback. This includes information like its volume level, its pitch shift, etc. as well " "as more complex information like its fade behavior, 3D properties, and per-sound reverb <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">properties.\n\n</a>" "Any sound playback will require <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> valid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXDescription.\n\n</a>" "As datablocks, SFXDescriptions can be set up as either networked datablocks or non-networked datablocks, " "though it generally makes sense <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep all descriptions non-networked since they will be used exclusively " "by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//A description <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> reasonable default range <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setting.\n</a>" "//The description is set up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign sounds <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the AudioChannelEffects <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group\n</a>" "//(defined in the core scripts). An alternative means <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> achieve this is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">the\n</a>" "//AudioEffects description as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> copy <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a>(\": AudioEffects\").\n" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "singleton <a href="/coding/class/classsfxdescription/">SFXDescription</a>( Audio3DSound )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  sourceGroup       = AudioChannelEffects;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  is3D              = true;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  referenceDistance = 20.0;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  maxDistance       = 100.0;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )

Detailed Description

Public Variables

const U32 sReverbSoundFlagDirectHFAuto 
const U32 sReverbSoundFlagInstance0 
const U32 sReverbSoundFlagInstance1 
const U32 sReverbSoundFlagInstance2 
const U32 sReverbSoundFlagInstance3 
const U32 sReverbSoundFlagRoomAuto 
const U32 sReverbSoundFlagRoomHFAuto 

Public Functions

AFTER_MODULE_INIT(SFX )

ConsoleDocClass(AudioDescription , "@brief Allows legacy <a href="/coding/class/classaudiodescription/">AudioDescription</a> datablocks <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be treated as <a href="/coding/class/classsfxdescription/">SFXDescription</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablocks.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxMisc\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )

ConsoleDocClass(SFXDescription , "@brief A description <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> how <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> sound should be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">played.\n\n</a>" "SFXDescriptions are used by the sound system <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> collect all parameters needed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> given " "sound <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> playback. This includes information like its volume level, its pitch shift, etc. as well " "as more complex information like its fade behavior, 3D properties, and per-sound reverb <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">properties.\n\n</a>" "Any sound playback will require <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> valid <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXDescription.\n\n</a>" "As datablocks, SFXDescriptions can be set up as either networked datablocks or non-networked datablocks, " "though it generally makes sense <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep all descriptions non-networked since they will be used exclusively " "by <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//A description <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 3D sound with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> reasonable default range <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setting.\n</a>" "//The description is set up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> assign sounds <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the AudioChannelEffects <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group\n</a>" "//(defined in the core scripts). An alternative means <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> achieve this is <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">the\n</a>" "//AudioEffects description as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> copy <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a>(\": AudioEffects\").\n" "\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "singleton <a href="/coding/class/classsfxdescription/">SFXDescription</a>( Audio3DSound )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  sourceGroup       = AudioChannelEffects;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  is3D              = true;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  referenceDistance = 20.0;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "  maxDistance       = 100.0;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )

IMPLEMENT_CO_DATABLOCK_V1(AudioDescription )

IMPLEMENT_CO_DATABLOCK_V1(SFXDescription )

  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//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 25// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
 26// Copyright (C) 2015 Faust Logic, Inc.
 27//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
 28#include "platform/platform.h"
 29
 30#include "sfx/sfxDescription.h"
 31#include "sfx/sfxSystem.h"
 32#include "sfx/sfxInternal.h"
 33#include "sfx/sfxSource.h"
 34#include "sfx/sfxTypes.h"
 35#include "sim/netConnection.h"
 36#include "core/stream/bitStream.h"
 37#include "core/stringTable.h"
 38#include "core/module.h"
 39#include "math/mathIO.h"
 40#include "math/mathTypes.h"
 41
 42
 43IMPLEMENT_CO_DATABLOCK_V1( SFXDescription );
 44
 45ConsoleDocClass( SFXDescription,
 46   "@brief A description for how a sound should be played.\n\n"
 47   
 48   "SFXDescriptions are used by the sound system to collect all parameters needed to set up a given "
 49   "sound for playback.  This includes information like its volume level, its pitch shift, etc. as well "
 50   "as more complex information like its fade behavior, 3D properties, and per-sound reverb properties.\n\n"
 51   
 52   "Any sound playback will require a valid SFXDescription.\n\n"
 53   
 54   "As datablocks, SFXDescriptions can be set up as either networked datablocks or non-networked datablocks, "
 55   "though it generally makes sense to keep all descriptions non-networked since they will be used exclusively "
 56   "by clients.\n\n"
 57   
 58   "@tsexample\n"
 59   "// A description for a 3D sound with a reasonable default range setting.\n"
 60   "// The description is set up to assign sounds to the AudioChannelEffects source group\n"
 61   "// (defined in the core scripts).  An alternative means to achieve this is to use the\n"
 62   "// AudioEffects description as a copy source (\": AudioEffects\").\n"
 63   "\n"
 64   "singleton SFXDescription( Audio3DSound )\n"
 65   "{\n"
 66   "  sourceGroup       = AudioChannelEffects;\n"
 67   "  is3D              = true;\n"
 68   "  referenceDistance = 20.0;\n"
 69   "  maxDistance       = 100.0;\n"
 70   "};\n"
 71   "@endtsexample\n\n"
 72   
 73   "@ingroup SFX\n"
 74   "@ingroup Datablocks\n"
 75);
 76
 77
 78// Constants.
 79static const U32 sReverbSoundFlagDirectHFAuto            = 0x01;
 80static const U32 sReverbSoundFlagRoomAuto                = 0x02;
 81static const U32 sReverbSoundFlagRoomHFAuto              = 0x04;
 82static const U32 sReverbSoundFlagInstance0               = 0x10;
 83static const U32 sReverbSoundFlagInstance1               = 0x20;
 84static const U32 sReverbSoundFlagInstance2               = 0x40;
 85static const U32 sReverbSoundFlagInstance3               = 0x80;
 86
 87AFTER_MODULE_INIT( SFX )
 88{
 89   Con::addConstant( "SFXDescription::REVERB_DIRECTHFAUTO", TypeS32, &sReverbSoundFlagDirectHFAuto,
 90      "Automatic setting of SFXDescription::reverbDirect due to distance to listener.\n"
 91      "@see SFXDescription::flags\n\n"
 92      "@ingroup SFXDescription" );
 93   Con::addConstant( "SFXDescription::REVERB_ROOMAUTO", TypeS32, &sReverbSoundFlagRoomAuto,
 94      "Automatic setting of SFXDescription::reverbRoom due to distance to listener.\n"
 95      "@see SFXDescription::flags\n\n"
 96      "@ingroup SFXDescription" );
 97   Con::addConstant( "SFXDescription::REVERB_ROOMHFAUTO", TypeS32, &sReverbSoundFlagRoomHFAuto,
 98      "Automatic setting of SFXDescription::reverbRoomHF due to distance to listener.\n"
 99      "@see SFXDescription::flags\n\n"
100      "@ingroup SFXDescription" );
101   Con::addConstant( "SFXDescription::REVERB_INSTANCE0", TypeS32, &sReverbSoundFlagInstance0,
102      "EAX4/SFX/GameCube/Wii: Specify channel to target reverb instance 0. Default target.\n"
103      "@see SFXDescription::flags\n\n"
104      "@ingroup SFXDescription" );
105   Con::addConstant( "SFXDescription::REVERB_INSTANCE1", TypeS32, &sReverbSoundFlagInstance1,
106      "EAX4/SFX/GameCube/Wii: Specify channel to target reverb instance 1.\n"
107      "@see SFXDescription::flags\n\n"
108      "@ingroup SFXDescription" );
109   Con::addConstant( "SFXDescription::REVERB_INSTANCE2", TypeS32, &sReverbSoundFlagInstance2,
110      "EAX4/SFX/GameCube/Wii: Specify channel to target reverb instance 2.\n"
111      "@see SFXDescription::flags\n\n"
112      "@ingroup SFXDescription" );
113   Con::addConstant( "SFXDescription::REVERB_INSTANCE3", TypeS32, &sReverbSoundFlagInstance3,
114      "EAX4/SFX/GameCube/Wii: Specify channel to target reverb instance 3.\n"
115      "@see SFXDescription::flags\n\n"
116      "@ingroup SFXDescription" );
117}
118
119
120//-----------------------------------------------------------------------------
121
122SFXDescription::SFXDescription()
123   :  SimDataBlock(),
124      mVolume( 1 ),
125      mPitch( 1 ),
126      mIsLooping( false ),
127      mIsStreaming( false ),
128      mIs3D( false ),
129      mUseHardware( false ),
130      mUseReverb( false ),
131      mMinDistance( 1 ),
132      mMaxDistance( 100 ),
133      mConeInsideAngle( 360 ),
134      mConeOutsideAngle( 360 ),
135      mConeOutsideVolume( 1 ),
136      mRolloffFactor( -1.f ), // Deactivated
137      mFadeInTime( 0.0f ),
138      mFadeOutTime( 0.0f ),
139      mFadeLoops( false ),
140      mStreamPacketSize( SFXInternal::SFXAsyncStream::DEFAULT_STREAM_PACKET_LENGTH ),
141      mStreamReadAhead( SFXInternal::SFXAsyncStream::DEFAULT_STREAM_LOOKAHEAD ),
142      mScatterDistance( 0.f, 0.f, 0.f ),
143      mPriority( 1.0f ),
144      mSourceGroup( NULL )
145{
146   dMemset( mParameters, 0, sizeof( mParameters ) );
147}
148
149//-----------------------------------------------------------------------------
150
151SFXDescription::SFXDescription( const SFXDescription& desc )
152   :  SimDataBlock(),
153      mVolume( desc.mVolume ),
154      mPitch( desc.mPitch ),
155      mIsLooping( desc.mIsLooping ),
156      mIsStreaming( desc.mIsStreaming ),
157      mIs3D( desc.mIs3D ),
158      mUseHardware( desc.mUseHardware ),
159      mMinDistance( desc.mMinDistance ),
160      mMaxDistance( desc.mMaxDistance ),
161      mConeInsideAngle( desc.mConeInsideAngle ),
162      mConeOutsideAngle( desc.mConeOutsideAngle ),
163      mConeOutsideVolume( desc.mConeOutsideVolume ),
164      mRolloffFactor( desc.mRolloffFactor ),
165      mSourceGroup( desc.mSourceGroup ),
166      mFadeInTime( desc.mFadeInTime ),
167      mFadeOutTime( desc.mFadeOutTime ),
168      mFadeInEase( desc.mFadeInEase ),
169      mFadeOutEase( desc.mFadeOutEase ),
170      mFadeLoops( desc.mFadeLoops ),
171      mStreamPacketSize( desc.mStreamPacketSize ),
172      mUseReverb( desc.mUseReverb ),
173      mStreamReadAhead( desc.mStreamReadAhead ),
174      mReverb( desc.mReverb ),
175      mScatterDistance( desc.mScatterDistance ),
176      mPriority( desc.mPriority )
177{
178   for( U32 i = 0; i < MaxNumParameters; ++ i )
179      mParameters[ i ] = desc.mParameters[ i ];
180}
181
182//-----------------------------------------------------------------------------
183
184SFXDescription::SFXDescription(const SFXDescription& other, bool temp_clone)
185   : SimDataBlock(other, temp_clone),
186      mVolume( other.mVolume ),
187      mPitch( other.mPitch ),
188      mIsLooping( other.mIsLooping ),
189      mIsStreaming( other.mIsStreaming ),
190      mIs3D( other.mIs3D ),
191      mUseHardware( other.mUseHardware ),
192      mMinDistance( other.mMinDistance ),
193      mMaxDistance( other.mMaxDistance ),
194      mConeInsideAngle( other.mConeInsideAngle ),
195      mConeOutsideAngle( other.mConeOutsideAngle ),
196      mConeOutsideVolume( other.mConeOutsideVolume ),
197      mRolloffFactor( other.mRolloffFactor ),
198      mSourceGroup( other.mSourceGroup ),
199      mFadeInTime( other.mFadeInTime ),
200      mFadeOutTime( other.mFadeOutTime ),
201      mFadeInEase( other.mFadeInEase ),
202      mFadeOutEase( other.mFadeOutEase ),
203      mFadeLoops( other.mFadeLoops ),
204      mStreamPacketSize( other.mStreamPacketSize ),
205      mStreamReadAhead( other.mStreamReadAhead ),
206      mUseReverb( other.mUseReverb ),
207      mReverb( other.mReverb ),
208      mPriority( other.mPriority ),
209      mScatterDistance( other.mScatterDistance )
210{
211   for( U32 i = 0; i < MaxNumParameters; ++ i )
212      mParameters[ i ] = other.mParameters[ i ];
213}
214
215void SFXDescription::initPersistFields()
216{
217   addGroup( "Playback" );
218   
219      addField( "sourceGroup",         TypeSFXSourceName, Offset( mSourceGroup, SFXDescription ),
220         "Group that sources playing with this description should be put into.\n\n"
221         "When a sound source is allocated, it will be made a child of the source group that is listed in its \n"
222         "description.  This group will then modulate several properties of the sound as it is played.\n\n"
223         "For example, one use of groups is to segregate sounds so that volume levels of different sound "
224         "groups such as interface audio and game audio can be controlled independently.\n\n"
225         "@ref SFXSource_hierarchies" );
226      addField( "volume",              TypeF32, Offset( mVolume, SFXDescription ),
227         "Base volume level for the sound.\n\n"
228         "This will be the starting point for volume attenuation on the sound.  The final effective volume of "
229         "a sound will be dependent on a number of parameters.\n\n"
230         "Must be between 0 (mute) and 1 (full volume).  Default is 1.\n\n"
231         "@ref SFXSource_volume" );
232      addField( "pitch",               TypeF32, Offset( mPitch, SFXDescription ),
233         "Pitch shift to apply to playback.\n\n"
234         "The pitch assigned to a sound determines the speed at which it is played back.  A pitch shift of 1 plays the "
235         "sound at its default speed.  A greater shift factor speeds up playback and a smaller shift factor slows it down.\n\n"
236         "Must be >0.  Default is 1." );
237      addField( "isLooping",           TypeBool, Offset( mIsLooping, SFXDescription ),
238         "If true, the sound will be played in an endless loop.\n\n"
239         "Default is false." );
240      addField( "priority",            TypeF32, Offset( mPriority, SFXDescription ),
241         "Priority level for virtualization of sounds (1 = base level).\n"
242         "When there are more concurrently active sounds than supported by the audio mixer, some of the sounds "
243         "need to be culled.  Which sounds are culled first depends primarily on total audibility of individual sounds. "
244         "However, the priority of invidual sounds may be decreased or decreased through this field.\n\n"
245         "@ref SFXSound_virtualization" );
246      addField( "useHardware",         TypeBool, Offset( mUseHardware, SFXDescription ),
247         "Whether the sound is allowed to be mixed in hardware.\n"
248         "If true, the sound system will try to allocate the voice for the sound directly "
249         "on the sound hardware for mixing by the hardware mixer.  Be aware that a hardware mixer "
250         "may not provide all features available to sounds mixed in software.\n\n"
251         "@note This flag currently only takes effect when using FMOD.\n\n"
252         "@note Generally, it is preferable to let sounds be mixed in software.\n\n" );
253      addField( "parameters",          TypeSFXParameterName, Offset( mParameters, SFXDescription ), MaxNumParameters,
254         "Names of the parameters to which sources using this description will automatically be linked.\n\n"
255         "Individual parameters are identified by their #internalName.\n\n"
256         "@ref SFX_interactive" );
257   
258   endGroup( "Playback" );
259   
260   addGroup( "Fading" );
261   
262      addField( "fadeInTime",          TypeF32,    Offset( mFadeInTime, SFXDescription ),
263         "Number of seconds to gradually fade in volume from zero when playback starts.\n"
264         "Must be >= 0.\n\n"
265         "@ref SFXSource_fades" );
266      addField( "fadeOutTime",         TypeF32,    Offset( mFadeOutTime, SFXDescription ),
267         "Number of seconds to gradually fade out volume down to zero when playback is stopped or paused.\n"
268         "Must be >=0.\n\n"
269         "@ref SFXSource_fades" );
270      addField( "fadeInEase",          TypeEaseF,  Offset( mFadeInEase, SFXDescription ),
271         "Easing curve for fade-in transition.\n"
272         "Volume fade-ins will interpolate volume along this curve.\n\n"
273         "@ref SFXSource_fades" );
274      addField( "fadeOutEase",         TypeEaseF,  Offset( mFadeOutEase, SFXDescription ),
275         "Easing curve for fade-out transition.\n"
276         "Volume fade-outs will interpolate volume along this curve.\n\n"
277         "@ref SFXSource_fades" );
278      addField( "fadeLoops",           TypeBool,   Offset( mFadeLoops, SFXDescription ),
279         "Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle.\n"
280         "By default, volume fading is applied to the beginning and end of the playback range, i.e. a fade-in segment "
281         "is placed at the beginning of the sound and a fade-out segment is paced at the end of a sound.  However, "
282         "when looping playback, this may be undesirable as each iteration of the sound will then have a fade-in and "
283         "fade-out effect.\n\n"
284         "To set up looping sounds such that a fade-in is applied only when the sound is first started (or playback resumed) "
285         "and a fade-out is only applied when the sound is explicitly paused or stopped, set this field to true.\n\n"
286         "Default is false.\n\n"
287         "@ref SFXSource_fades" );
288      
289   endGroup( "Fading" );
290
291   addGroup( "3D" );
292   
293      addField( "is3D",                TypeBool,   Offset( mIs3D, SFXDescription ),
294         "If true, sounds played with this description will have a position and orientation in space.\n"
295         "Unlike a non-positional sound, a 3D sound will have its volume attenuated depending on the distance to the "
296         "listener in space.  The farther the sound moves away from the listener, the less audible it will be.\n\n"
297         "Non-positional sounds, in contrast, will remain at their original volume regardless of where the listener is.\n\n"
298         "@note Whether a sound is positional or non-positional cannot be changed once the sound was created so this field "
299            "determines up front which is the case for a given sound.\n\n"
300         "@ref SFX_3d\n"
301         "@ref SFXSource_volume" );
302      addField( "referenceDistance",   TypeF32,    Offset( mMinDistance, SFXDescription ),
303         "Distance at which volume attenuation begins.\n"
304         "Up to this distance, the sound retains its base volume.\n\n"
305         "In the linear distance model, the volume will linearly from this distance onwards up to maxDistance where it "
306         "reaches zero.\n\n"
307         "In the logarithmic distance model, the reference distance determine how fast the sound volume decreases "
308         "with distance.  Each referenceDistance steps (scaled by the rolloff factor), the volume halves.\n\n"
309         "A rule of thumb is that for sounds that require you to be close to hear them in the real world, set the reference "
310         "distance to small values whereas for sounds that are widely audible set it to larger values.\n\n"
311         "Only applies to 3D sounds.\n"
312         "@see LevelInfo::soundDistanceModel\n\n"
313         "@ref SFX_3d\n"
314         "@ref SFXSource_volume" );
315      addField( "maxDistance",         TypeF32,    Offset( mMaxDistance, SFXDescription ),
316         "The distance at which attenuation stops.\n"
317         "In the linear distance model, the attenuated volume will be zero at this distance.\n\n"
318         "In the logarithmic model, attenuation will simply stop at this distance and the sound will keep its attenuated "
319         "volume from there on out.  As such, it primarily functions as a cutoff factor to exponential distance attentuation "
320         "to limit the number of voices relevant to updates.\n\n"
321         "Only applies to 3D sounds.\n"
322         "@see LevelInfo::soundDistanceModel\n\n"
323         "@ref SFX_3d\n"
324         "@ref SFXSource_volume" );
325      addField( "scatterDistance",     TypePoint3F,Offset( mScatterDistance, SFXDescription ),
326         "Bounds on random displacement of 3D sound positions.\n"
327         "When a 3D sound is created and given its initial position in space, this field is used to determine "
328         "the amount of randomization applied to the actual position given to the sound system.\n\n"
329         "The randomization uses the following scheme:"
330         "@verbatim\n"
331         "x += rand( - scatterDistance[ 0 ], scatterDistance[ 0 ] );\n"
332         "y += rand( - scatterDistance[ 1 ], scatterDistance[ 1 ] );\n"
333         "z += rand( - scatterDistance[ 2 ], scatterDistance[ 2 ] );\n"
334         "@endverbatim\n" );
335      addField( "coneInsideAngle",     TypeS32,    Offset( mConeInsideAngle, SFXDescription ),
336         "Inner sound cone angle in degrees.\n"
337         "This value determines the angle of the inner volume cone that protrudes out in the direction "
338         "of a sound.  Within this cone, the sound source retains full volume that is unaffected by sound cone "
339         "settings (though still affected by distance attenuation.)\n\n"
340         "Valid values are from 0 to 360. Must be less than coneOutsideAngle. Default is 360. Only for 3D sounds.\n\n"
341         "@ref SFXSource_cones" );
342      addField( "coneOutsideAngle",    TypeS32,    Offset( mConeOutsideAngle, SFXDescription ),
343         "Outer sound cone angle in degrees.\n"
344         "This value determines the angle of the outer volume cone that protrudes out in the direction of a sound "
345         "and surrounds the inner volume cone.  Within this cone, volume will linearly interpolate from the outer cone "
346         "hull inwards to the inner coner hull starting with the base volume scaled by coneOutsideVolume and ramping "
347         "up/down to the full base volume.\n\n"
348         "Valid values are from 0 to 360.  Must be >= coneInsideAngle.  Default is 360.  Only for 3D sounds.\n\n"
349         "@ref SFXSource_cones" );
350      addField( "coneOutsideVolume",   TypeF32,    Offset( mConeOutsideVolume, SFXDescription ),
351         "Determines the volume scale factor applied the a source's base volume level outside of the outer cone.\n"
352         "In the outer cone, starting from outside the inner cone, the scale factor smoothly interpolates from 1.0 (within the inner cone) "
353         "to this value.  At the moment, the allowed range is 0.0 (silence) to 1.0 (no attenuation) as amplification is only supported on "
354         "XAudio2 but not on the other devices.\n\n"
355         "Only for 3D sound.\n\n"
356         "@ref SFXSource_cones" );
357      addField( "rolloffFactor",       TypeF32,    Offset( mRolloffFactor, SFXDescription ),
358         "Scale factor to apply to logarithmic distance attenuation curve.  If -1, the global rolloff setting is used.\n\n"
359         "@note Per-sound rolloff is only supported on OpenAL and FMOD at the moment.  With other divices, the global rolloff setting "
360            "is used for all sounds.\n"
361         "@see LevelInfo::soundDistanceModel" );
362      
363   endGroup( "3D" );
364
365   addGroup( "Streaming" );
366   
367      addField( "isStreaming",         TypeBool,   Offset( mIsStreaming, SFXDescription ),
368         "If true, incrementally stream sounds; otherwise sounds are loaded in full.\n\n"
369         "@ref SFX_streaming" );
370      addField( "streamPacketSize",    TypeS32,    Offset( mStreamPacketSize, SFXDescription ),
371         "Number of seconds of sample data per single streaming packet.\n"
372         "This field allows to fine-tune streaming for individual sounds.  The streaming system "
373         "processes streamed sounds in batches called packets.  Each packet will contain a set amount "
374         "of sample data determined by this field.  The greater its value, the more sample data each "
375         "packet contains, the more work is done per packet.\n\n"
376         "@note This field only takes effect when Torque's own sound system performs the streaming. "
377            "When FMOD is used, this field is ignored and streaming is performed by FMOD.\n\n"
378         "@ref SFX_streaming" );
379      addField( "streamReadAhead",     TypeS32,    Offset( mStreamReadAhead, SFXDescription ),
380         "Number of sample packets to read and buffer in advance.\n"
381         "This field determines the number of packets that the streaming system will try to keep buffered "
382         "in advance.  As such it determines the number of packets that can be consumed by the sound "
383         "device before the playback queue is running dry.  Greater values thus allow for more lag "
384         "in the streaming pipeline.\n\n"
385         "@note This field only takes effect when Torque's own sound system performs the streaming. "
386            "When FMOD is used, this field is ignored and streaming is performed by FMOD.\n\n"
387         "@ref SFX_streaming" );
388         
389   endGroup( "Streaming" );
390
391   addGroup( "Reverb" );
392   
393   addField("useCustomReverb", TypeBool, Offset(mUseReverb, SFXDescription),
394      "If true, use the reverb properties defined here on sounds.\n"
395      "By default, sounds will be assigned a generic reverb profile.  By setting this flag to true, "
396      "a custom reverb setup can be defined using the \"Reverb\" properties that will then be assigned "
397      "to sounds playing with the description.\n\n"
398      "@ref SFX_reverb");
399   addField("reverbDensity", TypeF32, Offset(mReverb.flDensity, SFXDescription),
400      "Density of reverb environment.");
401   addField("reverbDiffusion", TypeF32, Offset(mReverb.flDiffusion, SFXDescription),
402      "Environment diffusion.");
403   addField("reverbGain", TypeF32, Offset(mReverb.flGain, SFXDescription),
404      "Reverb Gain Level.");
405   addField("reverbGainHF", TypeF32, Offset(mReverb.flGainHF, SFXDescription),
406      "Reverb Gain to high frequencies");
407   addField("reverbGainLF", TypeF32, Offset(mReverb.flGainLF, SFXDescription),
408      "Reverb Gain to high frequencies");
409   addField("reverbDecayTime", TypeF32, Offset(mReverb.flDecayTime, SFXDescription),
410      "Decay time for the reverb.");
411   addField("reverbDecayHFRatio", TypeF32, Offset(mReverb.flDecayHFRatio, SFXDescription),
412      "High frequency decay time ratio.");
413   addField("reverbDecayLFRatio", TypeF32, Offset(mReverb.flDecayLFRatio, SFXDescription),
414      "High frequency decay time ratio.");
415   addField("reflectionsGain", TypeF32, Offset(mReverb.flReflectionsGain, SFXDescription),
416      "Reflection Gain.");
417   addField("reflectionDelay", TypeF32, Offset(mReverb.flReflectionsDelay, SFXDescription),
418      "How long to delay reflections.");
419   addField("lateReverbGain", TypeF32, Offset(mReverb.flLateReverbGain, SFXDescription),
420      "Late reverb gain amount.");
421   addField("lateReverbDelay", TypeF32, Offset(mReverb.flLateReverbDelay, SFXDescription),
422      "Late reverb delay time.");
423   addField("reverbEchoTime", TypeF32, Offset(mReverb.flEchoTime, SFXDescription),
424      "Reverb echo time.");
425   addField("reverbEchoDepth", TypeF32, Offset(mReverb.flEchoDepth, SFXDescription),
426      "Reverb echo depth.");
427   addField("reverbModTime", TypeF32, Offset(mReverb.flModulationTime, SFXDescription),
428      "Reverb Modulation time.");
429   addField("reverbModDepth", TypeF32, Offset(mReverb.flModulationDepth, SFXDescription),
430      "Reverb Modulation Depth.");
431   addField("airAbsorbtionGainHF", TypeF32, Offset(mReverb.flAirAbsorptionGainHF, SFXDescription),
432      "High Frequency air absorbtion");
433   addField("reverbHFRef", TypeF32, Offset(mReverb.flHFReference, SFXDescription),
434      "Reverb High Frequency Reference.");
435   addField("reverbLFRef", TypeF32, Offset(mReverb.flLFReference, SFXDescription),
436      "Reverb Low Frequency Reference.");
437   addField("roomRolloffFactor", TypeF32, Offset(mReverb.flRoomRolloffFactor, SFXDescription),
438      "Rolloff factor for reverb.");
439   addField("decayHFLimit", TypeS32, Offset(mReverb.iDecayHFLimit, SFXDescription),
440      "High Frequency decay limit.");
441   endGroup("Reverb");
442   
443   Parent::initPersistFields();
444}
445
446//-----------------------------------------------------------------------------
447
448bool SFXDescription::onAdd()
449{
450   if ( !Parent::onAdd() )
451      return false;
452      
453   Sim::getSFXDescriptionSet()->addObject( this );
454   
455   // Convert a legacy 'channel' field, if we have one.
456   
457   static const char* sChannel = StringTable->insert( "channel" );
458   const char* channelValue = getDataField( sChannel, NULL );
459   if( channelValue && channelValue[ 0 ] )
460   {
461      const char* group = Con::evaluatef( "return sfxOldChannelToGroup( %s );", channelValue );
462      if( !Sim::findObject( group, mSourceGroup ) )
463         Con::errorf( "SFXDescription::onAdd - could not resolve channel '%s' to SFXSource", channelValue );
464   }
465   
466   // Validate the data we'll be passing to 
467   // the audio layer.
468   validate();
469
470   return true;
471}
472
473//-----------------------------------------------------------------------------
474
475void SFXDescription::validate()
476{
477   // Validate the data we'll be passing to the audio layer.
478   mVolume = mClampF( mVolume, 0, 1 );
479   
480   if( mPitch <= 0.0f )
481      mPitch = 1.0f;
482   if( mFadeInTime < 0.0f )
483      mFadeInTime = 0.0f;
484   if( mFadeOutTime < 0.0f )
485      mFadeOutTime = 0.0f;
486   if( mRolloffFactor < 0.f )
487      mRolloffFactor = -1.f;
488
489   if( mMinDistance < 0.f )
490      mMinDistance = 0.f;
491   if( mMaxDistance <= mMinDistance )
492      mMaxDistance = mMinDistance + 0.01f;
493
494   mConeInsideAngle     = mClamp( mConeInsideAngle, 0, 360 );
495   mConeOutsideAngle    = mClamp( mConeOutsideAngle, mConeInsideAngle, 360 );
496   mConeOutsideVolume   = mClampF( mConeOutsideVolume, 0, 1 );
497   
498   if( !mIs3D )
499      mUseReverb = false;
500   
501   mReverb.validate();
502}
503
504//-----------------------------------------------------------------------------
505
506void SFXDescription::packData( BitStream *stream )
507{
508   Parent::packData( stream );
509
510   stream->writeFloat( mVolume, 6 );
511   stream->write( mPitch );
512   stream->write( mPriority );
513
514   stream->writeFlag( mIsLooping );
515   stream->writeFlag( mFadeLoops );
516
517   stream->writeFlag( mIsStreaming );
518   stream->writeFlag( mIs3D );
519   stream->writeFlag( mUseReverb );
520   stream->writeFlag( mUseHardware );
521   
522   sfxWrite( stream, mSourceGroup );
523
524   if( mIs3D )
525   {
526      stream->write( mMinDistance );
527      stream->write( mMaxDistance );
528      stream->write( mRolloffFactor );
529      mathWrite( *stream, mScatterDistance );
530
531      stream->writeInt( mConeInsideAngle, 9 );
532      stream->writeInt( mConeOutsideAngle, 9 );
533
534      stream->writeFloat( mConeOutsideVolume, 6 );
535      
536      if( mUseReverb )
537      {
538         stream->write(mReverb.flDensity);
539         stream->write(mReverb.flDiffusion);
540         stream->write(mReverb.flGain);
541         stream->write(mReverb.flGainHF);
542         stream->write(mReverb.flGainLF);
543         stream->write(mReverb.flDecayTime);
544         stream->write(mReverb.flDecayHFRatio);
545         stream->write(mReverb.flDecayLFRatio);
546         stream->write(mReverb.flReflectionsGain);
547         stream->write(mReverb.flReflectionsDelay);
548         stream->write(mReverb.flLateReverbGain);
549         stream->write(mReverb.flLateReverbDelay);
550         stream->write(mReverb.flEchoTime);
551         stream->write(mReverb.flEchoDepth);
552         stream->write(mReverb.flModulationTime);
553         stream->write(mReverb.flModulationDepth);
554         stream->write(mReverb.flAirAbsorptionGainHF);
555         stream->write(mReverb.flHFReference);
556         stream->write(mReverb.flLFReference);
557         stream->write(mReverb.flRoomRolloffFactor);
558         stream->write(mReverb.iDecayHFLimit);
559      }
560   }
561
562   stream->write( mFadeInTime );
563   stream->write( mFadeOutTime );
564   stream->writeInt( mStreamPacketSize, 8 );
565   stream->writeInt( mStreamReadAhead, 8 );
566   
567   mathWrite( *stream, mFadeInEase );
568   mathWrite( *stream, mFadeOutEase );
569   
570   for( U32 i = 0; i < MaxNumParameters; ++ i )
571      if( stream->writeFlag( mParameters[ i ] ) )
572         stream->writeString( mParameters[ i ] );
573}
574
575//-----------------------------------------------------------------------------
576
577void SFXDescription::unpackData( BitStream *stream )
578{
579   Parent::unpackData( stream );
580
581   mVolume        = stream->readFloat( 6 );
582   stream->read( &mPitch );
583   stream->read( &mPriority );
584
585   mIsLooping     = stream->readFlag();
586   mFadeLoops     = stream->readFlag();
587
588   mIsStreaming   = stream->readFlag();
589   mIs3D          = stream->readFlag();
590   mUseReverb     = stream->readFlag();
591   mUseHardware   = stream->readFlag();
592   
593   String errorStr;
594   if( !sfxReadAndResolve( stream, &mSourceGroup, errorStr ) )
595      Con::errorf( "SFXDescription::unpackData: %s", errorStr.c_str() );
596
597   if( mIs3D )
598   {
599      stream->read( &mMinDistance );
600      stream->read( &mMaxDistance );
601      stream->read( &mRolloffFactor );
602      mathRead( *stream, &mScatterDistance );
603
604      mConeInsideAngle     = stream->readInt( 9 );
605      mConeOutsideAngle    = stream->readInt( 9 );
606
607      mConeOutsideVolume   = stream->readFloat( 6 );
608      
609      if( mUseReverb )
610      {
611         stream->read(&mReverb.flDensity);
612         stream->read(&mReverb.flDiffusion);
613         stream->read(&mReverb.flGain);
614         stream->read(&mReverb.flGainHF);
615         stream->read(&mReverb.flGainLF);
616         stream->read(&mReverb.flDecayTime);
617         stream->read(&mReverb.flDecayHFRatio);
618         stream->read(&mReverb.flDecayLFRatio);
619         stream->read(&mReverb.flReflectionsGain);
620         stream->read(&mReverb.flReflectionsDelay);
621         stream->read(&mReverb.flLateReverbGain);
622         stream->read(&mReverb.flLateReverbDelay);
623         stream->read(&mReverb.flEchoTime);
624         stream->read(&mReverb.flEchoDepth);
625         stream->read(&mReverb.flModulationTime);
626         stream->read(&mReverb.flModulationDepth);
627         stream->read(&mReverb.flAirAbsorptionGainHF);
628         stream->read(&mReverb.flHFReference);
629         stream->read(&mReverb.flLFReference);
630         stream->read(&mReverb.flRoomRolloffFactor);
631         stream->read(&mReverb.iDecayHFLimit);
632      }
633   }
634
635   stream->read( &mFadeInTime );
636   stream->read( &mFadeOutTime );
637   mStreamPacketSize = stream->readInt( 8 );
638   mStreamReadAhead = stream->readInt( 8 );
639   
640   mathRead( *stream, &mFadeInEase );
641   mathRead( *stream, &mFadeOutEase );
642   
643   for( U32 i = 0; i < MaxNumParameters; ++ i )
644      if( stream->readFlag() )
645         mParameters[ i ] = stream->readSTString();
646      else
647         mParameters[ i ] = NULL;
648}
649
650//-----------------------------------------------------------------------------
651
652void SFXDescription::inspectPostApply()
653{
654   Parent::inspectPostApply();
655   
656   validate();
657   
658   if( SFX )
659      SFX->notifyDescriptionChanged( this );
660}
661// This allows legacy AudioDescription datablocks to be recognized as an alias
662// for SFXDescription. It is intended to ease the transition from older scripts
663// especially those that still need to support pre-1.7 applications.
664// (This maybe removed in future releases so treat as deprecated.)
665class AudioDescription : public SFXDescription
666{
667   typedef SFXDescription Parent;
668public:
669   DECLARE_CONOBJECT(AudioDescription);
670};
671
672IMPLEMENT_CO_DATABLOCK_V1(AudioDescription);
673
674ConsoleDocClass( AudioDescription,
675   "@brief Allows legacy AudioDescription datablocks to be treated as SFXDescription datablocks.\n\n"
676
677   "@ingroup afxMisc\n"
678   "@ingroup AFX\n"
679   "@ingroup Datablocks\n"
680);
681
682