eas_wtengine.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /*----------------------------------------------------------------------------
  2. *
  3. * File:
  4. * eas_wtengine.c
  5. *
  6. * Contents and purpose:
  7. * This file contains the critical synthesizer components that need to
  8. * be optimized for best performance.
  9. *
  10. * Copyright Sonic Network Inc. 2004-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: 844 $
  26. * $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $
  27. *----------------------------------------------------------------------------
  28. */
  29. /*------------------------------------
  30. * includes
  31. *------------------------------------
  32. */
  33. #include "eas_types.h"
  34. #include "eas_math.h"
  35. #include "eas_audioconst.h"
  36. #include "eas_sndlib.h"
  37. #include "eas_wtengine.h"
  38. #include "eas_mixer.h"
  39. /*----------------------------------------------------------------------------
  40. * prototypes
  41. *----------------------------------------------------------------------------
  42. */
  43. extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
  44. extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
  45. #if defined(_OPTIMIZED_MONO)
  46. extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
  47. #else
  48. extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
  49. extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame);
  50. #endif
  51. #if defined(_FILTER_ENABLED)
  52. extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame);
  53. #endif
  54. #if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL)
  55. /*----------------------------------------------------------------------------
  56. * WT_VoiceGain
  57. *----------------------------------------------------------------------------
  58. * Purpose:
  59. * Output gain for individual voice
  60. *
  61. * Inputs:
  62. *
  63. * Outputs:
  64. *
  65. *----------------------------------------------------------------------------
  66. */
  67. /*lint -esym(715, pWTVoice) reserved for future use */
  68. void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  69. {
  70. EAS_I32 *pMixBuffer;
  71. EAS_PCM *pInputBuffer;
  72. EAS_I32 gain;
  73. EAS_I32 gainIncrement;
  74. EAS_I32 tmp0;
  75. EAS_I32 tmp1;
  76. EAS_I32 tmp2;
  77. EAS_I32 numSamples;
  78. #if (NUM_OUTPUT_CHANNELS == 2)
  79. EAS_I32 gainLeft, gainRight;
  80. #endif
  81. /* initialize some local variables */
  82. numSamples = pWTIntFrame->numSamples;
  83. pMixBuffer = pWTIntFrame->pMixBuffer;
  84. pInputBuffer = pWTIntFrame->pAudioBuffer;
  85. /*lint -e{703} <avoid multiply for performance>*/
  86. gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
  87. if (gainIncrement < 0)
  88. gainIncrement++;
  89. /*lint -e{703} <avoid multiply for performance>*/
  90. gain = pWTIntFrame->prevGain << 16;
  91. #if (NUM_OUTPUT_CHANNELS == 2)
  92. gainLeft = pWTVoice->gainLeft;
  93. gainRight = pWTVoice->gainRight;
  94. #endif
  95. while (numSamples--) {
  96. /* incremental gain step to prevent zipper noise */
  97. tmp0 = *pInputBuffer++;
  98. gain += gainIncrement;
  99. /*lint -e{704} <avoid divide>*/
  100. tmp2 = gain >> 16;
  101. /* scale sample by gain */
  102. tmp2 *= tmp0;
  103. /* stereo output */
  104. #if (NUM_OUTPUT_CHANNELS == 2)
  105. /*lint -e{704} <avoid divide>*/
  106. tmp2 = tmp2 >> 14;
  107. /* get the current sample in the final mix buffer */
  108. tmp1 = *pMixBuffer;
  109. /* left channel */
  110. tmp0 = tmp2 * gainLeft;
  111. /*lint -e{704} <avoid divide>*/
  112. tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS;
  113. tmp1 += tmp0;
  114. *pMixBuffer++ = tmp1;
  115. /* get the current sample in the final mix buffer */
  116. tmp1 = *pMixBuffer;
  117. /* right channel */
  118. tmp0 = tmp2 * gainRight;
  119. /*lint -e{704} <avoid divide>*/
  120. tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS;
  121. tmp1 += tmp0;
  122. *pMixBuffer++ = tmp1;
  123. /* mono output */
  124. #else
  125. /* get the current sample in the final mix buffer */
  126. tmp1 = *pMixBuffer;
  127. /*lint -e{704} <avoid divide>*/
  128. tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1);
  129. tmp1 += tmp2;
  130. *pMixBuffer++ = tmp1;
  131. #endif
  132. }
  133. }
  134. #endif
  135. #ifndef NATIVE_EAS_KERNEL
  136. /*----------------------------------------------------------------------------
  137. * WT_Interpolate
  138. *----------------------------------------------------------------------------
  139. * Purpose:
  140. * Interpolation engine for wavetable synth
  141. *
  142. * Inputs:
  143. *
  144. * Outputs:
  145. *
  146. *----------------------------------------------------------------------------
  147. */
  148. void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  149. {
  150. EAS_PCM *pOutputBuffer;
  151. EAS_I32 phaseInc;
  152. EAS_I32 phaseFrac;
  153. EAS_I32 acc0;
  154. const EAS_SAMPLE *pSamples;
  155. const EAS_SAMPLE *loopEnd;
  156. EAS_I32 samp1;
  157. EAS_I32 samp2;
  158. EAS_I32 numSamples;
  159. /* initialize some local variables */
  160. numSamples = pWTIntFrame->numSamples;
  161. pOutputBuffer = pWTIntFrame->pAudioBuffer;
  162. loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1;
  163. pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum;
  164. /*lint -e{713} truncation is OK */
  165. phaseFrac = pWTVoice->phaseFrac;
  166. phaseInc = pWTIntFrame->frame.phaseIncrement;
  167. /* fetch adjacent samples */
  168. #if defined(_8_BIT_SAMPLES)
  169. /*lint -e{701} <avoid multiply for performance>*/
  170. samp1 = pSamples[0] << 8;
  171. /*lint -e{701} <avoid multiply for performance>*/
  172. samp2 = pSamples[1] << 8;
  173. #else
  174. samp1 = pSamples[0];
  175. samp2 = pSamples[1];
  176. #endif
  177. while (numSamples--) {
  178. /* linear interpolation */
  179. acc0 = samp2 - samp1;
  180. acc0 = acc0 * phaseFrac;
  181. /*lint -e{704} <avoid divide>*/
  182. acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS);
  183. /* save new output sample in buffer */
  184. /*lint -e{704} <avoid divide>*/
  185. *pOutputBuffer++ = (EAS_I16)(acc0 >> 2);
  186. /* increment phase */
  187. phaseFrac += phaseInc;
  188. /*lint -e{704} <avoid divide>*/
  189. acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS;
  190. /* next sample */
  191. if (acc0 > 0) {
  192. /* advance sample pointer */
  193. pSamples += acc0;
  194. phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK);
  195. /* check for loop end */
  196. acc0 = (EAS_I32) (pSamples - loopEnd);
  197. if (acc0 >= 0)
  198. pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0;
  199. /* fetch new samples */
  200. #if defined(_8_BIT_SAMPLES)
  201. /*lint -e{701} <avoid multiply for performance>*/
  202. samp1 = pSamples[0] << 8;
  203. /*lint -e{701} <avoid multiply for performance>*/
  204. samp2 = pSamples[1] << 8;
  205. #else
  206. samp1 = pSamples[0];
  207. samp2 = pSamples[1];
  208. #endif
  209. }
  210. }
  211. /* save pointer and phase */
  212. pWTVoice->phaseAccum = (EAS_U32) pSamples;
  213. pWTVoice->phaseFrac = (EAS_U32) phaseFrac;
  214. }
  215. #endif
  216. #ifndef NATIVE_EAS_KERNEL
  217. /*----------------------------------------------------------------------------
  218. * WT_InterpolateNoLoop
  219. *----------------------------------------------------------------------------
  220. * Purpose:
  221. * Interpolation engine for wavetable synth
  222. *
  223. * Inputs:
  224. *
  225. * Outputs:
  226. *
  227. *----------------------------------------------------------------------------
  228. */
  229. void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  230. {
  231. EAS_PCM *pOutputBuffer;
  232. EAS_I32 phaseInc;
  233. EAS_I32 phaseFrac;
  234. EAS_I32 acc0;
  235. const EAS_SAMPLE *pSamples;
  236. EAS_I32 samp1;
  237. EAS_I32 samp2;
  238. EAS_I32 numSamples;
  239. /* initialize some local variables */
  240. numSamples = pWTIntFrame->numSamples;
  241. pOutputBuffer = pWTIntFrame->pAudioBuffer;
  242. phaseInc = pWTIntFrame->frame.phaseIncrement;
  243. pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum;
  244. phaseFrac = (EAS_I32)pWTVoice->phaseFrac;
  245. /* fetch adjacent samples */
  246. #if defined(_8_BIT_SAMPLES)
  247. /*lint -e{701} <avoid multiply for performance>*/
  248. samp1 = pSamples[0] << 8;
  249. /*lint -e{701} <avoid multiply for performance>*/
  250. samp2 = pSamples[1] << 8;
  251. #else
  252. samp1 = pSamples[0];
  253. samp2 = pSamples[1];
  254. #endif
  255. while (numSamples--) {
  256. /* linear interpolation */
  257. acc0 = samp2 - samp1;
  258. acc0 = acc0 * phaseFrac;
  259. /*lint -e{704} <avoid divide>*/
  260. acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS);
  261. /* save new output sample in buffer */
  262. /*lint -e{704} <avoid divide>*/
  263. *pOutputBuffer++ = (EAS_I16)(acc0 >> 2);
  264. /* increment phase */
  265. phaseFrac += phaseInc;
  266. /*lint -e{704} <avoid divide>*/
  267. acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS;
  268. /* next sample */
  269. if (acc0 > 0) {
  270. /* advance sample pointer */
  271. pSamples += acc0;
  272. phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK);
  273. /* fetch new samples */
  274. #if defined(_8_BIT_SAMPLES)
  275. /*lint -e{701} <avoid multiply for performance>*/
  276. samp1 = pSamples[0] << 8;
  277. /*lint -e{701} <avoid multiply for performance>*/
  278. samp2 = pSamples[1] << 8;
  279. #else
  280. samp1 = pSamples[0];
  281. samp2 = pSamples[1];
  282. #endif
  283. }
  284. }
  285. /* save pointer and phase */
  286. pWTVoice->phaseAccum = (EAS_U32) pSamples;
  287. pWTVoice->phaseFrac = (EAS_U32) phaseFrac;
  288. }
  289. #endif
  290. #if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL)
  291. /*----------------------------------------------------------------------------
  292. * WT_VoiceFilter
  293. *----------------------------------------------------------------------------
  294. * Purpose:
  295. * Implements a 2-pole filter
  296. *
  297. * Inputs:
  298. *
  299. * Outputs:
  300. *
  301. *----------------------------------------------------------------------------
  302. */
  303. void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame)
  304. {
  305. EAS_PCM *pAudioBuffer;
  306. EAS_I32 k;
  307. EAS_I32 b1;
  308. EAS_I32 b2;
  309. EAS_I32 z1;
  310. EAS_I32 z2;
  311. EAS_I32 acc0;
  312. EAS_I32 acc1;
  313. EAS_I32 numSamples;
  314. /* initialize some local variables */
  315. numSamples = pWTIntFrame->numSamples;
  316. pAudioBuffer = pWTIntFrame->pAudioBuffer;
  317. z1 = pFilter->z1;
  318. z2 = pFilter->z2;
  319. b1 = -pWTIntFrame->frame.b1;
  320. /*lint -e{702} <avoid divide> */
  321. b2 = -pWTIntFrame->frame.b2 >> 1;
  322. /*lint -e{702} <avoid divide> */
  323. k = pWTIntFrame->frame.k >> 1;
  324. while (numSamples--)
  325. {
  326. /* do filter calculations */
  327. acc0 = *pAudioBuffer;
  328. acc1 = z1 * b1;
  329. acc1 += z2 * b2;
  330. acc0 = acc1 + k * acc0;
  331. z2 = z1;
  332. /*lint -e{702} <avoid divide> */
  333. z1 = acc0 >> 14;
  334. *pAudioBuffer++ = (EAS_I16) z1;
  335. }
  336. /* save delay values */
  337. pFilter->z1 = (EAS_I16) z1;
  338. pFilter->z2 = (EAS_I16) z2;
  339. }
  340. #endif
  341. /*----------------------------------------------------------------------------
  342. * WT_NoiseGenerator
  343. *----------------------------------------------------------------------------
  344. * Purpose:
  345. * Generate pseudo-white noise using PRNG and interpolation engine
  346. *
  347. * Inputs:
  348. *
  349. * Outputs:
  350. *
  351. * Notes:
  352. * This output is scaled -12dB to prevent saturation in the filter. For a
  353. * high quality synthesizer, the output can be set to full scale, however
  354. * if the filter is used, it can overflow with certain coefficients. In this
  355. * case, either a saturation operation should take in the filter before
  356. * scaling back to 16 bits or the signal path should be increased to 18 bits
  357. * or more.
  358. *----------------------------------------------------------------------------
  359. */
  360. void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  361. {
  362. EAS_PCM *pOutputBuffer;
  363. EAS_I32 phaseInc;
  364. EAS_I32 tmp0;
  365. EAS_I32 tmp1;
  366. EAS_I32 nInterpolatedSample;
  367. EAS_I32 numSamples;
  368. /* initialize some local variables */
  369. numSamples = pWTIntFrame->numSamples;
  370. pOutputBuffer = pWTIntFrame->pAudioBuffer;
  371. phaseInc = pWTIntFrame->frame.phaseIncrement;
  372. /* get last two samples generated */
  373. /*lint -e{704} <avoid divide for performance>*/
  374. tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18;
  375. /*lint -e{704} <avoid divide for performance>*/
  376. tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18;
  377. /* generate a buffer of noise */
  378. while (numSamples--) {
  379. nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac));
  380. nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac);
  381. *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample;
  382. /* update PRNG */
  383. pWTVoice->phaseFrac += (EAS_U32) phaseInc;
  384. if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) {
  385. tmp0 = tmp1;
  386. pWTVoice->phaseAccum = pWTVoice->loopEnd;
  387. pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1);
  388. tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18;
  389. pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac);
  390. }
  391. }
  392. }
  393. #ifndef _OPTIMIZED_MONO
  394. /*----------------------------------------------------------------------------
  395. * WT_ProcessVoice
  396. *----------------------------------------------------------------------------
  397. * Purpose:
  398. * This routine does the block processing for one voice. It is isolated
  399. * from the main synth code to allow for various implementation-specific
  400. * optimizations. It calls the interpolator, filter, and gain routines
  401. * appropriate for a particular configuration.
  402. *
  403. * Inputs:
  404. *
  405. * Outputs:
  406. *
  407. * Notes:
  408. *----------------------------------------------------------------------------
  409. */
  410. void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  411. {
  412. /* use noise generator */
  413. if (pWTVoice->loopStart == WT_NOISE_GENERATOR)
  414. WT_NoiseGenerator(pWTVoice, pWTIntFrame);
  415. /* generate interpolated samples for looped waves */
  416. else if (pWTVoice->loopStart != pWTVoice->loopEnd)
  417. WT_Interpolate(pWTVoice, pWTIntFrame);
  418. /* generate interpolated samples for unlooped waves */
  419. else
  420. {
  421. WT_InterpolateNoLoop(pWTVoice, pWTIntFrame);
  422. }
  423. #ifdef _FILTER_ENABLED
  424. if (pWTIntFrame->frame.k != 0)
  425. WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame);
  426. #endif
  427. //2 TEST NEW MIXER FUNCTION
  428. #ifdef UNIFIED_MIXER
  429. {
  430. EAS_I32 gainLeft, gainIncLeft;
  431. #if (NUM_OUTPUT_CHANNELS == 2)
  432. EAS_I32 gainRight, gainIncRight;
  433. #endif
  434. gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1;
  435. gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS;
  436. #if (NUM_OUTPUT_CHANNELS == 2)
  437. gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1;
  438. gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS;
  439. EAS_MixStream(
  440. pWTIntFrame->pAudioBuffer,
  441. pWTIntFrame->pMixBuffer,
  442. pWTIntFrame->numSamples,
  443. gainLeft,
  444. gainRight,
  445. gainIncLeft,
  446. gainIncRight,
  447. MIX_FLAGS_STEREO_OUTPUT);
  448. #else
  449. EAS_MixStream(
  450. pWTIntFrame->pAudioBuffer,
  451. pWTIntFrame->pMixBuffer,
  452. pWTIntFrame->numSamples,
  453. gainLeft,
  454. 0,
  455. gainIncLeft,
  456. 0,
  457. 0);
  458. #endif
  459. }
  460. #else
  461. /* apply gain, and left and right gain */
  462. WT_VoiceGain(pWTVoice, pWTIntFrame);
  463. #endif
  464. }
  465. #endif
  466. #if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL)
  467. /*----------------------------------------------------------------------------
  468. * WT_InterpolateMono
  469. *----------------------------------------------------------------------------
  470. * Purpose:
  471. * A C version of the sample interpolation + gain routine, optimized for mono.
  472. * It's not pretty, but it matches the assembly code exactly.
  473. *
  474. * Inputs:
  475. *
  476. * Outputs:
  477. *
  478. * Notes:
  479. *----------------------------------------------------------------------------
  480. */
  481. void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  482. {
  483. EAS_I32 *pMixBuffer;
  484. const EAS_I8 *pLoopEnd;
  485. const EAS_I8 *pCurrentPhaseInt;
  486. EAS_I32 numSamples;
  487. EAS_I32 gain;
  488. EAS_I32 gainIncrement;
  489. EAS_I32 currentPhaseFrac;
  490. EAS_I32 phaseInc;
  491. EAS_I32 tmp0;
  492. EAS_I32 tmp1;
  493. EAS_I32 tmp2;
  494. EAS_I8 *pLoopStart;
  495. numSamples = pWTIntFrame->numSamples;
  496. pMixBuffer = pWTIntFrame->pMixBuffer;
  497. /* calculate gain increment */
  498. gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS);
  499. if (gainIncrement < 0)
  500. gainIncrement++;
  501. gain = pWTIntFrame->prevGain << 16;
  502. pCurrentPhaseInt = pWTVoice->pPhaseAccum;
  503. currentPhaseFrac = pWTVoice->phaseFrac;
  504. phaseInc = pWTIntFrame->phaseIncrement;
  505. pLoopStart = pWTVoice->pLoopStart;
  506. pLoopEnd = pWTVoice->pLoopEnd + 1;
  507. InterpolationLoop:
  508. tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd);
  509. if (tmp0 >= 0)
  510. pCurrentPhaseInt = pLoopStart + tmp0;
  511. tmp0 = *pCurrentPhaseInt;
  512. tmp1 = *(pCurrentPhaseInt + 1);
  513. tmp2 = phaseInc + currentPhaseFrac;
  514. tmp1 = tmp1 - tmp0;
  515. tmp1 = tmp1 * currentPhaseFrac;
  516. tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS);
  517. pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS);
  518. currentPhaseFrac = tmp2 & PHASE_FRAC_MASK;
  519. gain += gainIncrement;
  520. tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS);
  521. tmp0 = *pMixBuffer;
  522. tmp2 = tmp1 * tmp2;
  523. tmp2 = (tmp2 >> 9);
  524. tmp0 = tmp2 + tmp0;
  525. *pMixBuffer++ = tmp0;
  526. numSamples--;
  527. if (numSamples)
  528. goto InterpolationLoop;
  529. pWTVoice->pPhaseAccum = pCurrentPhaseInt;
  530. pWTVoice->phaseFrac = currentPhaseFrac;
  531. /*lint -e{702} <avoid divide>*/
  532. pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS);
  533. }
  534. #endif
  535. #ifdef _OPTIMIZED_MONO
  536. /*----------------------------------------------------------------------------
  537. * WT_ProcessVoice
  538. *----------------------------------------------------------------------------
  539. * Purpose:
  540. * This routine does the block processing for one voice. It is isolated
  541. * from the main synth code to allow for various implementation-specific
  542. * optimizations. It calls the interpolator, filter, and gain routines
  543. * appropriate for a particular configuration.
  544. *
  545. * Inputs:
  546. *
  547. * Outputs:
  548. *
  549. * Notes:
  550. * This special version works handles an optimized mono-only signal
  551. * without filters
  552. *----------------------------------------------------------------------------
  553. */
  554. void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
  555. {
  556. /* use noise generator */
  557. if (pWTVoice->loopStart== WT_NOISE_GENERATOR)
  558. {
  559. WT_NoiseGenerator(pWTVoice, pWTIntFrame);
  560. WT_VoiceGain(pWTVoice, pWTIntFrame);
  561. }
  562. /* or generate interpolated samples */
  563. else
  564. {
  565. WT_InterpolateMono(pWTVoice, pWTIntFrame);
  566. }
  567. }
  568. #endif