diff options
Diffstat (limited to 'arm-wt-22k/lib_src/eas_wtsynth.c')
-rw-r--r-- | arm-wt-22k/lib_src/eas_wtsynth.c | 1257 |
1 files changed, 0 insertions, 1257 deletions
diff --git a/arm-wt-22k/lib_src/eas_wtsynth.c b/arm-wt-22k/lib_src/eas_wtsynth.c deleted file mode 100644 index 3eadf2d..0000000 --- a/arm-wt-22k/lib_src/eas_wtsynth.c +++ /dev/null @@ -1,1257 +0,0 @@ -/*---------------------------------------------------------------------------- - * - * File: - * eas_wtsynth.c - * - * Contents and purpose: - * Implements the synthesizer functions. - * - * Copyright Sonic Network Inc. 2004 - - * 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: 795 $ - * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ - *---------------------------------------------------------------------------- -*/ - -// includes -#include "eas_data.h" -#include "eas_report.h" -#include "eas_host.h" -#include "eas_math.h" -#include "eas_synth_protos.h" -#include "eas_wtsynth.h" -#include "eas_pan.h" - -#ifdef DLS_SYNTHESIZER -#include "eas_dlssynth.h" -#endif - -#ifdef _METRICS_ENABLED -#include "eas_perf.h" -#endif - -/* local prototypes */ -static EAS_RESULT WT_Initialize(S_VOICE_MGR *pVoiceMgr); -static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); -static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); -static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); -static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); -static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); -static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); -static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents); -static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain); -static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); -static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); - -#ifdef EAS_SPLIT_WT_SYNTH -extern EAS_BOOL WTE_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer); -extern EAS_BOOL WTE_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); -#endif - -#ifdef _FILTER_ENABLED -static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt); -#endif - -#ifdef _STATS -extern double statsPhaseIncrement; -extern double statsMaxPhaseIncrement; -extern long statsPhaseSampleCount; -extern double statsSampleSize; -extern long statsSampleCount; -#endif - -/*---------------------------------------------------------------------------- - * Synthesizer interface - *---------------------------------------------------------------------------- -*/ - -const S_SYNTH_INTERFACE wtSynth = -{ - WT_Initialize, - WT_StartVoice, - WT_UpdateVoice, - WT_ReleaseVoice, - WT_MuteVoice, - WT_SustainPedal, - WT_UpdateChannel -}; - -#ifdef EAS_SPLIT_WT_SYNTH -const S_FRAME_INTERFACE wtFrameInterface = -{ - WTE_StartFrame, - WTE_EndFrame -}; -#endif - -/*---------------------------------------------------------------------------- - * WT_Initialize() - *---------------------------------------------------------------------------- - * Purpose: - * - * Inputs: - * pVoice - pointer to voice to initialize - * - * Outputs: - * - *---------------------------------------------------------------------------- -*/ -static EAS_RESULT WT_Initialize (S_VOICE_MGR *pVoiceMgr) -{ - EAS_INT i; - - for (i = 0; i < NUM_WT_VOICES; i++) - { - - pVoiceMgr->wtVoices[i].artIndex = DEFAULT_ARTICULATION_INDEX; - - pVoiceMgr->wtVoices[i].eg1State = DEFAULT_EG1_STATE; - pVoiceMgr->wtVoices[i].eg1Value = DEFAULT_EG1_VALUE; - pVoiceMgr->wtVoices[i].eg1Increment = DEFAULT_EG1_INCREMENT; - - pVoiceMgr->wtVoices[i].eg2State = DEFAULT_EG2_STATE; - pVoiceMgr->wtVoices[i].eg2Value = DEFAULT_EG2_VALUE; - pVoiceMgr->wtVoices[i].eg2Increment = DEFAULT_EG2_INCREMENT; - - /* left and right gain values are needed only if stereo output */ -#if (NUM_OUTPUT_CHANNELS == 2) - pVoiceMgr->wtVoices[i].gainLeft = DEFAULT_VOICE_GAIN; - pVoiceMgr->wtVoices[i].gainRight = DEFAULT_VOICE_GAIN; -#endif - - pVoiceMgr->wtVoices[i].phaseFrac = DEFAULT_PHASE_FRAC; - pVoiceMgr->wtVoices[i].phaseAccum = DEFAULT_PHASE_INT; - -#ifdef _FILTER_ENABLED - pVoiceMgr->wtVoices[i].filter.z1 = DEFAULT_FILTER_ZERO; - pVoiceMgr->wtVoices[i].filter.z2 = DEFAULT_FILTER_ZERO; -#endif - } - - return EAS_TRUE; -} - -/*---------------------------------------------------------------------------- - * WT_ReleaseVoice() - *---------------------------------------------------------------------------- - * Purpose: - * The selected voice is being released. - * - * Inputs: - * pEASData - pointer to S_EAS_DATA - * pVoice - pointer to voice to release - * - * Outputs: - * None - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pVoice) used in some implementations */ -static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) -{ - S_WT_VOICE *pWTVoice; - const S_ARTICULATION *pArticulation; - -#ifdef DLS_SYNTHESIZER - if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) - { - DLS_ReleaseVoice(pVoiceMgr, pSynth, pVoice, voiceNum); - return; - } -#endif - - pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; - pArticulation = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; - - /* release EG1 */ - pWTVoice->eg1State = eEnvelopeStateRelease; - pWTVoice->eg1Increment = pArticulation->eg1.releaseTime; - - /* - The spec says we should release EG2, but doing so with the current - voicing is causing clicks. This fix will need to be coordinated with - a new sound library release - */ - - /* release EG2 */ - pWTVoice->eg2State = eEnvelopeStateRelease; - pWTVoice->eg2Increment = pArticulation->eg2.releaseTime; -} - -/*---------------------------------------------------------------------------- - * WT_MuteVoice() - *---------------------------------------------------------------------------- - * Purpose: - * The selected voice is being muted. - * - * Inputs: - * pVoice - pointer to voice to release - * - * Outputs: - * None - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pSynth) used in some implementations */ -static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) -{ - -#ifdef DLS_SYNTHESIZER - if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) - { - DLS_MuteVoice(pVoiceMgr, pSynth, pVoice, voiceNum); - return; - } -#endif - - /* clear deferred action flags */ - pVoice->voiceFlags &= - ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | - VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | - VOICE_FLAG_DEFER_MUTE); - - /* set the envelope state */ - pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateMuted; - pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateMuted; -} - -/*---------------------------------------------------------------------------- - * WT_SustainPedal() - *---------------------------------------------------------------------------- - * Purpose: - * The selected voice is held due to sustain pedal - * - * Inputs: - * pVoice - pointer to voice to sustain - * - * Outputs: - * None - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pChannel) used in some implementations */ -static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) -{ - S_WT_VOICE *pWTVoice; - -#ifdef DLS_SYNTHESIZER - if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) - { - DLS_SustainPedal(pVoiceMgr, pSynth, pVoice, pChannel, voiceNum); - return; - } -#endif - - /* don't catch the voice if below the sustain level */ - pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; - if (pWTVoice->eg1Value < pSynth->pEAS->pArticulations[pWTVoice->artIndex].eg1.sustainLevel) - return; - - /* sustain flag is set, damper pedal is on */ - /* defer releasing this note until the damper pedal is off */ - pWTVoice->eg1State = eEnvelopeStateDecay; - pVoice->voiceState = eVoiceStatePlay; - - /* - because sustain pedal is on, this voice - should defer releasing its note - */ - pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; - -#ifdef _DEBUG_SYNTH - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_SustainPedal: defer note off because sustain pedal is on\n"); */ } -#endif -} - -/*---------------------------------------------------------------------------- - * WT_StartVoice() - *---------------------------------------------------------------------------- - * Purpose: - * Assign the region for the given instrument using the midi key number - * and the RPN2 (coarse tuning) value. By using RPN2 as part of the - * region selection process, we reduce the amount a given sample has - * to be transposed by selecting the closest recorded root instead. - * - * This routine is the second half of SynthAssignRegion(). - * If the region was successfully found by SynthFindRegionIndex(), - * then assign the region's parameters to the voice. - * - * Setup and initialize the following voice parameters: - * m_nRegionIndex - * - * Inputs: - * pVoice - ptr to the voice we have assigned for this channel - * nRegionIndex - index of the region - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * success - could find and assign the region for this voice's note otherwise - * failure - could not find nor assign the region for this voice's note - * - * Side Effects: - * psSynthObject->m_sVoice[].m_nRegionIndex is assigned - * psSynthObject->m_sVoice[] parameters are assigned - *---------------------------------------------------------------------------- -*/ -static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) -{ - S_WT_VOICE *pWTVoice; - const S_WT_REGION *pRegion; - const S_ARTICULATION *pArt; - S_SYNTH_CHANNEL *pChannel; - -#if (NUM_OUTPUT_CHANNELS == 2) - EAS_INT pan; -#endif - -#ifdef EAS_SPLIT_WT_SYNTH - S_WT_CONFIG wtConfig; -#endif - - /* no samples have been synthesized for this note yet */ - pVoice->regionIndex = regionIndex; - pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; - - /* get the articulation index for this region */ - pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; - pChannel = &pSynth->channels[pVoice->channel & 15]; - - /* update static channel parameters */ - if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS) - WT_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15); - -#ifdef DLS_SYNTHESIZER - if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) - return DLS_StartVoice(pVoiceMgr, pSynth, pVoice, voiceNum, regionIndex); -#endif - - pRegion = &(pSynth->pEAS->pWTRegions[regionIndex]); - pWTVoice->artIndex = pRegion->artIndex; - -#ifdef _DEBUG_SYNTH - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } -#endif - - pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; - - /* MIDI note on puts this voice into attack state */ - pWTVoice->eg1State = eEnvelopeStateAttack; - pWTVoice->eg1Value = 0; - pWTVoice->eg1Increment = pArt->eg1.attackTime; - pWTVoice->eg2State = eEnvelopeStateAttack; - pWTVoice->eg2Value = 0; - pWTVoice->eg2Increment = pArt->eg2.attackTime; - - /* init the LFO */ - pWTVoice->modLFO.lfoValue = 0; - pWTVoice->modLFO.lfoPhase = -pArt->lfoDelay; - - pVoice->gain = 0; - -#if (NUM_OUTPUT_CHANNELS == 2) - /* - Get the Midi CC10 pan value for this voice's channel - convert the pan value to an "angle" representation suitable for - our sin, cos calculator. This representation is NOT necessarily the same - as the transform in the GM manuals because of our sin, cos calculator. - "angle" = (CC10 - 64)/128 - */ - pan = (EAS_INT) pSynth->channels[pVoice->channel & 15].pan - 64; - pan += pArt->pan; - EAS_CalcPanControl(pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); -#endif - -#ifdef _FILTER_ENABLED - /* clear out the filter states */ - pWTVoice->filter.z1 = 0; - pWTVoice->filter.z2 = 0; -#endif - - /* if this wave is to be generated using noise generator */ - if (pRegion->region.keyGroupAndFlags & REGION_FLAG_USE_WAVE_GENERATOR) - { - pWTVoice->phaseAccum = 4574296; - pWTVoice->loopStart = WT_NOISE_GENERATOR; - pWTVoice->loopEnd = 4574295; - } - - /* normal sample */ - else - { - -#ifdef EAS_SPLIT_WT_SYNTH - if (voiceNum < NUM_PRIMARY_VOICES) - pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; - else - pWTVoice->phaseAccum = pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; -#else - pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; -#endif - - if (pRegion->region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) - { - pWTVoice->loopStart = pWTVoice->phaseAccum + pRegion->loopStart; - pWTVoice->loopEnd = pWTVoice->phaseAccum + pRegion->loopEnd - 1; - } - else - pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 1; - } - -#ifdef EAS_SPLIT_WT_SYNTH - /* configure off-chip voices */ - if (voiceNum >= NUM_PRIMARY_VOICES) - { - wtConfig.phaseAccum = pWTVoice->phaseAccum; - wtConfig.loopStart = pWTVoice->loopStart; - wtConfig.loopEnd = pWTVoice->loopEnd; - wtConfig.gain = pVoice->gain; - -#if (NUM_OUTPUT_CHANNELS == 2) - wtConfig.gainLeft = pWTVoice->gainLeft; - wtConfig.gainRight = pWTVoice->gainRight; -#endif - - WTE_ConfigVoice(voiceNum - NUM_PRIMARY_VOICES, &wtConfig, pVoiceMgr->pFrameBuffer); - } -#endif - - return EAS_SUCCESS; -} - -/*---------------------------------------------------------------------------- - * WT_CheckSampleEnd - *---------------------------------------------------------------------------- - * Purpose: - * Check for end of sample and calculate number of samples to synthesize - * - * Inputs: - * - * Outputs: - * - * Notes: - * - *---------------------------------------------------------------------------- -*/ -EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update) -{ - EAS_U32 endPhaseAccum; - EAS_U32 endPhaseFrac; - EAS_I32 numSamples; - EAS_BOOL done = EAS_FALSE; - - /* check to see if we hit the end of the waveform this time */ - /*lint -e{703} use shift for performance */ - endPhaseFrac = pWTVoice->phaseFrac + (pWTIntFrame->frame.phaseIncrement << SYNTH_UPDATE_PERIOD_IN_BITS); - endPhaseAccum = pWTVoice->phaseAccum + GET_PHASE_INT_PART(endPhaseFrac); - if (endPhaseAccum >= pWTVoice->loopEnd) - { - /* calculate how far current ptr is from end */ - numSamples = (EAS_I32) (pWTVoice->loopEnd - pWTVoice->phaseAccum); - - /* now account for the fractional portion */ - /*lint -e{703} use shift for performance */ - numSamples = (EAS_I32) ((numSamples << NUM_PHASE_FRAC_BITS) - pWTVoice->phaseFrac); - if (pWTIntFrame->frame.phaseIncrement) { - pWTIntFrame->numSamples = 1 + (numSamples / pWTIntFrame->frame.phaseIncrement); - } else { - pWTIntFrame->numSamples = numSamples; - } - - /* sound will be done this frame */ - done = EAS_TRUE; - } - - /* update data for off-chip synth */ - if (update) - { - pWTVoice->phaseFrac = endPhaseFrac; - pWTVoice->phaseAccum = endPhaseAccum; - } - - return done; -} - -/*---------------------------------------------------------------------------- - * WT_UpdateVoice() - *---------------------------------------------------------------------------- - * Purpose: - * Synthesize a block of samples for the given voice. - * Use linear interpolation. - * - * Inputs: - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * number of samples actually written to buffer - * - * Side Effects: - * - samples are added to the presently free buffer - * - *---------------------------------------------------------------------------- -*/ -static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) -{ - S_WT_VOICE *pWTVoice; - S_WT_INT_FRAME intFrame; - S_SYNTH_CHANNEL *pChannel; - const S_WT_REGION *pWTRegion; - const S_ARTICULATION *pArt; - EAS_I32 temp; - EAS_BOOL done; - -#ifdef DLS_SYNTHESIZER - if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) - return DLS_UpdateVoice(pVoiceMgr, pSynth, pVoice, voiceNum, pMixBuffer, numSamples); -#endif - - /* establish pointers to critical data */ - pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; - pWTRegion = &pSynth->pEAS->pWTRegions[pVoice->regionIndex & REGION_INDEX_MASK]; - pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; - pChannel = &pSynth->channels[pVoice->channel & 15]; - intFrame.prevGain = pVoice->gain; - - /* update the envelopes */ - WT_UpdateEG1(pWTVoice, &pArt->eg1); - WT_UpdateEG2(pWTVoice, &pArt->eg2); - - /* update the LFO */ - WT_UpdateLFO(&pWTVoice->modLFO, pArt->lfoFreq); - -#ifdef _FILTER_ENABLED - /* calculate filter if library uses filter */ - if (pSynth->pEAS->libAttr & LIB_FORMAT_FILTER_ENABLED) - WT_UpdateFilter(pWTVoice, &intFrame, pArt); - else - intFrame.frame.k = 0; -#endif - - /* update the gain */ - intFrame.frame.gainTarget = WT_UpdateGain(pVoice, pWTVoice, pArt, pChannel, pWTRegion->gain); - - /* calculate base pitch*/ - temp = pChannel->staticPitch + pWTRegion->tuning; - - /* include global transpose */ - if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) - temp += pVoice->note * 100; - else - temp += (pVoice->note + pSynth->globalTranspose) * 100; - intFrame.frame.phaseIncrement = WT_UpdatePhaseInc(pWTVoice, pArt, pChannel, temp); - - /* call into engine to generate samples */ - intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; - intFrame.pMixBuffer = pMixBuffer; - intFrame.numSamples = numSamples; - - /* check for end of sample */ - if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) - done = WT_CheckSampleEnd(pWTVoice, &intFrame, (EAS_BOOL) (voiceNum >= NUM_PRIMARY_VOICES)); - else - done = EAS_FALSE; - - if (intFrame.numSamples < 0) intFrame.numSamples = 0; - -#ifdef EAS_SPLIT_WT_SYNTH - if (voiceNum < NUM_PRIMARY_VOICES) - { -#ifndef _SPLIT_WT_TEST_HARNESS - WT_ProcessVoice(pWTVoice, &intFrame); -#endif - } - else - WTE_ProcessVoice(voiceNum - NUM_PRIMARY_VOICES, &intFrame.frame, pVoiceMgr->pFrameBuffer); -#else - WT_ProcessVoice(pWTVoice, &intFrame); -#endif - - /* clear flag */ - pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; - - /* if voice has finished, set flag for voice manager */ - if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) - done = EAS_TRUE; - - /* if the update interval has elapsed, then force the current gain to the next - * gain since we never actually reach the next gain when ramping -- we just get - * very close to the target gain. - */ - pVoice->gain = (EAS_I16) intFrame.frame.gainTarget; - - return done; -} - -/*---------------------------------------------------------------------------- - * WT_UpdatePhaseInc() - *---------------------------------------------------------------------------- - * Purpose: - * Calculate the phase increment - * - * Inputs: - * pVoice - pointer to the voice being updated - * psRegion - pointer to the region - * psArticulation - pointer to the articulation - * nChannelPitchForThisVoice - the portion of the pitch that is fixed for this - * voice during the duration of this synthesis - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * - * Side Effects: - * set the phase increment for this voice - *---------------------------------------------------------------------------- -*/ -static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) -{ - EAS_I32 temp; - - /*pitchCents due to CC1 = LFO * (CC1 / 128) * DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS */ - temp = MULT_EG1_EG1(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS, - ((pChannel->modWheel) << (NUM_EG1_FRAC_BITS -7))); - - /* pitchCents due to channel pressure = LFO * (channel pressure / 128) * DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS */ - temp += MULT_EG1_EG1(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS, - ((pChannel->channelPressure) << (NUM_EG1_FRAC_BITS -7))); - - /* now multiply the (channel pressure + CC1) pitch values by the LFO value */ - temp = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, temp); - - /* - add in the LFO pitch due to - channel pressure and CC1 along with - the LFO pitch, the EG2 pitch, and the - "static" pitch for this voice on this channel - */ - temp += pitchCents + - (MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToPitch)) + - (MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToPitch)); - - /* convert from cents to linear phase increment */ - return EAS_Calculate2toX(temp); -} - -/*---------------------------------------------------------------------------- - * WT_UpdateChannel() - *---------------------------------------------------------------------------- - * Purpose: - * Calculate and assign static channel parameters - * These values only need to be updated if one of the controller values - * for this channel changes - * - * Inputs: - * nChannel - channel to update - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * - * Side Effects: - * - the given channel's static gain and static pitch are updated - *---------------------------------------------------------------------------- -*/ -/*lint -esym(715, pVoiceMgr) reserved for future use */ -static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) -{ - EAS_I32 staticGain; - EAS_I32 pitchBend; - S_SYNTH_CHANNEL *pChannel; - - pChannel = &pSynth->channels[channel]; - - /* - nChannelGain = (CC7 * CC11)^2 * master volume - where CC7 == 100 by default, CC11 == 127, master volume == 32767 - */ - staticGain = MULT_EG1_EG1((pChannel->volume) << (NUM_EG1_FRAC_BITS - 7), - (pChannel->expression) << (NUM_EG1_FRAC_BITS - 7)); - - /* staticGain has to be squared */ - staticGain = MULT_EG1_EG1(staticGain, staticGain); - - pChannel->staticGain = (EAS_I16) MULT_EG1_EG1(staticGain, pSynth->masterVolume); - - /* - calculate pitch bend: RPN0 * ((2*pitch wheel)/16384 -1) - However, if we use the EG1 macros, remember that EG1 has a full - scale value of 32768 (instead of 16384). So instead of multiplying - by 2, multiply by 4 (left shift by 2), and subtract by 32768 instead - of 16384. This utilizes the fact that the EG1 macro places a binary - point 15 places to the left instead of 14 places. - */ - /*lint -e{703} <avoid multiply for performance>*/ - pitchBend = - (((EAS_I32)(pChannel->pitchBend) << 2) - - 32768); - - pChannel->staticPitch = - MULT_EG1_EG1(pitchBend, pChannel->pitchBendSensitivity); - - /* if this is not a drum channel, then add in the per-channel tuning */ - if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)) - pChannel->staticPitch += pChannel->finePitch + (pChannel->coarsePitch * 100); - - /* clear update flag */ - pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; - return; -} - -/*---------------------------------------------------------------------------- - * WT_UpdateGain() - *---------------------------------------------------------------------------- - * Purpose: - * Calculate and assign static voice parameters as part of WT_UpdateVoice() - * - * Inputs: - * pVoice - ptr to the synth voice that we want to synthesize - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * - * Side Effects: - * - various voice parameters are calculated and assigned - * - *---------------------------------------------------------------------------- -*/ -static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain) -{ - EAS_I32 lfoGain; - EAS_I32 temp; - - /* - If this voice was stolen, then the velocity is actually - for the new note, not the note that we are currently ramping down. - So we really shouldn't use this velocity. However, that would require - more memory to store the velocity value, and the improvement may - not be sufficient to warrant the added memory. - */ - /* velocity is fixed at note start for a given voice and must be squared */ - temp = (pVoice->velocity) << (NUM_EG1_FRAC_BITS - 7); - temp = MULT_EG1_EG1(temp, temp); - - /* region gain is fixed as part of the articulation */ - temp = MULT_EG1_EG1(temp, gain); - - /* include the channel gain */ - temp = MULT_EG1_EG1(temp, pChannel->staticGain); - - /* calculate LFO gain using an approximation for 10^x */ - lfoGain = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToGain); - lfoGain = MULT_EG1_EG1(lfoGain, LFO_GAIN_TO_CENTS); - - /* convert from a dB-like value to linear gain */ - lfoGain = EAS_Calculate2toX(lfoGain); - temp = MULT_EG1_EG1(temp, lfoGain); - - /* calculate the voice's gain */ - temp = (EAS_I16)MULT_EG1_EG1(temp, pWTVoice->eg1Value); - - return temp; -} - -/*---------------------------------------------------------------------------- - * WT_UpdateEG1() - *---------------------------------------------------------------------------- - * Purpose: - * Calculate the EG1 envelope for the given voice (but do not update any - * state) - * - * Inputs: - * pVoice - ptr to the voice whose envelope we want to update - * nVoice - this voice's number - used only for debug - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * nValue - the envelope value - * - * Side Effects: - * - updates EG1 state value for the given voice - *---------------------------------------------------------------------------- -*/ -static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) -{ - EAS_I32 temp; - - switch (pWTVoice->eg1State) - { - case eEnvelopeStateAttack: - temp = pWTVoice->eg1Value + pWTVoice->eg1Increment; - - /* check if we have reached peak amplitude */ - if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) - { - /* limit the volume */ - temp = SYNTH_FULL_SCALE_EG1_GAIN; - - /* prepare to move to decay state */ - pWTVoice->eg1State = eEnvelopeStateDecay; - pWTVoice->eg1Increment = pEnv->decayTime; - } - - break; - - /* exponential decay */ - case eEnvelopeStateDecay: - temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); - - /* check if we have reached sustain level */ - if (temp <= pEnv->sustainLevel) - { - /* enforce the sustain level */ - temp = pEnv->sustainLevel; - - /* if sustain level is zero, skip sustain & release the voice */ - if (temp > 0) - pWTVoice->eg1State = eEnvelopeStateSustain; - - /* move to sustain state */ - else - pWTVoice->eg1State = eEnvelopeStateMuted; - } - - break; - - case eEnvelopeStateSustain: - return; - - case eEnvelopeStateRelease: - temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); - - /* if we hit zero, this voice isn't contributing any audio */ - if (temp <= 0) - { - temp = 0; - pWTVoice->eg1State = eEnvelopeStateMuted; - } - break; - - /* voice is muted, set target to zero */ - case eEnvelopeStateMuted: - temp = 0; - break; - - case eEnvelopeStateInvalid: - default: - temp = 0; -#ifdef _DEBUG_SYNTH - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG1: error, %d is an unrecognized state\n", - pWTVoice->eg1State); */ } -#endif - break; - - } - - pWTVoice->eg1Value = (EAS_I16) temp; -} - -/*---------------------------------------------------------------------------- - * WT_UpdateEG2() - *---------------------------------------------------------------------------- - * Purpose: - * Update the EG2 envelope for the given voice - * - * Inputs: - * pVoice - ptr to the voice whose envelope we want to update - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * - * Side Effects: - * - updates EG2 values for the given voice - *---------------------------------------------------------------------------- -*/ - -static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) -{ - EAS_I32 temp; - - switch (pWTVoice->eg2State) - { - case eEnvelopeStateAttack: - temp = pWTVoice->eg2Value + pWTVoice->eg2Increment; - - /* check if we have reached peak amplitude */ - if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) - { - /* limit the volume */ - temp = SYNTH_FULL_SCALE_EG1_GAIN; - - /* prepare to move to decay state */ - pWTVoice->eg2State = eEnvelopeStateDecay; - - pWTVoice->eg2Increment = pEnv->decayTime; - } - - break; - - /* implement linear pitch decay in cents */ - case eEnvelopeStateDecay: - temp = pWTVoice->eg2Value -pWTVoice->eg2Increment; - - /* check if we have reached sustain level */ - if (temp <= pEnv->sustainLevel) - { - /* enforce the sustain level */ - temp = pEnv->sustainLevel; - - /* prepare to move to sustain state */ - pWTVoice->eg2State = eEnvelopeStateSustain; - } - break; - - case eEnvelopeStateSustain: - return; - - case eEnvelopeStateRelease: - temp = pWTVoice->eg2Value - pWTVoice->eg2Increment; - - if (temp <= 0) - { - temp = 0; - pWTVoice->eg2State = eEnvelopeStateMuted; - } - - break; - - /* voice is muted, set target to zero */ - case eEnvelopeStateMuted: - temp = 0; - break; - - case eEnvelopeStateInvalid: - default: - temp = 0; -#ifdef _DEBUG_SYNTH - { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG2: error, %d is an unrecognized state\n", - pWTVoice->eg2State); */ } -#endif - break; - } - - pWTVoice->eg2Value = (EAS_I16) temp; -} - -/*---------------------------------------------------------------------------- - * WT_UpdateLFO () - *---------------------------------------------------------------------------- - * Purpose: - * Calculate the LFO for the given voice - * - * Inputs: - * pLFO - ptr to the LFO data - * phaseInc - phase increment - * - * Outputs: - * - * Side Effects: - * - updates LFO values for the given voice - *---------------------------------------------------------------------------- -*/ -void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc) -{ - - /* To save memory, if m_nPhaseValue is negative, we are in the - * delay phase, and m_nPhaseValue represents the time left - * in the delay. - */ - if (pLFO->lfoPhase < 0) - { - pLFO->lfoPhase++; - return; - } - - /* calculate LFO output from phase value */ - /*lint -e{701} Use shift for performance */ - pLFO->lfoValue = (EAS_I16) (pLFO->lfoPhase << 2); - /*lint -e{502} <shortcut to turn sawtooth into triangle wave> */ - if ((pLFO->lfoPhase > 0x1fff) && (pLFO->lfoPhase < 0x6000)) - pLFO->lfoValue = ~pLFO->lfoValue; - - /* update LFO phase */ - pLFO->lfoPhase = (pLFO->lfoPhase + phaseInc) & 0x7fff; -} - -#ifdef _FILTER_ENABLED -/*---------------------------------------------------------------------------- - * WT_UpdateFilter() - *---------------------------------------------------------------------------- - * Purpose: - * Update the Filter parameters - * - * Inputs: - * pVoice - ptr to the voice whose filter we want to update - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * - * Side Effects: - * - updates Filter values for the given voice - *---------------------------------------------------------------------------- -*/ -static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt) -{ - EAS_I32 cutoff; - - /* no need to calculate filter coefficients if it is bypassed */ - if (pArt->filterCutoff == DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY) - { - pIntFrame->frame.k = 0; - return; - } - - /* determine the dynamic cutoff frequency */ - cutoff = MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToFc); - cutoff += pArt->filterCutoff; - - /* subtract the A5 offset and the sampling frequency */ - cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS; - - /* limit the cutoff frequency */ - if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS) - cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS; - else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS) - cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS; - - WT_SetFilterCoeffs(pIntFrame, cutoff, pArt->filterQ); -} -#endif - -#if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) -/*---------------------------------------------------------------------------- - * coef - *---------------------------------------------------------------------------- - * Table of filter coefficients for low-pass filter - *---------------------------------------------------------------------------- - * - * polynomial coefficients are based on 8kHz sampling frequency - * filter coef b2 = k2 = k2g0*k^0 + k2g1*k^1*(2^x) + k2g2*k^2*(2^x) - * - *where k2g0, k2g1, k2g2 are from the truncated power series expansion on theta - *(k*2^x = theta, but we incorporate the k along with the k2g0, k2g1, k2g2) - *note: this is a power series in 2^x, not k*2^x - *where k = (2*pi*440)/8kHz == convert octaves to radians - * - * so actually, the following coefs listed as k2g0, k2g1, k2g2 are really - * k2g0*k^0 = k2g0 - * k2g1*k^1 - * k2g2*k^2 - * - * - * filter coef n1 = numerator = n1g0*k^0 + n1g1*k^1*(2^x) + n1g2*k^2*(2^x) + n1g3*k^3*(2^x) - * - *where n1g0, n1g1, n1g2, n1g3 are from the truncated power series expansion on theta - *(k*2^x = theta, but we incorporate the k along with the n1g0, n1g1, n1g2, n2g3) - *note: this is a power series in 2^x, not k*2^x - *where k = (2*pi*440)/8kHz == convert octaves to radians - *we also include the optimization factor of 0.81 - * - * so actually, the following coefs listed as n1g0, n1g1, n1g2, n2g3 are really - * n1g0*k^0 = n1g0 - * n1g1*k^1 - * n1g2*k^2 - * n1g3*k^3 - * - * NOTE that n1g0 == n1g1 == 0, always, so we only need to store n1g2 and n1g3 - *---------------------------------------------------------------------------- -*/ - -static const EAS_I16 nk1g0 = -32768; -static const EAS_I16 nk1g2 = 1580; -static const EAS_I16 k2g0 = 32767; - -static const EAS_I16 k2g1[] = -{ - -11324, /* k2g1[0] = -0.3455751918948761 */ - -10387, /* k2g1[1] = -0.3169878073928751 */ - -9528, /* k2g1[2] = -0.29076528753345476 */ - -8740, /* k2g1[3] = -0.2667120011011279 */ - -8017, /* k2g1[4] = -0.24464850028971705 */ - -7353, /* k2g1[5] = -0.22441018194495696 */ - -6745, /* k2g1[6] = -0.20584605955455101 */ - -6187, /* k2g1[7] = -0.18881763682420102 */ - -5675, /* k2g1[8] = -0.1731978744360067 */ - -5206, /* k2g1[9] = -0.15887024228080968 */ - -4775, /* k2g1[10] = -0.14572785009373057 */ - -4380, /* k2g1[11] = -0.13367265000706827 */ - -4018, /* k2g1[12] = -0.1226147050712642 */ - -3685, /* k2g1[13] = -0.11247151828678581 */ - -3381, /* k2g1[14] = -0.10316741714122014 */ - -3101, /* k2g1[15] = -0.0946329890599603 */ - -2844, /* k2g1[16] = -0.08680456355870586 */ - -2609, /* k2g1[17] = -0.07962373723441349 */ - -2393, /* k2g1[18] = -0.07303693805092666 */ - -2195, /* k2g1[19] = -0.06699502566866912 */ - -2014, /* k2g1[20] = -0.06145292483669077 */ - -1847, /* k2g1[21] = -0.056369289112013346 */ - -1694, /* k2g1[22] = -0.05170619239747895 */ - -1554, /* k2g1[23] = -0.04742884599684141 */ - -1426, /* k2g1[24] = -0.043505339076210514 */ - -1308, /* k2g1[25] = -0.03990640059558053 */ - -1199, /* k2g1[26] = -0.03660518093435039 */ - -1100, /* k2g1[27] = -0.03357705158166837 */ - -1009, /* k2g1[28] = -0.030799421397205727 */ - -926, /* k2g1[29] = -0.028251568071585884 */ - -849 /* k2g1[30] = -0.025914483529091967 */ -}; - -static const EAS_I16 k2g2[] = -{ - 1957, /* k2g2[0] = 0.059711106626580836 */ - 1646, /* k2g2[1] = 0.05024063501786333 */ - 1385, /* k2g2[2] = 0.042272226217199664 */ - 1165, /* k2g2[3] = 0.03556764576567844 */ - 981, /* k2g2[4] = 0.029926444346999134 */ - 825, /* k2g2[5] = 0.025179964880280382 */ - 694, /* k2g2[6] = 0.02118630011706455 */ - 584, /* k2g2[7] = 0.01782604998793514 */ - 491, /* k2g2[8] = 0.014998751854573014 */ - 414, /* k2g2[9] = 0.012619876941179595 */ - 348, /* k2g2[10] = 0.010618303146468736 */ - 293, /* k2g2[11] = 0.008934188679954682 */ - 246, /* k2g2[12] = 0.007517182949855368 */ - 207, /* k2g2[13] = 0.006324921212866403 */ - 174, /* k2g2[14] = 0.005321757979794424 */ - 147, /* k2g2[15] = 0.004477701309210577 */ - 123, /* k2g2[16] = 0.00376751612730811 */ - 104, /* k2g2[17] = 0.0031699697655869644 */ - 87, /* k2g2[18] = 0.00266719715992703 */ - 74, /* k2g2[19] = 0.0022441667321724647 */ - 62, /* k2g2[20] = 0.0018882309854916855 */ - 52, /* k2g2[21] = 0.0015887483774966232 */ - 44, /* k2g2[22] = 0.0013367651661223448 */ - 37, /* k2g2[23] = 0.0011247477162958733 */ - 31, /* k2g2[24] = 0.0009463572640678758 */ - 26, /* k2g2[25] = 0.0007962604042473498 */ - 22, /* k2g2[26] = 0.0006699696356181593 */ - 18, /* k2g2[27] = 0.0005637091964589207 */ - 16, /* k2g2[28] = 0.00047430217920125243 */ - 13, /* k2g2[29] = 0.00039907554925166274 */ - 11 /* k2g2[30] = 0.00033578022828973666 */ -}; - -static const EAS_I16 n1g2[] = -{ - 3170, /* n1g2[0] = 0.0967319927350769 */ - 3036, /* n1g2[1] = 0.0926446051254155 */ - 2908, /* n1g2[2] = 0.08872992911818503 */ - 2785, /* n1g2[3] = 0.08498066682523227 */ - 2667, /* n1g2[4] = 0.08138982872895201 */ - 2554, /* n1g2[5] = 0.07795072065216213 */ - 2446, /* n1g2[6] = 0.0746569312785634 */ - 2343, /* n1g2[7] = 0.07150232020051943 */ - 2244, /* n1g2[8] = 0.06848100647187474 */ - 2149, /* n1g2[9] = 0.06558735764447099 */ - 2058, /* n1g2[10] = 0.06281597926792246 */ - 1971, /* n1g2[11] = 0.06016170483307614 */ - 1888, /* n1g2[12] = 0.05761958614040857 */ - 1808, /* n1g2[13] = 0.05518488407540374 */ - 1732, /* n1g2[14] = 0.052853059773715245 */ - 1659, /* n1g2[15] = 0.05061976615964251 */ - 1589, /* n1g2[16] = 0.04848083984214659 */ - 1521, /* n1g2[17] = 0.046432293353298 */ - 1457, /* n1g2[18] = 0.04447030771468711 */ - 1396, /* n1g2[19] = 0.04259122531793907 */ - 1337, /* n1g2[20] = 0.040791543106060944 */ - 1280, /* n1g2[21] = 0.03906790604290942 */ - 1226, /* n1g2[22] = 0.037417100858604564 */ - 1174, /* n1g2[23] = 0.035836050059229754 */ - 1125, /* n1g2[24] = 0.03432180618965023 */ - 1077, /* n1g2[25] = 0.03287154633875494 */ - 1032, /* n1g2[26] = 0.03148256687687814 */ - 988, /* n1g2[27] = 0.030152278415589925 */ - 946, /* n1g2[28] = 0.028878200980459685 */ - 906, /* n1g2[29] = 0.02765795938779331 */ - 868 /* n1g2[30] = 0.02648927881672521 */ -}; - -static const EAS_I16 n1g3[] = -{ - -548, /* n1g3[0] = -0.016714088475899017 */ - -481, /* n1g3[1] = -0.014683605122742116 */ - -423, /* n1g3[2] = -0.012899791676436092 */ - -371, /* n1g3[3] = -0.01133268185193299 */ - -326, /* n1g3[4] = -0.00995594976868754 */ - -287, /* n1g3[5] = -0.008746467702146129 */ - -252, /* n1g3[6] = -0.00768391756106361 */ - -221, /* n1g3[7] = -0.006750449563854721 */ - -194, /* n1g3[8] = -0.005930382380083576 */ - -171, /* n1g3[9] = -0.005209939699767622 */ - -150, /* n1g3[10] = -0.004577018805123356 */ - -132, /* n1g3[11] = -0.004020987256990177 */ - -116, /* n1g3[12] = -0.003532504280467257 */ - -102, /* n1g3[13] = -0.00310336384922047 */ - -89, /* n1g3[14] = -0.002726356832432369 */ - -78, /* n1g3[15] = -0.002395149888601605 */ - -69, /* n1g3[16] = -0.0021041790717285314 */ - -61, /* n1g3[17] = -0.0018485563625771063 */ - -53, /* n1g3[18] = -0.001623987554831628 */ - -47, /* n1g3[19] = -0.0014267001167177025 */ - -41, /* n1g3[20] = -0.0012533798162347005 */ - -36, /* n1g3[21] = -0.0011011150453668693 */ - -32, /* n1g3[22] = -0.0009673479079754438 */ - -28, /* n1g3[23] = -0.0008498312496971563 */ - -24, /* n1g3[24] = -0.0007465909079943587 */ - -21, /* n1g3[25] = -0.0006558925481952733 */ - -19, /* n1g3[26] = -0.0005762125284029567 */ - -17, /* n1g3[27] = -0.0005062123038325457 */ - -15, /* n1g3[28] = -0.0004447159405951901 */ - -13, /* n1g3[29] = -0.00039069036118270117 */ - -11 /* n1g3[30] = -0.00034322798979677605 */ -}; - -/*---------------------------------------------------------------------------- - * WT_SetFilterCoeffs() - *---------------------------------------------------------------------------- - * Purpose: - * Update the Filter parameters - * - * Inputs: - * pVoice - ptr to the voice whose filter we want to update - * pEASData - pointer to overall EAS data structure - * - * Outputs: - * - * Side Effects: - * - updates Filter values for the given voice - *---------------------------------------------------------------------------- -*/ -void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance) -{ - EAS_I32 temp; - - /* - Convert the cutoff, which has had A5 subtracted, using the 2^x approx - Note, this cutoff is related to theta cutoff by - theta = k * 2^x - We use 2^x and incorporate k in the power series coefs instead - */ - cutoff = EAS_Calculate2toX(cutoff); - - /* calculate b2 coef */ - temp = k2g1[resonance] + MULT_AUDIO_COEF(cutoff, k2g2[resonance]); - temp = k2g0 + MULT_AUDIO_COEF(cutoff, temp); - pIntFrame->frame.b2 = temp; - - /* calculate b1 coef */ - temp = MULT_AUDIO_COEF(cutoff, nk1g2); - temp = nk1g0 + MULT_AUDIO_COEF(cutoff, temp); - temp += MULT_AUDIO_COEF(temp, pIntFrame->frame.b2); - pIntFrame->frame.b1 = temp >> 1; - - /* calculate K coef */ - temp = n1g2[resonance] + MULT_AUDIO_COEF(cutoff, n1g3[resonance]); - temp = MULT_AUDIO_COEF(cutoff, temp); - temp = MULT_AUDIO_COEF(cutoff, temp); - pIntFrame->frame.k = temp; -} -#endif - |