Home | History | Annotate | Download | only in lib_src
      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 */
     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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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