| /*---------------------------------------------------------------------------- |
| * |
| * File: |
| * eas_dlssynth.c |
| * |
| * Contents and purpose: |
| * Implements the Mobile DLS synthesizer. |
| * |
| * Copyright Sonic Network Inc. 2006 |
| |
| * 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" |
| #include "eas_mdls.h" |
| #include "eas_dlssynth.h" |
| |
| #ifdef _METRICS_ENABLED |
| #include "eas_perf.h" |
| #endif |
| |
| static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState); |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_MuteVoice() |
| *---------------------------------------------------------------------------- |
| * Mute the voice using shutdown time from the DLS articulation data |
| *---------------------------------------------------------------------------- |
| */ |
| void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) |
| { |
| S_WT_VOICE *pWTVoice; |
| const S_DLS_ARTICULATION *pDLSArt; |
| |
| pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; |
| pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; |
| |
| /* 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 = eEnvelopeStateRelease; |
| pWTVoice->eg1Increment = pDLSArt->eg1ShutdownTime; |
| pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateRelease; |
| pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_ReleaseVoice() |
| *---------------------------------------------------------------------------- |
| * Release the selected voice. |
| *---------------------------------------------------------------------------- |
| */ |
| /*lint -esym(715, pVoice) standard API, pVoice may be used by other synthesizers */ |
| void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) |
| { |
| S_WT_VOICE *pWTVoice; |
| const S_DLS_ARTICULATION *pDLSArt; |
| |
| pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; |
| pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; |
| |
| /* if still in attack phase, convert units to log */ |
| /*lint -e{732} eg1Value is never negative */ |
| /*lint -e{703} use shift for performance */ |
| if (pWTVoice->eg1State == eEnvelopeStateAttack) |
| pWTVoice->eg1Value = (EAS_I16) ((EAS_flog2(pWTVoice->eg1Value) << 1) + 2048); |
| |
| /* release EG1 */ |
| pWTVoice->eg1State = eEnvelopeStateRelease; |
| pWTVoice->eg1Increment = pDLSArt->eg1.releaseTime; |
| |
| /* release EG2 */ |
| pWTVoice->eg2State = eEnvelopeStateRelease; |
| pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_SustainPedal() |
| *---------------------------------------------------------------------------- |
| * The sustain pedal was just depressed. If the voice is still |
| * above the sustain level, catch the voice and continue holding. |
| *---------------------------------------------------------------------------- |
| */ |
| /*lint -esym(715, pChannel) pChannel reserved for future use */ |
| void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) |
| { |
| S_WT_VOICE *pWTVoice; |
| const S_DLS_ARTICULATION *pDLSArt; |
| |
| pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; |
| pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; |
| |
| /* don't catch the voice if below the sustain level */ |
| if (pWTVoice->eg1Value < pDLSArt->eg1.sustainLevel) |
| return; |
| |
| /* defer releasing this note until the damper pedal is off */ |
| pWTVoice->eg1State = eEnvelopeStateDecay; |
| pVoice->voiceState = eVoiceStatePlay; |
| pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; |
| |
| #ifdef _DEBUG_SYNTH |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_SustainPedal: defer note off because sustain pedal is on\n"); */ } |
| #endif |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_UpdatePhaseInc() |
| *---------------------------------------------------------------------------- |
| * Calculate the oscillator phase increment for the next frame |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_I32 DLS_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) |
| { |
| EAS_I32 temp; |
| |
| /* start with base mod LFO modulation */ |
| temp = pDLSArt->modLFOToPitch; |
| |
| /* add mod wheel effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->modLFOCC1ToPitch * pChannel->modWheel) >> 7); |
| |
| /* add channel pressure effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->modLFOChanPressToPitch * pChannel->channelPressure) >> 7); |
| |
| /* add total mod LFO effect */ |
| pitchCents += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); |
| |
| /* start with base vib LFO modulation */ |
| temp = pDLSArt->vibLFOToPitch; |
| |
| /* add mod wheel effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->vibLFOCC1ToPitch * pChannel->modWheel) >> 7); |
| |
| /* add channel pressure effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->vibLFOChanPressToPitch * pChannel->channelPressure) >> 7); |
| |
| /* add total vibrato LFO effect */ |
| pitchCents += FMUL_15x15(temp, pWTVoice->vibLFO.lfoValue); |
| |
| /* add EG2 effect */ |
| pitchCents += FMUL_15x15(pDLSArt->eg2ToPitch, pWTVoice->eg2Value); |
| |
| /* convert from cents to linear phase increment */ |
| return EAS_Calculate2toX(pitchCents); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_UpdateGain() |
| *---------------------------------------------------------------------------- |
| * Calculate the gain for the next frame |
| *---------------------------------------------------------------------------- |
| */ |
| static EAS_I32 DLS_UpdateGain (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain, EAS_U8 velocity) |
| { |
| EAS_I32 temp; |
| |
| /* start with base mod LFO modulation */ |
| temp = pDLSArt->modLFOToGain; |
| |
| /* add mod wheel effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->modLFOCC1ToGain * pChannel->modWheel) >> 7); |
| |
| /* add channel pressure effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->modLFOChanPressToGain * pChannel->channelPressure) >> 7); |
| |
| /* add total mod LFO effect */ |
| gain += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); |
| if (gain > 0) |
| gain = 0; |
| |
| /* convert to linear gain including EG1 */ |
| if (pWTVoice->eg1State != eEnvelopeStateAttack) |
| { |
| gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT; |
| /*lint -e{702} use shift for performance */ |
| #if 1 |
| gain += (pWTVoice->eg1Value - 32767) >> 1; |
| gain = EAS_LogToLinear16(gain); |
| #else |
| gain = EAS_LogToLinear16(gain); |
| temp = EAS_LogToLinear16((pWTVoice->eg1Value - 32767) >> 1); |
| gain = FMUL_15x15(gain, temp); |
| #endif |
| } |
| else |
| { |
| gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT; |
| gain = EAS_LogToLinear16(gain); |
| gain = FMUL_15x15(gain, pWTVoice->eg1Value); |
| } |
| |
| /* include MIDI channel gain */ |
| gain = FMUL_15x15(gain, pChannel->staticGain); |
| |
| /* include velocity */ |
| if (pDLSArt->filterQandFlags & FLAG_DLS_VELOCITY_SENSITIVE) |
| { |
| temp = velocity << 8; |
| temp = FMUL_15x15(temp, temp); |
| gain = FMUL_15x15(gain, temp); |
| } |
| |
| /* return gain */ |
| return gain; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_UpdateFilter() |
| *---------------------------------------------------------------------------- |
| * Update the Filter parameters |
| *---------------------------------------------------------------------------- |
| */ |
| static void DLS_UpdateFilter (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, S_SYNTH_CHANNEL *pChannel, const S_DLS_ARTICULATION *pDLSArt) |
| { |
| EAS_I32 cutoff; |
| EAS_I32 temp; |
| |
| /* no need to calculate filter coefficients if it is bypassed */ |
| if (pDLSArt->filterCutoff == DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY) |
| { |
| pIntFrame->frame.k = 0; |
| return; |
| } |
| |
| /* start with base cutoff frequency */ |
| cutoff = pDLSArt->filterCutoff; |
| |
| /* get base mod LFO modulation */ |
| temp = pDLSArt->modLFOToFc; |
| |
| /* add mod wheel effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->modLFOCC1ToFc * pChannel->modWheel) >> 7); |
| |
| /* add channel pressure effect */ |
| /*lint -e{702} use shift for performance */ |
| temp += ((pDLSArt->modLFOChanPressToFc* pChannel->channelPressure) >> 7); |
| |
| /* add total mod LFO effect */ |
| cutoff += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); |
| |
| /* add EG2 effect */ |
| cutoff += FMUL_15x15(pWTVoice->eg2Value, pDLSArt->eg2ToFc); |
| |
| /* add velocity effect */ |
| /*lint -e{702} use shift for performance */ |
| cutoff += (pVoice->velocity * pDLSArt->velToFc) >> 7; |
| |
| /* add velocity effect */ |
| /*lint -e{702} use shift for performance */ |
| cutoff += (pVoice->note * pDLSArt->keyNumToFc) >> 7; |
| |
| /* 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, pDLSArt->filterQandFlags & FILTER_Q_MASK); |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_StartVoice() |
| *---------------------------------------------------------------------------- |
| * Start up a DLS voice |
| *---------------------------------------------------------------------------- |
| */ |
| EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) |
| { |
| S_WT_VOICE *pWTVoice; |
| const S_DLS_REGION *pDLSRegion; |
| const S_DLS_ARTICULATION *pDLSArt; |
| S_SYNTH_CHANNEL *pChannel; |
| |
| #ifdef _DEBUG_SYNTH |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } |
| #endif |
| |
| pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; |
| pChannel = &pSynth->channels[pVoice->channel & 15]; |
| pDLSRegion = &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK]; |
| pWTVoice->artIndex = pDLSRegion->wtRegion.artIndex; |
| pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; |
| |
| /* initialize the envelopes */ |
| pWTVoice->eg1State = eEnvelopeStateInit; |
| DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); |
| pWTVoice->eg2State = eEnvelopeStateInit; |
| DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); |
| |
| /* initialize the LFOs */ |
| pWTVoice->modLFO.lfoValue = 0; |
| pWTVoice->modLFO.lfoPhase = pDLSArt->modLFO.lfoDelay; |
| pWTVoice->vibLFO.lfoValue = 0; |
| pWTVoice->vibLFO.lfoPhase = pDLSArt->vibLFO.lfoDelay; |
| |
| /* initalize the envelopes and calculate initial gain */ |
| DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); |
| DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); |
| pVoice->gain = (EAS_I16) DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity); |
| |
| #if (NUM_OUTPUT_CHANNELS == 2) |
| EAS_CalcPanControl((EAS_INT) pChannel->pan - 64 + (EAS_INT) pDLSArt->pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); |
| #endif |
| |
| /* initialize the filter states */ |
| pWTVoice->filter.z1 = 0; |
| pWTVoice->filter.z2 = 0; |
| |
| /* initialize the oscillator */ |
| pWTVoice->phaseAccum = (EAS_U32) pSynth->pDLS->pDLSSamples + pSynth->pDLS->pDLSSampleOffsets[pDLSRegion->wtRegion.waveIndex]; |
| if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) |
| { |
| pWTVoice->loopStart = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopStart; |
| pWTVoice->loopEnd = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopEnd - 1; |
| } |
| else |
| pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pDLS->pDLSSampleLen[pDLSRegion->wtRegion.waveIndex] - 1; |
| |
| return EAS_SUCCESS; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_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 |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| EAS_BOOL DLS_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_SYNTH_CHANNEL *pChannel; |
| const S_DLS_REGION *pDLSRegion; |
| const S_DLS_ARTICULATION *pDLSArt; |
| S_WT_INT_FRAME intFrame; |
| EAS_I32 temp; |
| EAS_BOOL done = EAS_FALSE; |
| |
| /* establish pointers to critical data */ |
| pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; |
| pDLSRegion = &pSynth->pDLS->pDLSRegions[pVoice->regionIndex & REGION_INDEX_MASK]; |
| pChannel = &pSynth->channels[pVoice->channel & 15]; |
| pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; |
| |
| /* update the envelopes */ |
| DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); |
| DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); |
| |
| /* update the LFOs using the EAS synth function */ |
| WT_UpdateLFO(&pWTVoice->modLFO, pDLSArt->modLFO.lfoFreq); |
| WT_UpdateLFO(&pWTVoice->vibLFO, pDLSArt->vibLFO.lfoFreq); |
| |
| /* calculate base frequency */ |
| temp = pDLSArt->tuning + pChannel->staticPitch + pDLSRegion->wtRegion.tuning + |
| (((EAS_I32) pVoice->note * (EAS_I32) pDLSArt->keyNumToPitch) >> 7); |
| |
| /* don't transpose rhythm channel */ |
| if ((pChannel ->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) == 0) |
| temp += pSynth->globalTranspose * 100; |
| |
| /* calculate phase increment including modulation effects */ |
| intFrame.frame.phaseIncrement = DLS_UpdatePhaseInc(pWTVoice, pDLSArt, pChannel, temp); |
| |
| /* calculate gain including modulation effects */ |
| intFrame.frame.gainTarget = DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity); |
| intFrame.prevGain = pVoice->gain; |
| |
| DLS_UpdateFilter(pVoice, pWTVoice, &intFrame, pChannel, pDLSArt); |
| |
| /* call into engine to generate samples */ |
| intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; |
| intFrame.pMixBuffer = pMixBuffer; |
| intFrame.numSamples = numSamples; |
| if (numSamples < 0) |
| return EAS_FALSE; |
| |
| /* check for end of sample */ |
| if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) |
| done = WT_CheckSampleEnd(pWTVoice, &intFrame, EAS_FALSE); |
| |
| WT_ProcessVoice(pWTVoice, &intFrame); |
| |
| /* clear flag */ |
| pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; |
| |
| /* 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; |
| |
| /* if voice has finished, set flag for voice manager */ |
| if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) |
| done = EAS_TRUE; |
| |
| return done; |
| } |
| |
| /*---------------------------------------------------------------------------- |
| * DLS_UpdateEnvelope() |
| *---------------------------------------------------------------------------- |
| * 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 |
| * |
| *---------------------------------------------------------------------------- |
| */ |
| /*lint -esym(715, pChannel) pChannel not used in this instance */ |
| static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState) |
| { |
| EAS_I32 temp; |
| |
| switch (*pState) |
| { |
| /* initial state */ |
| case eEnvelopeStateInit: |
| *pState = eEnvelopeStateDelay; |
| *pValue = 0; |
| *pIncrement = pEnvParams->delayTime; |
| if (*pIncrement != 0) |
| return; |
| /*lint -e{825} falls through to next case */ |
| |
| case eEnvelopeStateDelay: |
| if (*pIncrement) |
| { |
| *pIncrement = *pIncrement - 1; |
| return; |
| } |
| |
| /* calculate attack rate */ |
| *pState = eEnvelopeStateAttack; |
| if (pEnvParams->attackTime != ZERO_TIME_IN_CENTS) |
| { |
| /*lint -e{702} use shift for performance */ |
| temp = pEnvParams->attackTime + ((pEnvParams->velToAttack * pVoice->velocity) >> 7); |
| *pIncrement = ConvertRate(temp); |
| return; |
| } |
| |
| *pValue = SYNTH_FULL_SCALE_EG1_GAIN; |
| /*lint -e{825} falls through to next case */ |
| |
| case eEnvelopeStateAttack: |
| if (*pValue < SYNTH_FULL_SCALE_EG1_GAIN) |
| { |
| temp = *pValue + *pIncrement; |
| *pValue = (EAS_I16) (temp < SYNTH_FULL_SCALE_EG1_GAIN ? temp : SYNTH_FULL_SCALE_EG1_GAIN); |
| return; |
| } |
| |
| /* calculate hold time */ |
| *pState = eEnvelopeStateHold; |
| if (pEnvParams->holdTime != ZERO_TIME_IN_CENTS) |
| { |
| /*lint -e{702} use shift for performance */ |
| temp = pEnvParams->holdTime + ((pEnvParams->keyNumToHold * pVoice->note) >> 7); |
| *pIncrement = ConvertDelay(temp); |
| return; |
| } |
| else |
| *pIncrement = 0; |
| /*lint -e{825} falls through to next case */ |
| |
| case eEnvelopeStateHold: |
| if (*pIncrement) |
| { |
| *pIncrement = *pIncrement - 1; |
| return; |
| } |
| |
| /* calculate decay rate */ |
| *pState = eEnvelopeStateDecay; |
| if (pEnvParams->decayTime != ZERO_TIME_IN_CENTS) |
| { |
| /*lint -e{702} use shift for performance */ |
| temp = pEnvParams->decayTime + ((pEnvParams->keyNumToDecay * pVoice->note) >> 7); |
| *pIncrement = ConvertRate(temp); |
| return; |
| } |
| |
| // *pValue = pEnvParams->sustainLevel; |
| /*lint -e{825} falls through to next case */ |
| |
| case eEnvelopeStateDecay: |
| if (*pValue > pEnvParams->sustainLevel) |
| { |
| temp = *pValue - *pIncrement; |
| *pValue = (EAS_I16) (temp > pEnvParams->sustainLevel ? temp : pEnvParams->sustainLevel); |
| return; |
| } |
| |
| *pState = eEnvelopeStateSustain; |
| *pValue = pEnvParams->sustainLevel; |
| /*lint -e{825} falls through to next case */ |
| |
| case eEnvelopeStateSustain: |
| return; |
| |
| case eEnvelopeStateRelease: |
| temp = *pValue - *pIncrement; |
| if (temp <= 0) |
| { |
| *pState = eEnvelopeStateMuted; |
| *pValue = 0; |
| } |
| else |
| *pValue = (EAS_I16) temp; |
| break; |
| |
| case eEnvelopeStateMuted: |
| *pValue = 0; |
| return; |
| |
| default: |
| { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Envelope in invalid state %d\n", *pState); */ } |
| break; |
| } |
| } |
| |