AudibleSound.cpp 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWAudio *
  23. * *
  24. * $Archive:: /Commando/Code/WWAudio/AudibleSound.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 12/14/01 11:20a $*
  29. * *
  30. * $Revision:: 35 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "audiblesound.h"
  36. #include "wwaudio.h"
  37. #include "ww3d.h"
  38. #include "wwdebug.h"
  39. #include "soundbuffer.h"
  40. #include "utils.h"
  41. #include "soundscene.h"
  42. #include "filteredsound.h"
  43. #include "threads.h"
  44. #include "soundchunkids.h"
  45. #include "simpledefinitionfactory.h"
  46. #include "persistfactory.h"
  47. #include "logicalsound.h"
  48. #include "definitionclassids.h"
  49. #include "soundstreamhandle.h"
  50. #include "sound2dhandle.h"
  51. #include "systimer.h"
  52. //////////////////////////////////////////////////////////////////////////////////
  53. // Static factories
  54. //////////////////////////////////////////////////////////////////////////////////
  55. DECLARE_DEFINITION_FACTORY(AudibleSoundDefinitionClass, CLASSID_SOUND_DEF, "Sound") _SoundDefFactory;
  56. SimplePersistFactoryClass<AudibleSoundDefinitionClass, CHUNKID_SOUND_DEF> _AudibleSoundDefPersistFactory;
  57. SimplePersistFactoryClass<AudibleSoundClass, CHUNKID_AUDIBLE_SOUND> _AudibleSoundPersistFactory;
  58. //////////////////////////////////////////////////////////////////////////////////
  59. // Save/Load constants
  60. //////////////////////////////////////////////////////////////////////////////////
  61. namespace AUDIBLE_SOUND_SAVELOAD
  62. {
  63. enum
  64. {
  65. CHUNKID_VARIABLES = 0x00000100,
  66. CHUNKID_BASE_CLASS
  67. };
  68. enum
  69. {
  70. VARID_STATE = 0x01,
  71. VARID_TYPE,
  72. VARID_PRIORITY,
  73. VARID_VOLUME,
  74. VARID_PAN,
  75. VARID_LOOP_COUNT,
  76. VARID_LOOPS_LEFT,
  77. VARID_SOUND_LENGTH,
  78. VARID_CURR_POS,
  79. VARID_TRANSFORM,
  80. VARID_PREV_TRANSFORM,
  81. VARID_IS_CULLED,
  82. VARID_IS_DIRTY,
  83. VARID_DROP_OFF,
  84. VARID_FILENAME,
  85. VARID_THIS_PTR,
  86. VARID_START_OFFSET,
  87. VARID_LISTENER_TRANSFORM,
  88. VARID_PITCH_FACTOR,
  89. VARID_PITCH_FACTOR_RND,
  90. VARID_VOLUME_RND,
  91. VARID_VIRTUAL_CHANNEL
  92. };
  93. }
  94. namespace AUDIBLE_SOUND_DEF_SAVELOAD
  95. {
  96. enum
  97. {
  98. CHUNKID_VARIABLES = 0x00000100,
  99. CHUNKID_BASE_CLASS = 0x00000200,
  100. };
  101. enum
  102. {
  103. VARID_UNUSED1 = 0x01,
  104. VARID_UNUSED2,
  105. VARID_PRIORITY,
  106. VARID_VOLUME,
  107. VARID_PAN,
  108. VARID_LOOP_COUNT,
  109. VARID_DROP_OFF,
  110. VARID_MAX_VOL,
  111. VARID_TYPE,
  112. VARID_IS3D,
  113. VARID_FILENAME,
  114. VARID_DISPLAY_TEXT,
  115. VARID_LOGICAL_MASK,
  116. VARID_LOGICAL_DELAY,
  117. VARID_CREATE_LOGICAL,
  118. VARID_LOGICAL_DROP_OFF,
  119. VARID_SPHERE_COLOR,
  120. VARID_START_OFFSET,
  121. VARID_PITCH_FACTOR,
  122. VARID_PITCH_FACTOR_RND,
  123. VARID_VOLUME_RND,
  124. VARID_VIRTUAL_CHANNEL
  125. };
  126. }
  127. ////////////////////////////////////////////////////////////////////////////////////////////////
  128. //
  129. // AudibleSoundClass
  130. //
  131. ////////////////////////////////////////////////////////////////////////////////////////////////
  132. AudibleSoundClass::AudibleSoundClass (void)
  133. : m_Priority (0.5F),
  134. m_RuntimePriority (0),
  135. m_SoundHandle (NULL),
  136. m_Length (0),
  137. m_CurrentPosition (0),
  138. m_Timestamp (0),
  139. m_State (STATE_STOPPED),
  140. m_Buffer (NULL),
  141. m_Volume (1.0F),
  142. m_RealVolume (1.0F),
  143. m_Pan (0.5F),
  144. m_LoopCount (1),
  145. m_LoopsLeft (0),
  146. m_Type (TYPE_SOUND_EFFECT),
  147. m_FadeType (FADE_NONE),
  148. m_FadeTimer (0),
  149. m_FadeTime (0),
  150. m_VirtualChannel (0),
  151. m_bDirty (true),
  152. m_DropOffRadius (1),
  153. m_IsCulled (true),
  154. m_pConvertedFormat (NULL),
  155. m_PrevTransform (1),
  156. m_Transform (1),
  157. m_ListenerTransform (1),
  158. m_Definition (NULL),
  159. m_LogicalSound (NULL),
  160. m_StartOffset (0),
  161. m_PitchFactor (1.0F)
  162. {
  163. return ;
  164. }
  165. ////////////////////////////////////////////////////////////////////////////////////////////////
  166. //
  167. // AudibleSoundClass
  168. //
  169. ////////////////////////////////////////////////////////////////////////////////////////////////
  170. AudibleSoundClass::AudibleSoundClass (const AudibleSoundClass &src)
  171. : m_Priority (0.5F),
  172. m_RuntimePriority (0),
  173. m_SoundHandle (NULL),
  174. m_Length (0),
  175. m_CurrentPosition (0),
  176. m_Timestamp (0),
  177. m_State (STATE_STOPPED),
  178. m_Buffer (NULL),
  179. m_Volume (1.0F),
  180. m_RealVolume (1.0F),
  181. m_Pan (0.5F),
  182. m_LoopCount (1),
  183. m_LoopsLeft (0),
  184. m_Type (TYPE_SOUND_EFFECT),
  185. m_FadeType (FADE_NONE),
  186. m_FadeTimer (0),
  187. m_FadeTime (0),
  188. m_VirtualChannel (0),
  189. m_bDirty (true),
  190. m_DropOffRadius (1),
  191. m_IsCulled (true),
  192. m_pConvertedFormat (NULL),
  193. m_PrevTransform (1),
  194. m_Transform (1),
  195. m_Definition (NULL),
  196. m_LogicalSound (NULL),
  197. m_StartOffset (0),
  198. m_PitchFactor (1.0F)
  199. {
  200. (*this) = src;
  201. return ;
  202. }
  203. ////////////////////////////////////////////////////////////////////////////////////////////////
  204. //
  205. // ~AudibleSoundClass
  206. //
  207. ////////////////////////////////////////////////////////////////////////////////////////////////
  208. AudibleSoundClass::~AudibleSoundClass (void)
  209. {
  210. m_State = STATE_STOPPED;
  211. Free_Conversion ();
  212. REF_PTR_RELEASE (m_LogicalSound);
  213. //
  214. // Delay the release of the buffer (fixes a sync bug
  215. // with Miles internals).
  216. //
  217. if (m_Buffer != NULL) {
  218. WWAudioThreadsClass::Add_Delayed_Release_Object (m_Buffer);
  219. //REF_PTR_RELEASE (m_Buffer);
  220. m_Buffer = NULL;
  221. }
  222. Free_Miles_Handle ();
  223. return ;
  224. }
  225. ////////////////////////////////////////////////////////////////////////////////////////////////
  226. //
  227. // operator=
  228. //
  229. ////////////////////////////////////////////////////////////////////////////////////////////////
  230. const AudibleSoundClass &
  231. AudibleSoundClass::operator= (const AudibleSoundClass &src)
  232. {
  233. m_Timestamp = src.m_Timestamp;
  234. m_Type = src.m_Type;
  235. m_FadeType = src.m_FadeType;
  236. m_FadeTimer = src.m_FadeTimer;
  237. m_FadeTime = src.m_FadeTime;
  238. m_VirtualChannel = src.m_VirtualChannel;
  239. m_LoopCount = src.m_LoopCount;
  240. m_LoopsLeft = src.m_LoopsLeft;
  241. m_Length = src.m_Length;
  242. m_CurrentPosition = src.m_CurrentPosition;
  243. m_bDirty = src.m_bDirty;
  244. m_DropOffRadius = src.m_DropOffRadius;
  245. m_PrevTransform = src.m_PrevTransform;
  246. m_RealVolume = src.m_RealVolume;
  247. m_State = STATE_STOPPED;
  248. Set_Buffer (src.m_Buffer);
  249. m_State = src.m_State;
  250. Cull_Sound (src.m_IsCulled);
  251. Set_Volume (src.m_RealVolume);
  252. Set_Pan (src.m_Pan);
  253. Set_Priority (src.m_Priority);
  254. Set_Transform (src.m_Transform);
  255. Set_Listener_Transform (src.m_ListenerTransform);
  256. return (*this);
  257. }
  258. ////////////////////////////////////////////////////////////////////////////////////////////////
  259. //
  260. // Set_Buffer
  261. //
  262. ////////////////////////////////////////////////////////////////////////////////////////////////
  263. void
  264. AudibleSoundClass::Set_Buffer (SoundBufferClass *buffer)
  265. {
  266. //
  267. // Delay the release of the buffer (fixes a sync bug
  268. // with Miles internals).
  269. //
  270. if (m_Buffer != NULL) {
  271. WWAudioThreadsClass::Add_Delayed_Release_Object (m_Buffer);
  272. //REF_PTR_RELEASE (m_Buffer);
  273. m_Buffer = NULL;
  274. }
  275. REF_PTR_SET (m_Buffer, buffer);
  276. // Stop playing if necessary
  277. bool resume = false;
  278. if (m_State == STATE_PLAYING) {
  279. resume = Stop (false);
  280. }
  281. // Get the time (in ms) that this buffer will play for...
  282. if (m_Buffer != NULL) {
  283. m_Length = m_Buffer->Get_Duration ();
  284. }
  285. // Reinitialize the handle with this new data
  286. Initialize_Miles_Handle ();
  287. // Resume playing if necessary
  288. if (resume) {
  289. Play ();
  290. }
  291. return ;
  292. }
  293. ////////////////////////////////////////////////////////////////////////////////////////////////
  294. //
  295. // Get_Buffer
  296. //
  297. ////////////////////////////////////////////////////////////////////////////////////////////////
  298. SoundBufferClass *
  299. AudibleSoundClass::Get_Buffer (void) const
  300. {
  301. if (m_Buffer) {
  302. m_Buffer->Add_Ref ();
  303. }
  304. return m_Buffer;
  305. }
  306. ////////////////////////////////////////////////////////////////////////////////////////////////
  307. //
  308. // Peek_Buffer
  309. //
  310. ////////////////////////////////////////////////////////////////////////////////////////////////
  311. SoundBufferClass *
  312. AudibleSoundClass::Peek_Buffer (void) const
  313. {
  314. return m_Buffer;
  315. }
  316. ////////////////////////////////////////////////////////////////////////////////////////////////
  317. //
  318. // Update_Fade
  319. //
  320. ////////////////////////////////////////////////////////////////////////////////////////////////
  321. void
  322. AudibleSoundClass::Update_Fade (void)
  323. {
  324. m_FadeTimer -= WW3D::Get_Frame_Time ();
  325. m_FadeTimer = max (m_FadeTimer, 0);
  326. //
  327. // Determine what percent we should ramp up or down to...
  328. //
  329. float percent = ((float)m_FadeTimer / (float)m_FadeTime);
  330. percent = WWMath::Clamp (percent, 0.0F, 1.0F);
  331. //
  332. // Invert the percent if we're fading in
  333. //
  334. if (m_FadeType == FADE_IN) {
  335. percent = 1.0F - percent;
  336. }
  337. //
  338. // Re-adjust the music and sound effect volumes
  339. //
  340. Internal_Set_Volume (m_RealVolume * percent);
  341. //
  342. // Reset the state as necessary
  343. //
  344. if (m_FadeTimer == 0) {
  345. //
  346. // Stop the sound when its done fading out
  347. //
  348. if (m_FadeType == FADE_OUT) {
  349. Stop ();
  350. }
  351. m_FadeType = FADE_NONE;
  352. }
  353. return ;
  354. }
  355. ////////////////////////////////////////////////////////////////////////////////////////////////
  356. //
  357. // Fade_Out
  358. //
  359. ////////////////////////////////////////////////////////////////////////////////////////////////
  360. void
  361. AudibleSoundClass::Fade_Out (int time_in_ms)
  362. {
  363. m_FadeTime = time_in_ms;
  364. m_FadeTimer = time_in_ms;
  365. m_FadeType = FADE_OUT;
  366. return ;
  367. }
  368. ////////////////////////////////////////////////////////////////////////////////////////////////
  369. //
  370. // Fade_In
  371. //
  372. ////////////////////////////////////////////////////////////////////////////////////////////////
  373. void
  374. AudibleSoundClass::Fade_In (int time_in_ms)
  375. {
  376. m_FadeTime = time_in_ms;
  377. m_FadeTimer = time_in_ms;
  378. m_FadeType = FADE_IN;
  379. //
  380. // Turn off the volume
  381. //
  382. Internal_Set_Volume (0.0F);
  383. //
  384. // Start the sample playing
  385. //
  386. Play ();
  387. return ;
  388. }
  389. ////////////////////////////////////////////////////////////////////////////////////////////////
  390. //
  391. // Verify_Playability
  392. //
  393. ////////////////////////////////////////////////////////////////////////////////////////////////
  394. bool
  395. AudibleSoundClass::Verify_Playability (void)
  396. {
  397. bool retval = true;
  398. if (m_VirtualChannel != 0) {
  399. retval = WWAudioClass::Get_Instance ()->Acquire_Virtual_Channel (this, m_VirtualChannel);
  400. }
  401. return retval;
  402. }
  403. ////////////////////////////////////////////////////////////////////////////////////////////////
  404. //
  405. // Play
  406. //
  407. ////////////////////////////////////////////////////////////////////////////////////////////////
  408. bool
  409. AudibleSoundClass::Play (bool alloc_handle)
  410. {
  411. MMSLockClass lock;
  412. //
  413. // Check to ensure this sound should really be playing...
  414. //
  415. if (Verify_Playability () == false) {
  416. return false;
  417. }
  418. //
  419. // If we don't have a valid handle already, try to get one from miles
  420. //
  421. if (alloc_handle && (m_pConvertedFormat == NULL)) {
  422. Allocate_Miles_Handle ();
  423. }
  424. //
  425. // Is the sound already playing?
  426. //
  427. if (m_State != STATE_PLAYING) {
  428. //
  429. // Let the audio system know this sound is playing
  430. //
  431. WWAudioClass::Get_Instance ()->Add_To_Playlist (this);
  432. m_State = STATE_PLAYING;
  433. m_Timestamp = TIMEGETTIME ();
  434. m_LoopsLeft = m_LoopCount;
  435. // If we have a valid handle, then start playing the sample
  436. if (m_SoundHandle != NULL) {
  437. m_SoundHandle->Start_Sample ();
  438. }
  439. m_CurrentPosition = m_StartOffset * m_Length;
  440. if (m_CurrentPosition > 0) {
  441. Seek (m_CurrentPosition);
  442. }
  443. // Fire an event
  444. On_Event (AudioCallbackClass::EVENT_SOUND_STARTED);
  445. //
  446. // Create the associate logical sound (if necessary)
  447. //
  448. if (m_LogicalSound == NULL && m_Definition != NULL) {
  449. m_LogicalSound = m_Definition->Create_Logical ();
  450. }
  451. //
  452. // Add this logical sound to the scene
  453. //
  454. if (m_LogicalSound != NULL) {
  455. m_LogicalSound->Set_User_Data (m_UserObj, m_UserData);
  456. m_LogicalSound->Set_Transform (m_Transform);
  457. m_LogicalSound->Add_To_Scene ();
  458. }
  459. //
  460. // Should we send off the text notification?
  461. //
  462. if (m_IsCulled == false && m_Definition != NULL) {
  463. const StringClass &text = m_Definition->Get_Display_Text ();
  464. WWAudioClass::Get_Instance ()->Fire_Text_Callback (this, text);
  465. }
  466. }
  467. return true;
  468. }
  469. ////////////////////////////////////////////////////////////////////////////////////////////////
  470. //
  471. // Pause
  472. //
  473. ////////////////////////////////////////////////////////////////////////////////////////////////
  474. bool
  475. AudibleSoundClass::Pause (void)
  476. {
  477. MMSLockClass lock;
  478. bool retval = false;
  479. if (m_State == STATE_PLAYING) {
  480. //
  481. // Update our current position so we can resume at the correct
  482. // location
  483. //
  484. m_CurrentPosition = TIMEGETTIME () - m_Timestamp;
  485. //
  486. // Get rid of our play-handle (this will stop the sound)
  487. //
  488. Free_Miles_Handle ();
  489. //
  490. // Remember our new state
  491. //
  492. m_State = STATE_PAUSED;
  493. retval = true;
  494. }
  495. // Return the true/false result code
  496. return retval;
  497. }
  498. ////////////////////////////////////////////////////////////////////////////////////////////////
  499. //
  500. // Resume
  501. //
  502. ////////////////////////////////////////////////////////////////////////////////////////////////
  503. bool
  504. AudibleSoundClass::Resume (void)
  505. {
  506. MMSLockClass lock;
  507. bool retval = false;
  508. if (m_State == STATE_PAUSED) {
  509. //
  510. // Re-sync our timestamp
  511. //
  512. m_Timestamp = TIMEGETTIME () - m_CurrentPosition;
  513. //
  514. // Ensure we have a play handle...
  515. //
  516. Allocate_Miles_Handle ();
  517. //
  518. // If we have a valid handle, then start playing the sample
  519. //
  520. if (m_SoundHandle != NULL) {
  521. m_SoundHandle->Start_Sample ();
  522. }
  523. //
  524. // Re-seek to the correct position in the sound
  525. //
  526. if (m_CurrentPosition > 0) {
  527. Seek (m_CurrentPosition);
  528. }
  529. //
  530. // Remember our new state
  531. //
  532. m_State = STATE_PLAYING;
  533. retval = true;
  534. }
  535. // Return the true/false result code
  536. return retval;
  537. }
  538. ////////////////////////////////////////////////////////////////////////////////////////////////
  539. //
  540. // Stop
  541. //
  542. ////////////////////////////////////////////////////////////////////////////////////////////////
  543. bool
  544. AudibleSoundClass::Stop (bool remove_from_playlist)
  545. {
  546. MMSLockClass lock;
  547. // Assume failure
  548. bool retval = false;
  549. if ((m_State == STATE_PAUSED) ||
  550. (m_State == STATE_PLAYING))
  551. {
  552. //
  553. // Actually stop the sample from playing
  554. //
  555. if (m_SoundHandle != NULL) {
  556. m_SoundHandle->Stop_Sample ();
  557. }
  558. //
  559. // Free up the handle we have been using
  560. //
  561. Free_Miles_Handle ();
  562. m_State = STATE_STOPPED;
  563. retval = true;
  564. //
  565. // Reset some of the playing attributes
  566. //
  567. m_Timestamp = 0;
  568. m_CurrentPosition = 0;
  569. //
  570. // Remove the sound from the current playlist
  571. //
  572. if (remove_from_playlist) {
  573. WWAudioClass::Get_Instance ()->Remove_From_Playlist (this);
  574. }
  575. //
  576. // Release the virtual channel as necessary
  577. //
  578. if (m_VirtualChannel > 0) {
  579. WWAudioClass::Get_Instance ()->Release_Virtual_Channel (this, m_VirtualChannel);
  580. }
  581. //
  582. // Stop the logical portion of the sound
  583. //
  584. if (m_LogicalSound != NULL && m_LogicalSound->Is_Single_Shot () == false) {
  585. m_LogicalSound->Remove_From_Scene ();
  586. }
  587. }
  588. // Return the true/false result code
  589. return retval;
  590. }
  591. ////////////////////////////////////////////////////////////////////////////////////////////////
  592. //
  593. // Seek
  594. //
  595. ////////////////////////////////////////////////////////////////////////////////////////////////
  596. void
  597. AudibleSoundClass::Seek (unsigned long milliseconds)
  598. {
  599. MMSLockClass lock;
  600. if ((milliseconds >= 0) && (milliseconds < m_Length)) {
  601. // Record our new position and recalculate the 'starting' timestamp
  602. // from this information
  603. m_CurrentPosition = milliseconds;
  604. if (m_State == STATE_PLAYING) {
  605. m_Timestamp = TIMEGETTIME () - m_CurrentPosition;
  606. }
  607. // Update the actual sound data if we are playing the sound
  608. if (m_SoundHandle != NULL) {
  609. m_SoundHandle->Set_Sample_MS_Position (m_CurrentPosition);
  610. }
  611. }
  612. return ;
  613. }
  614. ////////////////////////////////////////////////////////////////////////////////////////////////
  615. //
  616. // Set_Miles_Handle
  617. //
  618. ////////////////////////////////////////////////////////////////////////////////////////////////
  619. void
  620. AudibleSoundClass::Set_Miles_Handle (MILES_HANDLE handle)
  621. {
  622. //
  623. // Start fresh
  624. //
  625. Free_Miles_Handle ();
  626. //
  627. // Is our data valid?
  628. //
  629. if (handle != INVALID_MILES_HANDLE && m_Buffer != NULL) {
  630. //
  631. // Determine which type of sound handle to create, streaming or standard 2D
  632. //
  633. if (m_Buffer->Is_Streaming ()) {
  634. m_SoundHandle = new SoundStreamHandleClass;
  635. } else {
  636. m_SoundHandle = new Sound2DHandleClass;
  637. }
  638. //
  639. // Configure the sound handle
  640. //
  641. m_SoundHandle->Set_Miles_Handle (handle);
  642. //
  643. // Use this new handle
  644. //
  645. Initialize_Miles_Handle ();
  646. }
  647. return ;
  648. }
  649. ////////////////////////////////////////////////////////////////////////////////////////////////
  650. //
  651. // Initialize_Miles_Handle
  652. //
  653. ////////////////////////////////////////////////////////////////////////////////////////////////
  654. void
  655. AudibleSoundClass::Initialize_Miles_Handle (void)
  656. {
  657. MMSLockClass lock;
  658. // If this sound is already playing, then update its
  659. // playing position to make sure we really should
  660. // be playing it... (it will free the miles handle if not)
  661. if (m_State == STATE_PLAYING) {
  662. Update_Play_Position ();
  663. }
  664. // Do we have a valid sample handle from miles?
  665. if (m_SoundHandle != NULL) {
  666. //
  667. // Initialize the handle
  668. //
  669. m_SoundHandle->Initialize (m_Buffer);
  670. //
  671. // Record the total length of the sample in milliseconds...
  672. //
  673. m_SoundHandle->Get_Sample_MS_Position ((S32 *)&m_Length, NULL);
  674. //
  675. // Pass our cached settings onto miles
  676. //
  677. m_SoundHandle->Set_Sample_Volume (0);
  678. m_SoundHandle->Set_Sample_Pan (int(m_Pan * 127.0F));
  679. m_SoundHandle->Set_Sample_Loop_Count (m_LoopCount);
  680. //
  681. // Apply the pitch factor (if necessary)
  682. //
  683. if (m_PitchFactor != 1.0F) {
  684. Set_Pitch_Factor (m_PitchFactor);
  685. }
  686. // If this sound is already playing (and just now got a handle)
  687. // then make sure we start it.
  688. if (m_State == STATE_PLAYING) {
  689. m_SoundHandle->Start_Sample ();
  690. // Update the loop count based on the number of loops left
  691. m_SoundHandle->Set_Sample_Loop_Count (m_LoopsLeft);
  692. }
  693. // Seek to the position of the sound where we last left off.
  694. // For example, this sound could have gotten bumped due to a low priority,
  695. // but is now back and ready to resume at the position it would have been
  696. // at if it was never bumped.
  697. Seek (m_CurrentPosition);
  698. //
  699. // Pass the 'real' volume onto miles
  700. //
  701. float real_volume = Determine_Real_Volume ();
  702. m_SoundHandle->Set_Sample_Volume (int(real_volume * 127.0F));
  703. //
  704. // Associate this object instance with the handle
  705. //
  706. m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, (S32)this);
  707. }
  708. return ;
  709. }
  710. ////////////////////////////////////////////////////////////////////////////////////////////////
  711. //
  712. // Free_Miles_Handle
  713. //
  714. ////////////////////////////////////////////////////////////////////////////////////////////////
  715. void
  716. AudibleSoundClass::Free_Miles_Handle (void)
  717. {
  718. MMSLockClass lock;
  719. // Do we have a valid sample handle from miles?
  720. if (m_SoundHandle != NULL) {
  721. //
  722. // Release our hold on this handle
  723. //
  724. m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, NULL);
  725. m_SoundHandle->End_Sample ();
  726. //
  727. // Remove the association between file handle and AudibleSoundClass object
  728. //
  729. //m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, NULL);
  730. //
  731. // Free the sound handle object
  732. //
  733. delete m_SoundHandle;
  734. m_SoundHandle = NULL;
  735. }
  736. return ;
  737. }
  738. ////////////////////////////////////////////////////////////////////////////////////////////////
  739. //
  740. // Get_Pan
  741. //
  742. ////////////////////////////////////////////////////////////////////////////////////////////////
  743. float
  744. AudibleSoundClass::Get_Pan (void)
  745. {
  746. MMSLockClass lock;
  747. //
  748. // Do we have a valid sample handle from miles?
  749. //
  750. if (m_SoundHandle != NULL) {
  751. m_Pan = ((float)m_SoundHandle->Get_Sample_Pan ()) / 127.0F;
  752. }
  753. return m_Pan;
  754. }
  755. ////////////////////////////////////////////////////////////////////////////////////////////////
  756. //
  757. // Set_Pan
  758. //
  759. ////////////////////////////////////////////////////////////////////////////////////////////////
  760. void
  761. AudibleSoundClass::Set_Pan (float pan)
  762. {
  763. MMSLockClass lock;
  764. //
  765. // Cache the normalized pan value
  766. //
  767. m_Pan = min (pan, 1.0F);
  768. m_Pan = max (m_Pan, 0.0F);
  769. //
  770. // Do we have a valid sample handle from miles?
  771. //
  772. if (m_SoundHandle != NULL) {
  773. m_SoundHandle->Set_Sample_Pan (int(m_Pan * 127.0F));
  774. }
  775. return ;
  776. }
  777. ////////////////////////////////////////////////////////////////////////////////////////////////
  778. //
  779. // Set_Pitch_Factor
  780. //
  781. ////////////////////////////////////////////////////////////////////////////////////////////////
  782. void
  783. AudibleSoundClass::Set_Pitch_Factor (float factor)
  784. {
  785. MMSLockClass lock;
  786. m_PitchFactor = factor;
  787. //
  788. // Do we have a valid sample handle from miles?
  789. //
  790. if (m_SoundHandle != NULL) {
  791. if (m_Buffer != NULL) {
  792. //
  793. // Get the base rate of the sound and scale our playback rate
  794. // based on the factor
  795. //
  796. int base_rate = m_Buffer->Get_Rate ();
  797. int new_rate = base_rate * m_PitchFactor;
  798. m_SoundHandle->Set_Sample_Playback_Rate (new_rate);
  799. }
  800. }
  801. return ;
  802. }
  803. ////////////////////////////////////////////////////////////////////////////////////////////////
  804. //
  805. // Get_Playback_Rate
  806. //
  807. ////////////////////////////////////////////////////////////////////////////////////////////////
  808. int
  809. AudibleSoundClass::Get_Playback_Rate (void)
  810. {
  811. MMSLockClass lock;
  812. int retval = 0;
  813. // Do we have a valid sample handle from miles?
  814. if (m_SoundHandle != NULL) {
  815. retval = m_SoundHandle->Get_Sample_Playback_Rate ();
  816. }
  817. return retval;
  818. }
  819. ////////////////////////////////////////////////////////////////////////////////////////////////
  820. //
  821. // Set_Playback_Rate
  822. //
  823. ////////////////////////////////////////////////////////////////////////////////////////////////
  824. void
  825. AudibleSoundClass::Set_Playback_Rate (int rate_in_hz)
  826. {
  827. MMSLockClass lock;
  828. // Do we have a valid sample handle from miles?
  829. if (m_SoundHandle != NULL) {
  830. m_SoundHandle->Set_Sample_Playback_Rate (rate_in_hz);
  831. }
  832. return ;
  833. }
  834. ////////////////////////////////////////////////////////////////////////////////////////////////
  835. //
  836. // Get_Volume
  837. //
  838. ////////////////////////////////////////////////////////////////////////////////////////////////
  839. float
  840. AudibleSoundClass::Get_Volume (void)
  841. {
  842. MMSLockClass lock;
  843. // Do we have a valid sample handle from miles?
  844. if (m_SoundHandle != NULL) {
  845. m_Volume = ((float)m_SoundHandle->Get_Sample_Volume ()) / 127.0F;
  846. }
  847. // Return the current pan value
  848. return m_Volume;
  849. }
  850. ////////////////////////////////////////////////////////////////////////////////////////////////
  851. //
  852. // Internal_Set_Volume
  853. //
  854. ////////////////////////////////////////////////////////////////////////////////////////////////
  855. void
  856. AudibleSoundClass::Internal_Set_Volume (float volume)
  857. {
  858. MMSLockClass lock;
  859. //
  860. // Cache the normalized volume value
  861. //
  862. m_Volume = min (volume, 1.0F);
  863. m_Volume = max (m_Volume, 0.0F);
  864. //
  865. // Do we have a valid sample handle from miles?
  866. //
  867. if (m_SoundHandle != NULL) {
  868. //
  869. // Calculate the 'real' volume to set based on the global volume and the sound
  870. // effect volume.
  871. //
  872. float real_volume = Determine_Real_Volume ();
  873. m_SoundHandle->Set_Sample_Volume (int(real_volume * 127.0F));
  874. }
  875. return ;
  876. }
  877. ////////////////////////////////////////////////////////////////////////////////////////////////
  878. //
  879. // Set_Volume
  880. //
  881. ////////////////////////////////////////////////////////////////////////////////////////////////
  882. void
  883. AudibleSoundClass::Set_Volume (float volume)
  884. {
  885. MMSLockClass lock;
  886. //
  887. // Cache the normalized volume value
  888. //
  889. m_RealVolume = min (volume, 1.0F);
  890. m_RealVolume = max (m_RealVolume, 0.0F);
  891. //
  892. // Update the volume
  893. //
  894. Internal_Set_Volume (m_RealVolume);
  895. return ;
  896. }
  897. ////////////////////////////////////////////////////////////////////////////////////////////////
  898. //
  899. // Get_Loops_Left
  900. //
  901. ////////////////////////////////////////////////////////////////////////////////////////////////
  902. int
  903. AudibleSoundClass::Get_Loops_Left (void) const
  904. {
  905. return m_LoopsLeft;
  906. }
  907. ////////////////////////////////////////////////////////////////////////////////////////////////
  908. //
  909. // Set_Loop_Count
  910. //
  911. ////////////////////////////////////////////////////////////////////////////////////////////////
  912. void
  913. AudibleSoundClass::Set_Loop_Count (int count)
  914. {
  915. MMSLockClass lock;
  916. // Cache the loop count
  917. m_LoopCount = count;
  918. // Do we have a valid sample handle from miles?
  919. if (m_SoundHandle != NULL) {
  920. m_SoundHandle->Set_Sample_Loop_Count (m_LoopCount);
  921. }
  922. return ;
  923. }
  924. ////////////////////////////////////////////////////////////////////////////////////////////////
  925. //
  926. // Set_Priority
  927. //
  928. ////////////////////////////////////////////////////////////////////////////////////////////////
  929. void
  930. AudibleSoundClass::Set_Priority (float priority)
  931. {
  932. MMSLockClass lock;
  933. // Cache the normalized priority
  934. m_Priority = min (priority, 1.0F);
  935. m_Priority = max (m_Priority, 0.0F);
  936. return ;
  937. }
  938. ////////////////////////////////////////////////////////////////////////////////////////////////
  939. //
  940. // On_Frame_Update
  941. //
  942. ////////////////////////////////////////////////////////////////////////////////////////////////
  943. bool
  944. AudibleSoundClass::On_Frame_Update (unsigned int milliseconds)
  945. {
  946. //
  947. // Do we need to track this sound's play-progress?
  948. //
  949. if ((m_LoopCount != INFINITE_LOOPS) &&
  950. (m_State == STATE_PLAYING) &&
  951. (m_Length > 0))
  952. {
  953. Update_Play_Position ();
  954. }
  955. //
  956. // Update the fade as necessary
  957. //
  958. if (m_FadeType != FADE_NONE) {
  959. Update_Fade ();
  960. }
  961. if (m_pConvertedFormat != NULL) {
  962. m_pConvertedFormat->Re_Sync (*this);
  963. }
  964. //
  965. // Move the logical sound with the audible one...
  966. //
  967. if (m_LogicalSound != NULL) {
  968. m_LogicalSound->Set_Transform (m_Transform);
  969. }
  970. return true;
  971. }
  972. ////////////////////////////////////////////////////////////////////////////////////////////////
  973. //
  974. // Update_Play_Position
  975. //
  976. ////////////////////////////////////////////////////////////////////////////////////////////////
  977. void
  978. AudibleSoundClass::Update_Play_Position (void)
  979. {
  980. // Determine the current offset from the beginning of the sound buffer.
  981. unsigned long play_time = TIMEGETTIME () - m_Timestamp;
  982. m_CurrentPosition = play_time;
  983. // Have we gone past the end of a sounds play-time?
  984. if ((m_CurrentPosition > m_Length) && (m_Length > 0)) {
  985. // Normalize our position and timestamp information
  986. m_CurrentPosition = m_CurrentPosition % m_Length;
  987. m_Timestamp = TIMEGETTIME () - m_CurrentPosition;
  988. // Decrement our count of remaining loops (if necessary)
  989. if (m_LoopCount != INFINITE_LOOPS) {
  990. m_LoopsLeft -= (play_time / m_Length);
  991. }
  992. // Trigger the 'end loop' event
  993. On_Loop_End ();
  994. }
  995. return ;
  996. }
  997. ////////////////////////////////////////////////////////////////////////////////////////////////
  998. //
  999. // Allocate_Miles_Handle
  1000. //
  1001. ////////////////////////////////////////////////////////////////////////////////////////////////
  1002. void
  1003. AudibleSoundClass::Allocate_Miles_Handle (void)
  1004. {
  1005. //
  1006. // If we need to, get a play-handle from the audio system
  1007. //
  1008. if (m_SoundHandle == NULL) {
  1009. Set_Miles_Handle ((MILES_HANDLE)WWAudioClass::Get_Instance ()->Get_2D_Sample (*this));
  1010. }
  1011. return ;
  1012. }
  1013. ////////////////////////////////////////////////////////////////////////////////////////////////
  1014. //
  1015. // On_Loop_End
  1016. //
  1017. ////////////////////////////////////////////////////////////////////////////////////////////////
  1018. void
  1019. AudibleSoundClass::On_Loop_End (void)
  1020. {
  1021. // Determine if the sound is actually finished or still looping
  1022. if ((m_LoopCount != INFINITE_LOOPS) && (m_LoopsLeft < 1)) {
  1023. // Let the audio system know that we are done with this sound
  1024. Stop ();
  1025. if (m_Scene != NULL) {
  1026. Remove_From_Scene ();
  1027. }
  1028. // Fire an event
  1029. On_Event (AudioCallbackClass::EVENT_SOUND_ENDED);
  1030. } else {
  1031. Restart_Loop ();
  1032. }
  1033. return ;
  1034. }
  1035. ////////////////////////////////////////////////////////////////////////////////////////////////
  1036. //
  1037. // Determine_Real_Volume
  1038. //
  1039. ////////////////////////////////////////////////////////////////////////////////////////////////
  1040. float
  1041. AudibleSoundClass::Determine_Real_Volume (void) const
  1042. {
  1043. float volume = m_Volume;
  1044. // Is this a piece of music or is it a sound effect?
  1045. if (m_Type == TYPE_MUSIC) {
  1046. volume = volume * WWAudioClass::Get_Instance ()->Get_Music_Volume ();
  1047. } else if (m_Type == TYPE_SOUND_EFFECT) {
  1048. volume = volume * WWAudioClass::Get_Instance ()->Get_Sound_Effects_Volume ();
  1049. } else if (m_Type == TYPE_DIALOG) {
  1050. volume = volume * WWAudioClass::Get_Instance ()->Get_Dialog_Volume ();
  1051. } else if (m_Type == TYPE_CINEMATIC) {
  1052. volume = volume * WWAudioClass::Get_Instance ()->Get_Cinematic_Volume ();
  1053. }
  1054. // Return the 'real' volume
  1055. return volume;
  1056. }
  1057. ////////////////////////////////////////////////////////////////////////////////////////////////
  1058. //
  1059. // Get_Filename
  1060. //
  1061. ////////////////////////////////////////////////////////////////////////////////////////////////
  1062. LPCTSTR
  1063. AudibleSoundClass::Get_Filename (void) const
  1064. {
  1065. LPCTSTR filename = NULL;
  1066. if (m_Buffer != NULL) {
  1067. filename = m_Buffer->Get_Filename ();
  1068. }
  1069. return filename;
  1070. }
  1071. ////////////////////////////////////////////////////////////////////////////////////////////////
  1072. //
  1073. // Cull_Sound
  1074. //
  1075. ////////////////////////////////////////////////////////////////////////////////////////////////
  1076. void
  1077. AudibleSoundClass::Cull_Sound (bool culled)
  1078. {
  1079. // Is our state changing?
  1080. if (m_IsCulled != culled) {
  1081. m_IsCulled = culled;
  1082. //
  1083. // If this sound is culled, then throw away its play-handle.
  1084. // Otherwise, make sure we have a valid handle.
  1085. //
  1086. // Note: We also free the handle if a converted form
  1087. // of the sound is currently playing.
  1088. //
  1089. if (m_IsCulled || (m_pConvertedFormat != NULL)) {
  1090. Free_Miles_Handle ();
  1091. } else {
  1092. Allocate_Miles_Handle ();
  1093. }
  1094. }
  1095. return ;
  1096. }
  1097. ////////////////////////////////////////////////////////////////////////////////////////////////
  1098. //
  1099. // Set_Transform
  1100. //
  1101. ////////////////////////////////////////////////////////////////////////////////////////////////
  1102. void
  1103. AudibleSoundClass::Set_Transform (const Matrix3D &transform)
  1104. {
  1105. // Update our internal transform
  1106. m_PrevTransform = m_Transform;
  1107. m_Transform = transform;
  1108. Set_Dirty ();
  1109. return ;
  1110. }
  1111. ////////////////////////////////////////////////////////////////////////////////////////////////
  1112. //
  1113. // Set_Position
  1114. //
  1115. ////////////////////////////////////////////////////////////////////////////////////////////////
  1116. void
  1117. AudibleSoundClass::Set_Position (const Vector3 &position)
  1118. {
  1119. // Update our internal transform
  1120. m_Transform.Set_Translation (position);
  1121. Set_Dirty ();
  1122. return ;
  1123. }
  1124. ////////////////////////////////////////////////////////////////////////////////////////////////
  1125. //
  1126. // Add_To_Scene
  1127. //
  1128. ////////////////////////////////////////////////////////////////////////////////////////////////
  1129. void
  1130. AudibleSoundClass::Add_To_Scene (bool start_playing)
  1131. {
  1132. SoundSceneClass *scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
  1133. if ((scene != NULL) && (m_Scene == NULL)) {
  1134. //
  1135. // Add this sound to the static culling system
  1136. //
  1137. m_Scene = scene;
  1138. scene->Add_Static_Sound (this, start_playing);
  1139. }
  1140. return ;
  1141. }
  1142. ////////////////////////////////////////////////////////////////////////////////////////////////
  1143. //
  1144. // Remove_From_Scene
  1145. //
  1146. ////////////////////////////////////////////////////////////////////////////////////////////////
  1147. void
  1148. AudibleSoundClass::Remove_From_Scene (void)
  1149. {
  1150. if (m_Scene != NULL) {
  1151. //
  1152. // Remove this sound from the static culling system
  1153. //
  1154. m_Scene->Remove_Static_Sound (this);
  1155. m_Scene = NULL;
  1156. m_PhysWrapper = NULL;
  1157. }
  1158. return ;
  1159. }
  1160. ////////////////////////////////////////////////////////////////////////////////////////////////
  1161. //
  1162. // Set_DropOff_Radius
  1163. //
  1164. ////////////////////////////////////////////////////////////////////////////////////////////////
  1165. void
  1166. AudibleSoundClass::Set_DropOff_Radius (float radius)
  1167. {
  1168. m_DropOffRadius = radius;
  1169. Set_Dirty ();
  1170. return ;
  1171. }
  1172. ////////////////////////////////////////////////////////////////////////////////////////////////
  1173. //
  1174. // Re_Sync
  1175. //
  1176. ////////////////////////////////////////////////////////////////////////////////////////////////
  1177. void
  1178. AudibleSoundClass::Re_Sync (AudibleSoundClass &src)
  1179. {
  1180. m_Timestamp = src.m_Timestamp;
  1181. m_State = src.m_State;
  1182. m_Type = src.m_Type;
  1183. m_FadeType = src.m_FadeType;
  1184. m_FadeTimer = src.m_FadeTimer;
  1185. m_FadeTime = src.m_FadeTime;
  1186. m_VirtualChannel = src.m_VirtualChannel;
  1187. m_LoopCount = src.m_LoopCount;
  1188. m_LoopsLeft = src.m_LoopsLeft;
  1189. m_Length = src.m_Length;
  1190. m_CurrentPosition = src.m_CurrentPosition;
  1191. m_bDirty = src.m_bDirty;
  1192. m_DropOffRadius = src.m_DropOffRadius;
  1193. m_PrevTransform = src.m_PrevTransform;
  1194. Cull_Sound (src.m_IsCulled);
  1195. Set_Volume (src.m_RealVolume);
  1196. Set_Pan (src.m_Pan);
  1197. Set_Priority (src.m_Priority);
  1198. Set_Transform (src.m_Transform);
  1199. Set_Listener_Transform (src.m_ListenerTransform);
  1200. if (m_State != STATE_PLAYING) {
  1201. Free_Miles_Handle ();
  1202. }
  1203. return ;
  1204. }
  1205. ////////////////////////////////////////////////////////////////////////////////////////////////
  1206. //
  1207. // Free_Conversion
  1208. //
  1209. ////////////////////////////////////////////////////////////////////////////////////////////////
  1210. void
  1211. AudibleSoundClass::Free_Conversion (void)
  1212. {
  1213. if (m_pConvertedFormat != NULL) {
  1214. m_pConvertedFormat->Stop ();
  1215. REF_PTR_RELEASE (m_pConvertedFormat);
  1216. }
  1217. //
  1218. // Reacquire a play-handle if necessary
  1219. //
  1220. if ((m_IsCulled == false) && (m_State == STATE_PLAYING)) {
  1221. Allocate_Miles_Handle ();
  1222. }
  1223. return ;
  1224. }
  1225. ////////////////////////////////////////////////////////////////////////////////////////////////
  1226. //
  1227. // Convert_To_Filtered
  1228. //
  1229. ////////////////////////////////////////////////////////////////////////////////////////////////
  1230. void
  1231. AudibleSoundClass::Convert_To_Filtered (void)
  1232. {
  1233. if (m_pConvertedFormat == NULL) {
  1234. //
  1235. // Make a copy of the sound in its new format
  1236. //
  1237. m_pConvertedFormat = new FilteredSoundClass;
  1238. switch (Get_Class_ID ())
  1239. {
  1240. case CLASSID_3D:
  1241. (*m_pConvertedFormat) = (const Sound3DClass &)(*this);
  1242. break;
  1243. case CLASSID_PSEUDO3D:
  1244. (*m_pConvertedFormat) = (const SoundPseudo3DClass &)(*this);
  1245. break;
  1246. case CLASSID_FILTERED:
  1247. (*m_pConvertedFormat) = (const FilteredSoundClass &)(*this);
  1248. break;
  1249. default:
  1250. (*m_pConvertedFormat) = (*this);
  1251. break;
  1252. }
  1253. Free_Miles_Handle ();
  1254. }
  1255. return ;
  1256. }
  1257. ////////////////////////////////////////////////////////////////////////////////////////////////
  1258. //
  1259. // As_Converted_Format
  1260. //
  1261. ////////////////////////////////////////////////////////////////////////////////////////////////
  1262. AudibleSoundClass *
  1263. AudibleSoundClass::As_Converted_Format (void)
  1264. {
  1265. if (m_pConvertedFormat == NULL) {
  1266. Convert_To_Filtered ();
  1267. }
  1268. return m_pConvertedFormat;
  1269. }
  1270. ////////////////////////////////////////////////////////////////////////////////////////////////
  1271. //
  1272. // Get_Factory
  1273. //
  1274. ////////////////////////////////////////////////////////////////////////////////////////////////
  1275. const PersistFactoryClass &
  1276. AudibleSoundClass::Get_Factory (void) const
  1277. {
  1278. return _AudibleSoundPersistFactory;
  1279. }
  1280. //************************************************************************************************
  1281. //*
  1282. //* Start of AudibleSoundDefinitionClass
  1283. //*
  1284. //************************************************************************************************
  1285. ////////////////////////////////////////////////////////////////////////////////////////////////
  1286. //
  1287. // AudibleSoundDefinitionClass
  1288. //
  1289. ////////////////////////////////////////////////////////////////////////////////////////////////
  1290. AudibleSoundDefinitionClass::AudibleSoundDefinitionClass (void)
  1291. : m_Priority (0.5F),
  1292. m_Volume (1.0F),
  1293. m_Pan (0.5F),
  1294. m_LoopCount (1),
  1295. m_DropOffRadius (40.0F),
  1296. m_LogicalDropOffRadius (-1.0F),
  1297. m_MaxVolRadius (20.0F),
  1298. m_Is3D (true),
  1299. m_Type (AudibleSoundClass::TYPE_SOUND_EFFECT),
  1300. m_LogicalTypeMask (0),
  1301. m_LogicalNotifyDelay (2),
  1302. m_CreateLogical (false),
  1303. m_AttenuationSphereColor (0, 0.75F, 0.75F),
  1304. m_StartOffset (0),
  1305. m_PitchFactor (1.0F),
  1306. m_PitchFactorRandomizer (0.0F),
  1307. m_VolumeRandomizer (0.0F),
  1308. m_VirtualChannel (0)
  1309. {
  1310. //
  1311. // Audible sound params
  1312. //
  1313. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_SOUND_FILENAME, m_Filename, "Filename");
  1314. INT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_VirtualChannel, 0, 100);
  1315. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_DropOffRadius, "Drop-off Radius");
  1316. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_MaxVolRadius, "Max-Vol Radius");
  1317. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_BOOL, m_Is3D, "Is 3D Sound");
  1318. INT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_LoopCount, 0, 1000000);
  1319. FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_Volume, 0, 1.0F);
  1320. NAMED_FLOAT_UNITS_PARAM (AudibleSoundDefinitionClass, m_VolumeRandomizer, 0, 1.0F, "", "Volume Random (+/-)");
  1321. FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_Pan, 0, 1.0F);
  1322. FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_Priority, 0, 1.0F);
  1323. ENUM_PARAM (AudibleSoundDefinitionClass, m_Type, ( "Sound Effect", AudibleSoundClass::TYPE_SOUND_EFFECT,
  1324. "Music", AudibleSoundClass::TYPE_MUSIC,
  1325. "Dialog", AudibleSoundClass::TYPE_DIALOG,
  1326. "Cinematic", AudibleSoundClass::TYPE_CINEMATIC, 0));
  1327. FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_StartOffset, 0, 1.0F);
  1328. FLOAT_EDITABLE_PARAM (AudibleSoundDefinitionClass, m_PitchFactor, 0, 1.0F);
  1329. NAMED_FLOAT_UNITS_PARAM (AudibleSoundDefinitionClass, m_PitchFactorRandomizer, 0, 1.0F, "", "Pitch Factor Random (+/-)");
  1330. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_STRING, m_DisplayText, "Display Text");
  1331. //
  1332. // Logical sound params
  1333. //
  1334. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_BOOL, m_CreateLogical, "Create Logical Sound");
  1335. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_LogicalDropOffRadius, "Logical Drop-off Radius");
  1336. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_FLOAT, m_LogicalNotifyDelay, "Logical Notif Delay");
  1337. #ifdef PARAM_EDITING_ON
  1338. //
  1339. // Configure the logical type mask enumeration
  1340. //
  1341. EnumParameterClass *param = new EnumParameterClass (&m_LogicalTypeMask);
  1342. param->Set_Name ("Logical Type");
  1343. int count = WWAudioClass::Get_Instance ()->Get_Logical_Type_Count ();
  1344. for (int index = 0; index < count; index ++) {
  1345. StringClass display_name(0,true);
  1346. int id = WWAudioClass::Get_Instance ()->Get_Logical_Type (index, display_name);
  1347. param->Add_Value (display_name, id);
  1348. }
  1349. GENERIC_EDITABLE_PARAM(AudibleSoundDefinitionClass, param);
  1350. #endif
  1351. NAMED_EDITABLE_PARAM (AudibleSoundDefinitionClass, ParameterClass::TYPE_COLOR, m_AttenuationSphereColor, "Sphere Color");
  1352. return ;
  1353. }
  1354. // SKB: Put here because of conficts with CLASSID_???? with other projects.
  1355. uint32 AudibleSoundDefinitionClass::Get_Class_ID (void) const
  1356. {
  1357. return CLASSID_SOUND;
  1358. }
  1359. ////////////////////////////////////////////////////////////////////////////////////////////////
  1360. //
  1361. // Initialize_From_Sound
  1362. //
  1363. ////////////////////////////////////////////////////////////////////////////////////////////////
  1364. void
  1365. AudibleSoundDefinitionClass::Initialize_From_Sound (AudibleSoundClass *sound)
  1366. {
  1367. //
  1368. // Read the settings from the sound object
  1369. //
  1370. if (sound != NULL) {
  1371. Sound3DClass *sound_3d = sound->As_Sound3DClass ();
  1372. //
  1373. // Choose defaults for the values that we can't get from
  1374. // the sound.
  1375. //
  1376. m_LogicalDropOffRadius = -1.0F;
  1377. m_LogicalNotifyDelay = 2;
  1378. m_LogicalTypeMask = 0;
  1379. m_CreateLogical = false;
  1380. m_Pan = 0.5F;
  1381. m_DisplayText = "";
  1382. //
  1383. // Copy the values that we can from the sound object
  1384. //
  1385. m_Filename = sound->Get_Filename ();
  1386. m_DropOffRadius = sound->Get_DropOff_Radius ();
  1387. m_Priority = sound->Peek_Priority ();
  1388. m_Is3D = (sound_3d != NULL);
  1389. m_Type = sound->Get_Type ();
  1390. m_LoopCount = sound->Get_Loop_Count ();
  1391. m_Volume = sound->Get_Volume ();
  1392. m_StartOffset = sound->Get_Start_Offset ();
  1393. m_PitchFactor = sound->Get_Pitch_Factor ();
  1394. m_VirtualChannel = sound->Get_Virtual_Channel ();
  1395. if (sound_3d != NULL) {
  1396. m_MaxVolRadius = sound_3d->Get_Max_Vol_Radius ();
  1397. }
  1398. }
  1399. return ;
  1400. }
  1401. ////////////////////////////////////////////////////////////////////////////////////////////////
  1402. //
  1403. // Get_Factory
  1404. //
  1405. ////////////////////////////////////////////////////////////////////////////////////////////////
  1406. const PersistFactoryClass &
  1407. AudibleSoundDefinitionClass::Get_Factory (void) const
  1408. {
  1409. return _AudibleSoundDefPersistFactory;
  1410. }
  1411. //////////////////////////////////////////////////////////////////////////////////
  1412. //
  1413. // Save
  1414. //
  1415. //////////////////////////////////////////////////////////////////////////////////
  1416. bool
  1417. AudibleSoundDefinitionClass::Save (ChunkSaveClass &csave)
  1418. {
  1419. using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
  1420. bool retval = true;
  1421. csave.Begin_Chunk (CHUNKID_VARIABLES);
  1422. retval &= Save_Variables (csave);
  1423. csave.End_Chunk ();
  1424. csave.Begin_Chunk (CHUNKID_BASE_CLASS);
  1425. retval &= DefinitionClass::Save (csave);
  1426. csave.End_Chunk ();
  1427. return retval;
  1428. }
  1429. //////////////////////////////////////////////////////////////////////////////////
  1430. //
  1431. // Load
  1432. //
  1433. //////////////////////////////////////////////////////////////////////////////////
  1434. bool
  1435. AudibleSoundDefinitionClass::Load (ChunkLoadClass &cload)
  1436. {
  1437. using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
  1438. bool retval = true;
  1439. while (cload.Open_Chunk ()) {
  1440. switch (cload.Cur_Chunk_ID ()) {
  1441. case CHUNKID_VARIABLES:
  1442. retval &= Load_Variables (cload);
  1443. break;
  1444. case CHUNKID_BASE_CLASS:
  1445. retval &= DefinitionClass::Load (cload);
  1446. break;
  1447. }
  1448. cload.Close_Chunk ();
  1449. }
  1450. return retval;
  1451. }
  1452. //////////////////////////////////////////////////////////////////////////////////
  1453. //
  1454. // Save_Variables
  1455. //
  1456. //////////////////////////////////////////////////////////////////////////////////
  1457. bool
  1458. AudibleSoundDefinitionClass::Save_Variables (ChunkSaveClass &csave)
  1459. {
  1460. using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
  1461. //
  1462. // Save the audible variables
  1463. //
  1464. WRITE_MICRO_CHUNK (csave, VARID_PRIORITY, m_Priority)
  1465. WRITE_MICRO_CHUNK (csave, VARID_VOLUME, m_Volume)
  1466. WRITE_MICRO_CHUNK (csave, VARID_PAN, m_Pan)
  1467. WRITE_MICRO_CHUNK (csave, VARID_LOOP_COUNT, m_LoopCount)
  1468. WRITE_MICRO_CHUNK (csave, VARID_DROP_OFF, m_DropOffRadius)
  1469. WRITE_MICRO_CHUNK (csave, VARID_MAX_VOL, m_MaxVolRadius)
  1470. WRITE_MICRO_CHUNK (csave, VARID_TYPE, m_Type)
  1471. WRITE_MICRO_CHUNK (csave, VARID_IS3D, m_Is3D)
  1472. WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_FILENAME, m_Filename)
  1473. WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_DISPLAY_TEXT, m_DisplayText)
  1474. WRITE_MICRO_CHUNK (csave, VARID_START_OFFSET, m_StartOffset);
  1475. WRITE_MICRO_CHUNK (csave, VARID_PITCH_FACTOR, m_PitchFactor);
  1476. WRITE_MICRO_CHUNK (csave, VARID_PITCH_FACTOR_RND, m_PitchFactorRandomizer);
  1477. WRITE_MICRO_CHUNK (csave, VARID_VOLUME_RND, m_VolumeRandomizer);
  1478. WRITE_MICRO_CHUNK (csave, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
  1479. //
  1480. // Save the logical variables
  1481. //
  1482. WRITE_MICRO_CHUNK (csave, VARID_LOGICAL_MASK, m_LogicalTypeMask)
  1483. WRITE_MICRO_CHUNK (csave, VARID_LOGICAL_DELAY, m_LogicalNotifyDelay)
  1484. WRITE_MICRO_CHUNK (csave, VARID_CREATE_LOGICAL, m_CreateLogical)
  1485. WRITE_MICRO_CHUNK (csave, VARID_LOGICAL_DROP_OFF, m_LogicalDropOffRadius)
  1486. WRITE_MICRO_CHUNK (csave, VARID_SPHERE_COLOR, m_AttenuationSphereColor)
  1487. return true;
  1488. }
  1489. //////////////////////////////////////////////////////////////////////////////////
  1490. //
  1491. // Load_Variables
  1492. //
  1493. //////////////////////////////////////////////////////////////////////////////////
  1494. bool
  1495. AudibleSoundDefinitionClass::Load_Variables (ChunkLoadClass &cload)
  1496. {
  1497. using namespace AUDIBLE_SOUND_DEF_SAVELOAD;
  1498. //
  1499. // Loop through all the microchunks that define the variables
  1500. //
  1501. while (cload.Open_Micro_Chunk ()) {
  1502. switch (cload.Cur_Micro_Chunk_ID ()) {
  1503. READ_MICRO_CHUNK (cload, VARID_PRIORITY, m_Priority)
  1504. READ_MICRO_CHUNK (cload, VARID_VOLUME, m_Volume)
  1505. READ_MICRO_CHUNK (cload, VARID_PAN, m_Pan)
  1506. READ_MICRO_CHUNK (cload, VARID_LOOP_COUNT, m_LoopCount)
  1507. READ_MICRO_CHUNK (cload, VARID_DROP_OFF, m_DropOffRadius)
  1508. READ_MICRO_CHUNK (cload, VARID_MAX_VOL, m_MaxVolRadius)
  1509. READ_MICRO_CHUNK (cload, VARID_TYPE, m_Type)
  1510. READ_MICRO_CHUNK (cload, VARID_IS3D, m_Is3D)
  1511. READ_MICRO_CHUNK_WWSTRING (cload, VARID_FILENAME, m_Filename)
  1512. READ_MICRO_CHUNK_WWSTRING (cload, VARID_DISPLAY_TEXT, m_DisplayText)
  1513. READ_MICRO_CHUNK (cload, VARID_LOGICAL_MASK, m_LogicalTypeMask)
  1514. READ_MICRO_CHUNK (cload, VARID_LOGICAL_DELAY, m_LogicalNotifyDelay)
  1515. READ_MICRO_CHUNK (cload, VARID_CREATE_LOGICAL, m_CreateLogical)
  1516. READ_MICRO_CHUNK (cload, VARID_LOGICAL_DROP_OFF, m_LogicalDropOffRadius)
  1517. READ_MICRO_CHUNK (cload, VARID_SPHERE_COLOR, m_AttenuationSphereColor)
  1518. READ_MICRO_CHUNK (cload, VARID_START_OFFSET, m_StartOffset);
  1519. READ_MICRO_CHUNK (cload, VARID_PITCH_FACTOR, m_PitchFactor);
  1520. READ_MICRO_CHUNK (cload, VARID_PITCH_FACTOR_RND, m_PitchFactorRandomizer);
  1521. READ_MICRO_CHUNK (cload, VARID_VOLUME_RND, m_VolumeRandomizer);
  1522. READ_MICRO_CHUNK (cload, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
  1523. }
  1524. cload.Close_Micro_Chunk ();
  1525. }
  1526. return true;
  1527. }
  1528. //////////////////////////////////////////////////////////////////////////////////
  1529. //
  1530. // Create
  1531. //
  1532. //////////////////////////////////////////////////////////////////////////////////
  1533. PersistClass *
  1534. AudibleSoundDefinitionClass::Create (void) const
  1535. {
  1536. return Create_Sound (CLASSID_3D);
  1537. }
  1538. //////////////////////////////////////////////////////////////////////////////////
  1539. //
  1540. // Create_Sound
  1541. //
  1542. //////////////////////////////////////////////////////////////////////////////////
  1543. AudibleSoundClass *
  1544. AudibleSoundDefinitionClass::Create_Sound (int classid_hint) const
  1545. {
  1546. AudibleSoundClass *new_sound = NULL;
  1547. //
  1548. // If this is a relative path, strip it off and assume
  1549. // the current directory is set correctly.
  1550. //
  1551. StringClass real_filename(m_Filename,true);
  1552. const char *dir_delimiter = ::strrchr (m_Filename, '\\');
  1553. if (dir_delimiter != NULL && m_Filename.Get_Length () > 2 && m_Filename[1] != ':') {
  1554. real_filename = (dir_delimiter + 1);
  1555. }
  1556. //
  1557. // Should we create a 2D or 3D sound?
  1558. //
  1559. if (m_Is3D && classid_hint != CLASSID_2D) {
  1560. new_sound = WWAudioClass::Get_Instance ()->Create_3D_Sound (real_filename, classid_hint);
  1561. } else {
  1562. new_sound = WWAudioClass::Get_Instance ()->Create_Sound_Effect (real_filename);
  1563. }
  1564. //
  1565. // Did we successfully create the sound?
  1566. //
  1567. if (new_sound != NULL) {
  1568. //
  1569. // Configure the sound
  1570. //
  1571. new_sound->Set_Type ((AudibleSoundClass::SOUND_TYPE)m_Type);
  1572. new_sound->Set_Priority (m_Priority);
  1573. new_sound->Set_Loop_Count (m_LoopCount);
  1574. new_sound->Set_DropOff_Radius (m_DropOffRadius);
  1575. new_sound->Set_Definition ((AudibleSoundDefinitionClass *)this);
  1576. new_sound->Set_Start_Offset (m_StartOffset);
  1577. new_sound->Set_Virtual_Channel (m_VirtualChannel);
  1578. //
  1579. // Randomize the volume and pitch as necessary
  1580. //
  1581. float volume = m_Volume;
  1582. if (m_VolumeRandomizer != 0) {
  1583. volume += WWMath::Random_Float (-m_VolumeRandomizer, m_VolumeRandomizer);
  1584. }
  1585. float pitch_factor = m_PitchFactor;
  1586. if (m_PitchFactor != 0) {
  1587. pitch_factor += WWMath::Random_Float (-m_PitchFactorRandomizer, m_PitchFactorRandomizer);
  1588. }
  1589. //
  1590. // Set the volume and pitch
  1591. //
  1592. new_sound->Set_Volume (volume);
  1593. new_sound->Set_Pitch_Factor (pitch_factor);
  1594. if (new_sound->As_Sound3DClass () != NULL) {
  1595. ((Sound3DClass *)new_sound)->Set_Max_Vol_Radius (m_MaxVolRadius);
  1596. }
  1597. }
  1598. return new_sound;
  1599. }
  1600. //////////////////////////////////////////////////////////////////////////////////
  1601. //
  1602. // Create_Logical
  1603. //
  1604. //////////////////////////////////////////////////////////////////////////////////
  1605. LogicalSoundClass *
  1606. AudibleSoundDefinitionClass::Create_Logical (void)
  1607. {
  1608. LogicalSoundClass *logical_sound = NULL;
  1609. if (m_CreateLogical) {
  1610. //
  1611. // Create and configure the logical sound
  1612. //
  1613. logical_sound = new LogicalSoundClass;
  1614. logical_sound->Set_Type_Mask (m_LogicalTypeMask);
  1615. logical_sound->Set_Notify_Delay (m_LogicalNotifyDelay);
  1616. logical_sound->Set_Single_Shot (m_LoopCount != 0);
  1617. //
  1618. // Use the audible sound's drop-off radius if the logical
  1619. // isn't set...
  1620. //
  1621. if (m_LogicalDropOffRadius < 0) {
  1622. logical_sound->Set_DropOff_Radius (m_DropOffRadius);
  1623. } else {
  1624. logical_sound->Set_DropOff_Radius (m_LogicalDropOffRadius);
  1625. }
  1626. }
  1627. return logical_sound;
  1628. }
  1629. //////////////////////////////////////////////////////////////////////////////////
  1630. //
  1631. // Save
  1632. //
  1633. //////////////////////////////////////////////////////////////////////////////////
  1634. bool
  1635. AudibleSoundClass::Save (ChunkSaveClass &csave)
  1636. {
  1637. using namespace AUDIBLE_SOUND_SAVELOAD;
  1638. csave.Begin_Chunk (CHUNKID_BASE_CLASS);
  1639. SoundSceneObjClass::Save (csave);
  1640. csave.End_Chunk ();
  1641. uint32 temp_position = 0;
  1642. csave.Begin_Chunk (CHUNKID_VARIABLES);
  1643. WRITE_MICRO_CHUNK (csave, VARID_STATE, m_State);
  1644. WRITE_MICRO_CHUNK (csave, VARID_TYPE, m_Type);
  1645. WRITE_MICRO_CHUNK (csave, VARID_PRIORITY, m_Priority);
  1646. WRITE_MICRO_CHUNK (csave, VARID_VOLUME, m_Volume);
  1647. WRITE_MICRO_CHUNK (csave, VARID_PAN, m_Pan);
  1648. WRITE_MICRO_CHUNK (csave, VARID_LOOP_COUNT, m_LoopCount);
  1649. WRITE_MICRO_CHUNK (csave, VARID_LOOPS_LEFT, m_LoopsLeft);
  1650. WRITE_MICRO_CHUNK (csave, VARID_SOUND_LENGTH, m_Length);
  1651. WRITE_MICRO_CHUNK (csave, VARID_CURR_POS, temp_position);
  1652. WRITE_MICRO_CHUNK (csave, VARID_TRANSFORM, m_Transform);
  1653. WRITE_MICRO_CHUNK (csave, VARID_PREV_TRANSFORM, m_PrevTransform);
  1654. WRITE_MICRO_CHUNK (csave, VARID_IS_CULLED, m_IsCulled);
  1655. WRITE_MICRO_CHUNK (csave, VARID_IS_DIRTY, m_bDirty);
  1656. WRITE_MICRO_CHUNK (csave, VARID_DROP_OFF, m_DropOffRadius);
  1657. WRITE_MICRO_CHUNK (csave, VARID_START_OFFSET, m_StartOffset);
  1658. WRITE_MICRO_CHUNK (csave, VARID_PITCH_FACTOR, m_PitchFactor);
  1659. WRITE_MICRO_CHUNK (csave, VARID_LISTENER_TRANSFORM, m_ListenerTransform);
  1660. WRITE_MICRO_CHUNK (csave, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
  1661. if (m_Buffer != NULL) {
  1662. WRITE_MICRO_CHUNK_STRING (csave, VARID_FILENAME, m_Buffer->Get_Filename ());
  1663. }
  1664. AudibleSoundClass *this_ptr = this;
  1665. WRITE_MICRO_CHUNK (csave, VARID_THIS_PTR, this_ptr);
  1666. csave.End_Chunk ();
  1667. return true;
  1668. }
  1669. //////////////////////////////////////////////////////////////////////////////////
  1670. //
  1671. // Load
  1672. //
  1673. //////////////////////////////////////////////////////////////////////////////////
  1674. bool
  1675. AudibleSoundClass::Load (ChunkLoadClass &cload)
  1676. {
  1677. using namespace AUDIBLE_SOUND_SAVELOAD;
  1678. StringClass filename(0,true);
  1679. while (cload.Open_Chunk ()) {
  1680. switch (cload.Cur_Chunk_ID ()) {
  1681. case CHUNKID_BASE_CLASS:
  1682. SoundSceneObjClass::Load (cload);
  1683. break;
  1684. case CHUNKID_VARIABLES:
  1685. {
  1686. //
  1687. // Read all the variables from their micro-chunks
  1688. //
  1689. while (cload.Open_Micro_Chunk ()) {
  1690. switch (cload.Cur_Micro_Chunk_ID ()) {
  1691. READ_MICRO_CHUNK (cload, VARID_STATE, m_State);
  1692. READ_MICRO_CHUNK (cload, VARID_TYPE, m_Type);
  1693. READ_MICRO_CHUNK (cload, VARID_PRIORITY, m_Priority);
  1694. READ_MICRO_CHUNK (cload, VARID_VOLUME, m_Volume);
  1695. READ_MICRO_CHUNK (cload, VARID_PAN, m_Pan);
  1696. READ_MICRO_CHUNK (cload, VARID_LOOP_COUNT, m_LoopCount);
  1697. READ_MICRO_CHUNK (cload, VARID_LOOPS_LEFT, m_LoopsLeft);
  1698. READ_MICRO_CHUNK (cload, VARID_SOUND_LENGTH, m_Length);
  1699. READ_MICRO_CHUNK (cload, VARID_CURR_POS, m_CurrentPosition);
  1700. READ_MICRO_CHUNK (cload, VARID_TRANSFORM, m_Transform);
  1701. READ_MICRO_CHUNK (cload, VARID_PREV_TRANSFORM, m_PrevTransform);
  1702. READ_MICRO_CHUNK (cload, VARID_IS_CULLED, m_IsCulled);
  1703. READ_MICRO_CHUNK (cload, VARID_IS_DIRTY, m_bDirty);
  1704. READ_MICRO_CHUNK (cload, VARID_DROP_OFF, m_DropOffRadius);
  1705. READ_MICRO_CHUNK (cload, VARID_START_OFFSET, m_StartOffset);
  1706. READ_MICRO_CHUNK (cload, VARID_PITCH_FACTOR, m_PitchFactor);
  1707. READ_MICRO_CHUNK (cload, VARID_LISTENER_TRANSFORM, m_ListenerTransform);
  1708. READ_MICRO_CHUNK (cload, VARID_VIRTUAL_CHANNEL, m_VirtualChannel);
  1709. READ_MICRO_CHUNK_WWSTRING (cload, VARID_FILENAME, filename);
  1710. case VARID_THIS_PTR:
  1711. {
  1712. AudibleSoundClass *old_ptr = NULL;
  1713. cload.Read(&old_ptr, sizeof (old_ptr));
  1714. SaveLoadSystemClass::Register_Pointer (old_ptr, this);
  1715. }
  1716. break;
  1717. }
  1718. cload.Close_Micro_Chunk ();
  1719. }
  1720. }
  1721. break;
  1722. }
  1723. cload.Close_Chunk ();
  1724. }
  1725. //
  1726. // Reconstruct the sound buffer we had before we saved
  1727. //
  1728. if (filename.Get_Length () > 0) {
  1729. bool is_3d = (As_Sound3DClass () != NULL);
  1730. SoundBufferClass *buffer = WWAudioClass::Get_Instance ()->Get_Sound_Buffer (filename, is_3d);
  1731. Set_Buffer (buffer);
  1732. REF_PTR_RELEASE (buffer);
  1733. }
  1734. return true;
  1735. }