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