SoundData.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Sound/SoundData.h>
  14. #include <Engine/Base/Memory.h>
  15. #include <Engine/Base/Stream.h>
  16. #include <Engine/Base/ListIterator.inl>
  17. #include <Engine/Sound/Wave.h>
  18. #include <Engine/Sound/SoundDecoder.h>
  19. #include <Engine/Sound/SoundLibrary.h>
  20. #include <Engine/Sound/SoundObject.h>
  21. #include <Engine/Templates/Stock_CSoundData.h>
  22. /* ====================================================
  23. *
  24. * Sound data awareness functions
  25. */
  26. /*
  27. * Pause all playing
  28. */
  29. void CSoundData::PausePlayingObjects(void)
  30. {
  31. // for all objects linked to data pause playing
  32. FOREACHINLIST(CSoundObject, so_Node, sd_ClhLinkList, itCsoPause) {
  33. // pause playing
  34. itCsoPause->Pause();
  35. }
  36. }
  37. /*
  38. * For all objects resume play
  39. */
  40. void CSoundData::ResumePlayingObjects(void)
  41. {
  42. // for all objects resume play
  43. FOREACHINLIST(CSoundObject, so_Node, sd_ClhLinkList, itCsoResume) {
  44. // call play method again
  45. itCsoResume->Resume();
  46. }
  47. }
  48. /*
  49. * Add object in sound aware list
  50. */
  51. void CSoundData::AddObjectLink(CSoundObject &CsoAdd)
  52. {
  53. // add object to list tail
  54. sd_ClhLinkList.AddTail(CsoAdd.so_Node);
  55. }
  56. /*
  57. * Remove a object from aware list
  58. */
  59. void CSoundData::RemoveObjectLink(CSoundObject &CsoRemove)
  60. {
  61. // remove it from list
  62. CsoRemove.so_Node.Remove();
  63. }
  64. /* ====================================================
  65. *
  66. * Class global methods
  67. */
  68. // Constructor
  69. CSoundData::CSoundData()
  70. {
  71. sd_pswBuffer = NULL;
  72. }
  73. // Destructor
  74. CSoundData::~CSoundData()
  75. {
  76. Clear();
  77. }
  78. // Free Buffer (and all linked Objects)
  79. void CSoundData::ClearBuffer(void)
  80. {
  81. // if buffer exist
  82. if( sd_pswBuffer!=NULL) {
  83. // release it
  84. FreeMemory( sd_pswBuffer);
  85. sd_pswBuffer = NULL;
  86. }
  87. }
  88. // Get Sound Length in seconds
  89. double CSoundData::GetSecondsLength(void)
  90. {
  91. // if not encoded
  92. if (!(sd_ulFlags&SDF_ENCODED) ) {
  93. // len is read from wave
  94. return sd_dSecondsLength;
  95. // if encoded
  96. } else {
  97. // implement this!!!!
  98. ASSERT(FALSE);
  99. return 0;
  100. }
  101. }
  102. /* ====================================================
  103. *
  104. * Input methods (load sound in SoundData class)
  105. */
  106. // Read sound in memory
  107. void CSoundData::Read_t(CTStream *inFile) // throw char *
  108. {
  109. // synchronize access to sounds
  110. CTSingleLock slSounds(&_pSound->sl_csSound, TRUE);
  111. ASSERT( sd_pswBuffer==NULL);
  112. sd_ulFlags = NONE;
  113. // get filename
  114. CTFileName fnm = inFile->GetDescription();
  115. // if this is encoded file
  116. if (fnm.FileExt()==".ogg" || fnm.FileExt()==".mp3") {
  117. CSoundDecoder *pmpd = new CSoundDecoder(fnm);
  118. if (pmpd->IsOpen()) {
  119. pmpd->GetFormat(sd_wfeFormat);
  120. }
  121. delete pmpd;
  122. // mark that this is streaming encoded file
  123. sd_ulFlags = SDF_ENCODED|SDF_STREAMING;
  124. // if this is wave file
  125. } else {
  126. // load wave info
  127. PCMWaveInput CpwiLoad;
  128. sd_wfeFormat = CpwiLoad.LoadInfo_t(inFile);
  129. // store sample length in seconds and average byte rate
  130. sd_dSecondsLength = CpwiLoad.GetSecondsLength();
  131. // if sound library is in lower format convert sound to library format
  132. if ((_pSound->sl_SwfeFormat).nSamplesPerSec < sd_wfeFormat.nSamplesPerSec) {
  133. sd_wfeFormat.nSamplesPerSec = (_pSound->sl_SwfeFormat).nSamplesPerSec;
  134. }
  135. // same goes for bits/sample (must be 16)
  136. sd_wfeFormat.wBitsPerSample = 16;
  137. // if library is active create buffer and load sound data
  138. if (_pSound->IsActive()) {
  139. // create Buffer
  140. sd_slBufferSampleSize = CpwiLoad.GetDataLength(sd_wfeFormat);
  141. SLONG slBufferSize = CpwiLoad.DetermineBufferSize(sd_wfeFormat);
  142. sd_pswBuffer = (SWORD*)AllocMemory( slBufferSize+8);
  143. // load data into buffer
  144. CpwiLoad.LoadData_t( inFile, sd_pswBuffer, sd_wfeFormat);
  145. // copy first sample to the last one (this is needed for linear interpolation)
  146. (ULONG&)(((UBYTE*)sd_pswBuffer)[slBufferSize]) = *(ULONG*)sd_pswBuffer;
  147. }
  148. }
  149. // add to sound aware list
  150. _pSound->AddSoundAware(*this);
  151. }
  152. // Sound can't be written to file
  153. void CSoundData::Write_t( CTStream *outFile)
  154. {
  155. ASSERTALWAYS("Cannot write sounds!");
  156. throw TRANS("Cannot write sounds!");
  157. }
  158. /* Get the description of this object. */
  159. CTString CSoundData::GetDescription(void)
  160. {
  161. CTString str;
  162. str.PrintF("%dkHz %dbit %s %.2lfs",
  163. sd_wfeFormat.nSamplesPerSec/1000,
  164. sd_wfeFormat.wBitsPerSample,
  165. sd_wfeFormat.nChannels==1 ? "mono" : "stereo",
  166. sd_dSecondsLength);
  167. return str;
  168. }
  169. /* ====================================================
  170. *
  171. * Class CLEAR method
  172. */
  173. // Free memory allocated for sound and Release DXBuffer
  174. void CSoundData::Clear(void)
  175. {
  176. // synchronize access to sounds
  177. CTSingleLock slSounds(&_pSound->sl_csSound, TRUE);
  178. // clear BASE class
  179. CSerial::Clear();
  180. // free DXBuffer
  181. ClearBuffer();
  182. // if added as sound aware, remove it from sound aware list
  183. if(IsHooked()) {
  184. _pSound->RemoveSoundAware(*this);
  185. }
  186. }
  187. // check if this kind of objects is auto-freed
  188. BOOL CSoundData::IsAutoFreed(void)
  189. {
  190. return FALSE;
  191. }
  192. // get amount of memory used by this object
  193. SLONG CSoundData::GetUsedMemory(void)
  194. {
  195. SLONG slUsed = sizeof(*this);
  196. if( sd_pswBuffer!=NULL) {
  197. ASSERT( sd_wfeFormat.nChannels==1 || sd_wfeFormat.nChannels==2);
  198. slUsed += sd_slBufferSampleSize * sd_wfeFormat.nChannels *2; // all sounds are 16-bit
  199. }
  200. return slUsed;
  201. }
  202. /* ====================================================
  203. *
  204. * Reference counting functions
  205. */
  206. // Add one reference
  207. void CSoundData::AddReference(void)
  208. {
  209. if (this!=NULL) {
  210. MarkUsed();
  211. }
  212. }
  213. // Remove one reference
  214. void CSoundData::RemReference(void)
  215. {
  216. if (this!=NULL) {
  217. _pSoundStock->Release(this);
  218. }
  219. }