--- linuxsampler/trunk/src/engines/gig/Voice.cpp 2005/06/06 16:54:20 614 +++ linuxsampler/trunk/src/engines/gig/Voice.cpp 2005/07/16 19:37:52 696 @@ -61,7 +61,7 @@ KeyGroup = 0; SynthesisMode = 0; // set all mode bits to 0 first // select synthesis implementation (currently either pure C++ or MMX+SSE(1)) - #if ARCH_X86 + #if CONFIG_ASM && ARCH_X86 SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); #else SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false); @@ -117,157 +117,50 @@ * Initializes and triggers the voice, a disk stream will be launched if * needed. * - * @param pEngineChannel - engine channel on which this voice was ordered - * @param itNoteOnEvent - event that caused triggering of this voice - * @param PitchBend - MIDI detune factor (-8192 ... +8191) - * @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data - * @param iLayer - layer number this voice refers to (only if this is a layered sound of course) - * @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false) - * @param VoiceStealingAllowed - wether the voice is allowed to steal voices for further subvoices + * @param pEngineChannel - engine channel on which this voice was ordered + * @param itNoteOnEvent - event that caused triggering of this voice + * @param PitchBend - MIDI detune factor (-8192 ... +8191) + * @param pDimRgn - points to the dimension region which provides sample wave(s) and articulation data + * @param VoiceType - type of this voice + * @param iKeyGroup - a value > 0 defines a key group in which this voice is member of * @returns 0 on success, a value < 0 if the voice wasn't triggered * (either due to an error or e.g. because no region is * defined for the given key) */ - int Voice::Trigger(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealingAllowed) { + int Voice::Trigger(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent, int PitchBend, ::gig::DimensionRegion* pDimRgn, type_t VoiceType, int iKeyGroup) { this->pEngineChannel = pEngineChannel; - if (!pInstrument) { - dmsg(1,("voice::trigger: !pInstrument\n")); - exit(EXIT_FAILURE); - } + this->pDimRgn = pDimRgn; + #if CONFIG_DEVMODE if (itNoteOnEvent->FragmentPos() > pEngine->MaxSamplesPerCycle) { // just a sanity check for debugging dmsg(1,("Voice::Trigger(): ERROR, TriggerDelay > Totalsamples\n")); } #endif // CONFIG_DEVMODE - Type = type_normal; + Type = VoiceType; MIDIKey = itNoteOnEvent->Param.Note.Key; - pRegion = pInstrument->GetRegion(MIDIKey); PlaybackState = playback_state_init; // mark voice as triggered, but no audio rendered yet Delay = itNoteOnEvent->FragmentPos(); itTriggerEvent = itNoteOnEvent; itKillEvent = Pool::Iterator(); + KeyGroup = iKeyGroup; + pSample = pDimRgn->pSample; // sample won't change until the voice is finished - if (!pRegion) { - dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey)); - return -1; - } + // calculate volume + const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); - // only mark the first voice of a layered voice (group) to be in a - // key group, so the layered voices won't kill each other - KeyGroup = (iLayer == 0 && !ReleaseTriggerVoice) ? pRegion->KeyGroup : 0; + Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) - // get current dimension values to select the right dimension region - //FIXME: controller values for selecting the dimension region here are currently not sample accurate - uint DimValues[8] = { 0 }; - for (int i = pRegion->Dimensions - 1; i >= 0; i--) { - switch (pRegion->pDimensionDefinitions[i].dimension) { - case ::gig::dimension_samplechannel: - DimValues[i] = 0; //TODO: we currently ignore this dimension - break; - case ::gig::dimension_layer: - DimValues[i] = iLayer; - break; - case ::gig::dimension_velocity: - DimValues[i] = itNoteOnEvent->Param.Note.Velocity; - break; - case ::gig::dimension_channelaftertouch: - DimValues[i] = 0; //TODO: we currently ignore this dimension - break; - case ::gig::dimension_releasetrigger: - Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal; - DimValues[i] = (uint) ReleaseTriggerVoice; - break; - case ::gig::dimension_keyboard: - DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension; - break; - case ::gig::dimension_roundrobin: - DimValues[i] = (uint) pEngineChannel->pMIDIKeyInfo[MIDIKey].RoundRobinIndex; // incremented for each note on - break; - case ::gig::dimension_random: - pEngine->RandomSeed = pEngine->RandomSeed * 1103515245 + 12345; // classic pseudo random number generator - DimValues[i] = (uint) pEngine->RandomSeed >> (32 - pRegion->pDimensionDefinitions[i].bits); // highest bits are most random - break; - case ::gig::dimension_modwheel: - DimValues[i] = pEngineChannel->ControllerTable[1]; - break; - case ::gig::dimension_breath: - DimValues[i] = pEngineChannel->ControllerTable[2]; - break; - case ::gig::dimension_foot: - DimValues[i] = pEngineChannel->ControllerTable[4]; - break; - case ::gig::dimension_portamentotime: - DimValues[i] = pEngineChannel->ControllerTable[5]; - break; - case ::gig::dimension_effect1: - DimValues[i] = pEngineChannel->ControllerTable[12]; - break; - case ::gig::dimension_effect2: - DimValues[i] = pEngineChannel->ControllerTable[13]; - break; - case ::gig::dimension_genpurpose1: - DimValues[i] = pEngineChannel->ControllerTable[16]; - break; - case ::gig::dimension_genpurpose2: - DimValues[i] = pEngineChannel->ControllerTable[17]; - break; - case ::gig::dimension_genpurpose3: - DimValues[i] = pEngineChannel->ControllerTable[18]; - break; - case ::gig::dimension_genpurpose4: - DimValues[i] = pEngineChannel->ControllerTable[19]; - break; - case ::gig::dimension_sustainpedal: - DimValues[i] = pEngineChannel->ControllerTable[64]; - break; - case ::gig::dimension_portamento: - DimValues[i] = pEngineChannel->ControllerTable[65]; - break; - case ::gig::dimension_sostenutopedal: - DimValues[i] = pEngineChannel->ControllerTable[66]; - break; - case ::gig::dimension_softpedal: - DimValues[i] = pEngineChannel->ControllerTable[67]; - break; - case ::gig::dimension_genpurpose5: - DimValues[i] = pEngineChannel->ControllerTable[80]; - break; - case ::gig::dimension_genpurpose6: - DimValues[i] = pEngineChannel->ControllerTable[81]; - break; - case ::gig::dimension_genpurpose7: - DimValues[i] = pEngineChannel->ControllerTable[82]; - break; - case ::gig::dimension_genpurpose8: - DimValues[i] = pEngineChannel->ControllerTable[83]; - break; - case ::gig::dimension_effect1depth: - DimValues[i] = pEngineChannel->ControllerTable[91]; - break; - case ::gig::dimension_effect2depth: - DimValues[i] = pEngineChannel->ControllerTable[92]; - break; - case ::gig::dimension_effect3depth: - DimValues[i] = pEngineChannel->ControllerTable[93]; - break; - case ::gig::dimension_effect4depth: - DimValues[i] = pEngineChannel->ControllerTable[94]; - break; - case ::gig::dimension_effect5depth: - DimValues[i] = pEngineChannel->ControllerTable[95]; - break; - case ::gig::dimension_none: - std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush; - break; - default: - std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush; - } - } - pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); + Volume *= pDimRgn->SampleAttenuation; - pSample = pDimRgn->pSample; // sample won't change until the voice is finished - if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent + // the volume of release triggered samples depends on note length + if (Type == type_release_trigger) { + float noteLength = float(pEngine->FrameTime + Delay - + pEngineChannel->pMIDIKeyInfo[MIDIKey].NoteOnTime) / pEngine->SampleRate; + float attenuation = 1 - 0.01053 * (256 >> pDimRgn->ReleaseTriggerDecay) * noteLength; + if (attenuation <= 0) return -1; + Volume *= attenuation; + } // select channel mode (mono or stereo) SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); @@ -333,12 +226,6 @@ this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents } - const double velocityAttenuation = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity); - - Volume = velocityAttenuation / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) - - Volume *= pDimRgn->SampleAttenuation; - // the length of the decay and release curves are dependent on the velocity const double velrelease = 1 / pDimRgn->GetVelocityRelease(itNoteOnEvent->Param.Note.Velocity); @@ -362,20 +249,23 @@ } if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue; - // calculate influence of EG1 controller on EG1's parameters (TODO: needs to be fine tuned) - double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 0.0; - double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 0.0; - double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 0.0; + // calculate influence of EG1 controller on EG1's parameters + // (eg1attack is different from the others) + double eg1attack = (pDimRgn->EG1ControllerAttackInfluence) ? + 1 + 0.031 * (double) (pDimRgn->EG1ControllerAttackInfluence == 1 ? + 1 : 1 << pDimRgn->EG1ControllerAttackInfluence) * eg1controllervalue : 1.0; + double eg1decay = (pDimRgn->EG1ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerDecayInfluence) * eg1controllervalue : 1.0; + double eg1release = (pDimRgn->EG1ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG1ControllerReleaseInfluence) * eg1controllervalue : 1.0; pEG1->Trigger(pDimRgn->EG1PreAttack, - pDimRgn->EG1Attack + eg1attack, + pDimRgn->EG1Attack * eg1attack, pDimRgn->EG1Hold, pSample->LoopStart, - (pDimRgn->EG1Decay1 + eg1decay) * velrelease, - (pDimRgn->EG1Decay2 + eg1decay) * velrelease, + pDimRgn->EG1Decay1 * eg1decay * velrelease, + pDimRgn->EG1Decay2 * eg1decay * velrelease, pDimRgn->EG1InfiniteSustain, pDimRgn->EG1Sustain, - (pDimRgn->EG1Release + eg1release) * velrelease, + pDimRgn->EG1Release * eg1release * velrelease, // the SSE synthesis implementation requires // the vca start to be 16 byte aligned SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ? @@ -404,20 +294,20 @@ } if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue; - // calculate influence of EG2 controller on EG2's parameters (TODO: needs to be fine tuned) - double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 0.0; - double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 0.0; - double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 0.0001 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 0.0; + // calculate influence of EG2 controller on EG2's parameters + double eg2attack = (pDimRgn->EG2ControllerAttackInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerAttackInfluence) * eg2controllervalue : 1.0; + double eg2decay = (pDimRgn->EG2ControllerDecayInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerDecayInfluence) * eg2controllervalue : 1.0; + double eg2release = (pDimRgn->EG2ControllerReleaseInfluence) ? 1 + 0.00775 * (double) (1 << pDimRgn->EG2ControllerReleaseInfluence) * eg2controllervalue : 1.0; pEG2->Trigger(pDimRgn->EG2PreAttack, - pDimRgn->EG2Attack + eg2attack, + pDimRgn->EG2Attack * eg2attack, false, pSample->LoopStart, - (pDimRgn->EG2Decay1 + eg2decay) * velrelease, - (pDimRgn->EG2Decay2 + eg2decay) * velrelease, + pDimRgn->EG2Decay1 * eg2decay * velrelease, + pDimRgn->EG2Decay2 * eg2decay * velrelease, pDimRgn->EG2InfiniteSustain, pDimRgn->EG2Sustain, - (pDimRgn->EG2Release + eg2release) * velrelease, + pDimRgn->EG2Release * eg2release * velrelease, Delay, velocityAttenuation); } @@ -437,34 +327,40 @@ case ::gig::lfo1_ctrl_internal: lfo1_internal_depth = pDimRgn->LFO1InternalDepth; pLFO1->ExtController = 0; // no external controller + bLFO1Enabled = (lfo1_internal_depth > 0); break; case ::gig::lfo1_ctrl_modwheel: lfo1_internal_depth = 0; pLFO1->ExtController = 1; // MIDI controller 1 + bLFO1Enabled = (pDimRgn->LFO1ControlDepth > 0); break; case ::gig::lfo1_ctrl_breath: lfo1_internal_depth = 0; pLFO1->ExtController = 2; // MIDI controller 2 + bLFO1Enabled = (pDimRgn->LFO1ControlDepth > 0); break; case ::gig::lfo1_ctrl_internal_modwheel: lfo1_internal_depth = pDimRgn->LFO1InternalDepth; pLFO1->ExtController = 1; // MIDI controller 1 + bLFO1Enabled = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0); break; case ::gig::lfo1_ctrl_internal_breath: lfo1_internal_depth = pDimRgn->LFO1InternalDepth; pLFO1->ExtController = 2; // MIDI controller 2 + bLFO1Enabled = (lfo1_internal_depth > 0 || pDimRgn->LFO1ControlDepth > 0); break; default: lfo1_internal_depth = 0; pLFO1->ExtController = 0; // no external controller + bLFO1Enabled = false; } - pLFO1->Trigger(pDimRgn->LFO1Frequency, - lfo1_internal_depth, - pDimRgn->LFO1ControlDepth, - pEngineChannel->ControllerTable[pLFO1->ExtController], - pDimRgn->LFO1FlipPhase, - pEngine->SampleRate, - Delay); + if (bLFO1Enabled) pLFO1->Trigger(pDimRgn->LFO1Frequency, + lfo1_internal_depth, + pDimRgn->LFO1ControlDepth, + pEngineChannel->ControllerTable[pLFO1->ExtController], + pDimRgn->LFO1FlipPhase, + pEngine->SampleRate, + Delay); } @@ -475,34 +371,40 @@ case ::gig::lfo2_ctrl_internal: lfo2_internal_depth = pDimRgn->LFO2InternalDepth; pLFO2->ExtController = 0; // no external controller + bLFO2Enabled = (lfo2_internal_depth > 0); break; case ::gig::lfo2_ctrl_modwheel: lfo2_internal_depth = 0; pLFO2->ExtController = 1; // MIDI controller 1 + bLFO2Enabled = (pDimRgn->LFO2ControlDepth > 0); break; case ::gig::lfo2_ctrl_foot: lfo2_internal_depth = 0; pLFO2->ExtController = 4; // MIDI controller 4 + bLFO2Enabled = (pDimRgn->LFO2ControlDepth > 0); break; case ::gig::lfo2_ctrl_internal_modwheel: lfo2_internal_depth = pDimRgn->LFO2InternalDepth; pLFO2->ExtController = 1; // MIDI controller 1 + bLFO2Enabled = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0); break; case ::gig::lfo2_ctrl_internal_foot: lfo2_internal_depth = pDimRgn->LFO2InternalDepth; pLFO2->ExtController = 4; // MIDI controller 4 + bLFO2Enabled = (lfo2_internal_depth > 0 || pDimRgn->LFO2ControlDepth > 0); break; default: lfo2_internal_depth = 0; pLFO2->ExtController = 0; // no external controller + bLFO2Enabled = false; } - pLFO2->Trigger(pDimRgn->LFO2Frequency, - lfo2_internal_depth, - pDimRgn->LFO2ControlDepth, - pEngineChannel->ControllerTable[pLFO2->ExtController], - pDimRgn->LFO2FlipPhase, - pEngine->SampleRate, - Delay); + if (bLFO2Enabled) pLFO2->Trigger(pDimRgn->LFO2Frequency, + lfo2_internal_depth, + pDimRgn->LFO2ControlDepth, + pEngineChannel->ControllerTable[pLFO2->ExtController], + pDimRgn->LFO2FlipPhase, + pEngine->SampleRate, + Delay); } @@ -513,34 +415,40 @@ case ::gig::lfo3_ctrl_internal: lfo3_internal_depth = pDimRgn->LFO3InternalDepth; pLFO3->ExtController = 0; // no external controller + bLFO3Enabled = (lfo3_internal_depth > 0); break; case ::gig::lfo3_ctrl_modwheel: lfo3_internal_depth = 0; pLFO3->ExtController = 1; // MIDI controller 1 + bLFO3Enabled = (pDimRgn->LFO3ControlDepth > 0); break; case ::gig::lfo3_ctrl_aftertouch: lfo3_internal_depth = 0; pLFO3->ExtController = 0; // TODO: aftertouch not implemented yet + bLFO3Enabled = false; // see TODO comment in line above break; case ::gig::lfo3_ctrl_internal_modwheel: lfo3_internal_depth = pDimRgn->LFO3InternalDepth; pLFO3->ExtController = 1; // MIDI controller 1 + bLFO3Enabled = (lfo3_internal_depth > 0 || pDimRgn->LFO3ControlDepth > 0); break; case ::gig::lfo3_ctrl_internal_aftertouch: lfo3_internal_depth = pDimRgn->LFO3InternalDepth; pLFO1->ExtController = 0; // TODO: aftertouch not implemented yet + bLFO3Enabled = (lfo3_internal_depth > 0 /*|| pDimRgn->LFO3ControlDepth > 0*/); // see TODO comment in line above break; default: lfo3_internal_depth = 0; pLFO3->ExtController = 0; // no external controller + bLFO3Enabled = false; } - pLFO3->Trigger(pDimRgn->LFO3Frequency, - lfo3_internal_depth, - pDimRgn->LFO3ControlDepth, - pEngineChannel->ControllerTable[pLFO3->ExtController], - false, - pEngine->SampleRate, - Delay); + if (bLFO3Enabled) pLFO3->Trigger(pDimRgn->LFO3Frequency, + lfo3_internal_depth, + pDimRgn->LFO3ControlDepth, + pEngineChannel->ControllerTable[pLFO3->ExtController], + false, + pEngine->SampleRate, + Delay); } @@ -683,11 +591,13 @@ SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); } - pLFO1->Process(Samples); - pLFO2->Process(Samples); - if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active - SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); - SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); + if (bLFO1Enabled) pLFO1->Process(Samples); + if (bLFO2Enabled) pLFO2->Process(Samples); + if (bLFO3Enabled) { + if (pLFO3->Process(Samples)) { // if pitch LFO modulation is active + SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); + SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); + } } if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode))