--- linuxsampler/trunk/src/engines/sfz/SfzSignalUnitRack.h 2011/07/28 18:24:12 2222 +++ linuxsampler/trunk/src/engines/sfz/SfzSignalUnitRack.h 2011/12/08 20:03:47 2296 @@ -27,11 +27,14 @@ #include "EG.h" #include "EGADSR.h" #include "../common/AbstractVoice.h" +#include "../common/PulseLFO.h" +#include "../common/SawLFO.h" +#include "../common/SineLFO.h" namespace LinuxSampler { namespace sfz { - const int MaxUnitCount = 1000; - const int maxEgCount = 100; // Maximum number of v2 envelope generators - const int maxLfoCount = 100; // Maximum number of v2 LFOs + const int MaxUnitCount = 200; + const int maxEgCount = 30; // Maximum number of v2 envelope generators + const int maxLfoCount = 30; // Maximum number of v2 LFOs class Voice; class SfzSignalUnitRack; @@ -50,8 +53,75 @@ } double GetSampleRate(); + float GetInfluence(ArrayList< ::sfz::CC>& cc); }; + + class CCUnit: public CCSignalUnit { + public: + Voice* pVoice; + + CCUnit(SfzSignalUnitRack* rack, Listener* l = NULL); + + virtual void Trigger(); + + void SetCCs(::sfz::Array& pCC); + void SetCCs(::sfz::Array& pCC); + void SetCCs(ArrayList< ::sfz::CC>& cc); + + virtual void AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth, float Step); + + int GetCurveCount(); + ::sfz::Curve* GetCurve(int idx); + + double GetSampleRate(); + }; + + class CurveCCUnit: public CCUnit { + public: + CurveCCUnit(SfzSignalUnitRack* rack, Listener* l = NULL): CCUnit(rack, l) { } + + virtual float Normalize(uint8_t val, short int curve = -1) { + if (curve == -1) return val / 127.0f; + return GetCurve(curve)->v[val]; + } + }; + + + + class SmoothCCUnit: public CurveCCUnit { + protected: + RTList* pSmoothers; + public: + SmoothCCUnit(SfzSignalUnitRack* rack, Listener* l = NULL): CurveCCUnit(rack, l), pSmoothers(NULL) { } + virtual ~SmoothCCUnit(); + + virtual void AddSmoothCC(uint8_t Controller, float Influence, short int Curve, float Smooth, float Step); + virtual void RemoveAllCCs() { CurveCCUnit::RemoveAllCCs(); pSmoothers->clear(); } + virtual void InitCCList(Pool* pCCPool, Pool* pSmootherPool); + + void InitSmoothers(Pool* pSmootherPool); + }; + + + class XFInCCUnit: public CCUnit { + public: + XFInCCUnit(SfzSignalUnitRack* rack, Listener* l = NULL): CCUnit(rack, l) { } + + virtual bool Active() { return !pCtrls->isEmpty(); } + virtual void Calculate(); + virtual void SetCrossFadeCCs(::sfz::Array& loCCs, ::sfz::Array& hiCCs); + }; + + + class XFOutCCUnit: public XFInCCUnit { + public: + XFOutCCUnit(SfzSignalUnitRack* rack, Listener* l = NULL): XFInCCUnit(rack, l) { } + + virtual void Calculate(); + }; + + template class EGUnit: public SfzSignalUnit { public: @@ -106,12 +176,20 @@ public: int depth; EGv1Unit(SfzSignalUnitRack* rack): EGUnit(rack), depth(0) { } - virtual void Trigger(); }; class EGv2Unit: public EGUnit< ::LinuxSampler::sfz::EG> { + protected: + ::sfz::EG egInfo; public: - EGv2Unit(SfzSignalUnitRack* rack): EGUnit< ::LinuxSampler::sfz::EG>(rack) { } + CCUnit suAmpOnCC; + CCUnit suVolOnCC; + CCUnit suPitchOnCC; + CCUnit suCutoffOnCC; + CCUnit suResOnCC; + CurveCCUnit suPanOnCC; + + EGv2Unit(SfzSignalUnitRack* rack); virtual void Trigger(); }; @@ -127,41 +205,118 @@ virtual void Trigger(); }; - class LFOUnit: public SfzSignalUnit { + class AmpEGUnit: public EGv1Unit { public: - ::sfz::LFO* pLfoInfo; - LFOSigned lfo; + AmpEGUnit(SfzSignalUnitRack* rack): EGv1Unit(rack) { } + virtual void Trigger(); + }; + + class AbstractLfo { + public: + virtual float Render() = 0; + virtual void Update(const uint16_t& ExtControlValue) = 0; + virtual void Trigger(float Frequency, start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) = 0; + virtual void SetPhase(float phase) = 0; + virtual void SetFrequency(float Frequency, unsigned int SampleRate) = 0; + }; + + template + class LfoBase: public AbstractLfo, public T { + public: + LfoBase(float Max): T(Max) { } + virtual float Render() { return T::render(); } + + virtual void Update(const uint16_t& ExtControlValue) { T::update(ExtControlValue); } + + virtual void Trigger ( + float Frequency, start_level_t StartLevel, uint16_t InternalDepth, + uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate + ) { + T::trigger(Frequency, StartLevel, InternalDepth, ExtControlDepth, FlipPhase, SampleRate); + } - LFOUnit(SfzSignalUnitRack* rack): SfzSignalUnit(rack), pLfoInfo(NULL), lfo(1200.0f) { } - LFOUnit(const LFOUnit& Unit): SfzSignalUnit(Unit), lfo(1200.0f) { Copy(Unit); } + virtual void SetPhase(float phase) { T::setPhase(phase); } + + virtual void SetFrequency(float Frequency, unsigned int SampleRate) { + T::setFrequency(Frequency, SampleRate); + } + }; + + class LFOUnit; + + class FadeEGUnit: public EGUnit { + public: + FadeEGUnit(SfzSignalUnitRack* rack): EGUnit(rack) { } + virtual void Trigger() { } + virtual void EnterReleaseStage() { } + virtual void CancelRelease() { } + + friend class LFOUnit; + }; + + class LFOUnit: public SfzSignalUnit, public CCSignalUnit::Listener { + public: + ::sfz::LFO* pLfoInfo; + AbstractLfo* pLFO; + FadeEGUnit suFadeEG; + SmoothCCUnit suDepthOnCC; + SmoothCCUnit suFreqOnCC; + + LFOUnit(SfzSignalUnitRack* rack); + LFOUnit(const LFOUnit& Unit); void operator=(const LFOUnit& Unit) { Copy(Unit); } void Copy(const LFOUnit& Unit) { - pLfoInfo = Unit.pLfoInfo; + pLfoInfo = Unit.pLfoInfo; + suFadeEG = Unit.suFadeEG; SfzSignalUnit::Copy(Unit); } - virtual bool Active() { return true; } virtual void Trigger(); virtual void Increment(); virtual float GetLevel() { return Level; } + + // CCSignalUnit::Listener interface implementation + virtual void ValueChanged(CCSignalUnit* pUnit); }; class LFOv1Unit: public LFOUnit { public: ::sfz::LFO lfoInfo; + LfoBase lfo; - LFOv1Unit(SfzSignalUnitRack* rack): LFOUnit(rack) { pLfoInfo = &lfoInfo; } + LFOv1Unit(SfzSignalUnitRack* rack): LFOUnit(rack), lfo(1200.0f) { + pLfoInfo = &lfoInfo; pLFO = &lfo; + } virtual void Trigger(); }; class LFOv2Unit: public LFOUnit { + protected: + FixedArray lfos; + LfoBase lfo0; // triangle + LfoBase > lfo1; // sine + LfoBase > lfo2; // pulse 75% + LfoBase > lfo3; // square + LfoBase > lfo4; // pulse 25% + LfoBase > lfo5; // pulse 12,5% + LfoBase > lfo6; // saw up + LfoBase > lfo7; // saw down + + public: - LFOv2Unit(SfzSignalUnitRack* rack): LFOUnit(rack) { } + SmoothCCUnit suVolOnCC; + SmoothCCUnit suPitchOnCC; + SmoothCCUnit suPanOnCC; + SmoothCCUnit suCutoffOnCC; + SmoothCCUnit suResOnCC; + + LFOv2Unit(SfzSignalUnitRack* rack); virtual void Trigger(); + virtual bool Active() { return true; } }; class AmpLFOUnit: public LFOv1Unit { @@ -186,10 +341,16 @@ }; - - class EndpointUnit : public EndpointSignalUnit { + class EndpointUnit: public EndpointSignalUnit { + private: + float xfCoeff; // crossfade coefficient + float pitchVeltrackRatio; + public: Voice* pVoice; + XFInCCUnit suXFInCC; + XFOutCCUnit suXFOutCC; + SmoothCCUnit suPanOnCC; EndpointUnit(SfzSignalUnitRack* rack); @@ -209,13 +370,15 @@ virtual float CalculateResonance(float res) { return GetResonance() + res; } + + virtual float CalculateFilterCutoff(float cutoff); }; class SfzSignalUnitRack : public SignalUnitRack { private: EndpointUnit suEndpoint; - EGv1Unit suVolEG; + AmpEGUnit suVolEG; FilEGUnit suFilEG; PitchEGUnit suPitchEG; @@ -223,6 +386,25 @@ PitchLFOUnit suPitchLFO; FilLFOUnit suFilLFO; + CCUnit suEq1GainOnCC; + CCUnit suEq2GainOnCC; + CCUnit suEq3GainOnCC; + + CCUnit suEq1FreqOnCC; + CCUnit suEq2FreqOnCC; + CCUnit suEq3FreqOnCC; + + CCUnit suEq1BwOnCC; + CCUnit suEq2BwOnCC; + CCUnit suEq3BwOnCC; + + // SFZ v2 + + SmoothCCUnit suVolOnCC; + SmoothCCUnit suPitchOnCC; + SmoothCCUnit suCutoffOnCC; + SmoothCCUnit suResOnCC; + FixedArray EGs; // used for optimization - contains only the ones that are modulating volume @@ -231,9 +413,24 @@ // used for optimization - contains only the ones that are modulating pitch FixedArray pitchEGs; + // used for optimization - contains only the ones that are modulating filter cutoff + FixedArray filEGs; + + // used for optimization - contains only the ones that are modulating resonance + FixedArray resEGs; + + // used for optimization - contains only the ones that are modulating pitch + FixedArray panEGs; + FixedArray LFOs; + // used for optimization - contains only the ones that are modulating volume + FixedArray volLFOs; + + // used for optimization - contains only the ones that are modulating pitch + FixedArray pitchLFOs; + // used for optimization - contains only the ones that are modulating filter cutoff FixedArray filLFOs; @@ -258,6 +455,14 @@ virtual void Trigger(); virtual void EnterFadeOutStage(); + /** Called when the engine is set and the engine's pools are ready to use. */ + void InitRTLists(); + + /** Invoked when the voice gone inactive. */ + void Reset(); + + virtual void UpdateEqSettings(EqSupport* pEqSupport); + friend class EndpointUnit; }; }} // namespace LinuxSampler::sfz