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