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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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