soundrobj.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  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 : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/soundrobj.cpp $*
  25. * *
  26. * Author:: Patrick Smith *
  27. * *
  28. * $Modtime:: 1/16/02 10:21a $*
  29. * *
  30. * $Revision:: 4 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "soundrobj.h"
  36. #include "audiblesound.h"
  37. #include "sound3d.h"
  38. #include "wwaudio.h"
  39. #include "ffactory.h"
  40. #include "wwfile.h"
  41. #include "chunkio.h"
  42. #include "scene.h"
  43. //////////////////////////////////////////////////////////////////////////////////
  44. // Global variables
  45. //////////////////////////////////////////////////////////////////////////////////
  46. SoundRenderObjLoaderClass _SoundRenderObjLoader;
  47. //////////////////////////////////////////////////////////////////////////////////
  48. //
  49. // SoundRenderObjClass
  50. //
  51. //////////////////////////////////////////////////////////////////////////////////
  52. SoundRenderObjClass::SoundRenderObjClass (void)
  53. : Flags (FLAG_STOP_WHEN_HIDDEN),
  54. Sound (NULL),
  55. IsInitialized (false)
  56. {
  57. return ;
  58. }
  59. //////////////////////////////////////////////////////////////////////////////////
  60. //
  61. // SoundRenderObjClass
  62. //
  63. //////////////////////////////////////////////////////////////////////////////////
  64. SoundRenderObjClass::SoundRenderObjClass (const SoundRenderObjClass &src)
  65. : Flags (FLAG_STOP_WHEN_HIDDEN),
  66. Sound (NULL),
  67. IsInitialized (false)
  68. {
  69. (*this) = src;
  70. return ;
  71. }
  72. //////////////////////////////////////////////////////////////////////////////////
  73. //
  74. // ~SoundRenderObjClass
  75. //
  76. //////////////////////////////////////////////////////////////////////////////////
  77. SoundRenderObjClass::~SoundRenderObjClass (void)
  78. {
  79. //
  80. // Remove the old sound from the world (if necessary)
  81. //
  82. if (Sound != NULL) {
  83. Sound->Attach_To_Object (NULL);
  84. Sound->Remove_From_Scene ();
  85. REF_PTR_RELEASE (Sound);
  86. }
  87. return ;
  88. }
  89. //////////////////////////////////////////////////////////////////////////////////
  90. //
  91. // operator=
  92. //
  93. //////////////////////////////////////////////////////////////////////////////////
  94. const SoundRenderObjClass &
  95. SoundRenderObjClass::operator= (const SoundRenderObjClass &src)
  96. {
  97. //
  98. // Create a definition from the src sound object
  99. //
  100. AudibleSoundDefinitionClass definition;
  101. definition.Initialize_From_Sound (src.Sound);
  102. //
  103. // Create the internal sound object from the definition
  104. //
  105. Set_Sound (&definition);
  106. //
  107. // Copy the other misc settings
  108. //
  109. Name = src.Name;
  110. return *this;
  111. }
  112. //////////////////////////////////////////////////////////////////////////////////
  113. //
  114. // Set_Sound
  115. //
  116. //////////////////////////////////////////////////////////////////////////////////
  117. void
  118. SoundRenderObjClass::Set_Sound (AudibleSoundDefinitionClass *definition)
  119. {
  120. //
  121. // Remove the old sound from the world (if necessary)
  122. //
  123. if (Sound != NULL) {
  124. Sound->Remove_From_Scene ();
  125. REF_PTR_RELEASE (Sound);
  126. }
  127. //
  128. // Create the sound object from its definition
  129. //
  130. if (definition != NULL) {
  131. Sound = (AudibleSoundClass *)definition->Create ();
  132. }
  133. return ;
  134. }
  135. //////////////////////////////////////////////////////////////////////////////////
  136. //
  137. // On_Frame_Update
  138. //
  139. //////////////////////////////////////////////////////////////////////////////////
  140. void
  141. SoundRenderObjClass::On_Frame_Update (void)
  142. {
  143. //
  144. // Stop the sound from playing (if necessary)
  145. //
  146. if ( Sound != NULL &&
  147. Sound->Is_In_Scene () &&
  148. Sound->Is_Playing () == false)
  149. {
  150. Sound->Attach_To_Object (NULL);
  151. Sound->Remove_From_Scene ();
  152. }
  153. return ;
  154. }
  155. //////////////////////////////////////////////////////////////////////////////////
  156. //
  157. // Set_Hidden
  158. //
  159. //////////////////////////////////////////////////////////////////////////////////
  160. void
  161. SoundRenderObjClass::Set_Hidden (int onoff)
  162. {
  163. int before = Is_Not_Hidden_At_All ();
  164. RenderObjClass::Set_Hidden (onoff);
  165. //
  166. // If we've changed state, then update the visibility
  167. //
  168. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  169. IsInitialized = true;
  170. Update_On_Visibilty ();
  171. }
  172. return ;
  173. }
  174. //////////////////////////////////////////////////////////////////////////////////
  175. //
  176. // Set_Visible
  177. //
  178. //////////////////////////////////////////////////////////////////////////////////
  179. void
  180. SoundRenderObjClass::Set_Visible (int onoff)
  181. {
  182. int before = Is_Not_Hidden_At_All ();
  183. RenderObjClass::Set_Visible (onoff);
  184. //
  185. // If we've changed state, then update the visibility
  186. //
  187. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  188. IsInitialized = true;
  189. Update_On_Visibilty ();
  190. }
  191. return ;
  192. }
  193. //////////////////////////////////////////////////////////////////////////////////
  194. //
  195. // Set_Animation_Hidden
  196. //
  197. //////////////////////////////////////////////////////////////////////////////////
  198. void
  199. SoundRenderObjClass::Set_Animation_Hidden (int onoff)
  200. {
  201. int before = Is_Not_Hidden_At_All ();
  202. RenderObjClass::Set_Animation_Hidden (onoff);
  203. //
  204. // If we've changed state, then update the visibility
  205. //
  206. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  207. IsInitialized = true;
  208. Update_On_Visibilty ();
  209. }
  210. return ;
  211. }
  212. //////////////////////////////////////////////////////////////////////////////////
  213. //
  214. // Set_Force_Visible
  215. //
  216. //////////////////////////////////////////////////////////////////////////////////
  217. void
  218. SoundRenderObjClass::Set_Force_Visible (int onoff)
  219. {
  220. int before = Is_Not_Hidden_At_All ();
  221. RenderObjClass::Set_Force_Visible (onoff);
  222. //
  223. // If we've changed state, then update the visibility
  224. //
  225. if (IsInitialized == false || Is_Not_Hidden_At_All () != before) {
  226. IsInitialized = true;
  227. Update_On_Visibilty ();
  228. }
  229. return ;
  230. }
  231. //////////////////////////////////////////////////////////////////////////////////
  232. //
  233. // Update_On_Visibilty
  234. //
  235. //////////////////////////////////////////////////////////////////////////////////
  236. void
  237. SoundRenderObjClass::Update_On_Visibilty (void)
  238. {
  239. if (Sound == NULL) {
  240. return ;
  241. }
  242. //
  243. // Ensure our transform is correct
  244. //
  245. Validate_Transform ();
  246. //
  247. // Either add the sound object to the sound scene
  248. // or remove it from the sound scene depending
  249. // on the visibility state of the render object.
  250. //
  251. if ( Is_Not_Hidden_At_All () &&
  252. Sound->Is_In_Scene () == false &&
  253. Peek_Scene () != NULL)
  254. {
  255. //
  256. // Make sure the sound is properly attached to this render
  257. // object and then add it to the scene
  258. //
  259. Sound->Attach_To_Object (this);
  260. Sound->Add_To_Scene (true);
  261. } else if ((Is_Not_Hidden_At_All () == false) || (Peek_Scene () == NULL)) {
  262. //
  263. // Remove the sound from the scene (it will stop playing)
  264. //
  265. if ((Flags & FLAG_STOP_WHEN_HIDDEN) != 0 || (Peek_Scene () == NULL)) {
  266. Sound->Attach_To_Object (NULL);
  267. Sound->Remove_From_Scene ();
  268. }
  269. }
  270. return ;
  271. }
  272. //////////////////////////////////////////////////////////////////////////////////
  273. //
  274. // Get_Sound
  275. //
  276. //////////////////////////////////////////////////////////////////////////////////
  277. AudibleSoundClass *
  278. SoundRenderObjClass::Get_Sound (void) const
  279. {
  280. if (Sound != NULL) {
  281. Sound->Add_Ref ();
  282. }
  283. return Sound;
  284. }
  285. //////////////////////////////////////////////////////////////////////////////
  286. //
  287. // Set_Flag
  288. //
  289. //////////////////////////////////////////////////////////////////////////////
  290. void
  291. SoundRenderObjClass::Set_Flag (uint32 flag, bool onoff)
  292. {
  293. Flags &= ~flag;
  294. if (onoff) {
  295. Flags |= flag;
  296. }
  297. return ;
  298. }
  299. //////////////////////////////////////////////////////////////////////////////////
  300. //
  301. // Notify_Added
  302. //
  303. //////////////////////////////////////////////////////////////////////////////////
  304. void
  305. SoundRenderObjClass::Notify_Added (SceneClass *scene)
  306. {
  307. RenderObjClass::Notify_Added (scene);
  308. scene->Register (this, SceneClass::ON_FRAME_UPDATE);
  309. Update_On_Visibilty ();
  310. return ;
  311. }
  312. //////////////////////////////////////////////////////////////////////////////////
  313. //
  314. // Notify_Removed
  315. //
  316. //////////////////////////////////////////////////////////////////////////////////
  317. void
  318. SoundRenderObjClass::Notify_Removed (SceneClass *scene)
  319. {
  320. scene->Unregister (this, SceneClass::ON_FRAME_UPDATE);
  321. RenderObjClass::Notify_Removed (scene);
  322. Update_On_Visibilty ();
  323. return ;
  324. }
  325. //////////////////////////////////////////////////////////////////////////////////
  326. //
  327. // Set_Transform
  328. //
  329. //////////////////////////////////////////////////////////////////////////////////
  330. void
  331. SoundRenderObjClass::Set_Transform (const Matrix3D &tm)
  332. {
  333. RenderObjClass::Set_Transform (tm);
  334. if (IsInitialized == false) {
  335. IsInitialized = true;
  336. Update_On_Visibilty ();
  337. }
  338. return ;
  339. }
  340. //////////////////////////////////////////////////////////////////////////////////
  341. //
  342. // Set_Position
  343. //
  344. //////////////////////////////////////////////////////////////////////////////////
  345. void
  346. SoundRenderObjClass::Set_Position (const Vector3 &pos)
  347. {
  348. RenderObjClass::Set_Position (pos);
  349. if (IsInitialized == false) {
  350. IsInitialized = true;
  351. Update_On_Visibilty ();
  352. }
  353. return ;
  354. }
  355. //*********************************************************************************
  356. //
  357. // Start of SoundRenderObjDefClass
  358. //
  359. //*********************************************************************************
  360. //////////////////////////////////////////////////////////////////////////////////
  361. //
  362. // SoundRenderObjDefClass
  363. //
  364. //////////////////////////////////////////////////////////////////////////////////
  365. SoundRenderObjDefClass::SoundRenderObjDefClass (void)
  366. : Version (W3D_CURRENT_SOUNDROBJ_VERSION),
  367. Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN)
  368. {
  369. return ;
  370. }
  371. //////////////////////////////////////////////////////////////////////////////////
  372. //
  373. // SoundRenderObjDefClass
  374. //
  375. //////////////////////////////////////////////////////////////////////////////////
  376. SoundRenderObjDefClass::SoundRenderObjDefClass (SoundRenderObjClass &render_obj)
  377. : Version (W3D_CURRENT_SOUNDROBJ_VERSION),
  378. Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN)
  379. {
  380. Initialize (render_obj);
  381. return ;
  382. }
  383. //////////////////////////////////////////////////////////////////////////////////
  384. //
  385. // SoundRenderObjDefClass
  386. //
  387. //////////////////////////////////////////////////////////////////////////////////
  388. SoundRenderObjDefClass::SoundRenderObjDefClass (const SoundRenderObjDefClass &src)
  389. : Version (W3D_CURRENT_SOUNDROBJ_VERSION),
  390. Flags (SoundRenderObjClass::FLAG_STOP_WHEN_HIDDEN)
  391. {
  392. (*this) = src;
  393. return ;
  394. }
  395. //////////////////////////////////////////////////////////////////////////////////
  396. //
  397. // ~SoundRenderObjDefClass
  398. //
  399. //////////////////////////////////////////////////////////////////////////////////
  400. SoundRenderObjDefClass::~SoundRenderObjDefClass (void)
  401. {
  402. return ;
  403. }
  404. //////////////////////////////////////////////////////////////////////////////////
  405. //
  406. // operator=
  407. //
  408. //////////////////////////////////////////////////////////////////////////////////
  409. const SoundRenderObjDefClass &
  410. SoundRenderObjDefClass::operator= (const SoundRenderObjDefClass &src)
  411. {
  412. Definition = src.Definition;
  413. Version = src.Version;
  414. Name = src.Name;
  415. return (*this);
  416. }
  417. //////////////////////////////////////////////////////////////////////////////////
  418. //
  419. // Create
  420. //
  421. //////////////////////////////////////////////////////////////////////////////////
  422. RenderObjClass *
  423. SoundRenderObjDefClass::Create (void)
  424. {
  425. //
  426. // Allocate and initialize a new instance
  427. //
  428. SoundRenderObjClass *render_obj = new SoundRenderObjClass;
  429. render_obj->Set_Name (Name);
  430. render_obj->Set_Sound (&Definition);
  431. render_obj->Set_Flags (Flags);
  432. return render_obj;
  433. }
  434. //////////////////////////////////////////////////////////////////////////////////
  435. //
  436. // Initialize
  437. //
  438. //////////////////////////////////////////////////////////////////////////////////
  439. void
  440. SoundRenderObjDefClass::Initialize (SoundRenderObjClass &render_obj)
  441. {
  442. //
  443. // Copy the settings from the sound object into our definition
  444. //
  445. Definition.Initialize_From_Sound (render_obj.Peek_Sound ());
  446. //
  447. // Copy the flags from the render object
  448. //
  449. Flags = (SoundRenderObjClass::FLAGS)render_obj.Get_Flags ();
  450. //
  451. // Copy the name
  452. //
  453. Name = render_obj.Get_Name ();
  454. return ;
  455. }
  456. ///////////////////////////////////////////////////////////////////////////////////
  457. //
  458. // Load
  459. //
  460. ///////////////////////////////////////////////////////////////////////////////////
  461. WW3DErrorType
  462. SoundRenderObjDefClass::Load_W3D (ChunkLoadClass &cload)
  463. {
  464. WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED;
  465. //
  466. // Attempt to read the different sections of the definition
  467. //
  468. if ((Read_Header (cload) == WW3D_ERROR_OK) &&
  469. (Read_Definition (cload) == WW3D_ERROR_OK))
  470. {
  471. retval = WW3D_ERROR_OK;
  472. }
  473. return retval;
  474. }
  475. //////////////////////////////////////////////////////////////////////////////////
  476. //
  477. // Save_W3D
  478. //
  479. //////////////////////////////////////////////////////////////////////////////////
  480. WW3DErrorType
  481. SoundRenderObjDefClass::Save_W3D (ChunkSaveClass &csave)
  482. {
  483. WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED;
  484. //
  485. // Begin a chunk that identifies a sound render object
  486. //
  487. if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ) == TRUE) {
  488. //
  489. // Attempt to save the different sections of the aggregate definition
  490. //
  491. if ((Write_Header (csave) == WW3D_ERROR_OK) &&
  492. (Write_Definition (csave) == WW3D_ERROR_OK))
  493. {
  494. retval = WW3D_ERROR_OK;
  495. }
  496. csave.End_Chunk ();
  497. }
  498. return retval;
  499. }
  500. ///////////////////////////////////////////////////////////////////////////////////
  501. //
  502. // Read_Header
  503. //
  504. ///////////////////////////////////////////////////////////////////////////////////
  505. WW3DErrorType
  506. SoundRenderObjDefClass::Read_Header (ChunkLoadClass &cload)
  507. {
  508. WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED;
  509. //
  510. // Is this the header chunk?
  511. //
  512. if (cload.Open_Chunk () &&
  513. (cload.Cur_Chunk_ID () == W3D_CHUNK_SOUNDROBJ_HEADER))
  514. {
  515. //
  516. // Read the header from the chunk
  517. //
  518. W3dSoundRObjHeaderStruct header = { 0 };
  519. if (cload.Read (&header, sizeof (header)) == sizeof (header)) {
  520. //
  521. // Copy the names from the header structure
  522. //
  523. Name = header.Name;
  524. Version = header.Version;
  525. Flags = (SoundRenderObjClass::FLAGS)header.Flags;
  526. retval = WW3D_ERROR_OK;
  527. }
  528. cload.Close_Chunk ();
  529. }
  530. return retval;
  531. }
  532. ///////////////////////////////////////////////////////////////////////////////////
  533. //
  534. // Read_Definition
  535. //
  536. ///////////////////////////////////////////////////////////////////////////////////
  537. WW3DErrorType
  538. SoundRenderObjDefClass::Read_Definition (ChunkLoadClass &cload)
  539. {
  540. WW3DErrorType retval = WW3D_ERROR_LOAD_FAILED;
  541. //
  542. // Is this the right chunk?
  543. //
  544. if (cload.Open_Chunk () &&
  545. (cload.Cur_Chunk_ID () == W3D_CHUNK_SOUNDROBJ_DEFINITION))
  546. {
  547. //
  548. // Ask the definition to load its settings from the chunk
  549. //
  550. if (Definition.Load (cload)) {
  551. retval = WW3D_ERROR_OK;
  552. }
  553. cload.Close_Chunk ();
  554. }
  555. return retval;
  556. }
  557. ///////////////////////////////////////////////////////////////////////////////////
  558. //
  559. // Write_Header
  560. //
  561. ///////////////////////////////////////////////////////////////////////////////////
  562. WW3DErrorType
  563. SoundRenderObjDefClass::Write_Header (ChunkSaveClass &csave)
  564. {
  565. WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED;
  566. //
  567. // Begin a chunk that identifies the aggregate
  568. //
  569. if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ_HEADER) == TRUE) {
  570. //
  571. // Fill the header structure
  572. //
  573. W3dSoundRObjHeaderStruct header = { 0 };
  574. header.Version = W3D_CURRENT_AGGREGATE_VERSION;
  575. header.Flags = Flags;
  576. ::lstrcpyn (header.Name, (const char *)Name, sizeof (header.Name));
  577. header.Name[sizeof (header.Name) - 1] = 0;
  578. //
  579. // Write the header out to the chunk
  580. //
  581. if (csave.Write (&header, sizeof (header)) == sizeof (header)) {
  582. retval = WW3D_ERROR_OK;
  583. }
  584. // End the header chunk
  585. csave.End_Chunk ();
  586. }
  587. return retval;
  588. }
  589. ///////////////////////////////////////////////////////////////////////////////////
  590. //
  591. // Write_Definition
  592. //
  593. ///////////////////////////////////////////////////////////////////////////////////
  594. WW3DErrorType
  595. SoundRenderObjDefClass::Write_Definition (ChunkSaveClass &csave)
  596. {
  597. WW3DErrorType retval = WW3D_ERROR_SAVE_FAILED;
  598. //
  599. // Save the definition to its own chunk
  600. //
  601. if (csave.Begin_Chunk (W3D_CHUNK_SOUNDROBJ_DEFINITION) == TRUE) {
  602. if (Definition.Save (csave)) {
  603. retval = WW3D_ERROR_OK;
  604. }
  605. csave.End_Chunk ();
  606. }
  607. return retval;
  608. }
  609. //*********************************************************************************
  610. //
  611. // Start of SoundRenderObjDefClass
  612. //
  613. //*********************************************************************************
  614. ///////////////////////////////////////////////////////////////////////////////////
  615. //
  616. // Load_W3D
  617. //
  618. ///////////////////////////////////////////////////////////////////////////////////
  619. PrototypeClass *
  620. SoundRenderObjLoaderClass::Load_W3D (ChunkLoadClass &cload)
  621. {
  622. SoundRenderObjPrototypeClass *prototype = NULL;
  623. //
  624. // Create a definition object
  625. //
  626. SoundRenderObjDefClass *definition = new SoundRenderObjDefClass;
  627. if (definition != NULL) {
  628. //
  629. // Ask the definition object to load the sound data
  630. //
  631. if (definition->Load_W3D (cload) == WW3D_ERROR_OK) {
  632. //
  633. // Success! Create a prototype from the definition
  634. //
  635. prototype = new SoundRenderObjPrototypeClass (definition);
  636. }
  637. REF_PTR_RELEASE (definition);
  638. }
  639. return prototype;
  640. }