Wave.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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/Base/Stream.h>
  14. #include <Engine/Base/ErrorReporting.h>
  15. #include <Engine/Sound/Wave.h>
  16. /* ====================================================
  17. *
  18. * CONVERSION FUNCTIONS
  19. *
  20. */
  21. // check wave format
  22. void PCMWaveInput::CheckWaveFormat_t(WAVEFORMATEX wfeCheck, char *pcErrorString)
  23. {
  24. // check format tag
  25. if (wfeCheck.wFormatTag != 1) {
  26. ThrowF_t(TRANS("%s: Invalid format tag, not a PCM Wave file!"), pcErrorString);
  27. }
  28. // check bits per sample
  29. if (wfeCheck.wBitsPerSample != 8 &&
  30. wfeCheck.wBitsPerSample != 16) {
  31. ThrowF_t(TRANS("%s: Unknown Bits Per Sample value!"), pcErrorString);
  32. }
  33. // check number of channels
  34. if (wfeCheck.nChannels != 1 &&
  35. wfeCheck.nChannels != 2) {
  36. ThrowF_t(TRANS("%s: Invalid number of channels!"), pcErrorString);
  37. }
  38. //ASSERT( wfeCheck.wBitsPerSample==16);
  39. }
  40. // Get next data
  41. inline ULONG PCMWaveInput::GetData_t(CTStream *pCstrInput)
  42. {
  43. ASSERT(pwi_bInfoLoaded);
  44. // read data according to bits per sample value
  45. if (pwi_wfeWave.wBitsPerSample==8) {
  46. // read UBYTE
  47. UBYTE ubData;
  48. *pCstrInput >> ubData;
  49. return ((ULONG)ubData) <<16; // (shift) prepare data for shrink/expand operation
  50. } else {
  51. // read UWORD
  52. SWORD swData;
  53. *pCstrInput >> swData;
  54. return ((ULONG)(swData+0x8000)) <<8; // (shift) prepare data for shrink/expand operation
  55. }
  56. }
  57. // Store data
  58. inline void PCMWaveInput::StoreData(ULONG ulData)
  59. {
  60. ASSERT( pwi_wfeDesired.wBitsPerSample==16);
  61. *pwi_pswMemory++ = ((SWORD)(ulData>>8) -0x8000); // (shift) restore data format
  62. }
  63. /*
  64. * Copy data
  65. */
  66. void PCMWaveInput::CopyData_t(CTStream *pCstrInput)
  67. {
  68. // for all input data (mono and stereo)
  69. ULONG ulDataCount = GetDataLength() * pwi_wfeWave.nChannels;
  70. while (ulDataCount > 0) {
  71. StoreData(GetData_t(pCstrInput)); // read and store data from input (hidden BitsPerSample conversion!)
  72. ulDataCount--; // to next data
  73. }
  74. }
  75. /*
  76. * Shrink data
  77. */
  78. // Shrink data
  79. void PCMWaveInput::ShrinkData_t(CTStream *pCstrInput)
  80. {
  81. ASSERT(pwi_dRatio>1.0);
  82. // *** MONO ***
  83. if (pwi_wfeWave.nChannels == 1) {
  84. DOUBLE dInterData, dTempData, dRatio;
  85. ULONG ulDataCount;
  86. // data intermediate value
  87. dInterData = 0.0;
  88. // for all input data (mono)
  89. ulDataCount = GetDataLength();
  90. dRatio = pwi_dRatio;
  91. while (ulDataCount > 0) {
  92. // read part of data (<100%)
  93. if (dRatio<1.0) {
  94. dTempData = GetData_t(pCstrInput);
  95. dInterData += dTempData*dRatio;
  96. StoreData(ULONG(dInterData/pwi_dRatio));
  97. // new intermediate value
  98. dRatio = 1 - dRatio;
  99. dInterData = dTempData*dRatio;
  100. dRatio = pwi_dRatio - dRatio;
  101. // read complete data (100%)
  102. } else {
  103. dInterData += GetData_t(pCstrInput);
  104. dRatio -= 1.0;
  105. }
  106. ulDataCount--; // to next data
  107. }
  108. StoreData(ULONG(dInterData/(pwi_dRatio-dRatio)));
  109. // *** STEREO ***
  110. } else if (pwi_wfeWave.nChannels == 2) {
  111. DOUBLE dLInterData, dRInterData, dLTempData, dRTempData, dRatio;
  112. ULONG ulDataCount;
  113. // data intermediate value
  114. dLInterData = 0.0;
  115. dRInterData = 0.0;
  116. // for all input data (mono)
  117. ulDataCount = GetDataLength();
  118. dRatio = pwi_dRatio;
  119. while (ulDataCount > 0) {
  120. // read part of data (<100%)
  121. if (dRatio<1.0) {
  122. dLTempData = GetData_t(pCstrInput);
  123. dRTempData = GetData_t(pCstrInput);
  124. dLInterData += dLTempData*dRatio;
  125. dRInterData += dRTempData*dRatio;
  126. StoreData(ULONG(dLInterData/pwi_dRatio));
  127. StoreData(ULONG(dRInterData/pwi_dRatio));
  128. // new intermediate value
  129. dRatio = 1 - dRatio;
  130. dLInterData = dLTempData*dRatio;
  131. dRInterData = dRTempData*dRatio;
  132. dRatio = pwi_dRatio - dRatio;
  133. // read complete data (100%)
  134. } else {
  135. dLInterData += GetData_t(pCstrInput);
  136. dRInterData += GetData_t(pCstrInput);
  137. dRatio -= 1.0;
  138. }
  139. ulDataCount--; // to next data
  140. }
  141. StoreData(ULONG(dLInterData/(pwi_dRatio-dRatio)));
  142. StoreData(ULONG(dRInterData/(pwi_dRatio-dRatio)));
  143. }
  144. }
  145. /* ====================================================
  146. *
  147. * WAVE FUNCTIONS
  148. *
  149. */
  150. /*
  151. * Load Wave info
  152. */
  153. WAVEFORMATEX PCMWaveInput::LoadInfo_t(CTStream *pCstrInput)
  154. {
  155. // if already loaded -> exception
  156. if (pwi_bInfoLoaded) {
  157. throw (TRANS("PCM Wave Input: Info already loaded."));
  158. }
  159. /* Read Riff */
  160. pCstrInput->ExpectID_t(CChunkID("RIFF")); // ID "RIFF"
  161. (*pCstrInput) >> pwi_ulRiffLength; // Ucitaj duljinu file-a
  162. /* Read Wave */
  163. pCstrInput->ExpectID_t(CChunkID("WAVE")); // ID "WAVE"
  164. pCstrInput->ExpectID_t(CChunkID("fmt ")); // ID "fmt "
  165. // read Format Chunk length
  166. SLONG slFmtLength;
  167. (*pCstrInput) >> slFmtLength;
  168. // read WAVE format
  169. (*pCstrInput) >> pwi_wfeWave.wFormatTag;
  170. (*pCstrInput) >> pwi_wfeWave.nChannels;
  171. (*pCstrInput) >> pwi_wfeWave.nSamplesPerSec;
  172. (*pCstrInput) >> pwi_wfeWave.nAvgBytesPerSec;
  173. (*pCstrInput) >> pwi_wfeWave.nBlockAlign;
  174. (*pCstrInput) >> pwi_wfeWave.wBitsPerSample;
  175. pwi_wfeWave.cbSize = 0; // Only for PCM Wave !!!
  176. // WARNING !!! - Only for PCM Wave - Skip extra information if exists
  177. if( slFmtLength > 16) {
  178. //WarningMessage("PCM Wave Input: Wave format Extra information skipped!");
  179. pCstrInput->Seek_t(slFmtLength - 16, CTStream::SD_CUR);
  180. }
  181. // WARNING - If exist Fact chunk skip it (purpose unknown)
  182. if( pCstrInput->GetID_t() == CChunkID("fact")) {
  183. //WarningMessage("PCM Wave Input: Fact Chunk skipped!");
  184. SLONG slSkipLength;
  185. (*pCstrInput) >> slSkipLength;
  186. pCstrInput->Seek_t(slSkipLength, CTStream::SD_CUR);
  187. // seek back on Chunk ID
  188. } else {
  189. pCstrInput->Seek_t(-CID_LENGTH, CTStream::SD_CUR);
  190. }
  191. /* Read Data */
  192. pCstrInput->ExpectID_t(CChunkID("data")); // ID "data"
  193. // read Data length (in bytes)
  194. (*pCstrInput) >> pwi_ulDataLength;
  195. /* Check PCM format */
  196. CheckWaveFormat_t(pwi_wfeWave, "PCM Wave Input (input)");
  197. // mark Info loaded
  198. pwi_bInfoLoaded = TRUE;
  199. // ASSERT( pwi_wfeWave.wBitsPerSample==16);
  200. // return Wave Format
  201. return pwi_wfeWave;
  202. }
  203. /*
  204. * Load and convert Wave data
  205. */
  206. void PCMWaveInput::LoadData_t(CTStream *pCstrInput, SWORD *pswMemory, WAVEFORMATEX &SwfeDesired)
  207. {
  208. // if info not loaded -> exception
  209. if (!pwi_bInfoLoaded) {
  210. throw (TRANS("PCM Wave Input: Info not loaded."));
  211. }
  212. // if already loaded -> exception
  213. if (pwi_bDataLoaded) {
  214. throw (TRANS("PCM Wave Input: Data already loaded"));
  215. }
  216. // set memory pointer
  217. pwi_pswMemory = pswMemory;
  218. // store and check desired sound format
  219. CheckWaveFormat_t(SwfeDesired, "PCM Wave Input (desired)");
  220. pwi_wfeDesired = SwfeDesired;
  221. // calculate expand/shrink ratio (number of channels remain the same)
  222. pwi_dRatio = (DOUBLE)pwi_wfeDesired.nSamplesPerSec / (DOUBLE)pwi_wfeWave.nSamplesPerSec;
  223. // determine converion type from input and desired sound frequency, and convert sound
  224. if (pwi_dRatio < 1) {
  225. pwi_dRatio = 1/pwi_dRatio;
  226. ShrinkData_t(pCstrInput);
  227. } else if (pwi_dRatio > 1) {
  228. ASSERTALWAYS("Can't expand wave data");
  229. memset(pwi_pswMemory, 0, DetermineBufferSize(pwi_wfeDesired));
  230. // copy data
  231. } else {
  232. ASSERT(pwi_dRatio==1.0f);
  233. CopyData_t(pCstrInput);
  234. }
  235. // data is loaded (and maybe converted from 16-bits)
  236. if( pwi_wfeWave.wBitsPerSample==8) SwfeDesired.nBlockAlign *= 2;
  237. pwi_bDataLoaded = TRUE;
  238. }
  239. /*
  240. * Length in bytes
  241. */
  242. ULONG PCMWaveInput::GetByteLength(void)
  243. {
  244. ASSERT(pwi_bInfoLoaded);
  245. return pwi_ulDataLength;
  246. }
  247. /*
  248. * Length in blocks
  249. */
  250. ULONG PCMWaveInput::GetDataLength(void)
  251. {
  252. ASSERT(pwi_bInfoLoaded);
  253. return GetByteLength() / (pwi_wfeWave.nChannels * pwi_wfeWave.wBitsPerSample/8);
  254. }
  255. ULONG PCMWaveInput::GetDataLength(WAVEFORMATEX SwfeDesired)
  256. {
  257. ASSERT(pwi_bInfoLoaded);
  258. // return buffer size
  259. return DetermineBufferSize(SwfeDesired) / (SwfeDesired.nChannels * SwfeDesired.wBitsPerSample/8);
  260. }
  261. /*
  262. * Length in seconds
  263. */
  264. DOUBLE PCMWaveInput::GetSecondsLength(void)
  265. {
  266. ASSERT(pwi_bInfoLoaded);
  267. return (DOUBLE)GetDataLength() / (DOUBLE)pwi_wfeWave.nSamplesPerSec;
  268. }
  269. /*
  270. * Buffer length in bytes
  271. */
  272. ULONG PCMWaveInput::DetermineBufferSize(void)
  273. {
  274. return DetermineBufferSize(pwi_wfeWave);
  275. }
  276. ULONG PCMWaveInput::DetermineBufferSize( WAVEFORMATEX SwfeDesired)
  277. {
  278. ASSERT(pwi_bInfoLoaded);
  279. DOUBLE dRatio;
  280. // calculate ratio between formats
  281. dRatio = (DOUBLE)SwfeDesired.nSamplesPerSec / (DOUBLE)pwi_wfeWave.nSamplesPerSec
  282. * (DOUBLE)SwfeDesired.wBitsPerSample / (DOUBLE)pwi_wfeWave.wBitsPerSample;
  283. // return buffer size (must calculate with data length to avoid miss align data, for example:
  284. // 16 bit sound with 2 channels must be aligned to 4 bytes boundary and a multiply with
  285. // random ratio can as result give any possible number
  286. DOUBLE ret = ceil(dRatio*GetDataLength()) * (pwi_wfeWave.nChannels*(pwi_wfeWave.wBitsPerSample/8));
  287. return (ULONG)ret;
  288. }