1 /*----------------------------------------------------------------------------
2  *
3  * File:
4  * eas_dlssynth.c
5  *
6  * Contents and purpose:
7  * Implements the Mobile DLS synthesizer.
8  *
9  * Copyright Sonic Network Inc. 2006
10 
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  *----------------------------------------------------------------------------
24  * Revision Control:
25  *   $Revision: 795 $
26  *   $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $
27  *----------------------------------------------------------------------------
28 */
29 
30 // includes
31 #include "eas_data.h"
32 #include "eas_report.h"
33 #include "eas_host.h"
34 #include "eas_math.h"
35 #include "eas_synth_protos.h"
36 #include "eas_wtsynth.h"
37 #include "eas_pan.h"
38 #include "eas_mdls.h"
39 #include "eas_dlssynth.h"
40 
41 #ifdef _METRICS_ENABLED
42 #include "eas_perf.h"
43 #endif
44 
45 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);
46 
47 /*----------------------------------------------------------------------------
48  * DLS_MuteVoice()
49  *----------------------------------------------------------------------------
50  * Mute the voice using shutdown time from the DLS articulation data
51  *----------------------------------------------------------------------------
52 */
DLS_MuteVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum)53 void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
54 {
55     S_WT_VOICE *pWTVoice;
56     const S_DLS_ARTICULATION *pDLSArt;
57 
58     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
59     pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
60 
61     /* clear deferred action flags */
62     pVoice->voiceFlags &=
63         ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF |
64         VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF |
65         VOICE_FLAG_DEFER_MUTE);
66 
67     /* set the envelope state */
68     pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateRelease;
69     pWTVoice->eg1Increment = pDLSArt->eg1ShutdownTime;
70     pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateRelease;
71     pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime;
72 }
73 
74 /*----------------------------------------------------------------------------
75  * DLS_ReleaseVoice()
76  *----------------------------------------------------------------------------
77  * Release the selected voice.
78  *----------------------------------------------------------------------------
79 */
80 /*lint -esym(715, pVoice) standard API, pVoice may be used by other synthesizers */
DLS_ReleaseVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum)81 void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum)
82 {
83     S_WT_VOICE *pWTVoice;
84     const S_DLS_ARTICULATION *pDLSArt;
85 
86     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
87     pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
88 
89     /* if still in attack phase, convert units to log */
90     /*lint -e{732} eg1Value is never negative */
91     /*lint -e{703} use shift for performance */
92     if (pWTVoice->eg1State == eEnvelopeStateAttack)
93         pWTVoice->eg1Value = (EAS_I16) ((EAS_flog2(pWTVoice->eg1Value) << 1) + 2048);
94 
95     /* release EG1 */
96     pWTVoice->eg1State = eEnvelopeStateRelease;
97     pWTVoice->eg1Increment = pDLSArt->eg1.releaseTime;
98 
99     /* release EG2 */
100     pWTVoice->eg2State = eEnvelopeStateRelease;
101     pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime;
102 }
103 
104 /*----------------------------------------------------------------------------
105  * DLS_SustainPedal()
106  *----------------------------------------------------------------------------
107  * The sustain pedal was just depressed. If the voice is still
108  * above the sustain level, catch the voice and continue holding.
109  *----------------------------------------------------------------------------
110 */
111 /*lint -esym(715, pChannel) pChannel reserved for future use */
DLS_SustainPedal(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,S_SYNTH_CHANNEL * pChannel,EAS_I32 voiceNum)112 void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum)
113 {
114     S_WT_VOICE *pWTVoice;
115     const S_DLS_ARTICULATION *pDLSArt;
116 
117     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
118     pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
119 
120     /* don't catch the voice if below the sustain level */
121     if (pWTVoice->eg1Value < pDLSArt->eg1.sustainLevel)
122         return;
123 
124     /* defer releasing this note until the damper pedal is off */
125     pWTVoice->eg1State = eEnvelopeStateDecay;
126     pVoice->voiceState = eVoiceStatePlay;
127     pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF;
128 
129 #ifdef _DEBUG_SYNTH
130     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_SustainPedal: defer note off because sustain pedal is on\n"); */ }
131 #endif
132 }
133 
134 /*----------------------------------------------------------------------------
135  * DLS_UpdatePhaseInc()
136  *----------------------------------------------------------------------------
137  * Calculate the oscillator phase increment for the next frame
138  *----------------------------------------------------------------------------
139 */
DLS_UpdatePhaseInc(S_WT_VOICE * pWTVoice,const S_DLS_ARTICULATION * pDLSArt,S_SYNTH_CHANNEL * pChannel,EAS_I32 pitchCents)140 static EAS_I32 DLS_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents)
141 {
142     EAS_I32 temp;
143 
144     /* start with base mod LFO modulation */
145     temp = pDLSArt->modLFOToPitch;
146 
147     /* add mod wheel effect */
148     /*lint -e{702} use shift for performance */
149     temp += ((pDLSArt->modLFOCC1ToPitch * pChannel->modWheel) >> 7);
150 
151     /* add channel pressure effect */
152     /*lint -e{702} use shift for performance */
153     temp += ((pDLSArt->modLFOChanPressToPitch * pChannel->channelPressure) >> 7);
154 
155     /* add total mod LFO effect */
156     pitchCents += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue);
157 
158     /* start with base vib LFO modulation */
159     temp = pDLSArt->vibLFOToPitch;
160 
161     /* add mod wheel effect */
162     /*lint -e{702} use shift for performance */
163     temp += ((pDLSArt->vibLFOCC1ToPitch * pChannel->modWheel) >> 7);
164 
165     /* add channel pressure effect */
166     /*lint -e{702} use shift for performance */
167     temp += ((pDLSArt->vibLFOChanPressToPitch * pChannel->channelPressure) >> 7);
168 
169     /* add total vibrato LFO effect */
170     pitchCents += FMUL_15x15(temp, pWTVoice->vibLFO.lfoValue);
171 
172     /* add EG2 effect */
173     pitchCents += FMUL_15x15(pDLSArt->eg2ToPitch, pWTVoice->eg2Value);
174 
175     /* convert from cents to linear phase increment */
176     return EAS_Calculate2toX(pitchCents);
177 }
178 
179 /*----------------------------------------------------------------------------
180  * DLS_UpdateGain()
181  *----------------------------------------------------------------------------
182  * Calculate the gain for the next frame
183  *----------------------------------------------------------------------------
184 */
DLS_UpdateGain(S_WT_VOICE * pWTVoice,const S_DLS_ARTICULATION * pDLSArt,S_SYNTH_CHANNEL * pChannel,EAS_I32 gain,EAS_U8 velocity)185 static EAS_I32 DLS_UpdateGain (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain, EAS_U8 velocity)
186 {
187     EAS_I32 temp;
188 
189     /* start with base mod LFO modulation */
190     temp = pDLSArt->modLFOToGain;
191 
192     /* add mod wheel effect */
193     /*lint -e{702} use shift for performance */
194     temp += ((pDLSArt->modLFOCC1ToGain * pChannel->modWheel) >> 7);
195 
196     /* add channel pressure effect */
197     /*lint -e{702} use shift for performance */
198     temp += ((pDLSArt->modLFOChanPressToGain * pChannel->channelPressure) >> 7);
199 
200     /* add total mod LFO effect */
201     gain += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue);
202     if (gain > 0)
203         gain = 0;
204 
205     /* convert to linear gain including EG1 */
206     if (pWTVoice->eg1State != eEnvelopeStateAttack)
207     {
208         gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT;
209         /*lint -e{702} use shift for performance */
210 #if 1
211         gain += (pWTVoice->eg1Value - 32767) >> 1;
212         gain = EAS_LogToLinear16(gain);
213 #else
214         gain = EAS_LogToLinear16(gain);
215         temp = EAS_LogToLinear16((pWTVoice->eg1Value - 32767) >> 1);
216         gain = FMUL_15x15(gain, temp);
217 #endif
218     }
219     else
220     {
221         gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT;
222         gain = EAS_LogToLinear16(gain);
223         gain = FMUL_15x15(gain, pWTVoice->eg1Value);
224     }
225 
226     /* include MIDI channel gain */
227     gain = FMUL_15x15(gain, pChannel->staticGain);
228 
229     /* include velocity */
230     if (pDLSArt->filterQandFlags & FLAG_DLS_VELOCITY_SENSITIVE)
231     {
232         temp = velocity << 8;
233         temp = FMUL_15x15(temp, temp);
234         gain = FMUL_15x15(gain, temp);
235     }
236 
237     /* return gain */
238     return gain;
239 }
240 
241 /*----------------------------------------------------------------------------
242  * DLS_UpdateFilter()
243  *----------------------------------------------------------------------------
244  * Update the Filter parameters
245  *----------------------------------------------------------------------------
246 */
DLS_UpdateFilter(S_SYNTH_VOICE * pVoice,S_WT_VOICE * pWTVoice,S_WT_INT_FRAME * pIntFrame,S_SYNTH_CHANNEL * pChannel,const S_DLS_ARTICULATION * pDLSArt)247 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)
248 {
249     EAS_I32 cutoff;
250     EAS_I32 temp;
251 
252     /* no need to calculate filter coefficients if it is bypassed */
253     if (pDLSArt->filterCutoff == DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY)
254     {
255         pIntFrame->frame.k = 0;
256         return;
257     }
258 
259     /* start with base cutoff frequency */
260     cutoff = pDLSArt->filterCutoff;
261 
262     /* get base mod LFO modulation */
263     temp = pDLSArt->modLFOToFc;
264 
265     /* add mod wheel effect */
266     /*lint -e{702} use shift for performance */
267     temp += ((pDLSArt->modLFOCC1ToFc * pChannel->modWheel) >> 7);
268 
269     /* add channel pressure effect */
270     /*lint -e{702} use shift for performance */
271     temp += ((pDLSArt->modLFOChanPressToFc* pChannel->channelPressure) >> 7);
272 
273     /* add total mod LFO effect */
274     cutoff += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue);
275 
276     /* add EG2 effect */
277     cutoff += FMUL_15x15(pWTVoice->eg2Value, pDLSArt->eg2ToFc);
278 
279     /* add velocity effect */
280     /*lint -e{702} use shift for performance */
281     cutoff += (pVoice->velocity * pDLSArt->velToFc) >> 7;
282 
283     /* add velocity effect */
284     /*lint -e{702} use shift for performance */
285     cutoff += (pVoice->note * pDLSArt->keyNumToFc) >> 7;
286 
287     /* subtract the A5 offset and the sampling frequency */
288     cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS;
289 
290     /* limit the cutoff frequency */
291     if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS)
292         cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS;
293     else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS)
294         cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS;
295 
296     WT_SetFilterCoeffs(pIntFrame, cutoff, pDLSArt->filterQandFlags & FILTER_Q_MASK);
297 }
298 
299 /*----------------------------------------------------------------------------
300  * DLS_StartVoice()
301  *----------------------------------------------------------------------------
302  * Start up a DLS voice
303  *----------------------------------------------------------------------------
304 */
DLS_StartVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum,EAS_U16 regionIndex)305 EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex)
306 {
307     S_WT_VOICE *pWTVoice;
308     const S_DLS_REGION *pDLSRegion;
309     const S_DLS_ARTICULATION *pDLSArt;
310     S_SYNTH_CHANNEL *pChannel;
311 
312 #ifdef _DEBUG_SYNTH
313     { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ }
314 #endif
315 
316     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
317     pChannel = &pSynth->channels[pVoice->channel & 15];
318     pDLSRegion = &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK];
319     pWTVoice->artIndex = pDLSRegion->wtRegion.artIndex;
320     pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
321 
322     /* initialize the envelopes */
323     pWTVoice->eg1State = eEnvelopeStateInit;
324     DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State);
325     pWTVoice->eg2State = eEnvelopeStateInit;
326     DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State);
327 
328     /* initialize the LFOs */
329     pWTVoice->modLFO.lfoValue = 0;
330     pWTVoice->modLFO.lfoPhase = pDLSArt->modLFO.lfoDelay;
331     pWTVoice->vibLFO.lfoValue = 0;
332     pWTVoice->vibLFO.lfoPhase = pDLSArt->vibLFO.lfoDelay;
333 
334     /* initalize the envelopes and calculate initial gain */
335     DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State);
336     DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State);
337     pVoice->gain = (EAS_I16) DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity);
338 
339 #if (NUM_OUTPUT_CHANNELS == 2)
340     EAS_CalcPanControl((EAS_INT) pChannel->pan - 64 + (EAS_INT) pDLSArt->pan, &pWTVoice->gainLeft, &pWTVoice->gainRight);
341 #endif
342 
343     /* initialize the filter states */
344     pWTVoice->filter.z1 = 0;
345     pWTVoice->filter.z2 = 0;
346 
347     /* initialize the oscillator */
348     pWTVoice->phaseAccum = (EAS_U32) pSynth->pDLS->pDLSSamples + pSynth->pDLS->pDLSSampleOffsets[pDLSRegion->wtRegion.waveIndex];
349     if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED)
350     {
351         pWTVoice->loopStart = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopStart;
352         pWTVoice->loopEnd = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopEnd - 1;
353     }
354     else
355         pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pDLS->pDLSSampleLen[pDLSRegion->wtRegion.waveIndex] - 1;
356 
357     return EAS_SUCCESS;
358 }
359 
360 /*----------------------------------------------------------------------------
361  * DLS_UpdateVoice()
362  *----------------------------------------------------------------------------
363  * Purpose:
364  * Synthesize a block of samples for the given voice.
365  * Use linear interpolation.
366  *
367  * Inputs:
368  * pEASData - pointer to overall EAS data structure
369  *
370  * Outputs:
371  * number of samples actually written to buffer
372  *
373  * Side Effects:
374  * - samples are added to the presently free buffer
375  *
376  *----------------------------------------------------------------------------
377 */
DLS_UpdateVoice(S_VOICE_MGR * pVoiceMgr,S_SYNTH * pSynth,S_SYNTH_VOICE * pVoice,EAS_I32 voiceNum,EAS_I32 * pMixBuffer,EAS_I32 numSamples)378 EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples)
379 {
380     S_WT_VOICE *pWTVoice;
381     S_SYNTH_CHANNEL *pChannel;
382     const S_DLS_REGION *pDLSRegion;
383     const S_DLS_ARTICULATION *pDLSArt;
384     S_WT_INT_FRAME intFrame;
385     EAS_I32 temp;
386     EAS_BOOL done = EAS_FALSE;
387 
388     /* establish pointers to critical data */
389     pWTVoice = &pVoiceMgr->wtVoices[voiceNum];
390     pDLSRegion = &pSynth->pDLS->pDLSRegions[pVoice->regionIndex & REGION_INDEX_MASK];
391     pChannel = &pSynth->channels[pVoice->channel & 15];
392     pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex];
393 
394     /* update the envelopes */
395     DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State);
396     DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State);
397 
398     /* update the LFOs using the EAS synth function */
399     WT_UpdateLFO(&pWTVoice->modLFO, pDLSArt->modLFO.lfoFreq);
400     WT_UpdateLFO(&pWTVoice->vibLFO, pDLSArt->vibLFO.lfoFreq);
401 
402     /* calculate base frequency */
403     temp = pDLSArt->tuning + pChannel->staticPitch + pDLSRegion->wtRegion.tuning +
404         (((EAS_I32) pVoice->note * (EAS_I32) pDLSArt->keyNumToPitch) >> 7);
405 
406     /* don't transpose rhythm channel */
407     if ((pChannel ->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) == 0)
408         temp += pSynth->globalTranspose * 100;
409 
410     /* calculate phase increment including modulation effects */
411     intFrame.frame.phaseIncrement = DLS_UpdatePhaseInc(pWTVoice, pDLSArt, pChannel, temp);
412 
413     /* calculate gain including modulation effects */
414     intFrame.frame.gainTarget = DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity);
415     intFrame.prevGain = pVoice->gain;
416 
417     DLS_UpdateFilter(pVoice, pWTVoice, &intFrame, pChannel, pDLSArt);
418 
419     /* call into engine to generate samples */
420     intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer;
421     intFrame.pMixBuffer = pMixBuffer;
422     intFrame.numSamples = numSamples;
423     if (numSamples < 0)
424         return EAS_FALSE;
425 
426     /* check for end of sample */
427     if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd))
428         done = WT_CheckSampleEnd(pWTVoice, &intFrame, EAS_FALSE);
429 
430     WT_ProcessVoice(pWTVoice, &intFrame);
431 
432     /* clear flag */
433     pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET;
434 
435     /* if the update interval has elapsed, then force the current gain to the next
436      * gain since we never actually reach the next gain when ramping -- we just get
437      * very close to the target gain.
438      */
439     pVoice->gain = (EAS_I16) intFrame.frame.gainTarget;
440 
441     /* if voice has finished, set flag for voice manager */
442     if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted))
443         done = EAS_TRUE;
444 
445     return done;
446 }
447 
448 /*----------------------------------------------------------------------------
449  * DLS_UpdateEnvelope()
450  *----------------------------------------------------------------------------
451  * Purpose:
452  * Synthesize a block of samples for the given voice.
453  * Use linear interpolation.
454  *
455  * Inputs:
456  * pEASData - pointer to overall EAS data structure
457  *
458  * Outputs:
459  * number of samples actually written to buffer
460  *
461  * Side Effects:
462  * - samples are added to the presently free buffer
463  *
464  *----------------------------------------------------------------------------
465 */
466 /*lint -esym(715, pChannel) pChannel not used in this instance */
DLS_UpdateEnvelope(S_SYNTH_VOICE * pVoice,S_SYNTH_CHANNEL * pChannel,const S_DLS_ENVELOPE * pEnvParams,EAS_I16 * pValue,EAS_I16 * pIncrement,EAS_U8 * pState)467 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)
468 {
469     EAS_I32 temp;
470 
471     switch (*pState)
472     {
473         /* initial state */
474         case eEnvelopeStateInit:
475             *pState = eEnvelopeStateDelay;
476             *pValue = 0;
477             *pIncrement = pEnvParams->delayTime;
478             if (*pIncrement != 0)
479                 return;
480             /*lint -e{825} falls through to next case */
481 
482         case eEnvelopeStateDelay:
483             if (*pIncrement)
484             {
485                 *pIncrement = *pIncrement - 1;
486                 return;
487             }
488 
489             /* calculate attack rate */
490             *pState = eEnvelopeStateAttack;
491             if (pEnvParams->attackTime != ZERO_TIME_IN_CENTS)
492             {
493                 /*lint -e{702} use shift for performance */
494                 temp = pEnvParams->attackTime + ((pEnvParams->velToAttack * pVoice->velocity) >> 7);
495                 *pIncrement = ConvertRate(temp);
496                 return;
497             }
498 
499             *pValue = SYNTH_FULL_SCALE_EG1_GAIN;
500             /*lint -e{825} falls through to next case */
501 
502         case eEnvelopeStateAttack:
503             if (*pValue < SYNTH_FULL_SCALE_EG1_GAIN)
504             {
505                 temp = *pValue + *pIncrement;
506                 *pValue = (EAS_I16) (temp < SYNTH_FULL_SCALE_EG1_GAIN ? temp : SYNTH_FULL_SCALE_EG1_GAIN);
507                 return;
508             }
509 
510             /* calculate hold time */
511             *pState = eEnvelopeStateHold;
512             if (pEnvParams->holdTime != ZERO_TIME_IN_CENTS)
513             {
514                 /*lint -e{702} use shift for performance */
515                 temp = pEnvParams->holdTime + ((pEnvParams->keyNumToHold * pVoice->note) >> 7);
516                 *pIncrement = ConvertDelay(temp);
517                 return;
518             }
519             else
520                 *pIncrement = 0;
521             /*lint -e{825} falls through to next case */
522 
523         case eEnvelopeStateHold:
524             if (*pIncrement)
525             {
526                 *pIncrement = *pIncrement - 1;
527                 return;
528             }
529 
530             /* calculate decay rate */
531             *pState = eEnvelopeStateDecay;
532             if (pEnvParams->decayTime != ZERO_TIME_IN_CENTS)
533             {
534                 /*lint -e{702} use shift for performance */
535                 temp = pEnvParams->decayTime + ((pEnvParams->keyNumToDecay * pVoice->note) >> 7);
536                 *pIncrement = ConvertRate(temp);
537                 return;
538             }
539 
540 //          *pValue = pEnvParams->sustainLevel;
541             /*lint -e{825} falls through to next case */
542 
543         case eEnvelopeStateDecay:
544             if (*pValue > pEnvParams->sustainLevel)
545             {
546                 temp = *pValue - *pIncrement;
547                 *pValue = (EAS_I16) (temp > pEnvParams->sustainLevel ? temp : pEnvParams->sustainLevel);
548                 return;
549             }
550 
551             *pState = eEnvelopeStateSustain;
552             *pValue = pEnvParams->sustainLevel;
553             /*lint -e{825} falls through to next case */
554 
555         case eEnvelopeStateSustain:
556             return;
557 
558         case eEnvelopeStateRelease:
559             temp = *pValue - *pIncrement;
560             if (temp <= 0)
561             {
562                 *pState = eEnvelopeStateMuted;
563                 *pValue = 0;
564             }
565             else
566                 *pValue = (EAS_I16) temp;
567             break;
568 
569         case eEnvelopeStateMuted:
570             *pValue = 0;
571             return;
572 
573         default:
574             { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Envelope in invalid state %d\n", *pState); */ }
575             break;
576     }
577 }
578 
579