| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program 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.
- **
- ** This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : WWAudio *
- * *
- * $Archive:: /Commando/Code/WWAudio/AudibleSound.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 12/14/01 11:20a $*
- * *
- * $Revision:: 35 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "audiblesound.h"
- #include "wwaudio.h"
- #include "ww3d.h"
- #include "wwdebug.h"
- #include "soundbuffer.h"
- #include "utils.h"
- #include "soundscene.h"
- #include "filteredsound.h"
- #include "threads.h"
- #include "soundchunkids.h"
- #include "simpledefinitionfactory.h"
- #include "persistfactory.h"
- #include "logicalsound.h"
- #include "definitionclassids.h"
- #include "soundstreamhandle.h"
- #include "sound2dhandle.h"
- #include "systimer.h"
- //////////////////////////////////////////////////////////////////////////////////
- // Static factories
- //////////////////////////////////////////////////////////////////////////////////
- DECLARE_DEFINITION_FACTORY(AudibleSoundDefinitionClass, CLASSID_SOUND_DEF, "Sound") _SoundDefFactory;
- SimplePersistFactoryClass<AudibleSoundDefinitionClass, CHUNKID_SOUND_DEF> _AudibleSoundDefPersistFactory;
- SimplePersistFactoryClass<AudibleSoundClass, CHUNKID_AUDIBLE_SOUND> _AudibleSoundPersistFactory;
- //////////////////////////////////////////////////////////////////////////////////
- // Save/Load constants
- //////////////////////////////////////////////////////////////////////////////////
- namespace AUDIBLE_SOUND_SAVELOAD
- {
- enum
- {
- CHUNKID_VARIABLES = 0x00000100,
- CHUNKID_BASE_CLASS
- };
- enum
- {
- VARID_STATE = 0x01,
- VARID_TYPE,
- VARID_PRIORITY,
- VARID_VOLUME,
- VARID_PAN,
- VARID_LOOP_COUNT,
- VARID_LOOPS_LEFT,
- VARID_SOUND_LENGTH,
- VARID_CURR_POS,
- VARID_TRANSFORM,
- VARID_PREV_TRANSFORM,
- VARID_IS_CULLED,
- VARID_IS_DIRTY,
- VARID_DROP_OFF,
- VARID_FILENAME,
- VARID_THIS_PTR,
- VARID_START_OFFSET,
- VARID_LISTENER_TRANSFORM,
- VARID_PITCH_FACTOR,
- VARID_PITCH_FACTOR_RND,
- VARID_VOLUME_RND,
- VARID_VIRTUAL_CHANNEL
- };
- }
- namespace AUDIBLE_SOUND_DEF_SAVELOAD
- {
- enum
- {
- CHUNKID_VARIABLES = 0x00000100,
- CHUNKID_BASE_CLASS = 0x00000200,
- };
- enum
- {
- VARID_UNUSED1 = 0x01,
- VARID_UNUSED2,
- VARID_PRIORITY,
- VARID_VOLUME,
- VARID_PAN,
- VARID_LOOP_COUNT,
- VARID_DROP_OFF,
- VARID_MAX_VOL,
- VARID_TYPE,
- VARID_IS3D,
- VARID_FILENAME,
- VARID_DISPLAY_TEXT,
- VARID_LOGICAL_MASK,
- VARID_LOGICAL_DELAY,
- VARID_CREATE_LOGICAL,
- VARID_LOGICAL_DROP_OFF,
- VARID_SPHERE_COLOR,
- VARID_START_OFFSET,
- VARID_PITCH_FACTOR,
- VARID_PITCH_FACTOR_RND,
- VARID_VOLUME_RND,
- VARID_VIRTUAL_CHANNEL
- };
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // AudibleSoundClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- AudibleSoundClass::AudibleSoundClass (void)
- : m_Priority (0.5F),
- m_RuntimePriority (0),
- m_SoundHandle (NULL),
- m_Length (0),
- m_CurrentPosition (0),
- m_Timestamp (0),
- m_State (STATE_STOPPED),
- m_Buffer (NULL),
- m_Volume (1.0F),
- m_RealVolume (1.0F),
- m_Pan (0.5F),
- m_LoopCount (1),
- m_LoopsLeft (0),
- m_Type (TYPE_SOUND_EFFECT),
- m_FadeType (FADE_NONE),
- m_FadeTimer (0),
- m_FadeTime (0),
- m_VirtualChannel (0),
- m_bDirty (true),
- m_DropOffRadius (1),
- m_IsCulled (true),
- m_pConvertedFormat (NULL),
- m_PrevTransform (1),
- m_Transform (1),
- m_ListenerTransform (1),
- m_Definition (NULL),
- m_LogicalSound (NULL),
- m_StartOffset (0),
- m_PitchFactor (1.0F)
- {
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // AudibleSoundClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- AudibleSoundClass::AudibleSoundClass (const AudibleSoundClass &src)
- : m_Priority (0.5F),
- m_RuntimePriority (0),
- m_SoundHandle (NULL),
- m_Length (0),
- m_CurrentPosition (0),
- m_Timestamp (0),
- m_State (STATE_STOPPED),
- m_Buffer (NULL),
- m_Volume (1.0F),
- m_RealVolume (1.0F),
- m_Pan (0.5F),
- m_LoopCount (1),
- m_LoopsLeft (0),
- m_Type (TYPE_SOUND_EFFECT),
- m_FadeType (FADE_NONE),
- m_FadeTimer (0),
- m_FadeTime (0),
- m_VirtualChannel (0),
- m_bDirty (true),
- m_DropOffRadius (1),
- m_IsCulled (true),
- m_pConvertedFormat (NULL),
- m_PrevTransform (1),
- m_Transform (1),
- m_Definition (NULL),
- m_LogicalSound (NULL),
- m_StartOffset (0),
- m_PitchFactor (1.0F)
- {
- (*this) = src;
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // ~AudibleSoundClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- AudibleSoundClass::~AudibleSoundClass (void)
- {
- m_State = STATE_STOPPED;
- Free_Conversion ();
- REF_PTR_RELEASE (m_LogicalSound);
- //
- // Delay the release of the buffer (fixes a sync bug
- // with Miles internals).
- //
- if (m_Buffer != NULL) {
- WWAudioThreadsClass::Add_Delayed_Release_Object (m_Buffer);
- //REF_PTR_RELEASE (m_Buffer);
- m_Buffer = NULL;
- }
- Free_Miles_Handle ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // operator=
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- const AudibleSoundClass &
- AudibleSoundClass::operator= (const AudibleSoundClass &src)
- {
- m_Timestamp = src.m_Timestamp;
- m_Type = src.m_Type;
- m_FadeType = src.m_FadeType;
- m_FadeTimer = src.m_FadeTimer;
- m_FadeTime = src.m_FadeTime;
- m_VirtualChannel = src.m_VirtualChannel;
- m_LoopCount = src.m_LoopCount;
- m_LoopsLeft = src.m_LoopsLeft;
- m_Length = src.m_Length;
- m_CurrentPosition = src.m_CurrentPosition;
- m_bDirty = src.m_bDirty;
- m_DropOffRadius = src.m_DropOffRadius;
- m_PrevTransform = src.m_PrevTransform;
- m_RealVolume = src.m_RealVolume;
- m_State = STATE_STOPPED;
- Set_Buffer (src.m_Buffer);
- m_State = src.m_State;
- Cull_Sound (src.m_IsCulled);
- Set_Volume (src.m_RealVolume);
- Set_Pan (src.m_Pan);
- Set_Priority (src.m_Priority);
- Set_Transform (src.m_Transform);
- Set_Listener_Transform (src.m_ListenerTransform);
- return (*this);
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Buffer
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Buffer (SoundBufferClass *buffer)
- {
- //
- // Delay the release of the buffer (fixes a sync bug
- // with Miles internals).
- //
- if (m_Buffer != NULL) {
- WWAudioThreadsClass::Add_Delayed_Release_Object (m_Buffer);
- //REF_PTR_RELEASE (m_Buffer);
- m_Buffer = NULL;
- }
- REF_PTR_SET (m_Buffer, buffer);
- // Stop playing if necessary
- bool resume = false;
- if (m_State == STATE_PLAYING) {
- resume = Stop (false);
- }
- // Get the time (in ms) that this buffer will play for...
- if (m_Buffer != NULL) {
- m_Length = m_Buffer->Get_Duration ();
- }
- // Reinitialize the handle with this new data
- Initialize_Miles_Handle ();
- // Resume playing if necessary
- if (resume) {
- Play ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Buffer
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- SoundBufferClass *
- AudibleSoundClass::Get_Buffer (void) const
- {
- if (m_Buffer) {
- m_Buffer->Add_Ref ();
- }
- return m_Buffer;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Peek_Buffer
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- SoundBufferClass *
- AudibleSoundClass::Peek_Buffer (void) const
- {
- return m_Buffer;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Update_Fade
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Update_Fade (void)
- {
- m_FadeTimer -= WW3D::Get_Frame_Time ();
- m_FadeTimer = max (m_FadeTimer, 0);
- //
- // Determine what percent we should ramp up or down to...
- //
- float percent = ((float)m_FadeTimer / (float)m_FadeTime);
- percent = WWMath::Clamp (percent, 0.0F, 1.0F);
- //
- // Invert the percent if we're fading in
- //
- if (m_FadeType == FADE_IN) {
- percent = 1.0F - percent;
- }
- //
- // Re-adjust the music and sound effect volumes
- //
- Internal_Set_Volume (m_RealVolume * percent);
- //
- // Reset the state as necessary
- //
- if (m_FadeTimer == 0) {
- //
- // Stop the sound when its done fading out
- //
- if (m_FadeType == FADE_OUT) {
- Stop ();
- }
- m_FadeType = FADE_NONE;
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Fade_Out
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Fade_Out (int time_in_ms)
- {
- m_FadeTime = time_in_ms;
- m_FadeTimer = time_in_ms;
- m_FadeType = FADE_OUT;
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Fade_In
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Fade_In (int time_in_ms)
- {
- m_FadeTime = time_in_ms;
- m_FadeTimer = time_in_ms;
- m_FadeType = FADE_IN;
- //
- // Turn off the volume
- //
- Internal_Set_Volume (0.0F);
- //
- // Start the sample playing
- //
- Play ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Verify_Playability
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Verify_Playability (void)
- {
- bool retval = true;
- if (m_VirtualChannel != 0) {
- retval = WWAudioClass::Get_Instance ()->Acquire_Virtual_Channel (this, m_VirtualChannel);
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Play
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Play (bool alloc_handle)
- {
- MMSLockClass lock;
- //
- // Check to ensure this sound should really be playing...
- //
- if (Verify_Playability () == false) {
- return false;
- }
- //
- // If we don't have a valid handle already, try to get one from miles
- //
- if (alloc_handle && (m_pConvertedFormat == NULL)) {
- Allocate_Miles_Handle ();
- }
- //
- // Is the sound already playing?
- //
- if (m_State != STATE_PLAYING) {
- //
- // Let the audio system know this sound is playing
- //
- WWAudioClass::Get_Instance ()->Add_To_Playlist (this);
- m_State = STATE_PLAYING;
- m_Timestamp = TIMEGETTIME ();
- m_LoopsLeft = m_LoopCount;
- // If we have a valid handle, then start playing the sample
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Start_Sample ();
- }
- m_CurrentPosition = m_StartOffset * m_Length;
- if (m_CurrentPosition > 0) {
- Seek (m_CurrentPosition);
- }
- // Fire an event
- On_Event (AudioCallbackClass::EVENT_SOUND_STARTED);
- //
- // Create the associate logical sound (if necessary)
- //
- if (m_LogicalSound == NULL && m_Definition != NULL) {
- m_LogicalSound = m_Definition->Create_Logical ();
- }
- //
- // Add this logical sound to the scene
- //
- if (m_LogicalSound != NULL) {
- m_LogicalSound->Set_User_Data (m_UserObj, m_UserData);
- m_LogicalSound->Set_Transform (m_Transform);
- m_LogicalSound->Add_To_Scene ();
- }
- //
- // Should we send off the text notification?
- //
- if (m_IsCulled == false && m_Definition != NULL) {
- const StringClass &text = m_Definition->Get_Display_Text ();
- WWAudioClass::Get_Instance ()->Fire_Text_Callback (this, text);
- }
- }
- return true;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Pause
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Pause (void)
- {
- MMSLockClass lock;
- bool retval = false;
- if (m_State == STATE_PLAYING) {
- //
- // Update our current position so we can resume at the correct
- // location
- //
- m_CurrentPosition = TIMEGETTIME () - m_Timestamp;
- //
- // Get rid of our play-handle (this will stop the sound)
- //
- Free_Miles_Handle ();
- //
- // Remember our new state
- //
- m_State = STATE_PAUSED;
- retval = true;
- }
- // Return the true/false result code
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Resume
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Resume (void)
- {
- MMSLockClass lock;
- bool retval = false;
- if (m_State == STATE_PAUSED) {
- //
- // Re-sync our timestamp
- //
- m_Timestamp = TIMEGETTIME () - m_CurrentPosition;
- //
- // Ensure we have a play handle...
- //
- Allocate_Miles_Handle ();
- //
- // If we have a valid handle, then start playing the sample
- //
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Start_Sample ();
- }
- //
- // Re-seek to the correct position in the sound
- //
- if (m_CurrentPosition > 0) {
- Seek (m_CurrentPosition);
- }
- //
- // Remember our new state
- //
- m_State = STATE_PLAYING;
- retval = true;
- }
- // Return the true/false result code
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Stop
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Stop (bool remove_from_playlist)
- {
- MMSLockClass lock;
- // Assume failure
- bool retval = false;
- if ((m_State == STATE_PAUSED) ||
- (m_State == STATE_PLAYING))
- {
- //
- // Actually stop the sample from playing
- //
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Stop_Sample ();
- }
- //
- // Free up the handle we have been using
- //
- Free_Miles_Handle ();
- m_State = STATE_STOPPED;
- retval = true;
- //
- // Reset some of the playing attributes
- //
- m_Timestamp = 0;
- m_CurrentPosition = 0;
- //
- // Remove the sound from the current playlist
- //
- if (remove_from_playlist) {
- WWAudioClass::Get_Instance ()->Remove_From_Playlist (this);
- }
- //
- // Release the virtual channel as necessary
- //
- if (m_VirtualChannel > 0) {
- WWAudioClass::Get_Instance ()->Release_Virtual_Channel (this, m_VirtualChannel);
- }
- //
- // Stop the logical portion of the sound
- //
- if (m_LogicalSound != NULL && m_LogicalSound->Is_Single_Shot () == false) {
- m_LogicalSound->Remove_From_Scene ();
- }
- }
- // Return the true/false result code
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Seek
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Seek (unsigned long milliseconds)
- {
- MMSLockClass lock;
- if ((milliseconds >= 0) && (milliseconds < m_Length)) {
- // Record our new position and recalculate the 'starting' timestamp
- // from this information
- m_CurrentPosition = milliseconds;
- if (m_State == STATE_PLAYING) {
- m_Timestamp = TIMEGETTIME () - m_CurrentPosition;
- }
- // Update the actual sound data if we are playing the sound
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Set_Sample_MS_Position (m_CurrentPosition);
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Miles_Handle
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Miles_Handle (MILES_HANDLE handle)
- {
- //
- // Start fresh
- //
- Free_Miles_Handle ();
- //
- // Is our data valid?
- //
- if (handle != INVALID_MILES_HANDLE && m_Buffer != NULL) {
- //
- // Determine which type of sound handle to create, streaming or standard 2D
- //
- if (m_Buffer->Is_Streaming ()) {
- m_SoundHandle = new SoundStreamHandleClass;
- } else {
- m_SoundHandle = new Sound2DHandleClass;
- }
- //
- // Configure the sound handle
- //
- m_SoundHandle->Set_Miles_Handle (handle);
- //
- // Use this new handle
- //
- Initialize_Miles_Handle ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Initialize_Miles_Handle
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Initialize_Miles_Handle (void)
- {
- MMSLockClass lock;
- // If this sound is already playing, then update its
- // playing position to make sure we really should
- // be playing it... (it will free the miles handle if not)
- if (m_State == STATE_PLAYING) {
- Update_Play_Position ();
- }
- // Do we have a valid sample handle from miles?
- if (m_SoundHandle != NULL) {
- //
- // Initialize the handle
- //
- m_SoundHandle->Initialize (m_Buffer);
- //
- // Record the total length of the sample in milliseconds...
- //
- m_SoundHandle->Get_Sample_MS_Position ((S32 *)&m_Length, NULL);
- //
- // Pass our cached settings onto miles
- //
- m_SoundHandle->Set_Sample_Volume (0);
- m_SoundHandle->Set_Sample_Pan (int(m_Pan * 127.0F));
- m_SoundHandle->Set_Sample_Loop_Count (m_LoopCount);
- //
- // Apply the pitch factor (if necessary)
- //
- if (m_PitchFactor != 1.0F) {
- Set_Pitch_Factor (m_PitchFactor);
- }
- // If this sound is already playing (and just now got a handle)
- // then make sure we start it.
- if (m_State == STATE_PLAYING) {
- m_SoundHandle->Start_Sample ();
- // Update the loop count based on the number of loops left
- m_SoundHandle->Set_Sample_Loop_Count (m_LoopsLeft);
- }
- // Seek to the position of the sound where we last left off.
- // For example, this sound could have gotten bumped due to a low priority,
- // but is now back and ready to resume at the position it would have been
- // at if it was never bumped.
- Seek (m_CurrentPosition);
- //
- // Pass the 'real' volume onto miles
- //
- float real_volume = Determine_Real_Volume ();
- m_SoundHandle->Set_Sample_Volume (int(real_volume * 127.0F));
- //
- // Associate this object instance with the handle
- //
- m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, (S32)this);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Free_Miles_Handle
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Free_Miles_Handle (void)
- {
- MMSLockClass lock;
- // Do we have a valid sample handle from miles?
- if (m_SoundHandle != NULL) {
- //
- // Release our hold on this handle
- //
- m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, NULL);
- m_SoundHandle->End_Sample ();
- //
- // Remove the association between file handle and AudibleSoundClass object
- //
- //m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, NULL);
- //
- // Free the sound handle object
- //
- delete m_SoundHandle;
- m_SoundHandle = NULL;
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Pan
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- float
- AudibleSoundClass::Get_Pan (void)
- {
- MMSLockClass lock;
- //
- // Do we have a valid sample handle from miles?
- //
- if (m_SoundHandle != NULL) {
- m_Pan = ((float)m_SoundHandle->Get_Sample_Pan ()) / 127.0F;
- }
- return m_Pan;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Pan
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Pan (float pan)
- {
- MMSLockClass lock;
- //
- // Cache the normalized pan value
- //
- m_Pan = min (pan, 1.0F);
- m_Pan = max (m_Pan, 0.0F);
- //
- // Do we have a valid sample handle from miles?
- //
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Set_Sample_Pan (int(m_Pan * 127.0F));
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Pitch_Factor
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Pitch_Factor (float factor)
- {
- MMSLockClass lock;
- m_PitchFactor = factor;
- //
- // Do we have a valid sample handle from miles?
- //
- if (m_SoundHandle != NULL) {
- if (m_Buffer != NULL) {
- //
- // Get the base rate of the sound and scale our playback rate
- // based on the factor
- //
- int base_rate = m_Buffer->Get_Rate ();
- int new_rate = base_rate * m_PitchFactor;
- m_SoundHandle->Set_Sample_Playback_Rate (new_rate);
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Playback_Rate
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- int
- AudibleSoundClass::Get_Playback_Rate (void)
- {
- MMSLockClass lock;
- int retval = 0;
- // Do we have a valid sample handle from miles?
- if (m_SoundHandle != NULL) {
- retval = m_SoundHandle->Get_Sample_Playback_Rate ();
- }
- return retval;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Playback_Rate
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Playback_Rate (int rate_in_hz)
- {
- MMSLockClass lock;
- // Do we have a valid sample handle from miles?
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Set_Sample_Playback_Rate (rate_in_hz);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Volume
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- float
- AudibleSoundClass::Get_Volume (void)
- {
- MMSLockClass lock;
- // Do we have a valid sample handle from miles?
- if (m_SoundHandle != NULL) {
- m_Volume = ((float)m_SoundHandle->Get_Sample_Volume ()) / 127.0F;
- }
- // Return the current pan value
- return m_Volume;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Internal_Set_Volume
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Internal_Set_Volume (float volume)
- {
- MMSLockClass lock;
- //
- // Cache the normalized volume value
- //
- m_Volume = min (volume, 1.0F);
- m_Volume = max (m_Volume, 0.0F);
- //
- // Do we have a valid sample handle from miles?
- //
- if (m_SoundHandle != NULL) {
- //
- // Calculate the 'real' volume to set based on the global volume and the sound
- // effect volume.
- //
- float real_volume = Determine_Real_Volume ();
- m_SoundHandle->Set_Sample_Volume (int(real_volume * 127.0F));
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Volume
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Volume (float volume)
- {
- MMSLockClass lock;
- //
- // Cache the normalized volume value
- //
- m_RealVolume = min (volume, 1.0F);
- m_RealVolume = max (m_RealVolume, 0.0F);
- //
- // Update the volume
- //
- Internal_Set_Volume (m_RealVolume);
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Loops_Left
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- int
- AudibleSoundClass::Get_Loops_Left (void) const
- {
- return m_LoopsLeft;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Loop_Count
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Loop_Count (int count)
- {
- MMSLockClass lock;
- // Cache the loop count
- m_LoopCount = count;
- // Do we have a valid sample handle from miles?
- if (m_SoundHandle != NULL) {
- m_SoundHandle->Set_Sample_Loop_Count (m_LoopCount);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Priority
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Priority (float priority)
- {
- MMSLockClass lock;
- // Cache the normalized priority
- m_Priority = min (priority, 1.0F);
- m_Priority = max (m_Priority, 0.0F);
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // On_Frame_Update
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::On_Frame_Update (unsigned int milliseconds)
- {
- //
- // Do we need to track this sound's play-progress?
- //
- if ((m_LoopCount != INFINITE_LOOPS) &&
- (m_State == STATE_PLAYING) &&
- (m_Length > 0))
- {
- Update_Play_Position ();
- }
- //
- // Update the fade as necessary
- //
- if (m_FadeType != FADE_NONE) {
- Update_Fade ();
- }
- if (m_pConvertedFormat != NULL) {
- m_pConvertedFormat->Re_Sync (*this);
- }
- //
- // Move the logical sound with the audible one...
- //
- if (m_LogicalSound != NULL) {
- m_LogicalSound->Set_Transform (m_Transform);
- }
- return true;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Update_Play_Position
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Update_Play_Position (void)
- {
- // Determine the current offset from the beginning of the sound buffer.
- unsigned long play_time = TIMEGETTIME () - m_Timestamp;
- m_CurrentPosition = play_time;
- // Have we gone past the end of a sounds play-time?
- if ((m_CurrentPosition > m_Length) && (m_Length > 0)) {
- // Normalize our position and timestamp information
- m_CurrentPosition = m_CurrentPosition % m_Length;
- m_Timestamp = TIMEGETTIME () - m_CurrentPosition;
- // Decrement our count of remaining loops (if necessary)
- if (m_LoopCount != INFINITE_LOOPS) {
- m_LoopsLeft -= (play_time / m_Length);
- }
- // Trigger the 'end loop' event
- On_Loop_End ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Allocate_Miles_Handle
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Allocate_Miles_Handle (void)
- {
- //
- // If we need to, get a play-handle from the audio system
- //
- if (m_SoundHandle == NULL) {
- Set_Miles_Handle ((MILES_HANDLE)WWAudioClass::Get_Instance ()->Get_2D_Sample (*this));
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // On_Loop_End
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::On_Loop_End (void)
- {
- // Determine if the sound is actually finished or still looping
- if ((m_LoopCount != INFINITE_LOOPS) && (m_LoopsLeft < 1)) {
- // Let the audio system know that we are done with this sound
- Stop ();
- if (m_Scene != NULL) {
- Remove_From_Scene ();
- }
- // Fire an event
- On_Event (AudioCallbackClass::EVENT_SOUND_ENDED);
- } else {
- Restart_Loop ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Determine_Real_Volume
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- float
- AudibleSoundClass::Determine_Real_Volume (void) const
- {
- float volume = m_Volume;
- // Is this a piece of music or is it a sound effect?
- if (m_Type == TYPE_MUSIC) {
- volume = volume * WWAudioClass::Get_Instance ()->Get_Music_Volume ();
- } else if (m_Type == TYPE_SOUND_EFFECT) {
- volume = volume * WWAudioClass::Get_Instance ()->Get_Sound_Effects_Volume ();
- } else if (m_Type == TYPE_DIALOG) {
- volume = volume * WWAudioClass::Get_Instance ()->Get_Dialog_Volume ();
- } else if (m_Type == TYPE_CINEMATIC) {
- volume = volume * WWAudioClass::Get_Instance ()->Get_Cinematic_Volume ();
- }
- // Return the 'real' volume
- return volume;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Filename
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- LPCTSTR
- AudibleSoundClass::Get_Filename (void) const
- {
- LPCTSTR filename = NULL;
- if (m_Buffer != NULL) {
- filename = m_Buffer->Get_Filename ();
- }
- return filename;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Cull_Sound
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Cull_Sound (bool culled)
- {
- // Is our state changing?
- if (m_IsCulled != culled) {
- m_IsCulled = culled;
- //
- // If this sound is culled, then throw away its play-handle.
- // Otherwise, make sure we have a valid handle.
- //
- // Note: We also free the handle if a converted form
- // of the sound is currently playing.
- //
- if (m_IsCulled || (m_pConvertedFormat != NULL)) {
- Free_Miles_Handle ();
- } else {
- Allocate_Miles_Handle ();
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Transform
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Transform (const Matrix3D &transform)
- {
- // Update our internal transform
- m_PrevTransform = m_Transform;
- m_Transform = transform;
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_Position
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_Position (const Vector3 &position)
- {
- // Update our internal transform
- m_Transform.Set_Translation (position);
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Add_To_Scene
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Add_To_Scene (bool start_playing)
- {
- SoundSceneClass *scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
- if ((scene != NULL) && (m_Scene == NULL)) {
- //
- // Add this sound to the static culling system
- //
- m_Scene = scene;
- scene->Add_Static_Sound (this, start_playing);
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Remove_From_Scene
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Remove_From_Scene (void)
- {
- if (m_Scene != NULL) {
- //
- // Remove this sound from the static culling system
- //
- m_Scene->Remove_Static_Sound (this);
- m_Scene = NULL;
- m_PhysWrapper = NULL;
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Set_DropOff_Radius
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Set_DropOff_Radius (float radius)
- {
- m_DropOffRadius = radius;
- Set_Dirty ();
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Re_Sync
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Re_Sync (AudibleSoundClass &src)
- {
- m_Timestamp = src.m_Timestamp;
- m_State = src.m_State;
- m_Type = src.m_Type;
- m_FadeType = src.m_FadeType;
- m_FadeTimer = src.m_FadeTimer;
- m_FadeTime = src.m_FadeTime;
- m_VirtualChannel = src.m_VirtualChannel;
- m_LoopCount = src.m_LoopCount;
- m_LoopsLeft = src.m_LoopsLeft;
- m_Length = src.m_Length;
- m_CurrentPosition = src.m_CurrentPosition;
- m_bDirty = src.m_bDirty;
- m_DropOffRadius = src.m_DropOffRadius;
- m_PrevTransform = src.m_PrevTransform;
- Cull_Sound (src.m_IsCulled);
- Set_Volume (src.m_RealVolume);
- Set_Pan (src.m_Pan);
- Set_Priority (src.m_Priority);
- Set_Transform (src.m_Transform);
- Set_Listener_Transform (src.m_ListenerTransform);
- if (m_State != STATE_PLAYING) {
- Free_Miles_Handle ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Free_Conversion
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Free_Conversion (void)
- {
- if (m_pConvertedFormat != NULL) {
- m_pConvertedFormat->Stop ();
- REF_PTR_RELEASE (m_pConvertedFormat);
- }
- //
- // Reacquire a play-handle if necessary
- //
- if ((m_IsCulled == false) && (m_State == STATE_PLAYING)) {
- Allocate_Miles_Handle ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Convert_To_Filtered
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundClass::Convert_To_Filtered (void)
- {
- if (m_pConvertedFormat == NULL) {
- //
- // Make a copy of the sound in its new format
- //
- m_pConvertedFormat = new FilteredSoundClass;
- switch (Get_Class_ID ())
- {
- case CLASSID_3D:
- (*m_pConvertedFormat) = (const Sound3DClass &)(*this);
- break;
- case CLASSID_PSEUDO3D:
- (*m_pConvertedFormat) = (const SoundPseudo3DClass &)(*this);
- break;
- case CLASSID_FILTERED:
- (*m_pConvertedFormat) = (const FilteredSoundClass &)(*this);
- break;
- default:
- (*m_pConvertedFormat) = (*this);
- break;
- }
- Free_Miles_Handle ();
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // As_Converted_Format
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- AudibleSoundClass *
- AudibleSoundClass::As_Converted_Format (void)
- {
- if (m_pConvertedFormat == NULL) {
- Convert_To_Filtered ();
- }
- return m_pConvertedFormat;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Factory
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- const PersistFactoryClass &
- AudibleSoundClass::Get_Factory (void) const
- {
- return _AudibleSoundPersistFactory;
- }
- //************************************************************************************************
- //*
- //* Start of AudibleSoundDefinitionClass
- //*
- //************************************************************************************************
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // AudibleSoundDefinitionClass
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- AudibleSoundDefinitionClass::AudibleSoundDefinitionClass (void)
- : m_Priority (0.5F),
- m_Volume (1.0F),
- m_Pan (0.5F),
- m_LoopCount (1),
- m_DropOffRadius (40.0F),
- m_LogicalDropOffRadius (-1.0F),
- m_MaxVolRadius (20.0F),
- m_Is3D (true),
- m_Type (AudibleSoundClass::TYPE_SOUND_EFFECT),
- m_LogicalTypeMask (0),
- m_LogicalNotifyDelay (2),
- m_CreateLogical (false),
- m_AttenuationSphereColor (0, 0.75F, 0.75F),
- m_StartOffset (0),
- m_PitchFactor (1.0F),
- m_PitchFactorRandomizer (0.0F),
- m_VolumeRandomizer (0.0F),
- m_VirtualChannel (0)
- {
- //
- // Audible sound params
- //
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_SOUND_FILENAME, m_Filename, "Filename");
- INT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_VirtualChannel, 0, 100);
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_DropOffRadius, "Drop-off Radius");
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_MaxVolRadius, "Max-Vol Radius");
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_BOOL, m_Is3D, "Is 3D Sound");
- INT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_LoopCount, 0, 1000000);
- FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_Volume, 0, 1.0F);
- NAMED_FLOAT_UNITS_PARAM (AudibleSoundDefinitionClass, m_VolumeRandomizer, 0, 1.0F, "", "Volume Random (+/-)");
- FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_Pan, 0, 1.0F);
- FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_Priority, 0, 1.0F);
- ENUM_PARAM (AudibleSoundDefinitionClass, m_Type, ( "Sound Effect", AudibleSoundClass::TYPE_SOUND_EFFECT,
- "Music", AudibleSoundClass::TYPE_MUSIC,
- "Dialog", AudibleSoundClass::TYPE_DIALOG,
- "Cinematic", AudibleSoundClass::TYPE_CINEMATIC, 0));
- FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_StartOffset, 0, 1.0F);
- FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_PitchFactor, 0, 1.0F);
- NAMED_FLOAT_UNITS_PARAM (AudibleSoundDefinitionClass, m_PitchFactorRandomizer, 0, 1.0F, "", "Pitch Factor Random (+/-)");
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_STRING, m_DisplayText, "Display Text");
- //
- // Logical sound params
- //
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_BOOL, m_CreateLogical, "Create Logical Sound");
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_LogicalDropOffRadius, "Logical Drop-off Radius");
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_LogicalNotifyDelay, "Logical Notif Delay");
- #ifdef PARAM_EDITING_ON
- //
- // Configure the logical type mask enumeration
- //
- EnumParameterClass *param = new EnumParameterClass (&m_LogicalTypeMask);
- param->Set_Name ("Logical Type");
- int count = WWAudioClass::Get_Instance ()->Get_Logical_Type_Count ();
- for (int index = 0; index < count; index ++) {
- StringClass display_name(0,true);
- int id = WWAudioClass::Get_Instance ()->Get_Logical_Type (index, display_name);
- param->Add_Value (display_name, id);
- }
- GENERIC_EDITABLE_PARAM(AudibleSoundDefinitionClass, param);
- #endif
- NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_COLOR, m_AttenuationSphereColor, "Sphere Color");
- return ;
- }
- // SKB: Put here because of conficts with CLASSID_???? with other projects.
- uint32 AudibleSoundDefinitionClass::Get_Class_ID (void) const
- {
- return CLASSID_SOUND;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Initialize_From_Sound
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- void
- AudibleSoundDefinitionClass::Initialize_From_Sound (AudibleSoundClass *sound)
- {
- //
- // Read the settings from the sound object
- //
- if (sound != NULL) {
- Sound3DClass *sound_3d = sound->As_Sound3DClass ();
- //
- // Choose defaults for the values that we can't get from
- // the sound.
- //
- m_LogicalDropOffRadius = -1.0F;
- m_LogicalNotifyDelay = 2;
- m_LogicalTypeMask = 0;
- m_CreateLogical = false;
- m_Pan = 0.5F;
- m_DisplayText = "";
- //
- // Copy the values that we can from the sound object
- //
- m_Filename = sound->Get_Filename ();
- m_DropOffRadius = sound->Get_DropOff_Radius ();
- m_Priority = sound->Peek_Priority ();
- m_Is3D = (sound_3d != NULL);
- m_Type = sound->Get_Type ();
- m_LoopCount = sound->Get_Loop_Count ();
- m_Volume = sound->Get_Volume ();
- m_StartOffset = sound->Get_Start_Offset ();
- m_PitchFactor = sound->Get_Pitch_Factor ();
- m_VirtualChannel = sound->Get_Virtual_Channel ();
- if (sound_3d != NULL) {
- m_MaxVolRadius = sound_3d->Get_Max_Vol_Radius ();
- }
- }
- return ;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Get_Factory
- //
- ////////////////////////////////////////////////////////////////////////////////////////////////
- const PersistFactoryClass &
- AudibleSoundDefinitionClass::Get_Factory (void) const
- {
- return _AudibleSoundDefPersistFactory;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Save
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundDefinitionClass::Save (ChunkSaveClass &csave)
- {
- using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
- bool retval = true;
- csave.Begin_Chunk (CHUNKID_VARIABLES);
- retval &= Save_Variables (csave);
- csave.End_Chunk ();
- csave.Begin_Chunk (CHUNKID_BASE_CLASS);
- retval &= DefinitionClass::Save (csave);
- csave.End_Chunk ();
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Load
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundDefinitionClass::Load (ChunkLoadClass &cload)
- {
- using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
- bool retval = true;
- while (cload.Open_Chunk ()) {
- switch (cload.Cur_Chunk_ID ()) {
- case CHUNKID_VARIABLES:
- retval &= Load_Variables (cload);
- break;
- case CHUNKID_BASE_CLASS:
- retval &= DefinitionClass::Load (cload);
- break;
- }
- cload.Close_Chunk ();
- }
- return retval;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Save_Variables
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundDefinitionClass::Save_Variables (ChunkSaveClass &csave)
- {
- using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
- //
- // Save the audible variables
- //
- WRITE_MICRO_CHUNK (csave, VARID_PRIORITY, m_Priority)
- WRITE_MICRO_CHUNK (csave, VARID_VOLUME, m_Volume)
- WRITE_MICRO_CHUNK (csave, VARID_PAN, m_Pan)
- WRITE_MICRO_CHUNK (csave, VARID_LOOP_COUNT, m_LoopCount)
- WRITE_MICRO_CHUNK (csave, VARID_DROP_OFF, m_DropOffRadius)
- WRITE_MICRO_CHUNK (csave, VARID_MAX_VOL, m_MaxVolRadius)
- WRITE_MICRO_CHUNK (csave, VARID_TYPE, m_Type)
- WRITE_MICRO_CHUNK (csave, VARID_IS3D, m_Is3D)
- WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_FILENAME, m_Filename)
- WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_DISPLAY_TEXT, m_DisplayText)
- WRITE_MICRO_CHUNK (csave, VARID_START_OFFSET, m_StartOffset);
- WRITE_MICRO_CHUNK (csave, VARID_PITCH_FACTOR, m_PitchFactor);
- WRITE_MICRO_CHUNK (csave, VARID_PITCH_FACTOR_RND, m_PitchFactorRandomizer);
- WRITE_MICRO_CHUNK (csave, VARID_VOLUME_RND, m_VolumeRandomizer);
- WRITE_MICRO_CHUNK (csave, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
- //
- // Save the logical variables
- //
- WRITE_MICRO_CHUNK (csave, VARID_LOGICAL_MASK, m_LogicalTypeMask)
- WRITE_MICRO_CHUNK (csave, VARID_LOGICAL_DELAY, m_LogicalNotifyDelay)
- WRITE_MICRO_CHUNK (csave, VARID_CREATE_LOGICAL, m_CreateLogical)
- WRITE_MICRO_CHUNK (csave, VARID_LOGICAL_DROP_OFF, m_LogicalDropOffRadius)
- WRITE_MICRO_CHUNK (csave, VARID_SPHERE_COLOR, m_AttenuationSphereColor)
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Load_Variables
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundDefinitionClass::Load_Variables (ChunkLoadClass &cload)
- {
- using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
- //
- // Loop through all the microchunks that define the variables
- //
- while (cload.Open_Micro_Chunk ()) {
- switch (cload.Cur_Micro_Chunk_ID ()) {
- READ_MICRO_CHUNK (cload, VARID_PRIORITY, m_Priority)
- READ_MICRO_CHUNK (cload, VARID_VOLUME, m_Volume)
- READ_MICRO_CHUNK (cload, VARID_PAN, m_Pan)
- READ_MICRO_CHUNK (cload, VARID_LOOP_COUNT, m_LoopCount)
- READ_MICRO_CHUNK (cload, VARID_DROP_OFF, m_DropOffRadius)
- READ_MICRO_CHUNK (cload, VARID_MAX_VOL, m_MaxVolRadius)
- READ_MICRO_CHUNK (cload, VARID_TYPE, m_Type)
- READ_MICRO_CHUNK (cload, VARID_IS3D, m_Is3D)
- READ_MICRO_CHUNK_WWSTRING (cload, VARID_FILENAME, m_Filename)
- READ_MICRO_CHUNK_WWSTRING (cload, VARID_DISPLAY_TEXT, m_DisplayText)
- READ_MICRO_CHUNK (cload, VARID_LOGICAL_MASK, m_LogicalTypeMask)
- READ_MICRO_CHUNK (cload, VARID_LOGICAL_DELAY, m_LogicalNotifyDelay)
- READ_MICRO_CHUNK (cload, VARID_CREATE_LOGICAL, m_CreateLogical)
- READ_MICRO_CHUNK (cload, VARID_LOGICAL_DROP_OFF, m_LogicalDropOffRadius)
- READ_MICRO_CHUNK (cload, VARID_SPHERE_COLOR, m_AttenuationSphereColor)
- READ_MICRO_CHUNK (cload, VARID_START_OFFSET, m_StartOffset);
- READ_MICRO_CHUNK (cload, VARID_PITCH_FACTOR, m_PitchFactor);
- READ_MICRO_CHUNK (cload, VARID_PITCH_FACTOR_RND, m_PitchFactorRandomizer);
- READ_MICRO_CHUNK (cload, VARID_VOLUME_RND, m_VolumeRandomizer);
- READ_MICRO_CHUNK (cload, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
- }
- cload.Close_Micro_Chunk ();
- }
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Create
- //
- //////////////////////////////////////////////////////////////////////////////////
- PersistClass *
- AudibleSoundDefinitionClass::Create (void) const
- {
- return Create_Sound (CLASSID_3D);
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Create_Sound
- //
- //////////////////////////////////////////////////////////////////////////////////
- AudibleSoundClass *
- AudibleSoundDefinitionClass::Create_Sound (int classid_hint) const
- {
- AudibleSoundClass *new_sound = NULL;
- //
- // If this is a relative path, strip it off and assume
- // the current directory is set correctly.
- //
- StringClass real_filename(m_Filename,true);
- const char *dir_delimiter = ::strrchr (m_Filename, '\\');
- if (dir_delimiter != NULL && m_Filename.Get_Length () > 2 && m_Filename[1] != ':') {
- real_filename = (dir_delimiter + 1);
- }
- //
- // Should we create a 2D or 3D sound?
- //
- if (m_Is3D && classid_hint != CLASSID_2D) {
- new_sound = WWAudioClass::Get_Instance ()->Create_3D_Sound (real_filename, classid_hint);
- } else {
- new_sound = WWAudioClass::Get_Instance ()->Create_Sound_Effect (real_filename);
- }
- //
- // Did we successfully create the sound?
- //
- if (new_sound != NULL) {
- //
- // Configure the sound
- //
- new_sound->Set_Type ((AudibleSoundClass::SOUND_TYPE)m_Type);
- new_sound->Set_Priority (m_Priority);
- new_sound->Set_Loop_Count (m_LoopCount);
- new_sound->Set_DropOff_Radius (m_DropOffRadius);
- new_sound->Set_Definition ((AudibleSoundDefinitionClass *)this);
- new_sound->Set_Start_Offset (m_StartOffset);
- new_sound->Set_Virtual_Channel (m_VirtualChannel);
- //
- // Randomize the volume and pitch as necessary
- //
- float volume = m_Volume;
- if (m_VolumeRandomizer != 0) {
- volume += WWMath::Random_Float (-m_VolumeRandomizer, m_VolumeRandomizer);
- }
- float pitch_factor = m_PitchFactor;
- if (m_PitchFactor != 0) {
- pitch_factor += WWMath::Random_Float (-m_PitchFactorRandomizer, m_PitchFactorRandomizer);
- }
- //
- // Set the volume and pitch
- //
- new_sound->Set_Volume (volume);
- new_sound->Set_Pitch_Factor (pitch_factor);
- if (new_sound->As_Sound3DClass () != NULL) {
- ((Sound3DClass *)new_sound)->Set_Max_Vol_Radius (m_MaxVolRadius);
- }
- }
- return new_sound;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Create_Logical
- //
- //////////////////////////////////////////////////////////////////////////////////
- LogicalSoundClass *
- AudibleSoundDefinitionClass::Create_Logical (void)
- {
- LogicalSoundClass *logical_sound = NULL;
- if (m_CreateLogical) {
- //
- // Create and configure the logical sound
- //
- logical_sound = new LogicalSoundClass;
- logical_sound->Set_Type_Mask (m_LogicalTypeMask);
- logical_sound->Set_Notify_Delay (m_LogicalNotifyDelay);
- logical_sound->Set_Single_Shot (m_LoopCount != 0);
- //
- // Use the audible sound's drop-off radius if the logical
- // isn't set...
- //
- if (m_LogicalDropOffRadius < 0) {
- logical_sound->Set_DropOff_Radius (m_DropOffRadius);
- } else {
- logical_sound->Set_DropOff_Radius (m_LogicalDropOffRadius);
- }
- }
- return logical_sound;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Save
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Save (ChunkSaveClass &csave)
- {
- using namespace AUDIBLE_SOUND_SAVELOAD;
- csave.Begin_Chunk (CHUNKID_BASE_CLASS);
- SoundSceneObjClass::Save (csave);
- csave.End_Chunk ();
- uint32 temp_position = 0;
- csave.Begin_Chunk (CHUNKID_VARIABLES);
- WRITE_MICRO_CHUNK (csave, VARID_STATE, m_State);
- WRITE_MICRO_CHUNK (csave, VARID_TYPE, m_Type);
- WRITE_MICRO_CHUNK (csave, VARID_PRIORITY, m_Priority);
- WRITE_MICRO_CHUNK (csave, VARID_VOLUME, m_Volume);
- WRITE_MICRO_CHUNK (csave, VARID_PAN, m_Pan);
- WRITE_MICRO_CHUNK (csave, VARID_LOOP_COUNT, m_LoopCount);
- WRITE_MICRO_CHUNK (csave, VARID_LOOPS_LEFT, m_LoopsLeft);
- WRITE_MICRO_CHUNK (csave, VARID_SOUND_LENGTH, m_Length);
- WRITE_MICRO_CHUNK (csave, VARID_CURR_POS, temp_position);
- WRITE_MICRO_CHUNK (csave, VARID_TRANSFORM, m_Transform);
- WRITE_MICRO_CHUNK (csave, VARID_PREV_TRANSFORM, m_PrevTransform);
- WRITE_MICRO_CHUNK (csave, VARID_IS_CULLED, m_IsCulled);
- WRITE_MICRO_CHUNK (csave, VARID_IS_DIRTY, m_bDirty);
- WRITE_MICRO_CHUNK (csave, VARID_DROP_OFF, m_DropOffRadius);
- WRITE_MICRO_CHUNK (csave, VARID_START_OFFSET, m_StartOffset);
- WRITE_MICRO_CHUNK (csave, VARID_PITCH_FACTOR, m_PitchFactor);
- WRITE_MICRO_CHUNK (csave, VARID_LISTENER_TRANSFORM, m_ListenerTransform);
- WRITE_MICRO_CHUNK (csave, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
- if (m_Buffer != NULL) {
- WRITE_MICRO_CHUNK_STRING (csave, VARID_FILENAME, m_Buffer->Get_Filename ());
- }
- AudibleSoundClass *this_ptr = this;
- WRITE_MICRO_CHUNK (csave, VARID_THIS_PTR, this_ptr);
- csave.End_Chunk ();
- return true;
- }
- //////////////////////////////////////////////////////////////////////////////////
- //
- // Load
- //
- //////////////////////////////////////////////////////////////////////////////////
- bool
- AudibleSoundClass::Load (ChunkLoadClass &cload)
- {
- using namespace AUDIBLE_SOUND_SAVELOAD;
- StringClass filename(0,true);
- while (cload.Open_Chunk ()) {
- switch (cload.Cur_Chunk_ID ()) {
- case CHUNKID_BASE_CLASS:
- SoundSceneObjClass::Load (cload);
- break;
- case CHUNKID_VARIABLES:
- {
- //
- // Read all the variables from their micro-chunks
- //
- while (cload.Open_Micro_Chunk ()) {
- switch (cload.Cur_Micro_Chunk_ID ()) {
- READ_MICRO_CHUNK (cload, VARID_STATE, m_State);
- READ_MICRO_CHUNK (cload, VARID_TYPE, m_Type);
- READ_MICRO_CHUNK (cload, VARID_PRIORITY, m_Priority);
- READ_MICRO_CHUNK (cload, VARID_VOLUME, m_Volume);
- READ_MICRO_CHUNK (cload, VARID_PAN, m_Pan);
- READ_MICRO_CHUNK (cload, VARID_LOOP_COUNT, m_LoopCount);
- READ_MICRO_CHUNK (cload, VARID_LOOPS_LEFT, m_LoopsLeft);
- READ_MICRO_CHUNK (cload, VARID_SOUND_LENGTH, m_Length);
- READ_MICRO_CHUNK (cload, VARID_CURR_POS, m_CurrentPosition);
- READ_MICRO_CHUNK (cload, VARID_TRANSFORM, m_Transform);
- READ_MICRO_CHUNK (cload, VARID_PREV_TRANSFORM, m_PrevTransform);
- READ_MICRO_CHUNK (cload, VARID_IS_CULLED, m_IsCulled);
- READ_MICRO_CHUNK (cload, VARID_IS_DIRTY, m_bDirty);
- READ_MICRO_CHUNK (cload, VARID_DROP_OFF, m_DropOffRadius);
- READ_MICRO_CHUNK (cload, VARID_START_OFFSET, m_StartOffset);
- READ_MICRO_CHUNK (cload, VARID_PITCH_FACTOR, m_PitchFactor);
- READ_MICRO_CHUNK (cload, VARID_LISTENER_TRANSFORM, m_ListenerTransform);
- READ_MICRO_CHUNK (cload, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
- READ_MICRO_CHUNK_WWSTRING (cload, VARID_FILENAME, filename);
- case VARID_THIS_PTR:
- {
- AudibleSoundClass *old_ptr = NULL;
- cload.Read(&old_ptr, sizeof (old_ptr));
- SaveLoadSystemClass::Register_Pointer (old_ptr, this);
- }
- break;
- }
- cload.Close_Micro_Chunk ();
- }
- }
- break;
- }
- cload.Close_Chunk ();
- }
- //
- // Reconstruct the sound buffer we had before we saved
- //
- if (filename.Get_Length () > 0) {
- bool is_3d = (As_Sound3DClass () != NULL);
- SoundBufferClass *buffer = WWAudioClass::Get_Instance ()->Get_Sound_Buffer (filename, is_3d);
- Set_Buffer (buffer);
- REF_PTR_RELEASE (buffer);
- }
- return true;
- }
|