| /*---------------------------------------------------------------------------- |
| * |
| * File: |
| * eas_wtengine.c |
| * |
| * Contents and purpose: |
| * This file contains the critical synthesizer components that need to |
| * be optimized for best performance. |
| * |
| * Copyright Sonic Network Inc. 2004-2005 |
| |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *---------------------------------------------------------------------------- |
| * Revision Control: |
| * $Revision: 844 $ |
| * $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $ |
| *---------------------------------------------------------------------------- |
| */ |
| |
| /*------------------------------------ |
| * includes |
| *------------------------------------ |
| */ |
| #include "eas_types.h" |
| #include "eas_math.h" |
| #include "eas_audioconst.h" |
| #include "eas_sndlib.h" |
| #include "eas_wtengine.h" |
| #include "eas_mixer.h" |
| |
| /*---------------------------------------------------------------------------- |
| * prototypes |
| *---------------------------------------------------------------------------- |
| */ |
| extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); |
| extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); |
| |
| #if defined(_OPTIMIZED_MONO) |
| extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); |
| #else |
| extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); |
| extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); |
| #endif |
| |
| #if defined(_FILTER_ENABLED) |
| extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame); |
| #endif |
| |
| #if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL) |
| /*---------------------------------------------------------------------------- |
| * WT_VoiceGain |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Output gain for individual voice |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| /*lint -esym(715, pWTVoice) reserved for future use */ |
| void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| EAS_I32 *pMixBuffer; |
| EAS_PCM *pInputBuffer; |
| EAS_I32 gain; |
| EAS_I32 gainIncrement; |
| EAS_I32 tmp0; |
| EAS_I32 tmp1; |
| EAS_I32 tmp2; |
| EAS_I32 numSamples; |
| |
| #if (NUM_OUTPUT_CHANNELS == 2) |
| EAS_I32 gainLeft, gainRight; |
| #endif |
| |
| /* initialize some local variables */ |
| numSamples = pWTIntFrame->numSamples; |
| pMixBuffer = pWTIntFrame->pMixBuffer; |
| pInputBuffer = pWTIntFrame->pAudioBuffer; |
| |
| /*lint -e{703} <avoid multiply for performance>*/ |
| gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); |
| if (gainIncrement < 0) |
| gainIncrement++; |
| /*lint -e{703} <avoid multiply for performance>*/ |
| gain = pWTIntFrame->prevGain << 16; |
| |
| #if (NUM_OUTPUT_CHANNELS == 2) |
| gainLeft = pWTVoice->gainLeft; |
| gainRight = pWTVoice->gainRight; |
| #endif |
| |
| while (numSamples--) { |
| |
| /* incremental gain step to prevent zipper noise */ |
| tmp0 = *pInputBuffer++; |
| gain += gainIncrement; |
| /*lint -e{704} <avoid divide>*/ |
| tmp2 = gain >> 16; |
| |
| /* scale sample by gain */ |
| tmp2 *= tmp0; |
| |
| |
| /* stereo output */ |
| #if (NUM_OUTPUT_CHANNELS == 2) |
| /*lint -e{704} <avoid divide>*/ |
| tmp2 = tmp2 >> 14; |
| |
| /* get the current sample in the final mix buffer */ |
| tmp1 = *pMixBuffer; |
| |
| /* left channel */ |
| tmp0 = tmp2 * gainLeft; |
| /*lint -e{704} <avoid divide>*/ |
| tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; |
| tmp1 += tmp0; |
| *pMixBuffer++ = tmp1; |
| |
| /* get the current sample in the final mix buffer */ |
| tmp1 = *pMixBuffer; |
| |
| /* right channel */ |
| tmp0 = tmp2 * gainRight; |
| /*lint -e{704} <avoid divide>*/ |
| tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; |
| tmp1 += tmp0; |
| *pMixBuffer++ = tmp1; |
| |
| /* mono output */ |
| #else |
| |
| /* get the current sample in the final mix buffer */ |
| tmp1 = *pMixBuffer; |
| /*lint -e{704} <avoid divide>*/ |
| tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1); |
| tmp1 += tmp2; |
| *pMixBuffer++ = tmp1; |
| #endif |
| |
| } |
| } |
| #endif |
| |
| #ifndef NATIVE_EAS_KERNEL |
| /*---------------------------------------------------------------------------- |
| * WT_Interpolate |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Interpolation engine for wavetable synth |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| EAS_PCM *pOutputBuffer; |
| EAS_I32 phaseInc; |
| EAS_I32 phaseFrac; |
| EAS_I32 acc0; |
| const EAS_SAMPLE *pSamples; |
| const EAS_SAMPLE *loopEnd; |
| EAS_I32 samp1; |
| EAS_I32 samp2; |
| EAS_I32 numSamples; |
| |
| /* initialize some local variables */ |
| numSamples = pWTIntFrame->numSamples; |
| pOutputBuffer = pWTIntFrame->pAudioBuffer; |
| |
| loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1; |
| pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; |
| /*lint -e{713} truncation is OK */ |
| phaseFrac = pWTVoice->phaseFrac; |
| phaseInc = pWTIntFrame->frame.phaseIncrement; |
| |
| /* fetch adjacent samples */ |
| #if defined(_8_BIT_SAMPLES) |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp1 = pSamples[0] << 8; |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp2 = pSamples[1] << 8; |
| #else |
| samp1 = pSamples[0]; |
| samp2 = pSamples[1]; |
| #endif |
| |
| while (numSamples--) { |
| |
| /* linear interpolation */ |
| acc0 = samp2 - samp1; |
| acc0 = acc0 * phaseFrac; |
| /*lint -e{704} <avoid divide>*/ |
| acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); |
| |
| /* save new output sample in buffer */ |
| /*lint -e{704} <avoid divide>*/ |
| *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); |
| |
| /* increment phase */ |
| phaseFrac += phaseInc; |
| /*lint -e{704} <avoid divide>*/ |
| acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; |
| |
| /* next sample */ |
| if (acc0 > 0) { |
| |
| /* advance sample pointer */ |
| pSamples += acc0; |
| phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); |
| |
| /* check for loop end */ |
| acc0 = (EAS_I32) (pSamples - loopEnd); |
| if (acc0 >= 0) |
| pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0; |
| |
| /* fetch new samples */ |
| #if defined(_8_BIT_SAMPLES) |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp1 = pSamples[0] << 8; |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp2 = pSamples[1] << 8; |
| #else |
| samp1 = pSamples[0]; |
| samp2 = pSamples[1]; |
| #endif |
| } |
| } |
| |
| /* save pointer and phase */ |
| pWTVoice->phaseAccum = (EAS_U32) pSamples; |
| pWTVoice->phaseFrac = (EAS_U32) phaseFrac; |
| } |
| #endif |
| |
| #ifndef NATIVE_EAS_KERNEL |
| /*---------------------------------------------------------------------------- |
| * WT_InterpolateNoLoop |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Interpolation engine for wavetable synth |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| EAS_PCM *pOutputBuffer; |
| EAS_I32 phaseInc; |
| EAS_I32 phaseFrac; |
| EAS_I32 acc0; |
| const EAS_SAMPLE *pSamples; |
| EAS_I32 samp1; |
| EAS_I32 samp2; |
| EAS_I32 numSamples; |
| |
| /* initialize some local variables */ |
| numSamples = pWTIntFrame->numSamples; |
| pOutputBuffer = pWTIntFrame->pAudioBuffer; |
| |
| phaseInc = pWTIntFrame->frame.phaseIncrement; |
| pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; |
| phaseFrac = (EAS_I32)pWTVoice->phaseFrac; |
| |
| /* fetch adjacent samples */ |
| #if defined(_8_BIT_SAMPLES) |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp1 = pSamples[0] << 8; |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp2 = pSamples[1] << 8; |
| #else |
| samp1 = pSamples[0]; |
| samp2 = pSamples[1]; |
| #endif |
| |
| while (numSamples--) { |
| |
| |
| /* linear interpolation */ |
| acc0 = samp2 - samp1; |
| acc0 = acc0 * phaseFrac; |
| /*lint -e{704} <avoid divide>*/ |
| acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); |
| |
| /* save new output sample in buffer */ |
| /*lint -e{704} <avoid divide>*/ |
| *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); |
| |
| /* increment phase */ |
| phaseFrac += phaseInc; |
| /*lint -e{704} <avoid divide>*/ |
| acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; |
| |
| /* next sample */ |
| if (acc0 > 0) { |
| |
| /* advance sample pointer */ |
| pSamples += acc0; |
| phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); |
| |
| /* fetch new samples */ |
| #if defined(_8_BIT_SAMPLES) |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp1 = pSamples[0] << 8; |
| /*lint -e{701} <avoid multiply for performance>*/ |
| samp2 = pSamples[1] << 8; |
| #else |
| samp1 = pSamples[0]; |
| samp2 = pSamples[1]; |
| #endif |
| } |
| } |
| |
| /* save pointer and phase */ |
| pWTVoice->phaseAccum = (EAS_U32) pSamples; |
| pWTVoice->phaseFrac = (EAS_U32) phaseFrac; |
| } |
| #endif |
| |
| #if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL) |
| /*---------------------------------------------------------------------------- |
| * WT_VoiceFilter |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Implements a 2-pole filter |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| EAS_PCM *pAudioBuffer; |
| EAS_I32 k; |
| EAS_I32 b1; |
| EAS_I32 b2; |
| EAS_I32 z1; |
| EAS_I32 z2; |
| EAS_I32 acc0; |
| EAS_I32 acc1; |
| EAS_I32 numSamples; |
| |
| /* initialize some local variables */ |
| numSamples = pWTIntFrame->numSamples; |
| pAudioBuffer = pWTIntFrame->pAudioBuffer; |
| |
| z1 = pFilter->z1; |
| z2 = pFilter->z2; |
| b1 = -pWTIntFrame->frame.b1; |
| |
| /*lint -e{702} <avoid divide> */ |
| b2 = -pWTIntFrame->frame.b2 >> 1; |
| |
| /*lint -e{702} <avoid divide> */ |
| k = pWTIntFrame->frame.k >> 1; |
| |
| while (numSamples--) |
| { |
| |
| /* do filter calculations */ |
| acc0 = *pAudioBuffer; |
| acc1 = z1 * b1; |
| acc1 += z2 * b2; |
| acc0 = acc1 + k * acc0; |
| z2 = z1; |
| |
| /*lint -e{702} <avoid divide> */ |
| z1 = acc0 >> 14; |
| *pAudioBuffer++ = (EAS_I16) z1; |
| } |
| |
| /* save delay values */ |
| pFilter->z1 = (EAS_I16) z1; |
| pFilter->z2 = (EAS_I16) z2; |
| } |
| #endif |
| |
| /*---------------------------------------------------------------------------- |
| * WT_NoiseGenerator |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * Generate pseudo-white noise using PRNG and interpolation engine |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| * Notes: |
| * This output is scaled -12dB to prevent saturation in the filter. For a |
| * high quality synthesizer, the output can be set to full scale, however |
| * if the filter is used, it can overflow with certain coefficients. In this |
| * case, either a saturation operation should take in the filter before |
| * scaling back to 16 bits or the signal path should be increased to 18 bits |
| * or more. |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| EAS_PCM *pOutputBuffer; |
| EAS_I32 phaseInc; |
| EAS_I32 tmp0; |
| EAS_I32 tmp1; |
| EAS_I32 nInterpolatedSample; |
| EAS_I32 numSamples; |
| |
| /* initialize some local variables */ |
| numSamples = pWTIntFrame->numSamples; |
| pOutputBuffer = pWTIntFrame->pAudioBuffer; |
| phaseInc = pWTIntFrame->frame.phaseIncrement; |
| |
| /* get last two samples generated */ |
| /*lint -e{704} <avoid divide for performance>*/ |
| tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18; |
| /*lint -e{704} <avoid divide for performance>*/ |
| tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; |
| |
| /* generate a buffer of noise */ |
| while (numSamples--) { |
| nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac)); |
| nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac); |
| *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample; |
| |
| /* update PRNG */ |
| pWTVoice->phaseFrac += (EAS_U32) phaseInc; |
| if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) { |
| tmp0 = tmp1; |
| pWTVoice->phaseAccum = pWTVoice->loopEnd; |
| pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1); |
| tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; |
| pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac); |
| } |
| |
| } |
| } |
| |
| #ifndef _OPTIMIZED_MONO |
| /*---------------------------------------------------------------------------- |
| * WT_ProcessVoice |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * This routine does the block processing for one voice. It is isolated |
| * from the main synth code to allow for various implementation-specific |
| * optimizations. It calls the interpolator, filter, and gain routines |
| * appropriate for a particular configuration. |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| * Notes: |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| |
| /* use noise generator */ |
| if (pWTVoice->loopStart == WT_NOISE_GENERATOR) |
| WT_NoiseGenerator(pWTVoice, pWTIntFrame); |
| |
| /* generate interpolated samples for looped waves */ |
| else if (pWTVoice->loopStart != pWTVoice->loopEnd) |
| WT_Interpolate(pWTVoice, pWTIntFrame); |
| |
| /* generate interpolated samples for unlooped waves */ |
| else |
| { |
| WT_InterpolateNoLoop(pWTVoice, pWTIntFrame); |
| } |
| |
| #ifdef _FILTER_ENABLED |
| if (pWTIntFrame->frame.k != 0) |
| WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame); |
| #endif |
| |
| //2 TEST NEW MIXER FUNCTION |
| #ifdef UNIFIED_MIXER |
| { |
| EAS_I32 gainLeft, gainIncLeft; |
| |
| #if (NUM_OUTPUT_CHANNELS == 2) |
| EAS_I32 gainRight, gainIncRight; |
| #endif |
| |
| gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1; |
| gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS; |
| |
| #if (NUM_OUTPUT_CHANNELS == 2) |
| gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1; |
| gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS; |
| EAS_MixStream( |
| pWTIntFrame->pAudioBuffer, |
| pWTIntFrame->pMixBuffer, |
| pWTIntFrame->numSamples, |
| gainLeft, |
| gainRight, |
| gainIncLeft, |
| gainIncRight, |
| MIX_FLAGS_STEREO_OUTPUT); |
| |
| #else |
| EAS_MixStream( |
| pWTIntFrame->pAudioBuffer, |
| pWTIntFrame->pMixBuffer, |
| pWTIntFrame->numSamples, |
| gainLeft, |
| 0, |
| gainIncLeft, |
| 0, |
| 0); |
| #endif |
| } |
| |
| #else |
| /* apply gain, and left and right gain */ |
| WT_VoiceGain(pWTVoice, pWTIntFrame); |
| #endif |
| } |
| #endif |
| |
| #if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL) |
| /*---------------------------------------------------------------------------- |
| * WT_InterpolateMono |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * A C version of the sample interpolation + gain routine, optimized for mono. |
| * It's not pretty, but it matches the assembly code exactly. |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| * Notes: |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| EAS_I32 *pMixBuffer; |
| const EAS_I8 *pLoopEnd; |
| const EAS_I8 *pCurrentPhaseInt; |
| EAS_I32 numSamples; |
| EAS_I32 gain; |
| EAS_I32 gainIncrement; |
| EAS_I32 currentPhaseFrac; |
| EAS_I32 phaseInc; |
| EAS_I32 tmp0; |
| EAS_I32 tmp1; |
| EAS_I32 tmp2; |
| EAS_I8 *pLoopStart; |
| |
| numSamples = pWTIntFrame->numSamples; |
| pMixBuffer = pWTIntFrame->pMixBuffer; |
| |
| /* calculate gain increment */ |
| gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); |
| if (gainIncrement < 0) |
| gainIncrement++; |
| gain = pWTIntFrame->prevGain << 16; |
| |
| pCurrentPhaseInt = pWTVoice->pPhaseAccum; |
| currentPhaseFrac = pWTVoice->phaseFrac; |
| phaseInc = pWTIntFrame->phaseIncrement; |
| |
| pLoopStart = pWTVoice->pLoopStart; |
| pLoopEnd = pWTVoice->pLoopEnd + 1; |
| |
| InterpolationLoop: |
| tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd); |
| if (tmp0 >= 0) |
| pCurrentPhaseInt = pLoopStart + tmp0; |
| |
| tmp0 = *pCurrentPhaseInt; |
| tmp1 = *(pCurrentPhaseInt + 1); |
| |
| tmp2 = phaseInc + currentPhaseFrac; |
| |
| tmp1 = tmp1 - tmp0; |
| tmp1 = tmp1 * currentPhaseFrac; |
| |
| tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS); |
| |
| pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS); |
| currentPhaseFrac = tmp2 & PHASE_FRAC_MASK; |
| |
| gain += gainIncrement; |
| tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS); |
| |
| tmp0 = *pMixBuffer; |
| tmp2 = tmp1 * tmp2; |
| tmp2 = (tmp2 >> 9); |
| tmp0 = tmp2 + tmp0; |
| *pMixBuffer++ = tmp0; |
| |
| numSamples--; |
| if (numSamples > 0) |
| goto InterpolationLoop; |
| |
| pWTVoice->pPhaseAccum = pCurrentPhaseInt; |
| pWTVoice->phaseFrac = currentPhaseFrac; |
| /*lint -e{702} <avoid divide>*/ |
| pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS); |
| } |
| #endif |
| |
| #ifdef _OPTIMIZED_MONO |
| /*---------------------------------------------------------------------------- |
| * WT_ProcessVoice |
| *---------------------------------------------------------------------------- |
| * Purpose: |
| * This routine does the block processing for one voice. It is isolated |
| * from the main synth code to allow for various implementation-specific |
| * optimizations. It calls the interpolator, filter, and gain routines |
| * appropriate for a particular configuration. |
| * |
| * Inputs: |
| * |
| * Outputs: |
| * |
| * Notes: |
| * This special version works handles an optimized mono-only signal |
| * without filters |
| *---------------------------------------------------------------------------- |
| */ |
| void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) |
| { |
| |
| /* use noise generator */ |
| if (pWTVoice->loopStart== WT_NOISE_GENERATOR) |
| { |
| WT_NoiseGenerator(pWTVoice, pWTIntFrame); |
| WT_VoiceGain(pWTVoice, pWTIntFrame); |
| } |
| |
| /* or generate interpolated samples */ |
| else |
| { |
| WT_InterpolateMono(pWTVoice, pWTIntFrame); |
| } |
| } |
| #endif |
| |