MixBuf.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. //
  20. // MixBuf.cpp
  21. //
  22. // History:
  23. // 06/19/95 JMI Started.
  24. //
  25. // 12/19/95 JMI Altered to accept user supplied data space as well as
  26. // the space allocated by this module. Changed use of void*
  27. // in calls to UCHAR*.
  28. //
  29. // 08/02/96 MJR Updated non-WIN32 code (was using m_pData, should have
  30. // been m_pucData).
  31. //
  32. // 08/26/96 JMI Changed names of ms_usBitsPerSample, ms_ulSampleRate,
  33. // and ms_usNumChannels to ms_lBitsPerSample,
  34. // ms_lSampleRate, ms_lNumChannels.
  35. //
  36. // 08/30/96 JMI Silence() now uses memset() which seems to have improved
  37. // performance 4x for 8 bit and 2x for 16 bit b/c I was
  38. // doing a stupid 8 bit or 16 bit copy depending on sample
  39. // size.
  40. //
  41. // 10/30/96 JMI Changed:
  42. // Old label: New label:
  43. // ========= =========
  44. // CMixBuf RMixBuf
  45. //
  46. // 02/04/97 MJR Removed a lingering <smrtheap.hpp>. Also found out
  47. // that WIN32 was mistaken for _M_IX86.
  48. //
  49. // 07/05/97 MJR Optimized generic C versions of mixing loops.
  50. // Also optimized Intel x86 versions of mixing loops.
  51. //
  52. // 07/15/97 JRD Added optional dynamic volume adjustment to mix, both
  53. // globally and on a per sound chunk basis
  54. //
  55. // 07/17/97 JRD Enhanced multiple volume scaling accuracy
  56. //
  57. // 07/17/97 MJR Added FORCE_GENERIC_CODE macro to force use of generic
  58. // C/C++ code on all systems.
  59. //
  60. // 08/10/97 JRD Added a user setable parameter to cut off sound at a set
  61. // global volume. Note that this does NOT have to do with
  62. // the volume of the SAMPLE WAVE DATA, but rather the mix
  63. // volume passed to MixBuf
  64. //
  65. // 08/14/97 JRD Made dynamic (8-bit) scaling available to user directly for use
  66. // in ither applications.
  67. //
  68. // 08/20/97 JMI Fixed indexing problem with ASM 8bit scaling loop. Now
  69. // sounds very crunchy when scaling though. Also, moved
  70. // local var declarations that don't get used in ASM version
  71. // into #if/#endif block for non-ASM code.
  72. //
  73. // 10/30/97 JMI Broke mixers out into different functions to make it
  74. // easier to find a particular mixer and easier to add more
  75. // mixers. Also, added 8 to 16 and 16 to 8 bit conversion
  76. // functions so we can mix at a different bit depth than
  77. // we playback.
  78. //
  79. //////////////////////////////////////////////////////////////////////////////
  80. //
  81. // This module does the actual mixing for CMix. Each buffer mixes to its own
  82. // settings.
  83. //
  84. // Normal limitations: This module can mix data of the same sample rate with
  85. // different buffer sizes per channel, with different sample sizes (8 or
  86. // 16 bit PCM), and different numbers of channels (mono or stereo).
  87. //
  88. // For now limitations: In order to get this module running smoothly, it only
  89. // currently accepts data of the same sample rates, buffer sizes, sample
  90. // sizes, and number of channels.
  91. //
  92. //////////////////////////////////////////////////////////////////////////////
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #ifdef PATHS_IN_INCLUDES
  96. #include "BLUE/system.h"
  97. #include "BLUE/Blue.h"
  98. #include "GREEN/Mix/MixBuf.h"
  99. #else
  100. #include "System.h"
  101. #include "Blue.h"
  102. #include "MixBuf.h"
  103. #endif // PATHS_IN_INCLUDES
  104. //////////////////////////////////////////////////////////////////////////////
  105. // Module specific macros.
  106. //////////////////////////////////////////////////////////////////////////////
  107. // Define this to force generic C/C++ code to be used for all processors
  108. // instead of any processor-specific code that may exit. Otherwise,
  109. // comment this out to use any processor-specific code that may exist.
  110. #define FORCE_GENERIC_CODE
  111. // Silence for 8 bit.
  112. #define SILENCE_8 0x80
  113. // Silence for 16 bit.
  114. #define SILENCE_16 0x0000
  115. //////////////////////////////////////////////////////////////////////////////
  116. // Module specific typedefs.
  117. //////////////////////////////////////////////////////////////////////////////
  118. // Handy typedef for referring to a pointer as signed and unsigned char.
  119. typedef union
  120. {
  121. S8* ps8;
  122. U8* pu8;
  123. } P8;
  124. //////////////////////////////////////////////////////////////////////////////
  125. // Instantiate static members.
  126. //////////////////////////////////////////////////////////////////////////////
  127. long RMixBuf::ms_lSampleRate; // Sample rate for audio
  128. // playback/mix.
  129. long RMixBuf::ms_lSrcBitsPerSample; // Sample size in bits for sample data.
  130. // 0 for no preference.
  131. long RMixBuf::ms_lMixBitsPerSample; // Sample size in bits for mixing.
  132. long RMixBuf::ms_lDstBitsPerSample; // Sample size in bits for Blue data.
  133. long RMixBuf::ms_lNumChannels; // Number of channels (mono
  134. // or stereo).
  135. short RMixBuf::ms_sNumBufs = 0; // Number of RMixBufs allocated.
  136. UCHAR RMixBuf::ms_ucGlobalVolume = UCHAR(255); // Full volume is standard
  137. short RMixBuf::ms_sCutOffVolume = 1; // Volume to not bother mixing.
  138. //////////////////////////////////////////////////////////////////////////////
  139. // Handy conversion functions used by RMixBuf.
  140. //////////////////////////////////////////////////////////////////////////////
  141. //////////////////////////////////////////////////////////////////////////////
  142. //
  143. // Convert from 8 bps to 16 bps.
  144. //
  145. //////////////////////////////////////////////////////////////////////////////
  146. inline void Conv8to16( // Returns nothing.
  147. U8* pu8Src, // In: 8 bit src.
  148. S16* ps16Dst, // Out: 16 bit dst. Cannot be the same as the src.
  149. long lSamples) // In: Samples to convert.
  150. {
  151. while (lSamples--)
  152. {
  153. // Shift up to 16 bits and toggle sign bit based on 16 bit value (i.e.,
  154. // if it was 128 or more, we want no sign and, if it was under 128, we
  155. // want a sign -- I'm not sure if C does this for us or tries something
  156. // similar and screws me...need to check the assembly).
  157. *ps16Dst++ = (*pu8Src++ << 8) ^ 0x8000;
  158. }
  159. }
  160. //////////////////////////////////////////////////////////////////////////////
  161. //
  162. // Convert from 16 bps to 8 bps.
  163. //
  164. //////////////////////////////////////////////////////////////////////////////
  165. inline void Conv16to8( // Returns nothing.
  166. S16* ps16Src, // In: 16 bit src.
  167. U8* pu8Dst, // Out: 8 bit dst. _Can_ be the same as the src.
  168. long lSamples) // In: Samples to convert.
  169. {
  170. while (lSamples--)
  171. {
  172. // Toggle sign bit based on 16 bit value, add 256 / 2 for rounding, and
  173. // shift down to 8 bits.
  174. *pu8Dst++ = ( (*ps16Src++ ^ 0x8000) + 128) >> 8;
  175. }
  176. }
  177. //////////////////////////////////////////////////////////////////////////////
  178. // Handy mixer functions used by RMixBuf.
  179. //////////////////////////////////////////////////////////////////////////////
  180. //////////////////////////////////////////////////////////////////////////////
  181. //
  182. // Mix (8 bit src, 8 bit destination, no volume scaling, generic).
  183. //
  184. //////////////////////////////////////////////////////////////////////////////
  185. inline void Mix( // Returns nothing.
  186. U8* pu8Src, // In: Src.
  187. U8* pu8Dst, // In: Dst.
  188. long lSamples) // In: Number of samples to mix.
  189. {
  190. short sVal;
  191. while (lSamples--)
  192. {
  193. // Convert unsigned values into signed shorts, add them, clip sum,
  194. // convert back to unsigned value, and save result.
  195. // Add values after converting to signed.
  196. sVal = ((short)(*pu8Src++) - 128) + ((short)(*pu8Dst) - 128);
  197. // Clip.
  198. if (sVal > 127)
  199. sVal = 127;
  200. else if (sVal < -128)
  201. sVal = -128;
  202. // Stored as unsigned.
  203. *pu8Dst++ = (UCHAR)(sVal + 128);
  204. }
  205. }
  206. #if defined(SYS_BIN_X86)
  207. //////////////////////////////////////////////////////////////////////////////
  208. //
  209. // Mix (8 bit src, 8 bit destination, no volume scaling, Intel x86).
  210. //
  211. //////////////////////////////////////////////////////////////////////////////
  212. inline void MixX86( // Returns nothing.
  213. U8* pu8Src, // In: Src.
  214. U8* pu8Dst, // In: Dst.
  215. long lSamples) // In: Number of samples to mix.
  216. {
  217. _asm
  218. {
  219. // Safety with C:
  220. push esi;
  221. push edi;
  222. mov ecx, lSamples ; // Number of iterations.
  223. mov esi, pu8Src ; // Src pointer.
  224. mov edi, pu8Dst ; // Dst pointer.
  225. MixLoop8:
  226. mov al, [esi] ; // Get src val.
  227. sub al, 128 ; // Make signed.
  228. mov ah, [edi] ; // Get dst val.
  229. sub ah, 128 ; // Make signed.
  230. add ah, al ; // Mix.
  231. jno MixDone8 ; // If no overflow then we're done
  232. js MixWasPos8 ; // If negative then it overflowed positive
  233. mov ah, 080H ; // Set to max negative.
  234. jmp MixDone8
  235. MixWasPos8:
  236. mov ah, 07fH ; // Set to max positive.
  237. MixDone8:
  238. add ah, 128 ; // Unsign.
  239. mov [edi], ah ; // Store mixed value.
  240. inc esi ; // Next source value.
  241. inc edi ; // Next dest value.
  242. loop MixLoop8
  243. pop edi;
  244. pop esi;
  245. }
  246. }
  247. #endif // defined(SYS_BIN_X86)
  248. //////////////////////////////////////////////////////////////////////////////
  249. //
  250. // Mix (16 bit src, 16 bit destination, no volume scaling, generic).
  251. //
  252. //////////////////////////////////////////////////////////////////////////////
  253. inline void Mix( // Returns nothing.
  254. S16* ps16Src, // In: Src.
  255. S16* ps16Dst, // In: Dst.
  256. long lSamples) // In: Number of samples to mix.
  257. {
  258. long lVal;
  259. while (lSamples--)
  260. {
  261. // Add two signed values, clip sum to fit a 16 bit value and save
  262. // result.
  263. lVal = (long)(*ps16Src++) + (long)(*ps16Dst);
  264. if (lVal > 32767)
  265. lVal = 32767;
  266. else if (lVal < -32768)
  267. lVal = -32768;
  268. *ps16Dst++ = (S16)(lVal);
  269. }
  270. }
  271. #if defined(SYS_BIN_X86)
  272. //////////////////////////////////////////////////////////////////////////////
  273. //
  274. // Mix (16 bit src, 16 bit destination, no volume scaling, Intel x86).
  275. //
  276. //////////////////////////////////////////////////////////////////////////////
  277. inline void MixX86( // Returns nothing.
  278. S16* ps16Src, // In: Src.
  279. S16* ps16Dst, // In: Dst.
  280. long lSamples) // In: Number of samples to mix.
  281. {
  282. _asm
  283. {
  284. // Safety with C:
  285. push esi;
  286. push edi;
  287. mov ecx, lSamples ; // Number of iterations.
  288. mov esi, ps16Src ; // Src pointer.
  289. mov edi, ps16Dst ; // Dst pointer.
  290. MixLoop16:
  291. mov ax, [esi] ; // Get src val.
  292. add ax, [edi] ; // Add dst val.
  293. jno MixDone16 ; // If no overflow then we're done
  294. js MixWasPos16 ; // If negative then it overflowed positive
  295. mov ax, 08000H ; // Set to max negative.
  296. jmp MixDone16
  297. MixWasPos16:
  298. mov ax, 07fffH ; // Set to max positive.
  299. MixDone16:
  300. mov [edi], ax ; // Store mixed value.
  301. add esi, 2 ; // Next source value.
  302. add edi, 2 ; // Next dest value.
  303. loop MixLoop16
  304. pop edi;
  305. pop esi;
  306. }
  307. }
  308. #endif // defined(SYS_BIN_X86)
  309. //////////////////////////////////////////////////////////////////////////////
  310. //
  311. // Mix (8 bit src, 8 bit destination, volume scaling, generic).
  312. //
  313. //////////////////////////////////////////////////////////////////////////////
  314. inline void Mix( // Returns nothing.
  315. U8* pu8Src, // In: Src.
  316. U8* pu8Dst, // In: Dst.
  317. long lSamples, // In: Number of samples to mix.
  318. S16* psLowTable) // In: Volume scale table.
  319. {
  320. short sVal;
  321. while (lSamples--)
  322. {
  323. // Convert unsigned values into signed shorts, add them, clip sum,
  324. // convert back to unsigned value, and save result
  325. // Get signed source value, scaled by volume:
  326. // ENDIAN ALERT! Assuming first byte is low!
  327. sVal = psLowTable[*pu8Src++]; // scaled
  328. sVal = (sVal - 128) + (*pu8Dst - 128);
  329. if (sVal > 127)
  330. sVal = 127;
  331. else if (sVal < -128)
  332. sVal = -128;
  333. *pu8Dst++ = (UCHAR)(sVal + 128);
  334. }
  335. }
  336. #if defined(SYS_BIN_X86)
  337. //////////////////////////////////////////////////////////////////////////////
  338. //
  339. // Mix (8 bit src, 8 bit destination, volume scaling, Intel x86).
  340. //
  341. //////////////////////////////////////////////////////////////////////////////
  342. inline void MixX86( // Returns nothing.
  343. U8* pu8Src, // In: Src.
  344. U8* pu8Dst, // In: Dst.
  345. long lSamples, // In: Number of samples to mix.
  346. S16* psLowTable) // In: Volume scale table.
  347. {
  348. _asm
  349. {
  350. // Safety with C:
  351. push esi;
  352. push edi;
  353. mov ecx, lSamples ; // Number of iterations.
  354. mov esi, pu8Src ; // Src pointer.
  355. mov edi, pu8Dst ; // Dst pointer.
  356. mov ebx, 0 ; // Pre Clear
  357. mov edx, psLowTable; // Can't Dereference
  358. MixVolLoop8:
  359. mov bl, [esi] ; // Get src val.
  360. mov ax, [edx + ebx * 2] ; // Cut volume
  361. sub al, 128 ; // Make signed.
  362. mov ah, [edi] ; // Get dst val.
  363. sub ah, 128 ; // Make signed.
  364. add ah, al ; // Mix.
  365. jno MixVolDone8 ; // If no overflow then we're done
  366. js MixVolWasPos8 ; // If negative then it overflowed positive
  367. mov ah, 080H ; // Set to max negative.
  368. jmp MixVolDone8
  369. MixVolWasPos8:
  370. mov ah, 07fH ; // Set to max positive.
  371. MixVolDone8:
  372. add ah, 128 ; // Unsign.
  373. mov [edi], ah ; // Store mixed value.
  374. inc esi ; // Next source value.
  375. inc edi ; // Next dest value.
  376. loop MixVolLoop8
  377. pop edi;
  378. pop esi;
  379. }
  380. }
  381. #endif // defined(SYS_BIN_X86)
  382. //////////////////////////////////////////////////////////////////////////////
  383. //
  384. // Mix (16 bit src, 16 bit destination, volume scaling, generic).
  385. //
  386. //////////////////////////////////////////////////////////////////////////////
  387. inline void Mix( // Returns nothing.
  388. S16* ps16Src, // In: Src.
  389. S16* ps16Dst, // In: Dst.
  390. long lSamples, // In: Number of samples to mix.
  391. S16* psLowTable, // In: Volume scale table for low byte.
  392. S16* psHighTable) // In: Volume scale table for high byte.
  393. {
  394. long lVal;
  395. short sVal;
  396. short sHighSrc;
  397. short sLowSrc;
  398. // Move into a byte by byte, sign adjustable reference wrapper.
  399. P8 p8Src = { (S8*)ps16Src };
  400. while (lSamples--)
  401. {
  402. // Get signed source value, scaled by volume:
  403. // NOTE this confused the Hell out of me at first b/c it
  404. // looks as if these two sections are executing the same
  405. // code to access two different members of a struct but
  406. // in a different order. However, the order is actually
  407. // important as p8Src is a union (not a struct) and pu8
  408. // & ps8 refer to the very same pointer (just one as
  409. // unsigned and the other as signed). The order in this
  410. // case determines which byte is read first -- the signed
  411. // or the unsigned.
  412. #if defined(SYS_ENDIAN_LITTLE)
  413. sLowSrc = short (*p8Src.pu8++);
  414. sHighSrc = short (*p8Src.ps8++);
  415. #else
  416. sHighSrc = short (*p8Src.ps8++);
  417. sLowSrc = short (*p8Src.pu8++);
  418. #endif
  419. sVal = psLowTable[sLowSrc] + psHighTable[sHighSrc]; // scaled
  420. // Add two signed values, clip sum to fit a 16 bit value, and save
  421. // result.
  422. lVal = (long)(sVal) + (long)(*ps16Dst);
  423. if (lVal > 32767)
  424. lVal = 32767;
  425. else if (lVal < -32768)
  426. lVal = -32768;
  427. *ps16Dst++ = (short)(lVal);
  428. }
  429. }
  430. #if defined(SYS_BIN_X86)
  431. //////////////////////////////////////////////////////////////////////////////
  432. //
  433. // Mix (16 bit src, 16 bit destination, volume scaling, Intel x86).
  434. //
  435. //////////////////////////////////////////////////////////////////////////////
  436. inline void MixX86( // Returns nothing.
  437. S16* ps16Src, // In: Src.
  438. S16* ps16Dst, // In: Dst.
  439. long lSamples, // In: Number of samples to mix.
  440. S16* psTable) // In: Volume scale tables for high AND low byte.
  441. // One table is used to save registers but we could
  442. // have the second table as well instead of offseting
  443. // this table by DVA_LOW_OFFSET.
  444. {
  445. _asm
  446. {
  447. // Safety with C:
  448. push esi;
  449. push edi;
  450. mov ecx, lSamples ; // Number of iterations.
  451. mov esi, ps16Src ; // Src pointer.
  452. mov edi, ps16Dst ; // Dst pointer.
  453. mov ebx, 0 ; // Pre Clear
  454. mov edx, psTable ; // Can't Dereference Directly
  455. MixVolLoop16:
  456. // Do a source byte at a time:
  457. mov bl, [esi] ; // Get src val low byte.
  458. mov ax, [edx + DVA_LOW_OFFSET + ebx*2] ; // Cut volume
  459. inc esi ; //
  460. mov bl, [esi] ; // Get src val high byte
  461. add bl,128 ; // Make unsigned
  462. add ax, [edx + ebx*2] ; // Cut Volume
  463. inc esi ; // Next source value.
  464. add ax, [edi] ; // Add dst val.
  465. jno MixVolDone16 ; // If no overflow then we're done
  466. js MixVolWasPos16 ; // If negative then it overflowed positive
  467. mov ax, 08000H ; // Set to max negative.
  468. jmp MixVolDone16
  469. MixVolWasPos16:
  470. mov ax, 07fffH ; // Set to max positive.
  471. MixVolDone16:
  472. mov [edi], ax ; // Store mixed value.
  473. add edi, 2 ; // Next dest value.
  474. loop MixVolLoop16
  475. pop edi;
  476. pop esi;
  477. }
  478. }
  479. #endif // defined(SYS_BIN_X86)
  480. //////////////////////////////////////////////////////////////////////////////
  481. // RMixBuf ///////////////////////////////////////////////////////////////////
  482. //////////////////////////////////////////////////////////////////////////////
  483. //////////////////////////////////////////////////////////////////////////////
  484. // <Con|De>struction.
  485. //////////////////////////////////////////////////////////////////////////////
  486. //////////////////////////////////////////////////////////////////////////////
  487. //
  488. // Default constructor.
  489. //
  490. //////////////////////////////////////////////////////////////////////////////
  491. RMixBuf::RMixBuf(void)
  492. {
  493. ms_sNumBufs++;
  494. // Initialize members.
  495. Init();
  496. }
  497. //////////////////////////////////////////////////////////////////////////////
  498. //
  499. // Constructor Especial.
  500. //
  501. //////////////////////////////////////////////////////////////////////////////
  502. RMixBuf::RMixBuf(
  503. UCHAR* pu8Dst, // In: Destination buffer.
  504. ULONG ulSize) // In: Size of destination buffer in bytes.
  505. {
  506. ms_sNumBufs++;
  507. // Initialize members.
  508. Init();
  509. // Set data ptr and size.
  510. m_pu8Dst = pu8Dst;
  511. m_ulDstSize = ulSize;
  512. }
  513. //////////////////////////////////////////////////////////////////////////////
  514. //
  515. // Destructor.
  516. //
  517. //////////////////////////////////////////////////////////////////////////////
  518. RMixBuf::~RMixBuf(void)
  519. {
  520. Reset();
  521. ms_sNumBufs--;
  522. }
  523. //////////////////////////////////////////////////////////////////////////////
  524. // Internal Use.
  525. //////////////////////////////////////////////////////////////////////////////
  526. //////////////////////////////////////////////////////////////////////////////
  527. //
  528. // Intialize members.
  529. //
  530. //////////////////////////////////////////////////////////////////////////////
  531. void RMixBuf::Init(void)
  532. {
  533. m_pu8Dst = NULL;
  534. m_ulDstSize = 0L;
  535. m_pu8Mix = NULL;
  536. m_ulMixSize = 0L;
  537. m_sInUse = FALSE;
  538. m_sOwnMixBuf = FALSE;
  539. }
  540. //////////////////////////////////////////////////////////////////////////////
  541. //
  542. // Free dynamic data and re-init.
  543. //
  544. //////////////////////////////////////////////////////////////////////////////
  545. void RMixBuf::Reset(void)
  546. {
  547. ASSERT(m_sInUse == FALSE);
  548. if (m_sOwnMixBuf == TRUE)
  549. {
  550. if (m_pu8Mix != NULL)
  551. {
  552. free(m_pu8Mix);
  553. }
  554. }
  555. Init();
  556. }
  557. //////////////////////////////////////////////////////////////////////////////
  558. // Methods.
  559. //////////////////////////////////////////////////////////////////////////////
  560. //////////////////////////////////////////////////////////////////////////////
  561. //
  562. // Set all data to silence.
  563. //
  564. //////////////////////////////////////////////////////////////////////////////
  565. void RMixBuf::Silence(void)
  566. {
  567. ASSERT(m_sInUse == FALSE);
  568. if (m_pu8Mix != NULL)
  569. {
  570. switch (ms_lMixBitsPerSample)
  571. {
  572. case 8:
  573. memset(m_pu8Mix, SILENCE_8, m_ulMixSize);
  574. break;
  575. case 16:
  576. memset(m_pu8Mix, SILENCE_16, m_ulMixSize);
  577. break;
  578. default:
  579. TRACE("Silence(): Unsupported mixing bits per sample: %ld.\n",
  580. ms_lMixBitsPerSample);
  581. break;
  582. }
  583. }
  584. else
  585. {
  586. TRACE("Silence(): No mix buffer.\n");
  587. }
  588. }
  589. //////////////////////////////////////////////////////////////////////////////
  590. //
  591. // Set size of mix buffer in bytes. (Allocates buffer).
  592. // Returns 0 on success.
  593. //
  594. //////////////////////////////////////////////////////////////////////////////
  595. short RMixBuf::SetSize(ULONG ulSize)
  596. {
  597. short sRes = 0; // Assume success.
  598. ASSERT(m_sInUse == FALSE);
  599. // If there's already a buffer . . .
  600. if (m_pu8Mix)
  601. {
  602. // If we own the buffer . . .
  603. if (m_sOwnMixBuf)
  604. {
  605. // Free it.
  606. free(m_pu8Mix);
  607. // We no longer own it.
  608. m_sOwnMixBuf = FALSE;
  609. }
  610. m_ulMixSize = 0L;
  611. }
  612. // Allocate new data chunk.
  613. m_pu8Mix = (UCHAR*)malloc(ulSize);
  614. // If successful . . .
  615. if (m_pu8Mix != NULL)
  616. {
  617. // Success.
  618. m_sOwnMixBuf = TRUE;
  619. m_ulMixSize = ulSize;
  620. // Initialize to silence.
  621. Silence();
  622. }
  623. else
  624. {
  625. TRACE("SetSize(%lu): Unable to allocate buffer.\n", ulSize);
  626. sRes = -1;
  627. }
  628. return sRes;
  629. }
  630. //////////////////////////////////////////////////////////////////////////////
  631. //
  632. // Set the destination buffer.
  633. //
  634. //////////////////////////////////////////////////////////////////////////////
  635. void RMixBuf::SetDest( // Returns nothing.
  636. UCHAR* pu8Dst, // In: Destination buffer.
  637. ULONG ulSize) // In: Size of destination buffer in bytes.
  638. {
  639. // If mix is using dest . . .
  640. if (m_pu8Mix == m_pu8Dst)
  641. {
  642. // Clear it.
  643. m_pu8Mix = NULL;
  644. m_ulMixSize = 0;
  645. }
  646. m_pu8Dst = pu8Dst;
  647. m_ulDstSize = ulSize;
  648. // If incorrect size for mixer buffer . . .
  649. if (m_ulMixSize != m_ulDstSize && m_ulDstSize)
  650. {
  651. // If we can use the destination buffer (i.e., if the mix sample depth and
  652. // playback sample depth are the same) . . .
  653. if (ms_lMixBitsPerSample == ms_lDstBitsPerSample)
  654. {
  655. // Just use the destination buffer.
  656. m_pu8Mix = m_pu8Dst;
  657. m_ulMixSize = m_ulDstSize;
  658. // Since this is our first use, Silence() it.
  659. Silence();
  660. }
  661. else
  662. {
  663. // Set mix size to the size of the playback buffer but at the mix quality.
  664. long lNumSamples = m_ulDstSize * 8 / ms_lDstBitsPerSample;
  665. long lSize = lNumSamples * ms_lMixBitsPerSample / 8;
  666. if (SetSize(lSize) == 0)
  667. {
  668. // Note that SetSize() always Silence()s buffer.
  669. }
  670. else
  671. {
  672. TRACE("SetDest(): Unable to set size to %ld.\n", lSize);
  673. }
  674. }
  675. }
  676. }
  677. //////////////////////////////////////////////////////////////////////////////
  678. //
  679. // Build table for dynamic volume adjustment (DVA)
  680. //
  681. //////////////////////////////////////////////////////////////////////////////
  682. //////////////////////////////////////////////////////////////////////////////
  683. // CVA static members
  684. //////////////////////////////////////////////////////////////////////////////
  685. // This stores both the high and low arrasy in one, to save registers
  686. // (hence the '*2')
  687. short CDVA::ms_asHighByte[DVA_SIZE * 2][256]; // for 16-bit sound
  688. CDVA initVolumeControl; // create the tables
  689. CDVA::CDVA() // Create the tables!
  690. {
  691. // Create the 16-bit scaling codes..
  692. // The 8-bit codes are found by looking at the lower byte of the
  693. // table, as in ms_asLowByte.u8[i*2 + DVA_LOW_BYTE]
  694. // Note that volume scaling goes from 0 to 255 in steps of DVA_RESOLUTION
  695. // (this is to save memory)
  696. //================================================================
  697. // Input: 0-255 representing -32768 to +32767. ( (Input-128) * 256)
  698. // DIM Value: 0-255, 255 being identity
  699. // Output: 16 bit table yielding Input*256*DIM/255
  700. //================================================================
  701. long lSrcVal,lDimVal,lCurValue,lNumerator;
  702. short* psCur = &ms_asHighByte[0][0]; // assume linear addressing:
  703. double dSrcVal;
  704. // This is DimVal major!
  705. // I'm going to drop integral calculus for now and use multiplication.
  706. // This can be sped up later with I.C.
  707. for (lDimVal = 0; lDimVal < 256; lDimVal += DVA_RESOLUTION)
  708. {
  709. double dScale = double(lDimVal)/255.0;
  710. // offset for signed!
  711. for (dSrcVal = -32768.00; dSrcVal < 32767.0; dSrcVal += 256.0,psCur++)
  712. {
  713. *psCur = short(dSrcVal * dScale); // use I.C. to speed up!
  714. }
  715. }
  716. // Now, do the low byte... same as RMultiAlpha::ms_aucLiveDimming,
  717. // except, for speed's sake, we store the value as 16-bit:
  718. // The low byte array should simply follow the high byte array,
  719. // so I don't need to reset psCur.
  720. for (lDimVal = 0; lDimVal < 256; lDimVal += DVA_RESOLUTION)
  721. {
  722. lNumerator = 127; // for rounding
  723. lCurValue = 0;
  724. *psCur++ = 0; // initial value
  725. for (lSrcVal = 1; lSrcVal < 256; lSrcVal++,psCur++)
  726. {
  727. lNumerator += lDimVal;
  728. if (lNumerator >= 255)
  729. {
  730. lNumerator -= 255;
  731. lCurValue++;
  732. }
  733. *psCur = short(lCurValue);
  734. }
  735. }
  736. TRACE("Volume Control Initialized.\n");
  737. }
  738. //////////////////////////////////////////////////////////////////////////////
  739. //////////////////////////////////////////////////////////////////////////////
  740. //
  741. // Mix data in, with optional global x local1 x local2 volume adjustment
  742. // Returns 0 on success.
  743. //
  744. //////////////////////////////////////////////////////////////////////////////
  745. short RMixBuf::Mix( ULONG ulStartPos,
  746. U8* pu8Data,
  747. ULONG ulSize,
  748. long lSampleRate,
  749. long lBitsPerSample,
  750. long lNumChannels,
  751. UCHAR ucVolume,
  752. UCHAR ucVol2)
  753. {
  754. short sRes = 0; // Assume success.
  755. ASSERT(m_sInUse == FALSE);
  756. // If there's a mix buffer . . .
  757. if (m_ulMixSize != 0)
  758. {
  759. // Must be the same.
  760. ASSERT(lSampleRate == ms_lSampleRate);
  761. ASSERT(lNumChannels == ms_lNumChannels);
  762. // If ms_lSrcBitsPerSample is non-zero, lBitsPerSample must match.
  763. ASSERT(lBitsPerSample == ms_lSrcBitsPerSample || ms_lSrcBitsPerSample == 0);
  764. // *** TEMP ***
  765. // Temporarily enforce use of same bit depth on sources since we have
  766. // functions yet that convert and mix.
  767. // Delete this line once we have support.
  768. ASSERT(lBitsPerSample == ms_lSrcBitsPerSample);
  769. // *** END TEMP ***
  770. // If you do not have full accuracy in volume settings, round results
  771. // up to next actual volume.
  772. // Calculate current effective volume scaling on type * global:
  773. // This is actually the low byte. (hence DVA_SIZE + )
  774. short sCurVolume = CDVA::ms_asHighByte
  775. [DVA_SIZE + (ms_ucGlobalVolume>>DVA_SHIFT)][ucVol2];
  776. // Round up:
  777. sCurVolume = (sCurVolume + (DVA_RESOLUTION-1)) >> DVA_SHIFT;
  778. if (sCurVolume >= DVA_SIZE) sCurVolume = (DVA_SIZE-1); // overflow
  779. // Factor in current sample volume:
  780. sCurVolume = CDVA::ms_asHighByte
  781. [DVA_SIZE + sCurVolume][ucVolume];
  782. if (sCurVolume < DVA_RESOLUTION ) return sRes; // sound is off
  783. if (sCurVolume < ms_sCutOffVolume) return sRes; // Sound is clipped by user
  784. ASSERT(ulSize <= (m_ulMixSize - ulStartPos) );
  785. ULONG ulNum = MIN(ulSize, m_ulMixSize - ulStartPos);
  786. if (ulNum > 0)
  787. {
  788. if (sCurVolume > (255 - DVA_RESOLUTION)) // full volume, no scaling
  789. {
  790. switch (lBitsPerSample)
  791. {
  792. case 8:
  793. #if defined(FORCE_GENERIC_CODE) || !defined(SYS_BIN_X86)
  794. ::Mix( (U8*)pu8Data, (U8*)(m_pu8Mix + ulStartPos), ulNum);
  795. #else
  796. MixX86( (U8*)pu8Data, (U8*)(m_pu8Mix + ulStartPos), ulNum);
  797. #endif
  798. break;
  799. case 16:
  800. #if defined(FORCE_GENERIC_CODE) || !defined(SYS_BIN_X86)
  801. ::Mix( (S16*)pu8Data, (S16*)(m_pu8Mix + ulStartPos), ulNum / 2);
  802. #else
  803. MixX86( (S16*)pu8Data, (S16*)(m_pu8Mix + ulStartPos), ulNum / 2);
  804. #endif
  805. break;
  806. default:
  807. TRACE("Mix(): Unsupported bits per sample: %ld.\n",
  808. lBitsPerSample);
  809. sRes = -1;
  810. break;
  811. }
  812. }
  813. ////////////////////////////////////////////////////////////////////////////////
  814. else // do volume scaling
  815. ////////////////////////////////////////////////////////////////////////////////
  816. {
  817. // First, figure out which table apply to the current volume level:
  818. sCurVolume >>= DVA_SHIFT; // scale to an offset
  819. // Offset high by 128 to represent signed upper bytes
  820. short* psHighTable = 128 + CDVA::ms_asHighByte[sCurVolume];
  821. // The assembler doesn't know the offset is signed
  822. short* psASMHighTable = CDVA::ms_asHighByte[sCurVolume];
  823. // Low byte is by nature unsigned, so no offset
  824. // This is packed into the same table, offset by DVA_SIZE entries
  825. short* psLowTable = CDVA::ms_asHighByte[DVA_SIZE + sCurVolume];
  826. switch (lBitsPerSample)
  827. {
  828. case 8:
  829. #if defined(FORCE_GENERIC_CODE) || !defined(SYS_BIN_X86)
  830. ::Mix( (U8*)pu8Data, (U8*)(m_pu8Mix + ulStartPos), ulNum, psLowTable);
  831. #else
  832. MixX86( (U8*)pu8Data, (U8*)(m_pu8Mix + ulStartPos), ulNum, psLowTable);
  833. #endif
  834. break;
  835. case 16:
  836. #if defined(FORCE_GENERIC_CODE) || !defined(SYS_BIN_X86)
  837. ::Mix( (S16*)pu8Data, (S16*)(m_pu8Mix + ulStartPos), ulNum / 2, psLowTable, psHighTable);
  838. #else
  839. MixX86( (S16*)pu8Data, (S16*)(m_pu8Mix + ulStartPos), ulNum / 2, psASMHighTable);
  840. #endif
  841. break;
  842. default:
  843. TRACE("Mix(): Unsupported bits per sample: %u.\n",
  844. lBitsPerSample);
  845. sRes = -1;
  846. break;
  847. }
  848. }
  849. }
  850. }
  851. else
  852. {
  853. TRACE("Mix(): No mix buffer.\n");
  854. sRes = -2;
  855. }
  856. return sRes;
  857. }
  858. //////////////////////////////////////////////////////////////////////////////
  859. //
  860. // Prepare for destination. If necessary, converts to destination format.
  861. //
  862. //////////////////////////////////////////////////////////////////////////////
  863. void RMixBuf::PrepareForDest(void)
  864. {
  865. // If we are not mixing at the sample depth we intend to play at . . .
  866. if (ms_lDstBitsPerSample != ms_lMixBitsPerSample)
  867. {
  868. switch (ms_lDstBitsPerSample)
  869. {
  870. case 8:
  871. // Convert to 8 bit for playback.
  872. Conv16to8( (S16*)m_pu8Mix, m_pu8Dst, m_ulDstSize);
  873. break;
  874. case 16:
  875. // Convert to 16 bit for playback.
  876. Conv8to16(m_pu8Mix, (S16*)m_pu8Dst, m_ulMixSize);
  877. break;
  878. }
  879. }
  880. else
  881. {
  882. // Already the same. Should be using the same buffer.
  883. ASSERT(m_pu8Mix == m_pu8Dst);
  884. }
  885. }
  886. //////////////////////////////////////////////////////////////////////////////
  887. // EOF
  888. //////////////////////////////////////////////////////////////////////////////