• 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 & PHASE_FRAC_MASK;
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         EAS_I32 nextSamplePhaseInc;
222 
223         /* linear interpolation */
224         acc0 = samp2 - samp1;
225         acc0 = acc0 * phaseFrac;
226         /*lint -e{704} <avoid divide>*/
227         acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS);
228 
229         /* save new output sample in buffer */
230         /*lint -e{704} <avoid divide>*/
231         *pOutputBuffer++ = (EAS_I16)(acc0 >> 2);
232 
233         /* increment phase */
234         phaseFrac += phaseInc;
235         /*lint -e{704} <avoid divide>*/
236         nextSamplePhaseInc = phaseFrac >> NUM_PHASE_FRAC_BITS;
237 
238         /* next sample */
239         if (nextSamplePhaseInc > 0) {
240             /* advance sample pointer */
241             pSamples +=  nextSamplePhaseInc;
242             phaseFrac = phaseFrac & PHASE_FRAC_MASK;
243 
244             /* decrementing pSamples by entire buffer length until second pSample is within */
245             /* loopEnd                                                                      */
246             while (&pSamples[1] >= loopEnd) {
247                 pSamples -= (loopEnd - (const EAS_SAMPLE*)pWTVoice->loopStart);
248             }
249 
250             /* fetch new samples */
251 #if defined(_8_BIT_SAMPLES)
252             /*lint -e{701} <avoid multiply for performance>*/
253             samp1 = pSamples[0] << 8;
254             /*lint -e{701} <avoid multiply for performance>*/
255             samp2 = pSamples[1] << 8;
256 #else
257             samp1 = pSamples[0];
258             samp2 = pSamples[1];
259 #endif
260         }
261     }
262 
263     /* save pointer and phase */
264     pWTVoice->phaseAccum = (EAS_U32) pSamples;
265     pWTVoice->phaseFrac = (EAS_U32) phaseFrac;
266 }
267 #endif
268 
269 #if !defined(NATIVE_EAS_KERNEL) || defined(_16_BIT_SAMPLES)
270 /*----------------------------------------------------------------------------
271  * WT_InterpolateNoLoop
272  *----------------------------------------------------------------------------
273  * Purpose:
274  * Interpolation engine for wavetable synth
275  *
276  * Inputs:
277  *
278  * Outputs:
279  *
280  *----------------------------------------------------------------------------
281 */
WT_InterpolateNoLoop(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)282 void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
283 {
284     EAS_PCM *pOutputBuffer;
285     EAS_I32 phaseInc;
286     EAS_I32 phaseFrac;
287     EAS_I32 acc0;
288     const EAS_SAMPLE *pSamples;
289     const EAS_SAMPLE *bufferEndP1;
290     EAS_I32 samp1;
291     EAS_I32 samp2;
292     EAS_I32 numSamples;
293 
294     /* initialize some local variables */
295     numSamples = pWTIntFrame->numSamples;
296     if (numSamples <= 0) {
297         ALOGE("b/26366256");
298         android_errorWriteLog(0x534e4554, "26366256");
299         return;
300     }
301     pOutputBuffer = pWTIntFrame->pAudioBuffer;
302 
303     phaseInc = pWTIntFrame->frame.phaseIncrement;
304     bufferEndP1 = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1;
305     pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum;
306     phaseFrac = (EAS_I32)(pWTVoice->phaseFrac & PHASE_FRAC_MASK);
307 
308     /* fetch adjacent samples */
309 #if defined(_8_BIT_SAMPLES)
310     /*lint -e{701} <avoid multiply for performance>*/
311     samp1 = pSamples[0] << 8;
312     /*lint -e{701} <avoid multiply for performance>*/
313     samp2 = pSamples[1] << 8;
314 #else
315     samp1 = pSamples[0];
316     samp2 = pSamples[1];
317 #endif
318 
319     while (numSamples--) {
320 
321         EAS_I32 nextSamplePhaseInc;
322 
323         /* linear interpolation */
324         acc0 = samp2 - samp1;
325         acc0 = acc0 * phaseFrac;
326         /*lint -e{704} <avoid divide>*/
327         acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS);
328 
329         /* save new output sample in buffer */
330         /*lint -e{704} <avoid divide>*/
331         *pOutputBuffer++ = (EAS_I16)(acc0 >> 2);
332 
333         /* increment phase */
334         phaseFrac += phaseInc;
335         /*lint -e{704} <avoid divide>*/
336         nextSamplePhaseInc = phaseFrac >> NUM_PHASE_FRAC_BITS;
337 
338         /* next sample */
339         if (nextSamplePhaseInc > 0) {
340 
341             /* check for loop end */
342             if ( &pSamples[nextSamplePhaseInc+1] >= bufferEndP1) {
343                 break;
344             }
345 
346             /* advance sample pointer */
347             pSamples += nextSamplePhaseInc;
348             phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK);
349 
350             /* fetch new samples */
351 #if defined(_8_BIT_SAMPLES)
352             /*lint -e{701} <avoid multiply for performance>*/
353             samp1 = pSamples[0] << 8;
354             /*lint -e{701} <avoid multiply for performance>*/
355             samp2 = pSamples[1] << 8;
356 #else
357             samp1 = pSamples[0];
358             samp2 = pSamples[1];
359 #endif
360         }
361     }
362 
363     /* save pointer and phase */
364     pWTVoice->phaseAccum = (EAS_U32) pSamples;
365     pWTVoice->phaseFrac = (EAS_U32) phaseFrac;
366 }
367 #endif
368 
369 #if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL)
370 /*----------------------------------------------------------------------------
371  * WT_VoiceFilter
372  *----------------------------------------------------------------------------
373  * Purpose:
374  * Implements a 2-pole filter
375  *
376  * Inputs:
377  *
378  * Outputs:
379  *
380  *----------------------------------------------------------------------------
381 */
WT_VoiceFilter(S_FILTER_CONTROL * pFilter,S_WT_INT_FRAME * pWTIntFrame)382 void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame)
383 {
384     EAS_PCM *pAudioBuffer;
385     EAS_I32 k;
386     EAS_I32 b1;
387     EAS_I32 b2;
388     EAS_I32 z1;
389     EAS_I32 z2;
390     EAS_I32 acc0;
391     EAS_I32 acc1;
392     EAS_I32 numSamples;
393 
394     /* initialize some local variables */
395     numSamples = pWTIntFrame->numSamples;
396     if (numSamples <= 0) {
397         ALOGE("b/26366256");
398         android_errorWriteLog(0x534e4554, "26366256");
399         return;
400     }
401     pAudioBuffer = pWTIntFrame->pAudioBuffer;
402 
403     z1 = pFilter->z1;
404     z2 = pFilter->z2;
405     b1 = -pWTIntFrame->frame.b1;
406 
407     /*lint -e{702} <avoid divide> */
408     b2 = -pWTIntFrame->frame.b2 >> 1;
409 
410     /*lint -e{702} <avoid divide> */
411     k = pWTIntFrame->frame.k >> 1;
412 
413     while (numSamples--)
414     {
415 
416         /* do filter calculations */
417         acc0 = *pAudioBuffer;
418         acc1 = z1 * b1;
419         acc1 += z2 * b2;
420         acc0 = acc1 + k * acc0;
421         z2 = z1;
422 
423         /*lint -e{702} <avoid divide> */
424         z1 = acc0 >> 14;
425         *pAudioBuffer++ = (EAS_I16) z1;
426     }
427 
428     /* save delay values     */
429     pFilter->z1 = (EAS_I16) z1;
430     pFilter->z2 = (EAS_I16) z2;
431 }
432 #endif
433 
434 /*----------------------------------------------------------------------------
435  * WT_NoiseGenerator
436  *----------------------------------------------------------------------------
437  * Purpose:
438  * Generate pseudo-white noise using PRNG and interpolation engine
439  *
440  * Inputs:
441  *
442  * Outputs:
443  *
444  * Notes:
445  * This output is scaled -12dB to prevent saturation in the filter. For a
446  * high quality synthesizer, the output can be set to full scale, however
447  * if the filter is used, it can overflow with certain coefficients. In this
448  * case, either a saturation operation should take in the filter before
449  * scaling back to 16 bits or the signal path should be increased to 18 bits
450  * or more.
451  *----------------------------------------------------------------------------
452 */
WT_NoiseGenerator(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)453  void NO_INT_OVERFLOW_CHECKS WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
454  {
455     EAS_PCM *pOutputBuffer;
456     EAS_I32 phaseInc;
457     EAS_I32 tmp0;
458     EAS_I32 tmp1;
459     EAS_I32 nInterpolatedSample;
460     EAS_I32 numSamples;
461 
462     /* initialize some local variables */
463     numSamples = pWTIntFrame->numSamples;
464     if (numSamples <= 0) {
465         ALOGE("b/26366256");
466         android_errorWriteLog(0x534e4554, "26366256");
467         return;
468     }
469     pOutputBuffer = pWTIntFrame->pAudioBuffer;
470     phaseInc = pWTIntFrame->frame.phaseIncrement;
471 
472     /* get last two samples generated */
473     /*lint -e{704} <avoid divide for performance>*/
474     tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18;
475     /*lint -e{704} <avoid divide for performance>*/
476     tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18;
477 
478     /* generate a buffer of noise */
479     while (numSamples--) {
480         nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac));
481         nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac);
482         *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample;
483 
484         /* update PRNG */
485         pWTVoice->phaseFrac += (EAS_U32) phaseInc;
486         if (GET_PHASE_INT_PART(pWTVoice->phaseFrac))    {
487             tmp0 = tmp1;
488             pWTVoice->phaseAccum = pWTVoice->loopEnd;
489             pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1);
490             tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18;
491             pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac);
492         }
493 
494     }
495 }
496 
497 #ifndef _OPTIMIZED_MONO
498 /*----------------------------------------------------------------------------
499  * WT_ProcessVoice
500  *----------------------------------------------------------------------------
501  * Purpose:
502  * This routine does the block processing for one voice. It is isolated
503  * from the main synth code to allow for various implementation-specific
504  * optimizations. It calls the interpolator, filter, and gain routines
505  * appropriate for a particular configuration.
506  *
507  * Inputs:
508  *
509  * Outputs:
510  *
511  * Notes:
512  *----------------------------------------------------------------------------
513 */
WT_ProcessVoice(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)514 void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
515 {
516 
517     /* use noise generator */
518     if (pWTVoice->loopStart == WT_NOISE_GENERATOR)
519         WT_NoiseGenerator(pWTVoice, pWTIntFrame);
520 
521     /* generate interpolated samples for looped waves */
522     else if (pWTVoice->loopStart != pWTVoice->loopEnd)
523         WT_Interpolate(pWTVoice, pWTIntFrame);
524 
525     /* generate interpolated samples for unlooped waves */
526     else
527     {
528         WT_InterpolateNoLoop(pWTVoice, pWTIntFrame);
529     }
530 
531 #ifdef _FILTER_ENABLED
532     if (pWTIntFrame->frame.k != 0)
533         WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame);
534 #endif
535 
536 //2 TEST NEW MIXER FUNCTION
537 #ifdef UNIFIED_MIXER
538     {
539         EAS_I32 gainLeft, gainIncLeft;
540 
541 #if (NUM_OUTPUT_CHANNELS == 2)
542         EAS_I32 gainRight, gainIncRight;
543 #endif
544 
545         gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1;
546         gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS;
547 
548 #if (NUM_OUTPUT_CHANNELS == 2)
549         gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1;
550         gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS;
551         EAS_MixStream(
552             pWTIntFrame->pAudioBuffer,
553             pWTIntFrame->pMixBuffer,
554             pWTIntFrame->numSamples,
555             gainLeft,
556             gainRight,
557             gainIncLeft,
558             gainIncRight,
559             MIX_FLAGS_STEREO_OUTPUT);
560 
561 #else
562         EAS_MixStream(
563             pWTIntFrame->pAudioBuffer,
564             pWTIntFrame->pMixBuffer,
565             pWTIntFrame->numSamples,
566             gainLeft,
567             0,
568             gainIncLeft,
569             0,
570             0);
571 #endif
572     }
573 
574 #else
575     /* apply gain, and left and right gain */
576     WT_VoiceGain(pWTVoice, pWTIntFrame);
577 #endif
578 }
579 #endif
580 
581 #if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL)
582 /*----------------------------------------------------------------------------
583  * WT_InterpolateMono
584  *----------------------------------------------------------------------------
585  * Purpose:
586  * A C version of the sample interpolation + gain routine, optimized for mono.
587  * It's not pretty, but it matches the assembly code exactly.
588  *
589  * Inputs:
590  *
591  * Outputs:
592  *
593  * Notes:
594  *----------------------------------------------------------------------------
595 */
WT_InterpolateMono(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)596 void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
597 {
598     EAS_I32 *pMixBuffer;
599     const EAS_I8 *pLoopEnd;
600     const EAS_I8 *pCurrentPhaseInt;
601     EAS_I32 numSamples;
602     EAS_I32 gain;
603     EAS_I32 gainIncrement;
604     EAS_I32 currentPhaseFrac;
605     EAS_I32 phaseInc;
606     EAS_I32 tmp0;
607     EAS_I32 tmp1;
608     EAS_I32 tmp2;
609     EAS_I8 *pLoopStart;
610 
611     numSamples = pWTIntFrame->numSamples;
612     if (numSamples <= 0) {
613         ALOGE("b/26366256");
614         android_errorWriteLog(0x534e4554, "26366256");
615         return;
616     }
617     pMixBuffer = pWTIntFrame->pMixBuffer;
618 
619     /* calculate gain increment */
620     gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) * (1 << (16 - SYNTH_UPDATE_PERIOD_IN_BITS));
621     if (gainIncrement < 0)
622         gainIncrement++;
623     gain = pWTIntFrame->prevGain * (1 << 16);
624 
625     pCurrentPhaseInt = pWTVoice->pPhaseAccum;
626     currentPhaseFrac = pWTVoice->phaseFrac;
627     phaseInc = pWTIntFrame->phaseIncrement;
628 
629     pLoopStart = pWTVoice->pLoopStart;
630     pLoopEnd = pWTVoice->pLoopEnd + 1;
631 
632 InterpolationLoop:
633     tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd);
634     if (tmp0 >= 0)
635         pCurrentPhaseInt = pLoopStart + tmp0;
636 
637     tmp0 = *pCurrentPhaseInt;
638     tmp1 = *(pCurrentPhaseInt + 1);
639 
640     tmp2 = phaseInc + currentPhaseFrac;
641 
642     tmp1 = tmp1 - tmp0;
643     tmp1 = tmp1 * currentPhaseFrac;
644 
645     tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS);
646 
647     pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS);
648     currentPhaseFrac = tmp2 & PHASE_FRAC_MASK;
649 
650     gain += gainIncrement;
651     tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS);
652 
653     tmp0 = *pMixBuffer;
654     tmp2 = tmp1 * tmp2;
655     tmp2 = (tmp2 >> 9);
656     tmp0 = tmp2 + tmp0;
657     *pMixBuffer++ = tmp0;
658 
659     numSamples--;
660     if (numSamples > 0)
661         goto InterpolationLoop;
662 
663     pWTVoice->pPhaseAccum = pCurrentPhaseInt;
664     pWTVoice->phaseFrac = currentPhaseFrac;
665     /*lint -e{702} <avoid divide>*/
666     pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS);
667 }
668 #endif
669 
670 #ifdef _OPTIMIZED_MONO
671 /*----------------------------------------------------------------------------
672  * WT_ProcessVoice
673  *----------------------------------------------------------------------------
674  * Purpose:
675  * This routine does the block processing for one voice. It is isolated
676  * from the main synth code to allow for various implementation-specific
677  * optimizations. It calls the interpolator, filter, and gain routines
678  * appropriate for a particular configuration.
679  *
680  * Inputs:
681  *
682  * Outputs:
683  *
684  * Notes:
685  * This special version works handles an optimized mono-only signal
686  * without filters
687  *----------------------------------------------------------------------------
688 */
WT_ProcessVoice(S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pWTIntFrame)689 void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame)
690 {
691 
692     /* use noise generator */
693     if (pWTVoice->loopStart== WT_NOISE_GENERATOR)
694     {
695         WT_NoiseGenerator(pWTVoice, pWTIntFrame);
696         WT_VoiceGain(pWTVoice, pWTIntFrame);
697     }
698 
699     /* or generate interpolated samples */
700     else
701     {
702         WT_InterpolateMono(pWTVoice, pWTIntFrame);
703     }
704 }
705 #endif
706 
707