--- linuxsampler/trunk/src/engines/sfz/SfzSignalUnitRack.cpp 2011/08/02 13:44:57 2225 +++ linuxsampler/trunk/src/engines/sfz/SfzSignalUnitRack.cpp 2011/08/08 13:40:04 2232 @@ -34,28 +34,26 @@ return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE; } - - void EGv1Unit::Trigger() { - ::sfz::Region* const pRegion = pVoice->pRegion; - - // the length of the decay and release curves are dependent on the velocity - const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity); - - // set the delay trigger - uiDelayTrigger = (pRegion->ampeg_delay + pRegion->ampeg_vel2delay * velrelease) * GetSampleRate(); - - EG.trigger(uint(pRegion->ampeg_start * 10), - std::max(0.0, pRegion->ampeg_attack + pRegion->ampeg_vel2attack * velrelease), - std::max(0.0, pRegion->ampeg_hold + pRegion->ampeg_vel2hold * velrelease), - std::max(0.0, pRegion->ampeg_decay + pRegion->ampeg_vel2decay * velrelease), - uint(std::min(std::max(0.0, 10 * (pRegion->ampeg_sustain + pRegion->ampeg_vel2sustain * velrelease)), 1000.0)), - std::max(0.0, pRegion->ampeg_release + pRegion->ampeg_vel2release * velrelease), - GetSampleRate()); + float SfzSignalUnit::GetInfluence(ArrayList< ::sfz::CC>& cc) { + float f = 0; + for (int i = 0; i < cc.size(); i++) { + int val = pVoice->GetControllerValue(cc[i].Controller); + f += (val / 127.0f) * cc[i].Influence; + } + return f; } void EGv2Unit::Trigger() { - EG.trigger(*pEGInfo, GetSampleRate(), pVoice->MIDIVelocity); + egInfo = *pEGInfo; + for (int i = 0; i < egInfo.node.size(); i++) { + float f = GetInfluence(egInfo.node[i].level_oncc); + egInfo.node[i].level = std::min(egInfo.node[i].level + f, 1.0f); + + f = GetInfluence(egInfo.node[i].time_oncc); + egInfo.node[i].time = std::min(egInfo.node[i].time + f, 100.0f); + } + EG.trigger(egInfo, GetSampleRate(), pVoice->MIDIVelocity); } @@ -98,6 +96,53 @@ GetSampleRate()); } + + void AmpEGUnit::Trigger() { + ::sfz::Region* const pRegion = pVoice->pRegion; + + // the length of the decay and release curves are dependent on the velocity + const double velrelease = 1 / pVoice->GetVelocityRelease(pVoice->MIDIVelocity); + + // set the delay trigger + float delay = pRegion->ampeg_delay + pRegion->ampeg_vel2delay * velrelease; + delay += GetInfluence(pRegion->ampeg_delaycc); + uiDelayTrigger = std::max(0.0f, delay) * GetSampleRate(); + + float start = (pRegion->ampeg_start + GetInfluence(pRegion->ampeg_startcc)) * 10; + + float attack = pRegion->ampeg_attack + pRegion->ampeg_vel2attack * velrelease; + attack = std::max(0.0f, attack + GetInfluence(pRegion->ampeg_attackcc)); + + float hold = pRegion->ampeg_hold + pRegion->ampeg_vel2hold * velrelease; + hold = std::max(0.0f, hold + GetInfluence(pRegion->ampeg_holdcc)); + + float decay = pRegion->ampeg_decay + pRegion->ampeg_vel2decay * velrelease; + decay = std::max(0.0f, decay + GetInfluence(pRegion->ampeg_decaycc)); + + float sustain = pRegion->ampeg_sustain + pRegion->ampeg_vel2sustain * velrelease; + sustain = 10 * (sustain + GetInfluence(pRegion->ampeg_sustaincc)); + + float release = pRegion->ampeg_release + pRegion->ampeg_vel2release * velrelease; + release = std::max(0.0f, release + GetInfluence(pRegion->ampeg_releasecc)); + + EG.trigger ( + uint(std::min(std::max(0.0f, start), 1000.0f)), attack, hold, decay, + uint(std::min(std::max(0.0f, sustain), 1000.0f)), release, GetSampleRate() + ); + } + + + LFOUnit::LFOUnit(SfzSignalUnitRack* rack) + : SfzSignalUnit(rack), pLfoInfo(NULL), pLFO(NULL), + suFadeEG(rack), suFreqOnCC(rack, this) + { } + + LFOUnit::LFOUnit(const LFOUnit& Unit) + : SfzSignalUnit(Unit), suFadeEG(static_cast(Unit.pRack)), + suFreqOnCC(static_cast(Unit.pRack), this) + { + Copy(Unit); + } void LFOUnit::Increment() { if (DelayStage()) return; @@ -105,6 +150,7 @@ SignalUnit::Increment(); Level = pLFO->Render(); + if (suFadeEG.Active()) Level *= suFadeEG.GetLevel(); } void LFOUnit::Trigger() { @@ -113,13 +159,27 @@ // set the delay trigger uiDelayTrigger = pLfoInfo->delay * GetSampleRate(); + if(pLfoInfo->fade != 0 || !pLfoInfo->fade_oncc.empty()) { + float f = pLfoInfo->fade; + f += GetInfluence(pLfoInfo->fade_oncc); + + if (f != 0) { + suFadeEG.uiDelayTrigger = pLfoInfo->delay * GetSampleRate(); + suFadeEG.EG.trigger(0, f, 0, 0, 1000, 0, GetSampleRate()); + } + } + } + + void LFOUnit::ValueChanged(CCSignalUnit* pUnit) { + pLFO->SetFrequency(std::max(0.0f, suFreqOnCC.GetLevel() + pLfoInfo->freq), GetSampleRate()); } + void LFOv1Unit::Trigger() { LFOUnit::Trigger(); lfo.trigger ( - pLfoInfo->freq, + pLfoInfo->freq + suFreqOnCC.GetLevel(), start_level_mid, 1, 0, false, GetSampleRate() ); @@ -149,24 +209,21 @@ else pLFO = lfos[pLfoInfo->wave]; pLFO->Trigger ( - pLfoInfo->freq, + pLfoInfo->freq + suFreqOnCC.GetLevel(), start_level_mid, 1, 0, false, GetSampleRate() ); pLFO->Update(0); - float phase = pLfoInfo->phase; - for (int i = 0; i < pLfoInfo->phase_oncc.size(); i++) { - int val = pVoice->GetControllerValue(pLfoInfo->phase_oncc[i].Controller); - phase += (val / 127.0f) * pLfoInfo->phase_oncc[i].Influence; - } + float phase = pLfoInfo->phase + GetInfluence(pLfoInfo->phase_oncc); if (phase != 0) pLFO->SetPhase(phase); } void AmpLFOUnit::Trigger() { ::sfz::Region* const pRegion = pVoice->pRegion; - pLfoInfo->delay = pRegion->amplfo_delay; - pLfoInfo->freq = pRegion->amplfo_freq; + pLfoInfo->delay = pRegion->amplfo_delay; + pLfoInfo->freq = pRegion->amplfo_freq; + pLfoInfo->fade = pRegion->amplfo_fade; pLfoInfo->volume = pRegion->amplfo_depth; LFOv1Unit::Trigger(); @@ -175,7 +232,8 @@ void PitchLFOUnit::Trigger() { ::sfz::Region* const pRegion = pVoice->pRegion; pLfoInfo->delay = pRegion->pitchlfo_delay; - pLfoInfo->freq = pRegion->pitchlfo_freq; + pLfoInfo->freq = pRegion->pitchlfo_freq; + pLfoInfo->fade = pRegion->pitchlfo_fade; pLfoInfo->pitch = pRegion->pitchlfo_depth; LFOv1Unit::Trigger(); @@ -183,18 +241,22 @@ void FilLFOUnit::Trigger() { ::sfz::Region* const pRegion = pVoice->pRegion; - pLfoInfo->delay = pRegion->fillfo_delay; - pLfoInfo->freq = pRegion->fillfo_freq; + pLfoInfo->delay = pRegion->fillfo_delay; + pLfoInfo->freq = pRegion->fillfo_freq; + pLfoInfo->fade = pRegion->fillfo_fade; pLfoInfo->cutoff = pRegion->fillfo_depth; LFOv1Unit::Trigger(); } - CCUnit::CCUnit(SfzSignalUnitRack* rack): CCSignalUnit(rack) { } + CCUnit::CCUnit(SfzSignalUnitRack* rack, Listener* l): CCSignalUnit(rack, l) { + pVoice = NULL; + } void CCUnit::Trigger() { for (int i = 0; i < Ctrls.size(); i++) { Ctrls[i].Value = pVoice->GetControllerValue(Ctrls[i].Controller); + if (Ctrls[i].pSmoother != NULL) Ctrls[i].pSmoother->setValue(Ctrls[i].Value); } CCSignalUnit::Trigger(); } @@ -209,7 +271,36 @@ void CCUnit::SetCCs(ArrayList< ::sfz::CC>& cc) { RemoveAllCCs(); for (int i = 0; i < cc.size(); i++) { - if (cc[i].Influence != 0) AddCC(cc[i].Controller, cc[i].Influence); + if (cc[i].Influence != 0) { + short int curve = cc[i].Curve; + if (curve >= GetCurveCount()) curve = -1; + AddSmoothCC(cc[i].Controller, cc[i].Influence, curve, cc[i].Smooth); + } + } + } + + void CCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth) { + AddCC(Controller, Influence, Curve); + } + + int CCUnit::GetCurveCount() { + return pVoice->pRegion->GetInstrument()->curves.size(); + } + + ::sfz::Curve* CCUnit::GetCurve(int idx) { + return &pVoice->pRegion->GetInstrument()->curves[idx]; + } + + double CCUnit::GetSampleRate() { + return pVoice->GetSampleRate() / CONFIG_DEFAULT_SUBFRAGMENT_SIZE; + } + + void SmoothCCUnit::AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth) { + if (Smooth > 0) { + Smoothers[Controller].trigger(Smooth / 1000.0f, GetSampleRate()); + AddCC(Controller, Influence, Curve, &Smoothers[Controller]); + } else { + AddCC(Controller, Influence, Curve); } } @@ -244,11 +335,14 @@ EGv2Unit* eg = GetRack()->volEGs[i]; if (!eg->Active()) continue; vol += eg->GetLevel() * (eg->pEGInfo->amplitude / 100.0f); + } AmpLFOUnit* u = &(GetRack()->suAmpLFO); vol *= u->Active() ? ::sf2::ToRatio((u->GetLevel() * u->pLfoInfo->volume) * 10.0) : 1; + vol *= ::sf2::ToRatio(GetRack()->suVolOnCC.GetLevel() * 10.0); + return vol; } @@ -325,13 +419,15 @@ SfzSignalUnitRack::SfzSignalUnitRack(Voice* voice) : SignalUnitRack(MaxUnitCount), pVoice(voice), suEndpoint(this), suVolEG(this), suFilEG(this), suPitchEG(this), - EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), + EGs(maxEgCount), volEGs(maxEgCount), pitchEGs(maxEgCount), suVolOnCC(this), suAmpLFO(this), suPitchLFO(this), suFilLFO(this), LFOs(maxLfoCount), pitchLFOs(maxLfoCount), filLFOs(maxLfoCount), resLFOs(maxLfoCount), panLFOs(maxLfoCount) { suEndpoint.pVoice = suVolEG.pVoice = suFilEG.pVoice = suPitchEG.pVoice = voice; - suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = voice; - suPitchLFO.suDepthCC.pVoice = voice; + suAmpLFO.pVoice = suPitchLFO.pVoice = suFilLFO.pVoice = suVolOnCC.pVoice = voice; + suPitchLFO.suDepthCC.pVoice = suPitchLFO.suFadeEG.pVoice = suPitchLFO.suFreqOnCC.pVoice = voice; + suFilLFO.suFadeEG.pVoice = suFilLFO.suFreqOnCC.pVoice = voice; + suAmpLFO.suFadeEG.pVoice = suAmpLFO.suFreqOnCC.pVoice = voice; for (int i = 0; i < EGs.capacity(); i++) { EGs[i] = new EGv2Unit(this); @@ -341,7 +437,9 @@ for (int i = 0; i < LFOs.capacity(); i++) { LFOs[i] = new LFOv2Unit(this); LFOs[i]->pVoice = voice; + LFOs[i]->suFadeEG.pVoice = voice; LFOs[i]->suPitchOnCC.pVoice = voice; + LFOs[i]->suFreqOnCC.pVoice = voice; } } @@ -368,6 +466,8 @@ ::sfz::Region* const pRegion = pVoice->pRegion; + suVolOnCC.SetCCs(pRegion->volume_oncc); + for (int i = 0; i < pRegion->eg.size(); i++) { if (pRegion->eg[i].node.size() == 0) continue; @@ -397,6 +497,7 @@ lfo.pLfoInfo = &(pRegion->lfos[i]); LFOs.increment()->Copy(lfo); LFOs[LFOs.size() - 1]->suPitchOnCC.SetCCs(pRegion->lfos[i].pitch_oncc); + LFOs[LFOs.size() - 1]->suFreqOnCC.SetCCs(pRegion->lfos[i].freq_oncc); } else { std::cerr << "Maximum number of LFOs reached!" << std::endl; break; } if (pRegion->lfos[i].pitch != 0 || !pRegion->lfos[i].pitch_oncc.empty()) { @@ -421,23 +522,41 @@ } suPitchLFO.suDepthCC.SetCCs(pRegion->pitchlfo_depthcc); + suPitchLFO.suFreqOnCC.SetCCs(pRegion->pitchlfo_freqcc); + + suFilLFO.suFreqOnCC.SetCCs(pRegion->fillfo_freqcc); + + suAmpLFO.suFreqOnCC.SetCCs(pRegion->amplfo_freqcc); Units.clear(); + Units.add(&suVolOnCC); + Units.add(&suVolEG); Units.add(&suFilEG); Units.add(&suPitchEG); + + Units.add(&suPitchLFO.suFreqOnCC); // Don't change order! (should be triggered before the LFO) Units.add(&suPitchLFO); Units.add(&suPitchLFO.suDepthCC); + Units.add(&suPitchLFO.suFadeEG); + + Units.add(&suAmpLFO.suFreqOnCC); // Don't change order! (should be triggered before the LFO) Units.add(&suAmpLFO); + Units.add(&suAmpLFO.suFadeEG); + + Units.add(&suFilLFO.suFreqOnCC); // Don't change order! (should be triggered before the LFO) Units.add(&suFilLFO); + Units.add(&suFilLFO.suFadeEG); for (int i = 0; i < EGs.size(); i++) { Units.add(EGs[i]); } for (int i = 0; i < LFOs.size(); i++) { + Units.add(&(LFOs[i]->suFreqOnCC)); // Don't change order! (should be triggered before the LFO) Units.add(LFOs[i]); + Units.add(&(LFOs[i]->suFadeEG)); Units.add(&(LFOs[i]->suPitchOnCC)); }