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