eas_mixer.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*----------------------------------------------------------------------------
  2. *
  3. * File:
  4. * eas_mixer.c
  5. *
  6. * Contents and purpose:
  7. * This file contains the critical components of the mix engine that
  8. * must be optimized for best performance.
  9. *
  10. * Copyright Sonic Network Inc. 2005
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. *----------------------------------------------------------------------------
  24. * Revision Control:
  25. * $Revision: 706 $
  26. * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $
  27. *----------------------------------------------------------------------------
  28. */
  29. //3 dls: This module is in the midst of being converted from a synth
  30. //3 specific module to a general purpose mix engine
  31. /*------------------------------------
  32. * includes
  33. *------------------------------------
  34. */
  35. #include "eas_data.h"
  36. #include "eas_host.h"
  37. #include "eas_math.h"
  38. #include "eas_mixer.h"
  39. #include "eas_config.h"
  40. #include "eas_report.h"
  41. #ifdef _MAXIMIZER_ENABLED
  42. EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples);
  43. #endif
  44. /*------------------------------------
  45. * defines
  46. *------------------------------------
  47. */
  48. /* need to boost stereo by ~3dB to compensate for the panner */
  49. #define STEREO_3DB_GAIN_BOOST 512
  50. /*----------------------------------------------------------------------------
  51. * EAS_MixEngineInit()
  52. *----------------------------------------------------------------------------
  53. * Purpose:
  54. * Prepares the mix engine for work, allocates buffers, locates effects modules, etc.
  55. *
  56. * Inputs:
  57. * pEASData - instance data
  58. * pInstData - pointer to variable to receive instance data handle
  59. *
  60. * Outputs:
  61. *
  62. * Side Effects:
  63. *
  64. *----------------------------------------------------------------------------
  65. */
  66. EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData)
  67. {
  68. /* check Configuration Module for mix buffer allocation */
  69. if (pEASData->staticMemoryModel)
  70. pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER);
  71. else
  72. pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32));
  73. if (pEASData->pMixBuffer == NULL)
  74. {
  75. { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ }
  76. return EAS_ERROR_MALLOC_FAILED;
  77. }
  78. EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32));
  79. return EAS_SUCCESS;
  80. }
  81. /*----------------------------------------------------------------------------
  82. * EAS_MixEnginePrep()
  83. *----------------------------------------------------------------------------
  84. * Purpose:
  85. * Performs prep before synthesize a buffer of audio, such as clearing
  86. * audio buffers, etc.
  87. *
  88. * Inputs:
  89. * psEASData - pointer to overall EAS data structure
  90. *
  91. * Outputs:
  92. *
  93. * Side Effects:
  94. *
  95. *----------------------------------------------------------------------------
  96. */
  97. void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples)
  98. {
  99. /* clear the mix buffer */
  100. #if (NUM_OUTPUT_CHANNELS == 2)
  101. EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2);
  102. #else
  103. EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long));
  104. #endif
  105. /* need to clear other side-chain effect buffers (chorus & reverb) */
  106. }
  107. /*----------------------------------------------------------------------------
  108. * EAS_MixEnginePost
  109. *----------------------------------------------------------------------------
  110. * Purpose:
  111. * This routine does the post-processing after all voices have been
  112. * synthesized. It calls any sweeteners and does the final mixdown to
  113. * the output buffer.
  114. *
  115. * Inputs:
  116. *
  117. * Outputs:
  118. *
  119. * Notes:
  120. *----------------------------------------------------------------------------
  121. */
  122. void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples)
  123. {
  124. EAS_U16 gain;
  125. //3 dls: Need to restore the mix engine metrics
  126. /* calculate the gain multiplier */
  127. #ifdef _MAXIMIZER_ENABLED
  128. if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect)
  129. {
  130. EAS_I32 temp;
  131. temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples);
  132. temp = (temp * pEASData->masterGain) >> 15;
  133. if (temp > 32767)
  134. gain = 32767;
  135. else
  136. gain = (EAS_U16) temp;
  137. }
  138. else
  139. gain = (EAS_U16) pEASData->masterGain;
  140. #else
  141. gain = (EAS_U16) pEASData->masterGain;
  142. #endif
  143. /* Not using all the gain bits for now
  144. * Reduce the input to the compressor by 6dB to prevent saturation
  145. */
  146. #ifdef _COMPRESSOR_ENABLED
  147. if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData)
  148. gain = gain >> 5;
  149. else
  150. gain = gain >> 4;
  151. #else
  152. gain = gain >> 4;
  153. #endif
  154. /* convert 32-bit mix buffer to 16-bit output format */
  155. #if (NUM_OUTPUT_CHANNELS == 2)
  156. SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2));
  157. #else
  158. SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples);
  159. #endif
  160. #ifdef _ENHANCER_ENABLED
  161. /* enhancer effect */
  162. if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData)
  163. (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess)
  164. (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData,
  165. pEASData->pOutputAudioBuffer,
  166. pEASData->pOutputAudioBuffer,
  167. numSamples);
  168. #endif
  169. #ifdef _GRAPHIC_EQ_ENABLED
  170. /* graphic EQ effect */
  171. if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData)
  172. (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess)
  173. (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData,
  174. pEASData->pOutputAudioBuffer,
  175. pEASData->pOutputAudioBuffer,
  176. numSamples);
  177. #endif
  178. #ifdef _COMPRESSOR_ENABLED
  179. /* compressor effect */
  180. if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData)
  181. (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess)
  182. (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData,
  183. pEASData->pOutputAudioBuffer,
  184. pEASData->pOutputAudioBuffer,
  185. numSamples);
  186. #endif
  187. #ifdef _WOW_ENABLED
  188. /* WOW requires a 32-bit buffer, borrow the mix buffer and
  189. * pass it as the destination buffer
  190. */
  191. /*lint -e{740} temporarily passing a parameter through an existing I/F */
  192. if (pEASData->effectsModules[EAS_MODULE_WOW].effectData)
  193. (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess)
  194. (pEASData->effectsModules[EAS_MODULE_WOW].effectData,
  195. pEASData->pOutputAudioBuffer,
  196. (EAS_PCM*) pEASData->pMixBuffer,
  197. numSamples);
  198. #endif
  199. #ifdef _TONECONTROLEQ_ENABLED
  200. /* ToneControlEQ effect */
  201. if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData)
  202. (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess)
  203. (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData,
  204. pEASData->pOutputAudioBuffer,
  205. pEASData->pOutputAudioBuffer,
  206. numSamples);
  207. #endif
  208. #ifdef _REVERB_ENABLED
  209. /* Reverb effect */
  210. if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData)
  211. (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess)
  212. (pEASData->effectsModules[EAS_MODULE_REVERB].effectData,
  213. pEASData->pOutputAudioBuffer,
  214. pEASData->pOutputAudioBuffer,
  215. numSamples);
  216. #endif
  217. #ifdef _CHORUS_ENABLED
  218. /* Chorus effect */
  219. if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData)
  220. (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess)
  221. (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData,
  222. pEASData->pOutputAudioBuffer,
  223. pEASData->pOutputAudioBuffer,
  224. numSamples);
  225. #endif
  226. }
  227. #ifndef NATIVE_EAS_KERNEL
  228. /*----------------------------------------------------------------------------
  229. * SynthMasterGain
  230. *----------------------------------------------------------------------------
  231. * Purpose:
  232. * Mixes down audio from 32-bit to 16-bit target buffer
  233. *
  234. * Inputs:
  235. *
  236. * Outputs:
  237. *
  238. *----------------------------------------------------------------------------
  239. */
  240. void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) {
  241. /* loop through the buffer */
  242. while (numSamples--) {
  243. long s;
  244. /* read a sample from the input buffer and add some guard bits */
  245. s = *pInputBuffer++;
  246. /* add some guard bits */
  247. /*lint -e{704} <avoid divide for performance>*/
  248. s = s >> 7;
  249. /* apply master gain */
  250. s *= (long) nGain;
  251. /* shift to lower 16-bits */
  252. /*lint -e{704} <avoid divide for performance>*/
  253. s = s >> 9;
  254. /* saturate */
  255. s = SATURATE(s);
  256. *pOutputBuffer++ = (EAS_PCM)s;
  257. }
  258. }
  259. #endif
  260. /*----------------------------------------------------------------------------
  261. * EAS_MixEngineShutdown()
  262. *----------------------------------------------------------------------------
  263. * Purpose:
  264. * Shuts down effects modules and deallocates memory
  265. *
  266. * Inputs:
  267. * pEASData - instance data
  268. * pInstData - instance data handle
  269. *
  270. * Outputs:
  271. *
  272. * Side Effects:
  273. *
  274. *----------------------------------------------------------------------------
  275. */
  276. EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData)
  277. {
  278. /* check Configuration Module for static memory allocation */
  279. if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL))
  280. EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer);
  281. return EAS_SUCCESS;
  282. }
  283. #ifdef UNIFIED_MIXER
  284. #ifndef NATIVE_MIX_STREAM
  285. /*----------------------------------------------------------------------------
  286. * EAS_MixStream
  287. *----------------------------------------------------------------------------
  288. * Mix a 16-bit stream into a 32-bit buffer
  289. *
  290. * pInputBuffer 16-bit input buffer
  291. * pMixBuffer 32-bit mix buffer
  292. * numSamples number of samples to mix
  293. * gainLeft initial gain left or mono
  294. * gainRight initial gain right
  295. * gainLeft left gain increment per sample
  296. * gainRight right gain increment per sample
  297. * flags bit 0 = stereo source
  298. * bit 1 = stereo output
  299. *----------------------------------------------------------------------------
  300. */
  301. void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags)
  302. {
  303. EAS_I32 temp;
  304. EAS_INT src, dest;
  305. /* NOTE: There are a lot of optimizations that can be done
  306. * in the native implementations based on register
  307. * availability, etc. For example, it may make sense to
  308. * break this down into 8 separate routines:
  309. *
  310. * 1. Mono source to mono output
  311. * 2. Mono source to stereo output
  312. * 3. Stereo source to mono output
  313. * 4. Stereo source to stereo output
  314. * 5. Mono source to mono output - no gain change
  315. * 6. Mono source to stereo output - no gain change
  316. * 7. Stereo source to mono output - no gain change
  317. * 8. Stereo source to stereo output - no gain change
  318. *
  319. * Other possibilities include loop unrolling, skipping
  320. * a gain calculation every 2 or 4 samples, etc.
  321. */
  322. /* no gain change, use fast loops */
  323. if ((gainIncLeft == 0) && (gainIncRight == 0))
  324. {
  325. switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT))
  326. {
  327. /* mono to mono */
  328. case 0:
  329. gainLeft >>= 15;
  330. for (src = dest = 0; src < numSamples; src++, dest++)
  331. {
  332. pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
  333. }
  334. break;
  335. /* mono to stereo */
  336. case MIX_FLAGS_STEREO_OUTPUT:
  337. gainLeft >>= 15;
  338. gainRight >>= 15;
  339. for (src = dest = 0; src < numSamples; src++, dest+=2)
  340. {
  341. pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
  342. pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS;
  343. }
  344. break;
  345. /* stereo to mono */
  346. case MIX_FLAGS_STEREO_SOURCE:
  347. gainLeft >>= 15;
  348. gainRight >>= 15;
  349. for (src = dest = 0; src < numSamples; src+=2, dest++)
  350. {
  351. temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
  352. temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS);
  353. pMixBuffer[dest] += temp;
  354. }
  355. break;
  356. /* stereo to stereo */
  357. case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT:
  358. gainLeft >>= 15;
  359. gainRight >>= 15;
  360. for (src = dest = 0; src < numSamples; src+=2, dest+=2)
  361. {
  362. pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS;
  363. pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS;
  364. }
  365. break;
  366. }
  367. }
  368. /* gain change - do gain increment */
  369. else
  370. {
  371. switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT))
  372. {
  373. /* mono to mono */
  374. case 0:
  375. for (src = dest = 0; src < numSamples; src++, dest++)
  376. {
  377. gainLeft += gainIncLeft;
  378. pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
  379. }
  380. break;
  381. /* mono to stereo */
  382. case MIX_FLAGS_STEREO_OUTPUT:
  383. for (src = dest = 0; src < numSamples; src++, dest+=2)
  384. {
  385. gainLeft += gainIncLeft;
  386. gainRight += gainIncRight;
  387. pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
  388. pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS;
  389. }
  390. break;
  391. /* stereo to mono */
  392. case MIX_FLAGS_STEREO_SOURCE:
  393. for (src = dest = 0; src < numSamples; src+=2, dest++)
  394. {
  395. gainLeft += gainIncLeft;
  396. gainRight += gainIncRight;
  397. temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
  398. temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS);
  399. pMixBuffer[dest] += temp;
  400. }
  401. break;
  402. /* stereo to stereo */
  403. case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT:
  404. for (src = dest = 0; src < numSamples; src+=2, dest+=2)
  405. {
  406. gainLeft += gainIncLeft;
  407. gainRight += gainIncRight;
  408. pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS;
  409. pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS;
  410. }
  411. break;
  412. }
  413. }
  414. }
  415. #endif
  416. #endif