Sound3D.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  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/Sound3D.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 12/10/01 12:40p $*
  29. * *
  30. * $Revision:: 20 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "sound3d.h"
  36. #include "soundbuffer.h"
  37. #include "wwaudio.h"
  38. #include "soundscene.h"
  39. #include "utils.h"
  40. #include "soundchunkids.h"
  41. #include "persistfactory.h"
  42. #include "chunkio.h"
  43. #include "sound3dhandle.h"
  44. #include "systimer.h"
  45. //////////////////////////////////////////////////////////////////////////////////
  46. //
  47. // Static factories
  48. //
  49. //////////////////////////////////////////////////////////////////////////////////
  50. SimplePersistFactoryClass<Sound3DClass, CHUNKID_SOUND3D> _Sound3DPersistFactory;
  51. enum
  52. {
  53. CHUNKID_VARIABLES = 0x11090955,
  54. CHUNKID_BASE_CLASS
  55. };
  56. enum
  57. {
  58. VARID_AUTO_CALC_VEL = 0x01,
  59. VARID_CURR_VEL,
  60. VARID_XXX1,
  61. VARID_XXX2,
  62. VARID_MAX_VOL_RADIUS,
  63. VARID_IS_STATIC,
  64. };
  65. ////////////////////////////////////////////////////////////////////////////////////////////////
  66. //
  67. // Sound3DClass
  68. //
  69. ////////////////////////////////////////////////////////////////////////////////////////////////
  70. Sound3DClass::Sound3DClass (void)
  71. : m_bAutoCalcVel (true),
  72. m_CurrentVelocity (0, 0, 0),
  73. m_MaxVolRadius (0),
  74. m_LastUpdate (0),
  75. m_IsStatic (false),
  76. m_IsTransformInitted (false)
  77. {
  78. return ;
  79. }
  80. ////////////////////////////////////////////////////////////////////////////////////////////////
  81. //
  82. // Sound3DClass
  83. //
  84. ////////////////////////////////////////////////////////////////////////////////////////////////
  85. Sound3DClass::Sound3DClass (const Sound3DClass &src)
  86. : m_bAutoCalcVel (true),
  87. m_CurrentVelocity (0, 0, 0),
  88. m_MaxVolRadius (0),
  89. m_LastUpdate (0),
  90. m_IsStatic (false),
  91. m_IsTransformInitted (false),
  92. AudibleSoundClass (src)
  93. {
  94. (*this) = src;
  95. return ;
  96. }
  97. ////////////////////////////////////////////////////////////////////////////////////////////////
  98. //
  99. // ~Sound3DClass
  100. //
  101. ////////////////////////////////////////////////////////////////////////////////////////////////
  102. Sound3DClass::~Sound3DClass (void)
  103. {
  104. Free_Miles_Handle ();
  105. return ;
  106. }
  107. ////////////////////////////////////////////////////////////////////////////////////////////////
  108. //
  109. // operator=
  110. //
  111. ////////////////////////////////////////////////////////////////////////////////////////////////
  112. const Sound3DClass &
  113. Sound3DClass::operator= (const Sound3DClass &src)
  114. {
  115. m_bAutoCalcVel = src.m_bAutoCalcVel;
  116. m_CurrentVelocity = src.m_CurrentVelocity;
  117. m_MaxVolRadius = src.m_MaxVolRadius;
  118. m_IsStatic = src.m_IsStatic;
  119. m_LastUpdate = src.m_LastUpdate;
  120. // Call the base class
  121. AudibleSoundClass::operator= (src);
  122. return (*this);
  123. }
  124. ////////////////////////////////////////////////////////////////////////////////////////////////
  125. //
  126. // Play
  127. //
  128. ////////////////////////////////////////////////////////////////////////////////////////////////
  129. bool
  130. Sound3DClass::Play (bool alloc_handle)
  131. {
  132. // Record our first 'tick' if we just started playing
  133. if (m_State != STATE_PLAYING) {
  134. m_LastUpdate = TIMEGETTIME ();
  135. }
  136. // Allow the base class to process this call
  137. return AudibleSoundClass::Play (m_IsCulled == false);
  138. }
  139. ////////////////////////////////////////////////////////////////////////////////////////////////
  140. //
  141. // On_Frame_Update
  142. //
  143. ////////////////////////////////////////////////////////////////////////////////////////////////
  144. bool
  145. Sound3DClass::On_Frame_Update (unsigned int milliseconds)
  146. {
  147. Matrix3D prev_tm = m_PrevTransform;
  148. if (m_bDirty && (m_PhysWrapper != NULL)) {
  149. m_Scene->Update_Sound (m_PhysWrapper);
  150. m_bDirty = false;
  151. }
  152. //
  153. // Update the sound's position if its linked to a render object
  154. //
  155. Apply_Auto_Position ();
  156. //
  157. // Make sure the transform is initialized
  158. //
  159. if (m_IsTransformInitted == false) {
  160. prev_tm = m_Transform;
  161. }
  162. // Disabling auto-velocity because hardware doppler is poor...
  163. #if 0
  164. //
  165. // Update the current velocity if we are 'auto-calcing'.
  166. //
  167. if (m_bAutoCalcVel && Get_Class_ID () != CLASSID_LISTENER) {
  168. Vector3 last_pos = prev_tm.Get_Translation ();
  169. Vector3 curr_pos = m_Transform.Get_Translation ();
  170. //
  171. // Don't update the velocity if we haven't moved (optimization -- Miles calls
  172. // can be really slow)
  173. //
  174. if (last_pos != curr_pos) {
  175. Vector3 curr_vel;
  176. //
  177. // Extrapolate our current velocity given the last time slice and the distance
  178. // we moved.
  179. //
  180. float secs_since_last_update = (TIMEGETTIME () - m_LastUpdate);
  181. if (secs_since_last_update > 0) {
  182. curr_vel = ((curr_pos - last_pos) / secs_since_last_update);
  183. } else {
  184. curr_vel.Set (0, 0, 0);
  185. }
  186. Set_Velocity (curr_vel);
  187. }
  188. }
  189. #endif // doppler disable
  190. //
  191. // Remember when the last time we updated our 'auto-calc'
  192. // variables.
  193. //
  194. m_LastUpdate = TIMEGETTIME ();
  195. m_PrevTransform = m_Transform;
  196. //
  197. // If necessary, update the volume based on the distance
  198. // from the edge of the dropoff radius.
  199. //
  200. if (m_SoundHandle != NULL) {
  201. Update_Edge_Volume ();
  202. }
  203. return AudibleSoundClass::On_Frame_Update ();
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////////////////////
  206. //
  207. // Update_Edge_Volume
  208. //
  209. ////////////////////////////////////////////////////////////////////////////////////////////////
  210. void
  211. Sound3DClass::Update_Edge_Volume (void)
  212. {
  213. if (m_DropOffRadius == 0.0F || As_SoundPseudo3DClass () != NULL) {
  214. return ;
  215. }
  216. //
  217. // Find the difference in the sound position and its listener's position
  218. //
  219. Vector3 sound_pos = m_ListenerTransform.Get_Translation () - m_Transform.Get_Translation ();
  220. float distance = sound_pos.Quick_Length ();
  221. const float FALLOFF_RANGE = 0.85F;
  222. //
  223. // Are we close to the edge of the dropoff radius?
  224. //
  225. float falloff_start = (m_DropOffRadius * FALLOFF_RANGE);
  226. if (distance >= falloff_start && distance <= m_DropOffRadius) {
  227. //
  228. // Normalize our distance from the edge
  229. //
  230. float percent = (distance - falloff_start) / (m_DropOffRadius - falloff_start);
  231. percent = WWMath::Clamp (1.0F - percent, 0.0F, 1.0F);
  232. //
  233. // Update the sound volume
  234. //
  235. Internal_Set_Volume (m_RealVolume * percent);
  236. }
  237. return ;
  238. }
  239. ////////////////////////////////////////////////////////////////////////////////////////////////
  240. //
  241. // Set_Transform
  242. //
  243. ////////////////////////////////////////////////////////////////////////////////////////////////
  244. void
  245. Sound3DClass::Set_Transform (const Matrix3D &transform)
  246. {
  247. if (transform == m_Transform) {
  248. return ;
  249. }
  250. // Update our internal transform
  251. m_PrevTransform = m_Transform;
  252. m_Transform = transform;
  253. Set_Dirty ();
  254. if (m_IsTransformInitted == false) {
  255. m_PrevTransform = transform;
  256. m_IsTransformInitted = true;
  257. }
  258. Update_Miles_Transform ();
  259. return ;
  260. }
  261. ////////////////////////////////////////////////////////////////////////////////////////////////
  262. //
  263. // Set_Listener_Transform
  264. //
  265. ////////////////////////////////////////////////////////////////////////////////////////////////
  266. void
  267. Sound3DClass::Set_Listener_Transform (const Matrix3D &tm)
  268. {
  269. //
  270. // If the transform has changed, then cache the new transform
  271. // and update the sound's position in the "Mile's" world
  272. //
  273. if (m_ListenerTransform != tm) {
  274. m_ListenerTransform = tm;
  275. Update_Miles_Transform ();
  276. }
  277. return ;
  278. }
  279. ////////////////////////////////////////////////////////////////////////////////////////////////
  280. //
  281. // Update_Miles_Transform
  282. //
  283. ////////////////////////////////////////////////////////////////////////////////////////////////
  284. void
  285. Sound3DClass::Update_Miles_Transform (void)
  286. {
  287. //
  288. // Do we have a valid miles handle?
  289. //
  290. if (m_SoundHandle != NULL) {
  291. //
  292. // Build a matrix to transform coordinates from world-space to listener-space
  293. //
  294. Matrix3D world_to_listener_tm;
  295. m_ListenerTransform.Get_Orthogonal_Inverse (world_to_listener_tm);
  296. //
  297. // Transform the object's TM into "listener-space"
  298. //
  299. Matrix3D listener_space_tm = world_to_listener_tm * m_Transform;
  300. //
  301. // Pass the sound's position onto miles
  302. //
  303. Vector3 position = listener_space_tm.Get_Translation ();
  304. ::AIL_set_3D_position (m_SoundHandle->Get_H3DSAMPLE (), -position.Y, position.Z, position.X);
  305. //
  306. // Pass the sound's orientation (facing) onto miles
  307. //
  308. Vector3 facing = listener_space_tm.Get_X_Vector ();
  309. Vector3 up = listener_space_tm.Get_Z_Vector ();
  310. ::AIL_set_3D_orientation (m_SoundHandle->Get_H3DSAMPLE (),
  311. -facing.Y,
  312. facing.Z,
  313. facing.X,
  314. -up.Y,
  315. up.Z,
  316. up.X);
  317. }
  318. return ;
  319. }
  320. ////////////////////////////////////////////////////////////////////////////////////////////////
  321. //
  322. // Set_Position
  323. //
  324. ////////////////////////////////////////////////////////////////////////////////////////////////
  325. void
  326. Sound3DClass::Set_Position (const Vector3 &position)
  327. {
  328. //
  329. // Pass the sound's position onto miles
  330. //
  331. if (m_Transform.Get_Translation () != position) {
  332. // Update our internal transform
  333. //
  334. // SKB: 4/13/01 - Confirmed to be OK by Pat Smith.
  335. // Took Set_Transform() outside of condition because even if sound is
  336. // not playing I need to be able to change it's position.
  337. // I had a problem that sounds would never be added to the scene because
  338. // their positions stayed at 0,0,0 even after this Set_Postion() call.
  339. m_PrevTransform = m_Transform;
  340. m_Transform.Set_Translation (position);
  341. Set_Dirty ();
  342. if (m_IsTransformInitted == false) {
  343. m_PrevTransform = m_Transform;
  344. m_IsTransformInitted = true;
  345. }
  346. if (m_SoundHandle != NULL) {
  347. //
  348. // Transform the sound's position into 'listener-space'
  349. //
  350. Vector3 sound_pos = position;
  351. Vector3 listener_space_pos;
  352. Matrix3D::Inverse_Transform_Vector (m_ListenerTransform, sound_pos, &listener_space_pos);
  353. //
  354. // Update the object's position inside of Miles
  355. //
  356. ::AIL_set_3D_position (m_SoundHandle->Get_H3DSAMPLE (), -listener_space_pos.Y,
  357. listener_space_pos.Z, listener_space_pos.X);
  358. }
  359. }
  360. return ;
  361. }
  362. ////////////////////////////////////////////////////////////////////////////////////////////////
  363. //
  364. // Set_Velocity
  365. //
  366. ////////////////////////////////////////////////////////////////////////////////////////////////
  367. void
  368. Sound3DClass::Set_Velocity (const Vector3 &velocity)
  369. {
  370. MMSLockClass lock;
  371. m_CurrentVelocity = velocity;
  372. Set_Dirty ();
  373. //
  374. // Pass the sound's velocity onto miles
  375. //
  376. if (m_SoundHandle != NULL) {
  377. //WWDEBUG_SAY (("Current Velocity: %.2f %.2f %.2f\n", m_CurrentVelocity.X, m_CurrentVelocity.Y, m_CurrentVelocity.Z));
  378. ::AIL_set_3D_velocity_vector (m_SoundHandle->Get_H3DSAMPLE (),
  379. -m_CurrentVelocity.Y,
  380. m_CurrentVelocity.Z,
  381. m_CurrentVelocity.X);
  382. }
  383. return ;
  384. }
  385. ////////////////////////////////////////////////////////////////////////////////////////////////
  386. //
  387. // Set_DropOff_Radius
  388. //
  389. ////////////////////////////////////////////////////////////////////////////////////////////////
  390. void
  391. Sound3DClass::Set_DropOff_Radius (float radius)
  392. {
  393. //MMSLockClass lock;
  394. m_DropOffRadius = radius;
  395. Set_Dirty ();
  396. // Pass attenuation settings onto miles
  397. if (m_SoundHandle != NULL) {
  398. ::AIL_set_3D_sample_distances ( m_SoundHandle->Get_H3DSAMPLE (),
  399. m_DropOffRadius,
  400. (m_MaxVolRadius > 1.0F) ? m_MaxVolRadius : 1.0F);
  401. }
  402. return ;
  403. }
  404. ////////////////////////////////////////////////////////////////////////////////////////////////
  405. //
  406. // Set_Max_Vol_Radius
  407. //
  408. ////////////////////////////////////////////////////////////////////////////////////////////////
  409. void
  410. Sound3DClass::Set_Max_Vol_Radius (float radius)
  411. {
  412. m_MaxVolRadius = radius;
  413. Set_Dirty ();
  414. // Pass attenuation settings onto miles
  415. if (m_SoundHandle != NULL) {
  416. ::AIL_set_3D_sample_distances ( m_SoundHandle->Get_H3DSAMPLE (),
  417. m_DropOffRadius,
  418. (m_MaxVolRadius > 1.0F) ? m_MaxVolRadius : 1.0F);
  419. }
  420. return ;
  421. }
  422. ////////////////////////////////////////////////////////////////////////////////////////////////
  423. //
  424. // Initialize_Miles_Handle
  425. //
  426. ////////////////////////////////////////////////////////////////////////////////////////////////
  427. void
  428. Sound3DClass::Initialize_Miles_Handle (void)
  429. {
  430. MMSLockClass lock;
  431. // If this sound is already playing, then update its
  432. // playing position to make sure we really should
  433. // be playing it... (it will free the miles handle if not)
  434. if (m_State == STATE_PLAYING) {
  435. Update_Play_Position ();
  436. }
  437. // Do we have a valid sample handle from miles?
  438. if (m_SoundHandle != NULL) {
  439. //
  440. // Pass the actual sound data onto the sample
  441. //
  442. m_SoundHandle->Initialize (m_Buffer);
  443. //
  444. // Record the total length of the sample in milliseconds...
  445. //
  446. m_SoundHandle->Get_Sample_MS_Position ((S32 *)&m_Length, NULL);
  447. //
  448. // Pass our cached settings onto miles
  449. //
  450. float real_volume = Determine_Real_Volume ();
  451. m_SoundHandle->Set_Sample_Volume (int(real_volume * 127.0F));
  452. m_SoundHandle->Set_Sample_Pan (int(m_Pan * 127.0F));
  453. m_SoundHandle->Set_Sample_Loop_Count (m_LoopCount);
  454. //
  455. // Pass attenuation settings onto miles
  456. //
  457. ::AIL_set_3D_sample_distances ( m_SoundHandle->Get_H3DSAMPLE (),
  458. m_DropOffRadius,
  459. (m_MaxVolRadius > 1.0F) ? m_MaxVolRadius : 1.0F);
  460. //
  461. // Assign the 3D effects level accordingly (for reverb, etc)
  462. //
  463. ::AIL_set_3D_sample_effects_level (m_SoundHandle->Get_H3DSAMPLE (),
  464. WWAudioClass::Get_Instance ()->Get_Effects_Level ());
  465. //
  466. // Pass the sound's position and orientation onto Miles
  467. //
  468. Update_Miles_Transform ();
  469. //
  470. // Apply the pitch factor (if necessary)
  471. //
  472. if (m_PitchFactor != 1.0F) {
  473. Set_Pitch_Factor (m_PitchFactor);
  474. }
  475. // If this sound is already playing (and just now got a handle)
  476. // then make sure we start it.
  477. if (m_State == STATE_PLAYING) {
  478. m_SoundHandle->Start_Sample ();
  479. // Update the loop count based on the number of loops left
  480. m_SoundHandle->Set_Sample_Loop_Count (m_LoopsLeft);
  481. }
  482. // Seek to the position of the sound where we last left off.
  483. // For example, this sound could have gotten bumped due to a low priority,
  484. // but is now back and ready to resume at the position it would have been
  485. // at if it was never bumped.
  486. Seek (m_CurrentPosition);
  487. // Associate this object instance with the handle
  488. m_SoundHandle->Set_Sample_User_Data (INFO_OBJECT_PTR, (S32)this);
  489. }
  490. return ;
  491. }
  492. ////////////////////////////////////////////////////////////////////////////////////////////////
  493. //
  494. // Allocate_Miles_Handle
  495. //
  496. ////////////////////////////////////////////////////////////////////////////////////////////////
  497. void
  498. Sound3DClass::Allocate_Miles_Handle (void)
  499. {
  500. //MMSLockClass lock;
  501. //
  502. // If we need to, get a play-handle from the audio system
  503. //
  504. if (m_SoundHandle == NULL) {
  505. Set_Miles_Handle ((MILES_HANDLE)WWAudioClass::Get_Instance ()->Get_3D_Sample (*this));
  506. }
  507. return ;
  508. }
  509. ////////////////////////////////////////////////////////////////////////////////////////////////
  510. //
  511. // Add_To_Scene
  512. //
  513. ////////////////////////////////////////////////////////////////////////////////////////////////
  514. void
  515. Sound3DClass::Add_To_Scene (bool start_playing)
  516. {
  517. SoundSceneClass *scene = WWAudioClass::Get_Instance ()->Get_Sound_Scene ();
  518. if ((scene != NULL) && (m_Scene == NULL)) {
  519. // Determine what culling system this sound belongs to
  520. if (m_IsStatic) {
  521. scene->Add_Static_Sound (this, start_playing);
  522. } else {
  523. scene->Add_Sound (this, start_playing);
  524. }
  525. m_Scene = scene;
  526. }
  527. return ;
  528. }
  529. ////////////////////////////////////////////////////////////////////////////////////////////////
  530. //
  531. // Remove_From_Scene
  532. //
  533. ////////////////////////////////////////////////////////////////////////////////////////////////
  534. void
  535. Sound3DClass::Remove_From_Scene (void)
  536. {
  537. if (m_Scene != NULL) {
  538. // Determine what culling system this sound belongs to
  539. if (m_IsStatic) {
  540. m_Scene->Remove_Static_Sound (this);
  541. } else {
  542. m_Scene->Remove_Sound (this);
  543. }
  544. m_Scene = NULL;
  545. m_PhysWrapper = NULL;
  546. }
  547. return ;
  548. }
  549. ////////////////////////////////////////////////////////////////////////////////////////////////
  550. //
  551. // On_Loop_End
  552. //
  553. ////////////////////////////////////////////////////////////////////////////////////////////////
  554. void
  555. Sound3DClass::On_Loop_End (void)
  556. {
  557. // Allow the base class to process this message
  558. AudibleSoundClass::On_Loop_End ();
  559. return ;
  560. }
  561. /////////////////////////////////////////////////////////////////////////////////
  562. //
  563. // Get_Factory
  564. //
  565. /////////////////////////////////////////////////////////////////////////////////
  566. const PersistFactoryClass &
  567. Sound3DClass::Get_Factory (void) const
  568. {
  569. return _Sound3DPersistFactory;
  570. }
  571. //////////////////////////////////////////////////////////////////////////////////
  572. //
  573. // Save
  574. //
  575. //////////////////////////////////////////////////////////////////////////////////
  576. bool
  577. Sound3DClass::Save (ChunkSaveClass &csave)
  578. {
  579. csave.Begin_Chunk (CHUNKID_BASE_CLASS);
  580. AudibleSoundClass::Save (csave);
  581. csave.End_Chunk ();
  582. csave.Begin_Chunk (CHUNKID_VARIABLES);
  583. WRITE_MICRO_CHUNK (csave, VARID_AUTO_CALC_VEL, m_bAutoCalcVel);
  584. WRITE_MICRO_CHUNK (csave, VARID_CURR_VEL, m_CurrentVelocity);
  585. WRITE_MICRO_CHUNK (csave, VARID_MAX_VOL_RADIUS, m_MaxVolRadius);
  586. WRITE_MICRO_CHUNK (csave, VARID_IS_STATIC, m_IsStatic);
  587. csave.End_Chunk ();
  588. return true;
  589. }
  590. //////////////////////////////////////////////////////////////////////////////////
  591. //
  592. // Load
  593. //
  594. //////////////////////////////////////////////////////////////////////////////////
  595. bool
  596. Sound3DClass::Load (ChunkLoadClass &cload)
  597. {
  598. while (cload.Open_Chunk ()) {
  599. switch (cload.Cur_Chunk_ID ()) {
  600. case CHUNKID_BASE_CLASS:
  601. AudibleSoundClass::Load (cload);
  602. break;
  603. case CHUNKID_VARIABLES:
  604. {
  605. //
  606. // Read all the variables from their micro-chunks
  607. //
  608. while (cload.Open_Micro_Chunk ()) {
  609. switch (cload.Cur_Micro_Chunk_ID ()) {
  610. READ_MICRO_CHUNK (cload, VARID_AUTO_CALC_VEL, m_bAutoCalcVel);
  611. READ_MICRO_CHUNK (cload, VARID_CURR_VEL, m_CurrentVelocity);
  612. READ_MICRO_CHUNK (cload, VARID_MAX_VOL_RADIUS, m_MaxVolRadius);
  613. READ_MICRO_CHUNK (cload, VARID_IS_STATIC, m_IsStatic);
  614. }
  615. cload.Close_Micro_Chunk ();
  616. }
  617. }
  618. break;
  619. }
  620. cload.Close_Chunk ();
  621. }
  622. return true;
  623. }
  624. ////////////////////////////////////////////////////////////////////////////////////////////////
  625. //
  626. // Set_Miles_Handle
  627. //
  628. ////////////////////////////////////////////////////////////////////////////////////////////////
  629. void
  630. Sound3DClass::Set_Miles_Handle (MILES_HANDLE handle)
  631. {
  632. //
  633. // Start fresh
  634. //
  635. Free_Miles_Handle ();
  636. //
  637. // Is our data valid?
  638. //
  639. if (handle != INVALID_MILES_HANDLE && m_Buffer != NULL) {
  640. //
  641. // Configure the sound handle
  642. //
  643. m_SoundHandle = new Sound3DHandleClass;
  644. m_SoundHandle->Set_Miles_Handle (handle);
  645. //
  646. // Use this new handle
  647. //
  648. Initialize_Miles_Handle ();
  649. }
  650. return ;
  651. }