eas_chorus.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /*----------------------------------------------------------------------------
  2. *
  3. * File:
  4. * eas_chorus.c
  5. *
  6. * Contents and purpose:
  7. * Contains the implementation of the Chorus effect.
  8. *
  9. *
  10. * Copyright Sonic Network Inc. 2006
  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: 499 $
  26. * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $
  27. *----------------------------------------------------------------------------
  28. */
  29. #include "eas_data.h"
  30. #include "eas_effects.h"
  31. #include "eas_math.h"
  32. #include "eas_chorusdata.h"
  33. #include "eas_chorus.h"
  34. #include "eas_config.h"
  35. #include "eas_host.h"
  36. #include "eas_report.h"
  37. /* prototypes for effects interface */
  38. static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
  39. static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
  40. static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
  41. static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
  42. static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
  43. /* common effects interface for configuration module */
  44. const S_EFFECTS_INTERFACE EAS_Chorus =
  45. {
  46. ChorusInit,
  47. ChorusProcess,
  48. ChorusShutdown,
  49. ChorusGetParam,
  50. ChorusSetParam
  51. };
  52. //LFO shape table used by the chorus, larger table would sound better
  53. //this is a sine wave, where 32767 = 1.0
  54. static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = {
  55. 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170,
  56. 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728,
  57. 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329,
  58. 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212,
  59. 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519,
  60. -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785,
  61. -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621,
  62. -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010,
  63. -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608
  64. };
  65. /*----------------------------------------------------------------------------
  66. * InitializeChorus()
  67. *----------------------------------------------------------------------------
  68. * Purpose: Initializes chorus parameters
  69. *
  70. *
  71. * Inputs:
  72. *
  73. * Outputs:
  74. *
  75. *----------------------------------------------------------------------------
  76. */
  77. static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData)
  78. {
  79. S_CHORUS_OBJECT *pChorusData;
  80. S_CHORUS_PRESET *pPreset;
  81. EAS_I32 index;
  82. /* check Configuration Module for data allocation */
  83. if (pEASData->staticMemoryModel)
  84. pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS);
  85. /* allocate dynamic memory */
  86. else
  87. pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT));
  88. if (pChorusData == NULL)
  89. {
  90. { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ }
  91. return EAS_ERROR_MALLOC_FAILED;
  92. }
  93. /* clear the structure */
  94. EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT));
  95. ChorusReadInPresets(pChorusData);
  96. /* set some default values */
  97. pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT;
  98. pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT;
  99. pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT;
  100. pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT;
  101. pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT;
  102. //chorus rate and depth need some massaging from preset value (which is sample rate independent)
  103. //convert rate from steps of .05 Hz to value which can be used as phase increment,
  104. //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits
  105. //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate;
  106. //computing it as below allows rate steps to be evenly spaced
  107. //uses 32 bit divide, but only once when new value is selected
  108. pChorusData->m_nRate = (EAS_I16)
  109. ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
  110. //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction
  111. //want to compute ((depth * sampleRate)/20000)
  112. //use the following approximation since 105/32 is roughly 65536/20000
  113. /*lint -e{704} use shift for performance */
  114. pChorusData->m_nDepth = (EAS_I16)
  115. (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
  116. pChorusData->m_nLevel = pChorusData->m_nLevel;
  117. //zero delay memory for chorus
  118. for (index = CHORUS_L_SIZE - 1; index >= 0; index--)
  119. {
  120. pChorusData->chorusDelayL[index] = 0;
  121. }
  122. for (index = CHORUS_R_SIZE - 1; index >= 0; index--)
  123. {
  124. pChorusData->chorusDelayR[index] = 0;
  125. }
  126. //init delay line index, these are used to implement circular delay buffer
  127. pChorusData->chorusIndexL = 0;
  128. pChorusData->chorusIndexR = 0;
  129. //init LFO phase
  130. //16 bit whole part, 16 bit fraction
  131. pChorusData->lfoLPhase = 0;
  132. pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase;
  133. //init chorus delay position
  134. //right now chorus delay is a compile-time value, as is sample rate
  135. pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000);
  136. //now copy from the new preset into Chorus
  137. pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
  138. pChorusData->m_nLevel = pPreset->m_nLevel;
  139. pChorusData->m_nRate = pPreset->m_nRate;
  140. pChorusData->m_nDepth = pPreset->m_nDepth;
  141. pChorusData->m_nRate = (EAS_I16)
  142. ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
  143. /*lint -e{704} use shift for performance */
  144. pChorusData->m_nDepth = (EAS_I16)
  145. (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
  146. *pInstData = pChorusData;
  147. return EAS_SUCCESS;
  148. } /* end ChorusInit */
  149. /*----------------------------------------------------------------------------
  150. * WeightedTap()
  151. *----------------------------------------------------------------------------
  152. * Purpose: Does fractional array look-up using linear interpolation
  153. *
  154. * first convert indexDesired to actual desired index by taking into account indexReference
  155. * then do linear interpolation between two actual samples using fractional part
  156. *
  157. * Inputs:
  158. * array: pointer to array of signed 16 bit values, typically either PCM data or control data
  159. * indexReference: the circular buffer relative offset
  160. * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction)
  161. * indexLimit: the total size of the array, used to compute buffer wrap
  162. *
  163. * Outputs:
  164. * Value from the input array, linearly interpolated between two actual data values
  165. *
  166. *----------------------------------------------------------------------------
  167. */
  168. static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit)
  169. {
  170. EAS_I16 index;
  171. EAS_I16 fraction;
  172. EAS_I16 val1;
  173. EAS_I16 val2;
  174. //separate indexDesired into whole and fractional parts
  175. /*lint -e{704} use shift for performance */
  176. index = (EAS_I16)(indexDesired >> 16);
  177. /*lint -e{704} use shift for performance */
  178. fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part
  179. //adjust whole part by indexReference
  180. index = indexReference - index;
  181. //make sure we stay within array bounds, this implements circular buffer
  182. while (index < 0)
  183. {
  184. index += indexLimit;
  185. }
  186. //get two adjacent values from the array
  187. val1 = array[index];
  188. //handle special case when index == 0, else typical case
  189. if (index == 0)
  190. {
  191. val2 = array[indexLimit-1]; //get last value from array
  192. }
  193. else
  194. {
  195. val2 = array[index-1]; //get previous value from array
  196. }
  197. //compute linear interpolation as (val1 + ((val2-val1)*fraction))
  198. return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction));
  199. }
  200. /*----------------------------------------------------------------------------
  201. * ChorusProcess()
  202. *----------------------------------------------------------------------------
  203. * Purpose: compute the chorus on the input buffer, and mix into output buffer
  204. *
  205. *
  206. * Inputs:
  207. * src: pointer to input buffer of PCM values to be processed
  208. * dst: pointer to output buffer of PCM values we are to sume the result with
  209. * bufSize: the number of sample frames (i.e. stereo samples) in the buffer
  210. *
  211. * Outputs:
  212. * None
  213. *
  214. *----------------------------------------------------------------------------
  215. */
  216. //compute the chorus, and mix into output buffer
  217. static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples)
  218. {
  219. EAS_I32 ix;
  220. EAS_I32 nChannelNumber;
  221. EAS_I16 lfoValueLeft;
  222. EAS_I16 lfoValueRight;
  223. EAS_I32 positionOffsetL;
  224. EAS_I32 positionOffsetR;
  225. EAS_PCM tapL;
  226. EAS_PCM tapR;
  227. EAS_I32 tempValue;
  228. EAS_PCM nInputSample;
  229. EAS_I32 nOutputSample;
  230. EAS_PCM *pIn;
  231. EAS_PCM *pOut;
  232. S_CHORUS_OBJECT *pChorusData;
  233. pChorusData = (S_CHORUS_OBJECT*) pInstData;
  234. //if the chorus is disabled or turned all the way down
  235. if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0)
  236. {
  237. if (pSrc != pDst)
  238. EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM));
  239. return;
  240. }
  241. if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus)
  242. {
  243. ChorusUpdate(pChorusData);
  244. }
  245. for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++)
  246. {
  247. pIn = pSrc + nChannelNumber;
  248. pOut = pDst + nChannelNumber;
  249. if(nChannelNumber==0)
  250. {
  251. for (ix = 0; ix < numSamples; ix++)
  252. {
  253. nInputSample = *pIn;
  254. pIn += NUM_OUTPUT_CHANNELS;
  255. //feed input into chorus delay line
  256. pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample;
  257. //compute chorus lfo value using phase as fractional index into chorus shape table
  258. //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
  259. lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE);
  260. //scale chorus depth by lfo value to get relative fractional sample index
  261. //index is expressed as 32 bit number with 16 bit fractional part
  262. /*lint -e{703} use shift for performance */
  263. positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1);
  264. //add fixed chorus delay to get actual fractional sample index
  265. positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
  266. //get tap value from chorus delay using fractional sample index
  267. tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE);
  268. //scale by chorus level, then sum with input buffer contents and saturate
  269. tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel);
  270. nOutputSample = SATURATE(tempValue + nInputSample);
  271. *pOut = (EAS_I16)SATURATE(nOutputSample);
  272. pOut += NUM_OUTPUT_CHANNELS;
  273. //increment chorus delay index and make it wrap as needed
  274. //this implements circular buffer
  275. if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE)
  276. pChorusData->chorusIndexL = 0;
  277. //increment fractional lfo phase, and make it wrap as needed
  278. pChorusData->lfoLPhase += pChorusData->m_nRate;
  279. while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16))
  280. {
  281. pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16);
  282. }
  283. }
  284. }
  285. else
  286. {
  287. for (ix = 0; ix < numSamples; ix++)
  288. {
  289. nInputSample = *pIn;
  290. pIn += NUM_OUTPUT_CHANNELS;
  291. //feed input into chorus delay line
  292. pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample;
  293. //compute chorus lfo value using phase as fractional index into chorus shape table
  294. //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
  295. lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE);
  296. //scale chorus depth by lfo value to get relative fractional sample index
  297. //index is expressed as 32 bit number with 16 bit fractional part
  298. /*lint -e{703} use shift for performance */
  299. positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1);
  300. //add fixed chorus delay to get actual fractional sample index
  301. positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
  302. //get tap value from chorus delay using fractional sample index
  303. tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE);
  304. //scale by chorus level, then sum with output buffer contents and saturate
  305. tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel);
  306. nOutputSample = SATURATE(tempValue + nInputSample);
  307. *pOut = (EAS_I16)SATURATE(nOutputSample);
  308. pOut += NUM_OUTPUT_CHANNELS;
  309. //increment chorus delay index and make it wrap as needed
  310. //this implements circular buffer
  311. if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE)
  312. pChorusData->chorusIndexR = 0;
  313. //increment fractional lfo phase, and make it wrap as needed
  314. pChorusData->lfoRPhase += pChorusData->m_nRate;
  315. while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16))
  316. {
  317. pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16);
  318. }
  319. }
  320. }
  321. }
  322. } /* end ChorusProcess */
  323. /*----------------------------------------------------------------------------
  324. * ChorusShutdown()
  325. *----------------------------------------------------------------------------
  326. * Purpose:
  327. * Initializes the Chorus effect.
  328. *
  329. * Inputs:
  330. * pInstData - handle to instance data
  331. *
  332. * Outputs:
  333. *
  334. *
  335. * Side Effects:
  336. *
  337. *----------------------------------------------------------------------------
  338. */
  339. static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData)
  340. {
  341. /* check Configuration Module for static memory allocation */
  342. if (!pEASData->staticMemoryModel)
  343. EAS_HWFree(pEASData->hwInstData, pInstData);
  344. return EAS_SUCCESS;
  345. } /* end ChorusShutdown */
  346. /*----------------------------------------------------------------------------
  347. * ChorusGetParam()
  348. *----------------------------------------------------------------------------
  349. * Purpose:
  350. * Get a Chorus parameter
  351. *
  352. * Inputs:
  353. * pInstData - handle to instance data
  354. * param - parameter index
  355. * *pValue - pointer to variable to hold retrieved value
  356. *
  357. * Outputs:
  358. *
  359. *
  360. * Side Effects:
  361. *
  362. *----------------------------------------------------------------------------
  363. */
  364. static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
  365. {
  366. S_CHORUS_OBJECT *p;
  367. p = (S_CHORUS_OBJECT*) pInstData;
  368. switch (param)
  369. {
  370. case EAS_PARAM_CHORUS_BYPASS:
  371. *pValue = (EAS_I32) p->bypass;
  372. break;
  373. case EAS_PARAM_CHORUS_PRESET:
  374. *pValue = (EAS_I8) p->m_nCurrentChorus;
  375. break;
  376. case EAS_PARAM_CHORUS_RATE:
  377. *pValue = (EAS_I32) p->m_nRate;
  378. break;
  379. case EAS_PARAM_CHORUS_DEPTH:
  380. *pValue = (EAS_I32) p->m_nDepth;
  381. break;
  382. case EAS_PARAM_CHORUS_LEVEL:
  383. *pValue = (EAS_I32) p->m_nLevel;
  384. break;
  385. default:
  386. return EAS_ERROR_INVALID_PARAMETER;
  387. }
  388. return EAS_SUCCESS;
  389. } /* end ChorusGetParam */
  390. /*----------------------------------------------------------------------------
  391. * ChorusSetParam()
  392. *----------------------------------------------------------------------------
  393. * Purpose:
  394. * Set a Chorus parameter
  395. *
  396. * Inputs:
  397. * pInstData - handle to instance data
  398. * param - parameter index
  399. * *pValue - new paramter value
  400. *
  401. * Outputs:
  402. *
  403. *
  404. * Side Effects:
  405. *
  406. *----------------------------------------------------------------------------
  407. */
  408. static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
  409. {
  410. S_CHORUS_OBJECT *p;
  411. p = (S_CHORUS_OBJECT*) pInstData;
  412. switch (param)
  413. {
  414. case EAS_PARAM_CHORUS_BYPASS:
  415. p->bypass = (EAS_BOOL) value;
  416. break;
  417. case EAS_PARAM_CHORUS_PRESET:
  418. if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 &&
  419. value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4)
  420. return EAS_ERROR_INVALID_PARAMETER;
  421. p->m_nNextChorus = (EAS_I8)value;
  422. break;
  423. case EAS_PARAM_CHORUS_RATE:
  424. if(value<EAS_CHORUS_RATE_MIN || value>EAS_CHORUS_RATE_MAX)
  425. return EAS_ERROR_INVALID_PARAMETER;
  426. p->m_nRate = (EAS_I16) value;
  427. break;
  428. case EAS_PARAM_CHORUS_DEPTH:
  429. if(value<EAS_CHORUS_DEPTH_MIN || value>EAS_CHORUS_DEPTH_MAX)
  430. return EAS_ERROR_INVALID_PARAMETER;
  431. p->m_nDepth = (EAS_I16) value;
  432. break;
  433. case EAS_PARAM_CHORUS_LEVEL:
  434. if(value<EAS_CHORUS_LEVEL_MIN || value>EAS_CHORUS_LEVEL_MAX)
  435. return EAS_ERROR_INVALID_PARAMETER;
  436. p->m_nLevel = (EAS_I16) value;
  437. break;
  438. default:
  439. return EAS_ERROR_INVALID_PARAMETER;
  440. }
  441. return EAS_SUCCESS;
  442. } /* end ChorusSetParam */
  443. /*----------------------------------------------------------------------------
  444. * ChorusReadInPresets()
  445. *----------------------------------------------------------------------------
  446. * Purpose: sets global Chorus preset bank to defaults
  447. *
  448. * Inputs:
  449. *
  450. * Outputs:
  451. *
  452. *----------------------------------------------------------------------------
  453. */
  454. static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData)
  455. {
  456. int preset = 0;
  457. int defaultPreset = 0;
  458. //now init any remaining presets to defaults
  459. for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++)
  460. {
  461. S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset];
  462. if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1)
  463. {
  464. pPreset->m_nDepth = 39;
  465. pPreset->m_nRate = 30;
  466. pPreset->m_nLevel = 32767;
  467. }
  468. else if (defaultPreset == 1)
  469. {
  470. pPreset->m_nDepth = 21;
  471. pPreset->m_nRate = 45;
  472. pPreset->m_nLevel = 25000;
  473. }
  474. else if (defaultPreset == 2)
  475. {
  476. pPreset->m_nDepth = 53;
  477. pPreset->m_nRate = 25;
  478. pPreset->m_nLevel = 32000;
  479. }
  480. else if (defaultPreset == 3)
  481. {
  482. pPreset->m_nDepth = 32;
  483. pPreset->m_nRate = 37;
  484. pPreset->m_nLevel = 29000;
  485. }
  486. }
  487. return EAS_SUCCESS;
  488. }
  489. /*----------------------------------------------------------------------------
  490. * ChorusUpdate
  491. *----------------------------------------------------------------------------
  492. * Purpose:
  493. * Update the Chorus preset parameters as required
  494. *
  495. * Inputs:
  496. *
  497. * Outputs:
  498. *
  499. *
  500. * Side Effects:
  501. * - chorus paramters will be changed
  502. * - m_nCurrentRoom := m_nNextRoom
  503. *----------------------------------------------------------------------------
  504. */
  505. static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData)
  506. {
  507. S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
  508. pChorusData->m_nLevel = pPreset->m_nLevel;
  509. pChorusData->m_nRate = pPreset->m_nRate;
  510. pChorusData->m_nDepth = pPreset->m_nDepth;
  511. pChorusData->m_nRate = (EAS_I16)
  512. ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
  513. /*lint -e{704} use shift for performance */
  514. pChorusData->m_nDepth = (EAS_I16)
  515. (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
  516. pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus;
  517. return EAS_SUCCESS;
  518. } /* end ChorusUpdate */