--- linuxsampler/trunk/src/engines/gig/Voice.cpp 2005/09/11 15:56:29 770 +++ linuxsampler/trunk/src/engines/gig/Voice.cpp 2005/10/30 08:35:13 796 @@ -140,6 +140,7 @@ PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f; finalSynthesisParameters.dPos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points) + Pos = pDimRgn->SampleStartOffset; // Check if the sample needs disk streaming or is too short for that long cachedsamples = pSample->GetCache().Size / pSample->FrameSize; @@ -219,7 +220,6 @@ EG1.trigger(pDimRgn->EG1PreAttack, pDimRgn->EG1Attack * eg1attack, pDimRgn->EG1Hold, - pSample->LoopStart, pDimRgn->EG1Decay1 * eg1decay * velrelease, pDimRgn->EG1Decay2 * eg1decay * velrelease, pDimRgn->EG1InfiniteSustain, @@ -258,7 +258,6 @@ EG2.trigger(pDimRgn->EG2PreAttack, pDimRgn->EG2Attack * eg2attack, false, - pSample->LoopStart, pDimRgn->EG2Decay1 * eg2decay * velrelease, pDimRgn->EG2Decay2 * eg2decay * velrelease, pDimRgn->EG2InfiniteSustain, @@ -495,6 +494,7 @@ if (VCFCutoffCtrl.controller) { cvalue = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; if (pDimRgn->VCFCutoffControllerInvert) cvalue = 127 - cvalue; + // VCFVelocityScale in this case means Minimum cutoff if (cvalue < pDimRgn->VCFVelocityScale) cvalue = pDimRgn->VCFVelocityScale; } else { @@ -502,16 +502,13 @@ } cutoff *= float(cvalue) * 0.00787402f; // (1 / 127) if (cutoff > 1.0) cutoff = 1.0; - cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN; + cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449); + if (cutoff < 1.0) cutoff = 1.0; // calculate resonance - float resonance = (float) VCFResonanceCtrl.value * 0.00787f; // 0.0..1.0 - if (pDimRgn->VCFKeyboardTracking) { - resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f; - } - Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0) + float resonance = (float) (VCFResonanceCtrl.controller ? VCFResonanceCtrl.value : pDimRgn->VCFResonance) * 0.00787f; // 0.0..1.0 - VCFCutoffCtrl.fvalue = cutoff - CONFIG_FILTER_CUTOFF_MIN; + VCFCutoffCtrl.fvalue = cutoff - 1.0; VCFResonanceCtrl.fvalue = resonance; } else { @@ -611,9 +608,6 @@ break; } - // Reset synthesis event lists - pEngineChannel->pEvents->clear(); - // Reset delay Delay = 0; @@ -649,11 +643,11 @@ void Voice::processTransitionEvents(RTList::Iterator& itEvent, uint End) { for (; itEvent && itEvent->FragmentPos() <= End; ++itEvent) { if (itEvent->Type == Event::type_release) { - EG1.update(EGADSR::event_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); - EG2.update(EGADSR::event_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + EG1.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + EG2.update(EGADSR::event_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); } else if (itEvent->Type == Event::type_cancel_release) { - EG1.update(EGADSR::event_cancel_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); - EG2.update(EGADSR::event_cancel_release, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + EG1.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + EG2.update(EGADSR::event_cancel_release, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); } } } @@ -718,8 +712,10 @@ if (ccvalue < pDimRgn->VCFVelocityScale) ccvalue = pDimRgn->VCFVelocityScale; float cutoff = CutoffBase * float(ccvalue) * 0.00787402f; // (1 / 127) if (cutoff > 1.0) cutoff = 1.0; - cutoff = exp(cutoff * FILTER_CUTOFF_COEFF) * CONFIG_FILTER_CUTOFF_MIN - CONFIG_FILTER_CUTOFF_MIN; - VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time + cutoff = (cutoff < 0.5 ? cutoff * 4826 - 1 : cutoff * 5715 - 449); + if (cutoff < 1.0) cutoff = 1.0; + + VCFCutoffCtrl.fvalue = cutoff - 1.0; // needed for initialization of fFinalCutoff next time fFinalCutoff = cutoff; } @@ -754,6 +750,9 @@ while (itNoteEvent && itNoteEvent->FragmentPos() <= Skip) ++itNoteEvent; } + uint killPos; + if (itKillEvent) killPos = RTMath::Min(itKillEvent->FragmentPos(), pEngine->MaxFadeOutPos); + uint i = Skip; while (i < Samples) { int iSubFragmentEnd = RTMath::Min(i + CONFIG_DEFAULT_SUBFRAGMENT_SIZE, Samples); @@ -774,6 +773,12 @@ // process transition events (note on, note off & sustain pedal) processTransitionEvents(itNoteEvent, iSubFragmentEnd); + // if the voice was killed in this subfragment switch EG1 to fade out stage + if (itKillEvent && killPos <= iSubFragmentEnd) { + EG1.enterFadeOutStage(); + itKillEvent = Pool::Iterator(); + } + // process envelope generators switch (EG1.getSegmentType()) { case EGADSR::segment_lin: @@ -806,8 +811,8 @@ // if filter enabled then update filter coefficients if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) { - finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate); - finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff, fFinalResonance, pEngine->SampleRate); + finalSynthesisParameters.filterLeft.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate); + finalSynthesisParameters.filterRight.SetParameters(fFinalCutoff + 1.0, fFinalResonance, pEngine->SampleRate); } // do we need resampling? @@ -825,18 +830,27 @@ // render audio for one subfragment RunSynthesisFunction(SynthesisMode, &finalSynthesisParameters, &loop); + const double newPos = Pos + (iSubFragmentEnd - i) * finalSynthesisParameters.fFinalPitch; + // increment envelopes' positions if (EG1.active()) { + + // if sample has a loop and loop start has been reached in this subfragment, send a special event to EG1 to let it finish the attack hold stage + if (pSample->Loops && Pos <= pSample->LoopStart && pSample->LoopStart < newPos) { + EG1.update(EGADSR::event_hold_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + } + EG1.increment(1); - if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + if (!EG1.toStageEndLeft()) EG1.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); } if (EG2.active()) { EG2.increment(1); - if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, finalSynthesisParameters.dPos, finalSynthesisParameters.fFinalPitch, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); + if (!EG2.toStageEndLeft()) EG2.update(EGADSR::event_stage_end, pEngine->SampleRate / CONFIG_DEFAULT_SUBFRAGMENT_SIZE); } EG3.increment(1); if (!EG3.toEndLeft()) EG3.update(); // neutralize envelope coefficient if end reached + Pos = newPos; i = iSubFragmentEnd; } }