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