Permalink
Cannot retrieve contributors at this time
| /* | |
| SuperCollider real time audio synthesis system | |
| Copyright (c) 2002 James McCartney. All rights reserved. | |
| http://www.audiosynth.com | |
| This program is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2 of the License, or | |
| (at your option) any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program; if not, write to the Free Software | |
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| */ | |
| #include "SC_PlugIn.h" | |
| #include <algorithm> /* for std::min and std::max */ | |
| #include <boost/align/is_aligned.hpp> | |
| #include "simd_peakmeter.hpp" | |
| #ifdef NOVA_SIMD | |
| # include "simd_memory.hpp" | |
| # include "function_attributes.h" | |
| #endif | |
| static InterfaceTable* ft; | |
| ////////////////////////////////////////////////////////////////////////////////////////////////// | |
| struct Trig1 : public Unit { | |
| float m_prevtrig; | |
| long mCounter; | |
| }; | |
| struct Trig : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| long mCounter; | |
| }; | |
| struct SendTrig : public Unit { | |
| float m_prevtrig; | |
| }; | |
| struct SendReply : public Unit { | |
| float m_prevtrig; | |
| int m_valueSize; | |
| int m_valueOffset; | |
| float* m_values; | |
| int m_cmdNameSize; | |
| char* m_cmdName; | |
| }; | |
| struct Poll : public Unit { | |
| int m_samplesRemain, m_intervalSamples; | |
| float m_trig; | |
| float m_lastPoll; | |
| char* m_id_string; | |
| bool m_mayprint; | |
| }; | |
| struct ToggleFF : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| }; | |
| struct SetResetFF : public Unit { | |
| float mLevel; | |
| float m_prevtrig, m_prevreset; | |
| }; | |
| struct Latch : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| }; | |
| struct Gate : public Unit { | |
| float mLevel; | |
| }; | |
| struct Schmidt : public Unit { | |
| float mLevel; | |
| }; | |
| struct PulseDivider : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| long mCounter; | |
| }; | |
| struct PulseCount : public Unit { | |
| float mLevel; | |
| float m_prevtrig, m_prevreset; | |
| }; | |
| struct Stepper : public Unit { | |
| float mLevel; | |
| float m_prevtrig, m_prevreset; | |
| }; | |
| struct TDelay : public Unit { | |
| long mCounter; | |
| float m_prevtrig; | |
| }; | |
| struct ZeroCrossing : public Unit { | |
| float mLevel, m_prevfrac, m_previn; | |
| int32 mCounter; | |
| }; | |
| struct Timer : public Unit { | |
| float mLevel, m_prevfrac, m_previn; | |
| int32 mCounter; | |
| }; | |
| struct Sweep : public Unit { | |
| double mLevel; | |
| float m_previn; | |
| }; | |
| struct Phasor : public Unit { | |
| double mLevel; | |
| float m_previn; | |
| }; | |
| struct Peak : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| }; | |
| struct RunningMin : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| }; | |
| struct RunningMax : public Unit { | |
| float mLevel; | |
| float m_prevtrig; | |
| }; | |
| struct PeakFollower : public Unit { | |
| float mLevel; | |
| float mDecay; | |
| }; | |
| struct MostChange : public Unit { | |
| float mPrevA, mPrevB; | |
| int mRecent; | |
| }; | |
| struct LeastChange : public Unit { | |
| float mPrevA, mPrevB; | |
| int mRecent; | |
| }; | |
| struct LastValue : public Unit { | |
| float mPrev; | |
| float mCurr; | |
| }; | |
| struct Done : public Unit { | |
| Unit* m_src; | |
| }; | |
| struct FreeSelf : public Unit { | |
| float m_prevtrig; | |
| }; | |
| struct PauseSelf : public Unit { | |
| float m_prevtrig; | |
| }; | |
| struct Pause : public Unit { | |
| int m_state; | |
| }; | |
| struct Free : public Unit { | |
| float m_prevtrig; | |
| }; | |
| struct FreeSelfWhenDone : public Unit { | |
| Unit* m_src; | |
| }; | |
| struct PauseSelfWhenDone : public Unit { | |
| Unit* m_src; | |
| }; | |
| extern "C" { | |
| void Trig1_Ctor(Trig1* unit); | |
| void Trig1_next(Trig1* unit, int inNumSamples); | |
| void Trig1_next_k(Trig1* unit, int inNumSamples); | |
| void Trig_Ctor(Trig* unit); | |
| void Trig_next(Trig* unit, int inNumSamples); | |
| void Trig_next_k(Trig* unit, int inNumSamples); | |
| void SendTrig_Ctor(SendTrig* unit); | |
| void SendTrig_next(SendTrig* unit, int inNumSamples); | |
| void SendTrig_next_aka(SendTrig* unit, int inNumSamples); | |
| void SendReply_Ctor(SendReply* unit); | |
| void SendReply_next(SendReply* unit, int inNumSamples); | |
| void SendReply_next_aka(SendReply* unit, int inNumSamples); | |
| void Poll_Ctor(Poll* unit); | |
| void Poll_next_aa(Poll* unit, int inNumSamples); | |
| void Poll_next_ak(Poll* unit, int inNumSamples); | |
| void Poll_next_kk(Poll* unit, int inNumSamples); | |
| void SetResetFF_Ctor(SetResetFF* unit); | |
| void SetResetFF_next_a(SetResetFF* unit, int inNumSamples); | |
| void SetResetFF_next_k(SetResetFF* unit, int inNumSamples); | |
| void ToggleFF_Ctor(ToggleFF* unit); | |
| void ToggleFF_next(ToggleFF* unit, int inNumSamples); | |
| void Latch_Ctor(Latch* unit); | |
| void Latch_next_ak(Latch* unit, int inNumSamples); | |
| void Latch_next_aa(Latch* unit, int inNumSamples); | |
| void Gate_Ctor(Gate* unit); | |
| void Gate_next_ak(Gate* unit, int inNumSamples); | |
| void Gate_next_aa(Gate* unit, int inNumSamples); | |
| void Schmidt_Ctor(Schmidt* unit); | |
| void Schmidt_next(Schmidt* unit, int inNumSamples); | |
| void PulseDivider_Ctor(PulseDivider* unit); | |
| void PulseDivider_next(PulseDivider* unit, int inNumSamples); | |
| void PulseCount_Ctor(PulseCount* unit); | |
| void PulseCount_next_a(PulseCount* unit, int inNumSamples); | |
| void PulseCount_next_k(PulseCount* unit, int inNumSamples); | |
| void PulseCount_next_0(PulseCount* unit, int inNumSamples); | |
| void Stepper_Ctor(Stepper* unit); | |
| void Stepper_next_aa(Stepper* unit, int inNumSamples); | |
| void Stepper_next_ak(Stepper* unit, int inNumSamples); | |
| void Stepper_next_a0(Stepper* unit, int inNumSamples); | |
| void TDelay_Ctor(TDelay* unit); | |
| void TDelay_next(TDelay* unit, int inNumSamples); | |
| void ZeroCrossing_Ctor(ZeroCrossing* unit); | |
| void ZeroCrossing_next_a(ZeroCrossing* unit, int inNumSamples); | |
| void Timer_Ctor(Timer* unit); | |
| void Timer_next_a(Timer* unit, int inNumSamples); | |
| void Sweep_Ctor(Sweep* unit); | |
| void Sweep_next_0k(Sweep* unit, int inNumSamples); | |
| void Sweep_next_0a(Sweep* unit, int inNumSamples); | |
| void Sweep_next_kk(Sweep* unit, int inNumSamples); | |
| void Sweep_next_ka(Sweep* unit, int inNumSamples); | |
| void Sweep_next_ak(Sweep* unit, int inNumSamples); | |
| void Sweep_next_aa(Sweep* unit, int inNumSamples); | |
| void Phasor_Ctor(Phasor* unit); | |
| void Phasor_next_kk(Phasor* unit, int inNumSamples); | |
| void Phasor_next_ak(Phasor* unit, int inNumSamples); | |
| void Phasor_next_aa(Phasor* unit, int inNumSamples); | |
| void Peak_Ctor(Peak* unit); | |
| void Peak_next_ak(Peak* unit, int inNumSamples); | |
| void Peak_next_ai(Peak* unit, int inNumSamples); | |
| void Peak_next_aa(Peak* unit, int inNumSamples); | |
| void Peak_next_ak_k(Peak* unit, int inNumSamples); | |
| void Peak_next_ai_k(Peak* unit, int inNumSamples); | |
| void Peak_next_aa_k(Peak* unit, int inNumSamples); | |
| void RunningMin_Ctor(RunningMin* unit); | |
| void RunningMin_next_ak(RunningMin* unit, int inNumSamples); | |
| void RunningMin_next_ai(RunningMin* unit, int inNumSamples); | |
| void RunningMin_next_aa(RunningMin* unit, int inNumSamples); | |
| void RunningMax_Ctor(RunningMax* unit); | |
| void RunningMax_next_ak(RunningMax* unit, int inNumSamples); | |
| void RunningMax_next_ai(RunningMax* unit, int inNumSamples); | |
| void RunningMax_next_aa(RunningMax* unit, int inNumSamples); | |
| void PeakFollower_Ctor(PeakFollower* unit); | |
| void PeakFollower_next(PeakFollower* unit, int inNumSamples); | |
| void PeakFollower_next_ai(PeakFollower* unit, int inNumSamples); | |
| void MostChange_Ctor(MostChange* unit); | |
| void MostChange_next_ak(MostChange* unit, int inNumSamples); | |
| void MostChange_next_ka(MostChange* unit, int inNumSamples); | |
| void MostChange_next_aa(MostChange* unit, int inNumSamples); | |
| void LeastChange_Ctor(LeastChange* unit); | |
| void LeastChange_next_ak(LeastChange* unit, int inNumSamples); | |
| void LeastChange_next_ka(LeastChange* unit, int inNumSamples); | |
| void LeastChange_next_aa(LeastChange* unit, int inNumSamples); | |
| void LastValue_Ctor(LastValue* unit); | |
| void LastValue_next_ak(LastValue* unit, int inNumSamples); | |
| void LastValue_next_kk(LastValue* unit, int inNumSamples); | |
| void Done_Ctor(Done* unit); | |
| void Done_next(Done* unit, int inNumSamples); | |
| void FreeSelf_Ctor(FreeSelf* unit); | |
| void FreeSelf_next(FreeSelf* unit, int inNumSamples); | |
| void FreeSelfWhenDone_Ctor(FreeSelfWhenDone* unit); | |
| void FreeSelfWhenDone_next(FreeSelfWhenDone* unit, int inNumSamples); | |
| void PauseSelf_Ctor(PauseSelf* unit); | |
| void PauseSelf_next(PauseSelf* unit, int inNumSamples); | |
| void Pause_Ctor(Pause* unit); | |
| void Pause_next(Pause* unit, int inNumSamples); | |
| void Free_Ctor(Free* unit); | |
| void Free_next(Free* unit, int inNumSamples); | |
| void PauseSelfWhenDone_Ctor(PauseSelfWhenDone* unit); | |
| void PauseSelfWhenDone_next(PauseSelfWhenDone* unit, int inNumSamples); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| #ifdef NOVA_SIMD | |
| FLATTEN void Trig1_next_nova(Trig1* unit, int inNumSamples); | |
| FLATTEN void Trig1_next_k_nova(Trig1* unit, int inNumSamples); | |
| #endif | |
| void Trig1_Ctor(Trig1* unit) { | |
| if (unit->mCalcRate == calc_FullRate && INRATE(0) != calc_FullRate) { | |
| #ifdef NOVA_SIMD | |
| if (boost::alignment::is_aligned(BUFLENGTH, 16)) | |
| SETCALC(Trig1_next_k_nova); | |
| else | |
| #endif | |
| SETCALC(Trig1_next_k); | |
| } else { | |
| #ifdef NOVA_SIMD | |
| if (boost::alignment::is_aligned(BUFLENGTH, 16)) | |
| SETCALC(Trig1_next_nova); | |
| else | |
| #endif | |
| SETCALC(Trig1_next); | |
| } | |
| unit->mCounter = 0; | |
| unit->m_prevtrig = 0.f; | |
| Trig1_next(unit, 1); | |
| } | |
| void Trig1_next(Trig1* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| unsigned long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float zout; if (counter > 0) { zout = --counter ? 1.f : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| zout = 1.f; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| } | |
| void Trig1_next_k(Trig1* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float curtrig = ZIN0(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| unsigned long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, float zout; if (counter > 0) { zout = --counter ? 1.f : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| zout = 1.f; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| } | |
| #ifdef NOVA_SIMD | |
| void Trig1_next_nova(Trig1* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| unsigned long counter = unit->mCounter; | |
| if (counter > inNumSamples) { | |
| nova::setvec_simd(OUT(0), 1.f, inNumSamples); | |
| counter -= inNumSamples; | |
| assert(counter > 0); | |
| prevtrig = IN(0)[inNumSamples - 1]; | |
| } else { | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float zout; | |
| if (counter > 0) { zout = --counter ? 1.f : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| zout = 1.f; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| } | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| } | |
| void Trig1_next_k_nova(Trig1* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float curtrig = ZIN0(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| unsigned long counter = unit->mCounter; | |
| if (counter > inNumSamples) { | |
| nova::setvec_simd(OUT(0), 1.f, inNumSamples); | |
| counter -= inNumSamples; | |
| assert(counter > 0); | |
| prevtrig = curtrig; | |
| } else if (counter == 0 && (curtrig <= 0.f || prevtrig > 0.f)) { | |
| nova::zerovec_simd(OUT(0), inNumSamples); | |
| prevtrig = curtrig; | |
| } else { | |
| LOOP1( | |
| inNumSamples, float zout; if (counter > 0) { zout = --counter ? 1.f : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| zout = 1.f; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| } | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| } | |
| #endif | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| #ifdef NOVA_SIMD | |
| void Trig_next_nova(Trig* unit, int inNumSamples); | |
| void Trig_next_k_nova(Trig* unit, int inNumSamples); | |
| #endif | |
| void Trig_Ctor(Trig* unit) { | |
| if (unit->mCalcRate == calc_FullRate && INRATE(0) != calc_FullRate) { | |
| #ifdef NOVA_SIMD | |
| if (boost::alignment::is_aligned(BUFLENGTH, 16)) | |
| SETCALC(Trig_next_k_nova); | |
| else | |
| #endif | |
| SETCALC(Trig_next_k); | |
| } else { | |
| #ifdef NOVA_SIMD | |
| if (boost::alignment::is_aligned(BUFLENGTH, 16)) | |
| SETCALC(Trig_next_nova); | |
| else | |
| #endif | |
| SETCALC(Trig_next); | |
| } | |
| unit->mCounter = 0; | |
| unit->m_prevtrig = 0.f; | |
| unit->mLevel = 0.f; | |
| Trig_next(unit, 1); | |
| } | |
| void Trig_next(Trig* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| unsigned long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float zout; if (counter > 0) { zout = --counter ? level : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| level = curtrig; | |
| zout = level; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| unit->mLevel = level; | |
| } | |
| void Trig_next_k(Trig* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float curtrig = ZIN0(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| unsigned long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, float zout; if (counter > 0) { zout = --counter ? level : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| level = curtrig; | |
| zout = level; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| unit->mLevel = level; | |
| } | |
| #ifdef NOVA_SIMD | |
| void Trig_next_nova(Trig* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| unsigned long counter = unit->mCounter; | |
| if (counter > inNumSamples) { | |
| nova::setvec_simd(OUT(0), level, inNumSamples); | |
| counter -= inNumSamples; | |
| assert(counter > 0); | |
| prevtrig = IN(0)[inNumSamples - 1]; | |
| } else { | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float zout; | |
| if (counter > 0) { zout = --counter ? level : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| level = curtrig; | |
| zout = level; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| } | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| unit->mLevel = level; | |
| } | |
| void Trig_next_k_nova(Trig* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float curtrig = ZIN0(0); | |
| float dur = ZIN0(1); | |
| float sr = unit->mRate->mSampleRate; | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| unsigned long counter = unit->mCounter; | |
| if (counter > inNumSamples) { | |
| nova::setvec_simd(OUT(0), level, inNumSamples); | |
| counter -= inNumSamples; | |
| assert(counter > 0); | |
| prevtrig = curtrig; | |
| } else if (counter == 0 && (curtrig <= 0.f || prevtrig > 0.f)) { | |
| nova::zerovec_simd(OUT(0), inNumSamples); | |
| prevtrig = curtrig; | |
| } else { | |
| LOOP1( | |
| inNumSamples, float zout; if (counter > 0) { zout = --counter ? level : 0.f; } else { | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| counter = (long)(dur * sr + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| level = curtrig; | |
| zout = level; | |
| } else { | |
| zout = 0.f; | |
| } | |
| } prevtrig = curtrig; | |
| ZXP(out) = zout;); | |
| } | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| unit->mLevel = level; | |
| } | |
| #endif | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void SendTrig_Ctor(SendTrig* unit) { | |
| if (INRATE(2) == calc_FullRate) { | |
| SETCALC(SendTrig_next_aka); | |
| } else { | |
| SETCALC(SendTrig_next); | |
| } | |
| unit->m_prevtrig = 0.f; | |
| } | |
| void SendTrig_next(SendTrig* unit, int inNumSamples) { | |
| float* trig = ZIN(0); | |
| float prevtrig = unit->m_prevtrig; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); if (curtrig > 0.f && prevtrig <= 0.f) { | |
| SendTrigger(&unit->mParent->mNode, (int)ZIN0(1), ZIN0(2)); | |
| } prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| void SendTrig_next_aka(SendTrig* unit, int inNumSamples) { | |
| float* trig = ZIN(0); | |
| int id = (int)ZIN0(1); | |
| float* value = ZIN(2); | |
| float prevtrig = unit->m_prevtrig; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float curval = ZXP(value); | |
| if (curtrig > 0.f && prevtrig <= 0.f) { SendTrigger(&unit->mParent->mNode, id, curval); } prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| static void Unit_next_nop(SendReply* unit, int inNumSamples) {} | |
| void SendReply_Ctor(SendReply* unit) { | |
| const int kVarOffset = 3; | |
| unit->m_prevtrig = 0.f; | |
| unit->m_cmdNameSize = IN0(2); | |
| unit->m_valueSize = unit->mNumInputs - unit->m_cmdNameSize - kVarOffset; | |
| unit->m_valueOffset = kVarOffset + unit->m_cmdNameSize; | |
| // allocations | |
| const int cmdNameAllocSize = (unit->m_cmdNameSize + 1) * sizeof(char); | |
| const int valuesAllocSize = unit->m_valueSize * sizeof(float); | |
| char* chunk = (char*)RTAlloc(unit->mWorld, cmdNameAllocSize + valuesAllocSize); | |
| if (!chunk) { | |
| Print("SendReply: RT memory allocation failed\n"); | |
| SETCALC(Unit_next_nop); | |
| return; | |
| } | |
| unit->m_cmdName = chunk; | |
| unit->m_values = (float*)(chunk + cmdNameAllocSize); | |
| for (int i = 0; i < (int)unit->m_cmdNameSize; i++) | |
| unit->m_cmdName[i] = (char)IN0(kVarOffset + i); | |
| // terminate string | |
| unit->m_cmdName[unit->m_cmdNameSize] = 0; | |
| if (INRATE(0) == calc_FullRate) | |
| SETCALC(SendReply_next_aka); | |
| else | |
| SETCALC(SendReply_next); | |
| } | |
| void SendReply_Dtor(SendReply* unit) { RTFree(unit->mWorld, unit->m_cmdName); } | |
| void SendReply_next(SendReply* unit, int inNumSamples) { | |
| float* trig = IN(0); | |
| float prevtrig = unit->m_prevtrig; | |
| float* values = unit->m_values; | |
| int valueSize = unit->m_valueSize; | |
| int valueOffset = unit->m_valueOffset; | |
| for (int j = 0; j < inNumSamples; j++) { | |
| float curtrig = trig[j]; | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| for (int i = 0; i < valueSize; i++) | |
| values[i] = IN(i + valueOffset)[0]; | |
| SendNodeReply(&unit->mParent->mNode, (int)ZIN0(1), unit->m_cmdName, unit->m_valueSize, values); | |
| } | |
| prevtrig = curtrig; | |
| } | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| void SendReply_next_aka(SendReply* unit, int inNumSamples) { | |
| float* trig = IN(0); | |
| float prevtrig = unit->m_prevtrig; | |
| float* values = unit->m_values; | |
| int valueSize = unit->m_valueSize; | |
| int valueOffset = unit->m_valueOffset; | |
| for (int j = 0; j < inNumSamples; j++) { | |
| float curtrig = trig[j]; | |
| if (curtrig > 0.f && prevtrig <= 0.f) { | |
| for (int i = 0; i < valueSize; i++) { | |
| int offset = INRATE(i + valueOffset) != calc_FullRate ? 0 : j; | |
| values[i] = IN(i + valueOffset)[offset]; | |
| } | |
| SendNodeReply(&unit->mParent->mNode, (int)ZIN0(1), unit->m_cmdName, unit->m_valueSize, values); | |
| } | |
| prevtrig = curtrig; | |
| } | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void Poll_Ctor(Poll* unit) { | |
| if (INRATE(0) == calc_FullRate) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Poll_next_aa); | |
| } else { | |
| SETCALC(Poll_next_ak); | |
| } | |
| } else { | |
| SETCALC(Poll_next_kk); | |
| } | |
| unit->m_trig = IN0(0); | |
| const int idSize = (int)IN0(3); // number of chars in the id string | |
| unit->m_id_string = (char*)RTAlloc(unit->mWorld, (idSize + 1) * sizeof(char)); | |
| if (!unit->m_id_string) { | |
| Print("Poll: RT memory allocation failed\n"); | |
| SETCALC(Unit_next_nop); | |
| return; | |
| } | |
| for (int i = 0; i < idSize; i++) | |
| unit->m_id_string[i] = (char)IN0(4 + i); | |
| unit->m_id_string[idSize] = '\0'; | |
| unit->m_mayprint = unit->mWorld->mVerbosity >= -1; | |
| Poll_next_kk(unit, 1); | |
| } | |
| void Poll_Dtor(Poll* unit) { RTFree(unit->mWorld, unit->m_id_string); } | |
| void Poll_next_aa(Poll* unit, int inNumSamples) { | |
| float* in = IN(1); | |
| float* trig = IN(0); | |
| float lasttrig = unit->m_trig; | |
| for (int i = 0; i < inNumSamples; i++) { | |
| if ((lasttrig <= 0.0) && (trig[i] > 0.0)) { | |
| if (unit->m_mayprint) | |
| Print("%s: %g\n", unit->m_id_string, in[i]); | |
| if (IN0(2) >= 0.0) | |
| SendTrigger(&unit->mParent->mNode, (int)IN0(2), in[i]); | |
| } | |
| lasttrig = trig[i]; | |
| } | |
| unit->m_trig = lasttrig; | |
| } | |
| void Poll_next_kk(Poll* unit, int inNumSamples) { | |
| float in = IN0(1); | |
| float trig = IN0(0); | |
| if ((unit->m_trig <= 0.0) && (trig > 0.0)) { | |
| if (unit->m_mayprint) | |
| Print("%s: %g\n", unit->m_id_string, in); | |
| if (IN0(2) >= 0.0) | |
| SendTrigger(&unit->mParent->mNode, (int)IN0(2), in); | |
| } | |
| unit->m_trig = trig; | |
| } | |
| void Poll_next_ak(Poll* unit, int inNumSamples) { | |
| float in = IN0(1); | |
| float* trig = IN(0); | |
| float lasttrig = unit->m_trig; | |
| for (int i = 0; i < inNumSamples; i++) { | |
| if ((lasttrig <= 0.0) && (trig[i] > 0.0)) { | |
| if (unit->m_mayprint) { | |
| Print("%s: %g\n", unit->m_id_string, in); | |
| } | |
| if (IN0(2) >= 0.0) | |
| SendTrigger(&unit->mParent->mNode, (int)IN0(2), in); | |
| } | |
| lasttrig = trig[i]; | |
| } | |
| unit->m_trig = lasttrig; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void SetResetFF_Ctor(SetResetFF* unit) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(SetResetFF_next_a); | |
| } else { | |
| SETCALC(SetResetFF_next_k); | |
| } | |
| unit->m_prevtrig = 0.f; | |
| unit->m_prevreset = 0.f; | |
| unit->mLevel = 0.f; | |
| SetResetFF_next_k(unit, 1); | |
| } | |
| void SetResetFF_next_a(SetResetFF* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float* reset = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float prevreset = unit->m_prevreset; | |
| float level = unit->mLevel; | |
| LOOP1(inNumSamples, float curtrig = ZXP(trig); float curreset = ZXP(reset); | |
| if (prevreset <= 0.f && curreset > 0.f) level = 0.f; else if (prevtrig <= 0.f && curtrig > 0.f) level = 1.f; | |
| ZXP(out) = level; prevtrig = curtrig; prevreset = curreset;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->m_prevreset = prevreset; | |
| unit->mLevel = level; | |
| } | |
| void SetResetFF_next_k(SetResetFF* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float curreset = ZIN0(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float prevreset = unit->m_prevreset; | |
| float level = unit->mLevel; | |
| float curtrig = ZXP(trig); | |
| if (prevreset <= 0.f && curreset > 0.f) | |
| level = 0.f; | |
| else if (prevtrig <= 0.f && curtrig > 0.f) | |
| level = 1.f; | |
| ZXP(out) = level; | |
| prevtrig = curtrig; | |
| LOOP(inNumSamples - 1, curtrig = ZXP(trig); if (prevtrig <= 0.f && curtrig > 0.f) level = 1.f; ZXP(out) = level; | |
| prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->m_prevreset = curreset; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void ToggleFF_Ctor(ToggleFF* unit) { | |
| SETCALC(ToggleFF_next); | |
| unit->m_prevtrig = 0.f; | |
| unit->mLevel = 0.f; | |
| ZOUT0(0) = 0.f; | |
| } | |
| void ToggleFF_next(ToggleFF* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1(inNumSamples, float curtrig = ZXP(trig); if (prevtrig <= 0.f && curtrig > 0.f) level = 1.f - level; | |
| ZXP(out) = level; prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| #ifdef NOVA_SIMD | |
| void Latch_next_ak_nova(Latch* unit, int inNumSamples) { | |
| float level = unit->mLevel; | |
| float curtrig = ZIN0(1); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = ZIN0(0); | |
| nova::setvec_simd(OUT(0), level, inNumSamples); | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void Latch_next_ak_nova_64(Latch* unit, int inNumSamples) { | |
| float level = unit->mLevel; | |
| float curtrig = ZIN0(1); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = ZIN0(0); | |
| nova::setvec_simd<64>(OUT(0), level); | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| #endif | |
| void Latch_Ctor(Latch* unit) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Latch_next_aa); | |
| } else { | |
| #ifdef NOVA_SIMD | |
| if (BUFLENGTH == 64) | |
| SETCALC(Latch_next_ak_nova_64); | |
| if (boost::alignment::is_aligned(BUFLENGTH, 16)) | |
| SETCALC(Latch_next_ak_nova); | |
| else | |
| #endif | |
| SETCALC(Latch_next_ak); | |
| } | |
| unit->m_prevtrig = 0.f; | |
| unit->mLevel = 0.f; | |
| ZOUT0(0) = ZIN0(1) > 0.f ? ZIN0(0) : 0.f; | |
| } | |
| void Latch_next_ak(Latch* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float level = unit->mLevel; | |
| float curtrig = ZIN0(1); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = ZIN0(0); | |
| LOOP1(inNumSamples, ZXP(out) = level;); | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void Latch_next_aa(Latch* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); if (prevtrig <= 0.f && curtrig > 0.f) level = ZXP(in); | |
| else { PZ(in); } ZXP(out) = level; prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| #ifdef NOVA_SIMD | |
| FLATTEN void Gate_next_ak_nova(Gate* unit, int inNumSamples) { | |
| float* trig = ZIN(1); | |
| float level = unit->mLevel; | |
| float curtrig = ZXP(trig); | |
| if (curtrig > 0.f) { | |
| nova::copyvec_simd(OUT(0), IN(0), inNumSamples); | |
| unit->mLevel = IN(0)[inNumSamples - 1]; | |
| } else | |
| nova::setvec_simd(OUT(0), level, inNumSamples); | |
| } | |
| FLATTEN void Gate_next_ak_nova_64(Gate* unit, int inNumSamples) { | |
| float* trig = ZIN(1); | |
| float level = unit->mLevel; | |
| float curtrig = ZXP(trig); | |
| if (curtrig > 0.f) { | |
| nova::copyvec_simd<64>(OUT(0), IN(0)); | |
| unit->mLevel = IN(0)[inNumSamples - 1]; | |
| } else | |
| nova::setvec_simd<64>(OUT(0), level); | |
| } | |
| #endif | |
| void Gate_Ctor(Gate* unit) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Gate_next_aa); | |
| } else { | |
| #ifdef NOVA_SIMD | |
| if (BUFLENGTH == 64) | |
| SETCALC(Gate_next_ak_nova_64); | |
| if (boost::alignment::is_aligned(BUFLENGTH, 16)) | |
| SETCALC(Gate_next_ak_nova); | |
| else | |
| #endif | |
| SETCALC(Gate_next_ak); | |
| } | |
| unit->mLevel = 0.f; | |
| Gate_next_ak(unit, 1); | |
| } | |
| void Gate_next_ak(Gate* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float level = unit->mLevel; | |
| float curtrig = ZXP(trig); | |
| if (curtrig > 0.f) { | |
| LOOP1(inNumSamples, level = ZXP(in); ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } else { | |
| LOOP1(inNumSamples, ZXP(out) = level;); | |
| } | |
| } | |
| void Gate_next_aa(Gate* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); if (curtrig > 0.f) level = ZXP(in); | |
| else { PZ(in); } ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void Schmidt_Ctor(Schmidt* unit) { | |
| SETCALC(Schmidt_next); | |
| unit->mLevel = 0.f; | |
| Schmidt_next(unit, 1); | |
| } | |
| void Schmidt_next(Schmidt* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float lo = ZIN0(1); | |
| float hi = ZIN0(2); | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float zin = ZXP(in); if (level == 1.) { | |
| if (zin < lo) | |
| level = 0.f; | |
| } else { | |
| if (zin > hi) | |
| level = 1.f; | |
| } ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void PulseDivider_Ctor(PulseDivider* unit) { | |
| SETCALC(PulseDivider_next); | |
| unit->m_prevtrig = 0.f; | |
| unit->mLevel = 0.f; | |
| unit->mCounter = (long)floor(ZIN0(2) + 0.5); | |
| PulseDivider_next(unit, 1); | |
| } | |
| void PulseDivider_next(PulseDivider* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| long div = (long)ZIN0(1); | |
| float prevtrig = unit->m_prevtrig; | |
| long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, float z; float curtrig = ZXP(trig); if (prevtrig <= 0.f && curtrig > 0.f) { | |
| counter++; | |
| if (counter >= div) { | |
| counter = 0; | |
| z = 1.f; | |
| } else { | |
| z = 0.f; | |
| } | |
| } else { z = 0.f; } ZXP(out) = z; | |
| prevtrig = curtrig;); | |
| unit->mCounter = counter; | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void PulseCount_Ctor(PulseCount* unit) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(PulseCount_next_a); | |
| } else if (INRATE(1) == calc_BufRate) { | |
| SETCALC(PulseCount_next_k); | |
| } else { | |
| SETCALC(PulseCount_next_0); | |
| } | |
| unit->m_prevtrig = 0.f; | |
| unit->m_prevreset = 0.f; | |
| unit->mLevel = 0.f; | |
| PulseCount_next_k(unit, 1); | |
| } | |
| void PulseCount_next_a(PulseCount* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float* reset = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float prevreset = unit->m_prevreset; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float curreset = ZXP(reset); | |
| if (prevreset <= 0.f && curreset > 0.f) level = 0.f; | |
| else if (prevtrig <= 0.f && curtrig > 0.f) { level += 1.f; } ZXP(out) = level; prevtrig = curtrig; | |
| prevreset = curreset;); | |
| unit->mLevel = level; | |
| unit->m_prevtrig = prevtrig; | |
| unit->m_prevreset = prevreset; | |
| } | |
| void PulseCount_next_k(PulseCount* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float curreset = ZIN0(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float prevreset = unit->m_prevreset; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); if (prevreset <= 0.f && curreset > 0.f) level = 0.f; | |
| else if (prevtrig <= 0.f && curtrig > 0.f) { level += 1.f; } ZXP(out) = level; prevtrig = curtrig; | |
| prevreset = curreset;); | |
| unit->mLevel = level; | |
| unit->m_prevtrig = prevtrig; | |
| unit->m_prevreset = prevreset; | |
| } | |
| void PulseCount_next_0(PulseCount* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); | |
| if (prevtrig <= 0.f && curtrig > 0.f) { level += 1.f; } ZXP(out) = level; prevtrig = curtrig;); | |
| unit->mLevel = level; | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void Stepper_Ctor(Stepper* unit) { | |
| if (unit->mCalcRate == calc_FullRate && INRATE(0) == calc_FullRate && INRATE(1) == calc_ScalarRate) { | |
| SETCALC(Stepper_next_a0); | |
| } else if (unit->mCalcRate == calc_FullRate && INRATE(0) == calc_FullRate && INRATE(1) != calc_FullRate) { | |
| SETCALC(Stepper_next_ak); | |
| } else { | |
| SETCALC(Stepper_next_aa); | |
| } | |
| int32 resetval = (int32)ZIN0(5); | |
| unit->m_prevtrig = 0.f; | |
| unit->m_prevreset = 0.f; | |
| unit->mLevel = (float)resetval; | |
| Stepper_next_ak(unit, 1); | |
| } | |
| void Stepper_next_aa(Stepper* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float* reset = ZIN(1); | |
| int32 zmin = (int32)ZIN0(2); | |
| int32 zmax = (int32)ZIN0(3); | |
| int32 step = (int32)ZIN0(4); | |
| int32 resetval = (int32)ZIN0(5); | |
| float prevtrig = unit->m_prevtrig; | |
| float prevreset = unit->m_prevreset; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float curreset = ZXP(reset); if (prevreset <= 0.f && curreset > 0.f) { | |
| level = (float)sc_wrap(resetval, zmin, zmax); | |
| } else if (prevtrig <= 0.f && curtrig > 0.f) { | |
| level = (float)sc_wrap((int32)level + step, zmin, zmax); | |
| } ZXP(out) = level; | |
| prevtrig = curtrig; prevreset = curreset;); | |
| unit->mLevel = level; | |
| unit->m_prevtrig = prevtrig; | |
| unit->m_prevreset = prevreset; | |
| } | |
| void Stepper_next_ak(Stepper* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float curreset = ZIN0(1); | |
| int32 zmin = (int32)ZIN0(2); | |
| int32 zmax = (int32)ZIN0(3); | |
| int32 step = (int32)ZIN0(4); | |
| int32 resetval = (int32)ZIN0(5); | |
| float prevtrig = unit->m_prevtrig; | |
| float prevreset = unit->m_prevreset; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); if (prevreset <= 0.f && curreset > 0.f) { | |
| level = (float)sc_wrap(resetval, zmin, zmax); | |
| } else if (prevtrig <= 0.f && curtrig > 0.f) { | |
| level = (float)sc_wrap((int32)level + step, zmin, zmax); | |
| } ZXP(out) = level; | |
| prevtrig = curtrig; prevreset = curreset;); | |
| unit->mLevel = level; | |
| unit->m_prevtrig = prevtrig; | |
| unit->m_prevreset = prevreset; | |
| } | |
| void Stepper_next_a0(Stepper* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| int32 zmin = (int32)ZIN0(2); | |
| int32 zmax = (int32)ZIN0(3); | |
| int32 step = (int32)ZIN0(4); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); if (prevtrig <= 0.f && curtrig > 0.f) { | |
| level = (float)sc_wrap((int32)level + step, zmin, zmax); | |
| } ZXP(out) = level; | |
| prevtrig = curtrig;); | |
| unit->mLevel = level; | |
| unit->m_prevtrig = prevtrig; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void TDelay_Ctor(TDelay* unit) { | |
| SETCALC(TDelay_next); | |
| unit->m_prevtrig = 0.f; | |
| unit->mCounter = 0; | |
| TDelay_next(unit, 1); | |
| } | |
| void TDelay_next(TDelay* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* trig = ZIN(0); | |
| float dur = ZIN0(1); | |
| float prevtrig = unit->m_prevtrig; | |
| long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float zout; if (counter > 1) { | |
| counter--; | |
| zout = 0.f; | |
| } else if (counter <= 0) { | |
| if (prevtrig <= 0.f && curtrig > 0.f) { | |
| counter = (long)(dur * unit->mRate->mSampleRate + .5f); | |
| if (counter < 1) | |
| counter = 1; | |
| } | |
| zout = 0.f; | |
| } else { | |
| counter = 0; | |
| zout = 1.f; | |
| } ZXP(out) = zout; | |
| prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mCounter = counter; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void ZeroCrossing_Ctor(ZeroCrossing* unit) { | |
| SETCALC(ZeroCrossing_next_a); | |
| unit->m_prevfrac = 0.f; | |
| unit->m_previn = ZIN0(0); | |
| ZOUT0(0) = unit->mLevel = 0.f; | |
| unit->mCounter = 0; | |
| } | |
| void ZeroCrossing_next_a(ZeroCrossing* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float previn = unit->m_previn; | |
| float prevfrac = unit->m_prevfrac; | |
| float level = unit->mLevel; | |
| long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, counter++; float curin = ZXP(in); if (counter > 4 && previn <= 0.f && curin > 0.f) { | |
| float frac = -previn / (curin - previn); | |
| level = unit->mRate->mSampleRate / (frac + counter - prevfrac); | |
| prevfrac = frac; | |
| counter = 0; | |
| } ZXP(out) = level; | |
| previn = curin;); | |
| unit->m_previn = previn; | |
| unit->m_prevfrac = prevfrac; | |
| unit->mLevel = level; | |
| unit->mCounter = counter; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void Timer_Ctor(Timer* unit) { | |
| SETCALC(Timer_next_a); | |
| unit->m_prevfrac = 0.f; | |
| unit->m_previn = ZIN0(0); | |
| ZOUT0(0) = unit->mLevel = 0.f; | |
| unit->mCounter = 0; | |
| } | |
| void Timer_next_a(Timer* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float previn = unit->m_previn; | |
| float prevfrac = unit->m_prevfrac; | |
| float level = unit->mLevel; | |
| long counter = unit->mCounter; | |
| LOOP1( | |
| inNumSamples, counter++; float curin = ZXP(in); if (previn <= 0.f && curin > 0.f) { | |
| float frac = -previn / (curin - previn); | |
| level = unit->mRate->mSampleDur * (frac + counter - prevfrac); | |
| prevfrac = frac; | |
| counter = 0; | |
| } ZXP(out) = level; | |
| previn = curin;); | |
| unit->m_previn = previn; | |
| unit->m_prevfrac = prevfrac; | |
| unit->mLevel = level; | |
| unit->mCounter = counter; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void Sweep_Ctor(Sweep* unit) { | |
| if (INRATE(0) == calc_ScalarRate) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Sweep_next_0a); | |
| } else { | |
| SETCALC(Sweep_next_0k); | |
| } | |
| } else if (INRATE(0) == calc_BufRate) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Sweep_next_ka); | |
| } else { | |
| SETCALC(Sweep_next_kk); | |
| } | |
| } else { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Sweep_next_aa); | |
| } else { | |
| SETCALC(Sweep_next_ak); | |
| } | |
| } | |
| unit->m_previn = ZIN0(0); | |
| ZOUT0(0) = unit->mLevel = 0.f; | |
| } | |
| void Sweep_next_0k(Sweep* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| double rate = ZIN0(1) * SAMPLEDUR; | |
| double level = unit->mLevel; | |
| LOOP1(inNumSamples, level += rate; ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| void Sweep_next_0a(Sweep* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* rate = ZIN(1); | |
| double level = unit->mLevel; | |
| float sampledur = SAMPLEDUR; | |
| LOOP1(inNumSamples, float zrate = ZXP(rate) * sampledur; level += zrate; ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| void Sweep_next_kk(Sweep* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float curin = ZIN0(0); | |
| double rate = ZIN0(1) * SAMPLEDUR; | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| if (previn <= 0.f && curin > 0.f) { | |
| float frac = -previn / (curin - previn); | |
| level = frac * rate; | |
| } | |
| LOOP1(inNumSamples, level += rate; ZXP(out) = level;); | |
| unit->m_previn = curin; | |
| unit->mLevel = level; | |
| } | |
| void Sweep_next_ka(Sweep* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float curin = ZIN0(0); | |
| float* rate = ZIN(1); | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| float sampledur = SAMPLEDUR; | |
| if (previn <= 0.f && curin > 0.f) { | |
| float frac = -previn / (curin - previn); | |
| level = frac * rate[ZOFF] * sampledur; | |
| } | |
| LOOP1(inNumSamples, float zrate = ZXP(rate) * sampledur; level += zrate; ZXP(out) = level;); | |
| unit->m_previn = curin; | |
| unit->mLevel = level; | |
| } | |
| void Sweep_next_ak(Sweep* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| double rate = ZIN0(1) * SAMPLEDUR; | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curin = ZXP(in); if (previn <= 0.f && curin > 0.f) { | |
| float frac = -previn / (curin - previn); | |
| level = frac * rate; | |
| } else { level += rate; } ZXP(out) = level; | |
| previn = curin;); | |
| unit->m_previn = previn; | |
| unit->mLevel = level; | |
| } | |
| void Sweep_next_aa(Sweep* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* rate = ZIN(1); | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| float sampledur = SAMPLEDUR; | |
| LOOP1( | |
| inNumSamples, float curin = ZXP(in); float zrate = ZXP(rate) * sampledur; if (previn <= 0.f && curin > 0.f) { | |
| float frac = -previn / (curin - previn); | |
| level = frac * zrate; | |
| } else { level += zrate; } ZXP(out) = level; | |
| previn = curin;); | |
| unit->m_previn = previn; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void Phasor_Ctor(Phasor* unit) { | |
| if (unit->mCalcRate == calc_FullRate) { | |
| if (INRATE(0) == calc_FullRate) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Phasor_next_aa); | |
| } else { | |
| SETCALC(Phasor_next_ak); | |
| } | |
| } else { | |
| SETCALC(Phasor_next_kk); | |
| } | |
| } else { | |
| SETCALC(Phasor_next_ak); | |
| } | |
| unit->m_previn = ZIN0(0); | |
| ZOUT0(0) = unit->mLevel = ZIN0(2); | |
| } | |
| void Phasor_next_kk(Phasor* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float in = ZIN0(0); | |
| double rate = ZIN0(1); | |
| double start = ZIN0(2); | |
| double end = ZIN0(3); | |
| float resetPos = ZIN0(4); | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| if (previn <= 0.f && in > 0.f) { | |
| level = resetPos; | |
| } | |
| LOOP1(inNumSamples, level = sc_wrap(level, start, end); ZXP(out) = level; level += rate;); | |
| unit->m_previn = in; | |
| unit->mLevel = level; | |
| } | |
| void Phasor_next_ak(Phasor* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| double rate = ZIN0(1); | |
| double start = ZIN0(2); | |
| double end = ZIN0(3); | |
| float resetPos = ZIN0(4); | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curin = ZXP(in); if (previn <= 0.f && curin > 0.f) { | |
| float frac = 1.f - previn / (curin - previn); | |
| level = resetPos + frac * rate; | |
| } ZXP(out) = level; | |
| level += rate; level = sc_wrap(level, start, end); | |
| previn = curin;); | |
| unit->m_previn = previn; | |
| unit->mLevel = level; | |
| } | |
| void Phasor_next_aa(Phasor* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* rate = ZIN(1); | |
| double start = ZIN0(2); | |
| double end = ZIN0(3); | |
| float resetPos = ZIN0(4); | |
| float previn = unit->m_previn; | |
| double level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float curin = ZXP(in); double zrate = ZXP(rate); if (previn <= 0.f && curin > 0.f) { | |
| float frac = 1.f - previn / (curin - previn); | |
| level = resetPos + frac * zrate; | |
| } ZXP(out) = level; | |
| level += zrate; level = sc_wrap(level, start, end); previn = curin;); | |
| unit->m_previn = previn; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void Peak_next_ak_unroll(Peak* unit, int inNumSamples); | |
| void Peak_next_ai_unroll(Peak* unit, int inNumSamples); | |
| #ifdef NOVA_SIMD | |
| FLATTEN void Peak_next_ak_k_nova(Peak* unit, int inNumSamples); | |
| FLATTEN void Peak_next_ai_k_nova(Peak* unit, int inNumSamples); | |
| #endif | |
| void Peak_Ctor(Peak* unit) { | |
| if (BUFLENGTH == 1 && INRATE(0) == calc_FullRate) { | |
| /* audio-rate input with control-rate output */ | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Peak_next_aa_k); | |
| } else if (INRATE(1) == calc_ScalarRate) { | |
| #ifdef NOVA_SIMD | |
| if (INBUFLENGTH(0) & 7) | |
| SETCALC(Peak_next_ai_k); | |
| else | |
| SETCALC(Peak_next_ai_k_nova); | |
| #else | |
| SETCALC(Peak_next_ai_k); | |
| #endif | |
| } else { | |
| #ifdef NOVA_SIMD | |
| if (INBUFLENGTH(0) & 7) | |
| SETCALC(Peak_next_ak_k); | |
| else | |
| SETCALC(Peak_next_ak_k_nova); | |
| #else | |
| SETCALC(Peak_next_ak_k); | |
| #endif | |
| } | |
| } else { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(Peak_next_aa); | |
| } else if (INRATE(1) == calc_ScalarRate) { | |
| if (BUFLENGTH & 15) | |
| SETCALC(Peak_next_ai); | |
| else | |
| SETCALC(Peak_next_ai_unroll); | |
| } else { | |
| if (BUFLENGTH & 15) | |
| SETCALC(Peak_next_ak); | |
| else | |
| SETCALC(Peak_next_ak_unroll); | |
| } | |
| } | |
| unit->m_prevtrig = 0.f; | |
| ZOUT0(0) = unit->mLevel = ZIN0(0); | |
| } | |
| void Peak_next_ak(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float curtrig = ZIN0(1); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| LOOP1(inNumSamples, inlevel = std::abs(ZXP(in)); level = std::max(inlevel, level); ZXP(out) = level;); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = inlevel; | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_ai(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| LOOP1(inNumSamples, inlevel = std::abs(ZXP(in)); level = std::max(inlevel, level); ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_aa(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1(inNumSamples, float curtrig = ZXP(trig); float inlevel = std::abs(ZXP(in)); level = std::max(inlevel, level); | |
| ZXP(out) = level; if (prevtrig <= 0.f && curtrig > 0.f) level = inlevel; prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mLevel = level; | |
| } | |
| static inline float Peak_unroll_body(Peak* unit, int inNumSamples, float& level) { | |
| float* out = OUT(0); | |
| float* in = IN(0); | |
| float inlevel; | |
| using namespace std; | |
| for (int i = 0; i != inNumSamples; i += 8, out += 8, in += 8) { | |
| float level0 = max(abs(in[0]), level); | |
| float level1 = max(abs(in[1]), level0); | |
| float level2 = max(abs(in[2]), level1); | |
| float level3 = max(abs(in[3]), level2); | |
| float level4 = max(abs(in[4]), level3); | |
| float level5 = max(abs(in[5]), level4); | |
| float level6 = max(abs(in[6]), level5); | |
| inlevel = abs(in[7]); | |
| float level7 = max(inlevel, level6); | |
| out[0] = level0; | |
| out[1] = level1; | |
| out[2] = level2; | |
| out[3] = level3; | |
| out[4] = level4; | |
| out[5] = level5; | |
| out[6] = level6; | |
| out[7] = level7; | |
| level = level7; | |
| } | |
| return inlevel; /* input level of the last sample */ | |
| } | |
| void Peak_next_ak_unroll(Peak* unit, int inNumSamples) { | |
| float curtrig = ZIN0(1); | |
| float level = unit->mLevel; | |
| float inlevel = Peak_unroll_body(unit, inNumSamples, level); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = inlevel; | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_ai_unroll(Peak* unit, int inNumSamples) { | |
| float level = unit->mLevel; | |
| Peak_unroll_body(unit, inNumSamples, level); | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_ak_k(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float curtrig = ZIN0(1); | |
| float level; | |
| inNumSamples = INBUFLENGTH(0); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) { | |
| level = std::abs(ZXP(in)); | |
| inNumSamples -= 1; | |
| } else | |
| level = unit->mLevel; | |
| LOOP1(inNumSamples, level = std::max(std::abs(ZXP(in)), level);); | |
| ZXP(out) = level; | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_ai_k(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float level = unit->mLevel; | |
| inNumSamples = INBUFLENGTH(0); | |
| LOOP1(inNumSamples, level = std::max(std::abs(ZXP(in)), level);); | |
| ZXP(out) = level; | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_aa_k(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| float out_level; | |
| bool triggered = false; | |
| inNumSamples = INBUFLENGTH(0); | |
| LOOP1( | |
| inNumSamples, float curtrig = ZXP(trig); float inlevel = std::abs(ZXP(in)); level = std::max(inlevel, level); | |
| if (prevtrig <= 0.f && curtrig > 0.f) { | |
| triggered = true; | |
| out_level = level; | |
| level = inlevel; | |
| } prevtrig = curtrig;); | |
| if (triggered) | |
| ZXP(out) = out_level; | |
| else | |
| ZXP(out) = level; | |
| unit->m_prevtrig = prevtrig; | |
| unit->mLevel = level; | |
| } | |
| #ifdef NOVA_SIMD | |
| void Peak_next_ak_k_nova(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = IN(0); | |
| float curtrig = ZIN0(1); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| inNumSamples = INBUFLENGTH(0); | |
| inlevel = nova::peak_vec_simd(in, &level, inNumSamples); | |
| ZXP(out) = level; | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = inlevel; | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void Peak_next_ai_k_nova(Peak* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| inNumSamples = INBUFLENGTH(0); | |
| inlevel = nova::peak_vec_simd(in, &level, inNumSamples); | |
| ZXP(out) = level; | |
| unit->mLevel = level; | |
| } | |
| #endif | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void RunningMin_Ctor(RunningMin* unit) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(RunningMin_next_aa); | |
| } else if (INRATE(1) == calc_ScalarRate) { | |
| SETCALC(RunningMin_next_ai); | |
| } else { | |
| SETCALC(RunningMin_next_ak); | |
| } | |
| unit->m_prevtrig = 0.f; | |
| ZOUT0(0) = unit->mLevel = ZIN0(0); | |
| } | |
| void RunningMin_next_ak(RunningMin* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float curtrig = ZIN0(1); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| LOOP1(inNumSamples, inlevel = ZXP(in); if (inlevel < level) level = inlevel; ZXP(out) = level;); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = inlevel; | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void RunningMin_next_ai(RunningMin* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| LOOP1(inNumSamples, inlevel = ZXP(in); if (inlevel < level) level = inlevel; ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| void RunningMin_next_aa(RunningMin* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1(inNumSamples, float curtrig = ZXP(trig); float inlevel = ZXP(in); if (inlevel < level) level = inlevel; | |
| ZXP(out) = level; if (prevtrig <= 0.f && curtrig > 0.f) level = inlevel; prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void RunningMax_Ctor(RunningMax* unit) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(RunningMax_next_aa); | |
| } else if (INRATE(1) == calc_ScalarRate) { | |
| SETCALC(RunningMax_next_ai); | |
| } else { | |
| SETCALC(RunningMax_next_ak); | |
| } | |
| unit->m_prevtrig = 0.f; | |
| ZOUT0(0) = unit->mLevel = ZIN0(0); | |
| } | |
| void RunningMax_next_ak(RunningMax* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float curtrig = ZIN0(1); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| LOOP1(inNumSamples, inlevel = ZXP(in); if (inlevel > level) level = inlevel; ZXP(out) = level;); | |
| if (unit->m_prevtrig <= 0.f && curtrig > 0.f) | |
| level = inlevel; | |
| unit->m_prevtrig = curtrig; | |
| unit->mLevel = level; | |
| } | |
| void RunningMax_next_ai(RunningMax* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float level = unit->mLevel; | |
| float inlevel; | |
| LOOP1(inNumSamples, inlevel = ZXP(in); if (inlevel > level) level = inlevel; ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| void RunningMax_next_aa(RunningMax* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float* trig = ZIN(1); | |
| float prevtrig = unit->m_prevtrig; | |
| float level = unit->mLevel; | |
| LOOP1(inNumSamples, float curtrig = ZXP(trig); float inlevel = ZXP(in); if (inlevel > level) level = inlevel; | |
| ZXP(out) = level; if (prevtrig <= 0.f && curtrig > 0.f) level = inlevel; prevtrig = curtrig;); | |
| unit->m_prevtrig = prevtrig; | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void PeakFollower_Ctor(PeakFollower* unit) { | |
| if (INRATE(1) == calc_ScalarRate) { | |
| SETCALC(PeakFollower_next_ai); | |
| } else { | |
| SETCALC(PeakFollower_next); | |
| } | |
| unit->mDecay = ZIN0(1); | |
| ZOUT0(0) = unit->mLevel = ZIN0(0); | |
| } | |
| void PeakFollower_next(PeakFollower* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float decay = ZIN0(1); | |
| float level = unit->mLevel; | |
| if (decay == unit->mDecay) { | |
| LOOP1( | |
| inNumSamples, float inlevel = std::abs(ZXP(in)); if (inlevel >= level) { level = inlevel; } else { | |
| level = inlevel + decay * (level - inlevel); | |
| } ZXP(out) = level;); | |
| } else { | |
| float decay_slope = CALCSLOPE(decay, unit->mDecay); | |
| if (decay >= 0.f && unit->mDecay >= 0.f) { | |
| LOOP1( | |
| inNumSamples, float inlevel = std::abs(ZXP(in)); if (inlevel >= level) { level = inlevel; } else { | |
| level = inlevel + decay * (level - inlevel); | |
| decay += decay_slope; | |
| }; | |
| ZXP(out) = level;); | |
| } else if (decay <= 0.f && unit->mDecay <= 0.f) { | |
| LOOP1( | |
| inNumSamples, float inlevel = std::abs(ZXP(in)); if (inlevel >= level) { level = inlevel; } else { | |
| level = inlevel + decay * (level + inlevel); | |
| decay += decay_slope; | |
| }; | |
| ZXP(out) = level;); | |
| } else { | |
| LOOP1( | |
| inNumSamples, float inlevel = std::abs(ZXP(in)); if (inlevel >= level) { level = inlevel; } else { | |
| level = (1.f - std::abs(decay)) * inlevel + decay * level; | |
| decay += decay_slope; | |
| }; | |
| ZXP(out) = level;); | |
| }; | |
| } | |
| unit->mLevel = level; | |
| unit->mDecay = decay; | |
| } | |
| void PeakFollower_next_ai(PeakFollower* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float decay = ZIN0(1); | |
| float level = unit->mLevel; | |
| LOOP1( | |
| inNumSamples, float inlevel = std::abs(ZXP(in)); if (inlevel >= level) { level = inlevel; } else { | |
| level = inlevel + decay * (level - inlevel); | |
| } ZXP(out) = level;); | |
| unit->mLevel = level; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void MostChange_Ctor(MostChange* unit) { | |
| if (INRATE(0) == calc_FullRate) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(MostChange_next_aa); | |
| } else { | |
| SETCALC(MostChange_next_ak); | |
| } | |
| } else { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(MostChange_next_ka); | |
| } else { | |
| SETCALC(MostChange_next_aa); | |
| } | |
| } | |
| unit->mPrevA = 0.f; | |
| unit->mPrevB = 0.f; | |
| unit->mRecent = 1; | |
| MostChange_next_aa(unit, 1); | |
| } | |
| void MostChange_next_ak(MostChange* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* a = ZIN(0); | |
| float xb = ZIN0(1); | |
| float prevA = unit->mPrevA; | |
| float prevB = unit->mPrevB; | |
| int recent = unit->mRecent; | |
| LOOP1( | |
| inNumSamples, float xa = ZXP(a); float diff = std::abs(xa - prevA) - std::abs(xb - prevB); if (diff > 0.f) { | |
| recent = 0; | |
| ZXP(out) = xa; | |
| } else if (diff < 0.f) { | |
| recent = 1; | |
| ZXP(out) = xb; | |
| } else { ZXP(out) = recent ? xb : xa; } prevA = xa; | |
| prevB = xb;); | |
| unit->mPrevA = prevA; | |
| unit->mPrevB = prevB; | |
| unit->mRecent = recent; | |
| } | |
| void MostChange_next_aa(MostChange* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* a = ZIN(0); | |
| float* b = ZIN(1); | |
| float prevA = unit->mPrevA; | |
| float prevB = unit->mPrevB; | |
| int recent = unit->mRecent; | |
| LOOP1( | |
| inNumSamples, float xa = ZXP(a); float xb = ZXP(b); float diff = std::abs(xa - prevA) - std::abs(xb - prevB); | |
| if (diff > 0.f) { | |
| recent = 0; | |
| ZXP(out) = xa; | |
| } else if (diff < 0.f) { | |
| recent = 1; | |
| ZXP(out) = xb; | |
| } else { ZXP(out) = recent ? xb : xa; } prevA = xa; | |
| prevB = xb;); | |
| unit->mPrevA = prevA; | |
| unit->mPrevB = prevB; | |
| unit->mRecent = recent; | |
| } | |
| void MostChange_next_ka(MostChange* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float xa = ZIN0(0); | |
| float* b = ZIN(1); | |
| float prevA = unit->mPrevA; | |
| float prevB = unit->mPrevB; | |
| int recent = unit->mRecent; | |
| LOOP1( | |
| inNumSamples, float xb = ZXP(b); float diff = std::abs(xa - prevA) - std::abs(xb - prevB); if (diff > 0.f) { | |
| recent = 0; | |
| ZXP(out) = xa; | |
| } else if (diff < 0.f) { | |
| recent = 1; | |
| ZXP(out) = xb; | |
| } else { ZXP(out) = recent ? xb : xa; } prevA = xa; | |
| prevB = xb;); | |
| unit->mPrevA = prevA; | |
| unit->mPrevB = prevB; | |
| unit->mRecent = recent; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| void LeastChange_Ctor(LeastChange* unit) { | |
| if (INRATE(0) == calc_FullRate) { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(LeastChange_next_aa); | |
| } else { | |
| SETCALC(LeastChange_next_ak); | |
| } | |
| } else { | |
| if (INRATE(1) == calc_FullRate) { | |
| SETCALC(LeastChange_next_ka); | |
| } else { | |
| SETCALC(LeastChange_next_aa); | |
| } | |
| } | |
| unit->mPrevA = 0.f; | |
| unit->mPrevB = 0.f; | |
| unit->mRecent = 0; | |
| LeastChange_next_aa(unit, 1); | |
| } | |
| void LeastChange_next_ak(LeastChange* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* a = ZIN(0); | |
| float xb = ZIN0(1); | |
| float prevA = unit->mPrevA; | |
| float prevB = unit->mPrevB; | |
| int recent = unit->mRecent; | |
| LOOP1( | |
| inNumSamples, float xa = ZXP(a); float diff = std::abs(xa - prevA) - std::abs(xb - prevB); if (diff < 0.f) { | |
| recent = 0; | |
| ZXP(out) = xa; | |
| } else if (diff > 0.f) { | |
| recent = 1; | |
| ZXP(out) = xb; | |
| } else { ZXP(out) = recent ? xb : xa; } prevA = xa; | |
| prevB = xb;); | |
| unit->mPrevA = prevA; | |
| unit->mPrevB = prevB; | |
| unit->mRecent = recent; | |
| } | |
| void LeastChange_next_aa(LeastChange* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* a = ZIN(0); | |
| float* b = ZIN(1); | |
| float prevA = unit->mPrevA; | |
| float prevB = unit->mPrevB; | |
| int recent = unit->mRecent; | |
| LOOP1( | |
| inNumSamples, float xa = ZXP(a); float xb = ZXP(b); float diff = std::abs(xa - prevA) - std::abs(xb - prevB); | |
| if (diff < 0.f) { | |
| recent = 0; | |
| ZXP(out) = xa; | |
| } else if (diff > 0.f) { | |
| recent = 1; | |
| ZXP(out) = xb; | |
| } else { ZXP(out) = recent ? xb : xa; } prevA = xa; | |
| prevB = xb;); | |
| unit->mPrevA = prevA; | |
| unit->mPrevB = prevB; | |
| unit->mRecent = recent; | |
| } | |
| void LeastChange_next_ka(LeastChange* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float xa = ZIN0(0); | |
| float* b = ZIN(1); | |
| float prevA = unit->mPrevA; | |
| float prevB = unit->mPrevB; | |
| int recent = unit->mRecent; | |
| LOOP1( | |
| inNumSamples, float xb = ZXP(b); float diff = std::abs(xa - prevA) - std::abs(xb - prevB); if (diff < 0.f) { | |
| recent = 0; | |
| ZXP(out) = xa; | |
| } else if (diff > 0.f) { | |
| recent = 1; | |
| ZXP(out) = xb; | |
| } else { ZXP(out) = recent ? xb : xa; } prevA = xa; | |
| prevB = xb;); | |
| unit->mPrevA = prevA; | |
| unit->mPrevB = prevB; | |
| unit->mRecent = recent; | |
| } | |
| //////////////////// | |
| void LastValue_Ctor(LastValue* unit) { | |
| if (INRATE(0) == calc_FullRate) { | |
| SETCALC(LastValue_next_ak); | |
| } else { | |
| SETCALC(LastValue_next_kk); | |
| } | |
| unit->mPrev = ZIN0(0); | |
| unit->mCurr = ZIN0(0); | |
| LastValue_next_kk(unit, 1); | |
| } | |
| void LastValue_next_kk(LastValue* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float inval = ZIN0(0); | |
| float delta = ZIN0(1); | |
| float diff = std::abs(inval - unit->mCurr); | |
| if (diff >= delta) { | |
| unit->mPrev = unit->mCurr; | |
| unit->mCurr = inval; | |
| } | |
| float level = unit->mPrev; | |
| LOOP1(inNumSamples, ZXP(out) = level;); | |
| } | |
| void LastValue_next_ak(LastValue* unit, int inNumSamples) { | |
| float* out = ZOUT(0); | |
| float* in = ZIN(0); | |
| float delta = ZIN0(1); | |
| float prev = unit->mPrev; | |
| float curr = unit->mCurr; | |
| LOOP1( | |
| inNumSamples, float inval = ZXP(in); float diff = std::abs(inval - curr); if (diff >= delta) { | |
| prev = curr; | |
| curr = inval; | |
| } ZXP(out) = prev); | |
| unit->mPrev = prev; | |
| unit->mCurr = curr; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void Done_Ctor(Done* unit) { | |
| SETCALC(Done_next); | |
| unit->m_src = unit->mInput[0]->mFromUnit; | |
| Done_next(unit, 1); | |
| } | |
| void Done_next(Done* unit, int inNumSamples) { | |
| float* out = OUT(0); | |
| Unit* src = unit->m_src; | |
| if (src) | |
| *out = src->mDone ? 1.f : 0.f; | |
| else | |
| *out = 0.f; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void FreeSelf_Ctor(FreeSelf* unit) { | |
| SETCALC(FreeSelf_next); | |
| unit->m_prevtrig = 0.f; | |
| FreeSelf_next(unit, 1); | |
| } | |
| void FreeSelf_next(FreeSelf* unit, int inNumSamples) { | |
| float in = ZIN0(0); | |
| if (in > 0.f && unit->m_prevtrig <= 0.f) { | |
| NodeEnd(&unit->mParent->mNode); | |
| } | |
| unit->m_prevtrig = in; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void PauseSelf_Ctor(PauseSelf* unit) { | |
| SETCALC(PauseSelf_next); | |
| unit->m_prevtrig = 0.f; | |
| PauseSelf_next(unit, 1); | |
| } | |
| void PauseSelf_next(PauseSelf* unit, int inNumSamples) { | |
| float in = ZIN0(0); | |
| if (in > 0.f && unit->m_prevtrig <= 0.f) { | |
| NodeRun(&unit->mParent->mNode, 0); | |
| } | |
| unit->m_prevtrig = in; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void Pause_Ctor(Pause* unit) { | |
| SETCALC(Pause_next); | |
| unit->m_state = 1; | |
| ZOUT0(0) = ZIN0(0); | |
| } | |
| void Pause_next(Pause* unit, int inNumSamples) { | |
| float in = ZIN0(0); | |
| int state = in == 0.f ? 0 : 1; | |
| if (state != unit->m_state) { | |
| unit->m_state = state; | |
| int id = (int)ZIN0(1); | |
| Node* node = SC_GetNode(unit->mWorld, id); | |
| if (node) { | |
| NodeRun(node, state); | |
| } | |
| } | |
| ZOUT0(0) = in; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void Free_Ctor(Free* unit) { | |
| SETCALC(Free_next); | |
| unit->m_prevtrig = 0.f; | |
| ZOUT0(0) = ZIN0(0); | |
| } | |
| void Free_next(Free* unit, int inNumSamples) { | |
| float trig = ZIN0(0); | |
| if (trig > 0.f && unit->m_prevtrig <= 0) { | |
| int id = (int)ZIN0(1); | |
| Node* node = SC_GetNode(unit->mWorld, id); | |
| if (node) { | |
| NodeEnd(node); | |
| } | |
| } | |
| unit->m_prevtrig = trig; | |
| ZOUT0(0) = trig; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void FreeSelfWhenDone_Ctor(FreeSelfWhenDone* unit) { | |
| unit->m_src = unit->mInput[0]->mFromUnit; | |
| if (unit->m_src) { | |
| SETCALC(FreeSelfWhenDone_next); | |
| FreeSelfWhenDone_next(unit, 1); | |
| } else { | |
| SETCALC(ClearUnitOutputs); | |
| ClearUnitOutputs(unit, 1); | |
| } | |
| } | |
| void FreeSelfWhenDone_next(FreeSelfWhenDone* unit, int inNumSamples) { | |
| float* out = OUT(0); | |
| float* in = IN(0); | |
| Unit* src = unit->m_src; | |
| if (src->mDone) { | |
| NodeEnd(&unit->mParent->mNode); | |
| SETCALC(ClearUnitOutputs); | |
| } | |
| *out = *in; | |
| } | |
| ////////////////////////////////////////////////////////////////////////////////////////// | |
| void PauseSelfWhenDone_Ctor(PauseSelfWhenDone* unit) { | |
| unit->m_src = unit->mInput[0]->mFromUnit; | |
| if (unit->m_src) { | |
| SETCALC(PauseSelfWhenDone_next); | |
| PauseSelfWhenDone_next(unit, 1); | |
| } else { | |
| SETCALC(ClearUnitOutputs); | |
| ClearUnitOutputs(unit, 1); | |
| } | |
| } | |
| void PauseSelfWhenDone_next(PauseSelfWhenDone* unit, int inNumSamples) { | |
| float* out = OUT(0); | |
| float* in = IN(0); | |
| Unit* src = unit->m_src; | |
| if (src->mDone) { | |
| NodeRun(&unit->mParent->mNode, 0); | |
| SETCALC(ClearUnitOutputs); | |
| } | |
| *out = *in; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| struct SendPeakRMS : public Unit { | |
| // rate, level lag, replyid, channel count, [channels, ], cmd name size, [cmdname, ] | |
| static const int rateIndex = 0; | |
| static const int levelLagIndex = 1; | |
| static const int replyIdIndex = 2; | |
| static const int channelCountIndex = 3; | |
| static const int signalStartIndex = 4; | |
| SendPeakRMS(void) { | |
| SendPeakRMS* unit = this; | |
| mChannelCount = (unsigned int)IN0(channelCountIndex); | |
| size_t channelDataAllocSize = mChannelCount * 3 * sizeof(float); | |
| int cmdSizeIndex = signalStartIndex + mChannelCount; | |
| size_t cmdNameSize = IN0(cmdSizeIndex); | |
| size_t cmdNameAllocSize = (cmdNameSize + 1) * sizeof(char); | |
| void* allocData = RTAlloc(unit->mWorld, channelDataAllocSize + cmdNameAllocSize); | |
| if (!allocData) { | |
| Print("SendPeakRMS: RT memory allocation failed\n"); | |
| SETCALC(Unit_next_nop); | |
| return; | |
| } | |
| memset(allocData, 0, channelDataAllocSize); | |
| mChannelData = (float*)allocData; | |
| char* cmdName = (char*)(allocData) + channelDataAllocSize; | |
| size_t cmdNameIndex = cmdSizeIndex + 1; | |
| for (int i = 0; i < cmdNameSize; i++) | |
| cmdName[i] = (char)IN0(cmdNameIndex + i); | |
| cmdName[cmdNameSize] = 0; | |
| if ((FULLBUFLENGTH & 15) == 0) { | |
| if (mCalcRate == calc_FullRate) | |
| SETCALC(SendPeakRMS::perform_a<true>); | |
| else | |
| SETCALC(SendPeakRMS::perform_k<true>); | |
| } else { | |
| if (mCalcRate == calc_FullRate) | |
| SETCALC(SendPeakRMS::perform_a<false>); | |
| else | |
| SETCALC(SendPeakRMS::perform_k<false>); | |
| } | |
| float replyRate = IN0(rateIndex); | |
| mAudioSamplesPerTick = FULLRATE / replyRate; | |
| mControlSamplesPerTick = BUFRATE / replyRate; | |
| mPhaseRemain = (mCalcRate == calc_FullRate) ? mAudioSamplesPerTick : mControlSamplesPerTick; | |
| float32 lag = ZIN0(levelLagIndex); | |
| mB1 = (lag != 0.f) ? exp(log001 / (lag * replyRate)) : 0.f; | |
| } | |
| ~SendPeakRMS(void) { | |
| SendPeakRMS* unit = this; | |
| RTFree(unit->mWorld, mChannelData); | |
| } | |
| unsigned int mChannelCount; | |
| float* mChannelData; | |
| float mB1; | |
| int mAudioSamplesPerTick; | |
| int mControlSamplesPerTick; | |
| int mPhaseRemain; | |
| void performLevelLag(float& out, float y0, float& y1) { | |
| if (y0 >= y1) | |
| out = y1 = y0; | |
| else | |
| out = y1 = y0 + mB1 * (y1 - y0); | |
| } | |
| char* getCmdName(void) { | |
| void* buffer = mChannelData; | |
| return (char*)(buffer) + mChannelCount * 3 * sizeof(float); | |
| } | |
| void sendReply(void) { | |
| SendPeakRMS* unit = this; | |
| float* reply = (float*)alloca(mChannelCount * 2 * sizeof(float)); | |
| for (int i = 0; i != mChannelCount; ++i) { | |
| float& maxLevel = reply[2 * i]; | |
| float& rms = reply[2 * i + 1]; | |
| performLevelLag(maxLevel, mChannelData[2 * i], mChannelData[2 * mChannelCount + i]); | |
| if (INRATE(signalStartIndex + i) == calc_FullRate) | |
| rms = std::sqrt(mChannelData[2 * i + 1] / (float)mAudioSamplesPerTick); | |
| else | |
| rms = std::sqrt(mChannelData[2 * i + 1] / (float)mControlSamplesPerTick); | |
| } | |
| SendNodeReply(&unit->mParent->mNode, (int)ZIN0(replyIdIndex), getCmdName(), mChannelCount * 2, reply); | |
| memset(mChannelData, 0, mChannelCount * 2 * sizeof(float)); | |
| } | |
| template <bool simd> void analyzeFullBlock(void) { | |
| SendPeakRMS* unit = this; | |
| for (int i = 0; i != mChannelCount; ++i) { | |
| float* in = IN(signalStartIndex + i); | |
| int numSamples = INBUFLENGTH(signalStartIndex + i); | |
| float& level = mChannelData[2 * i]; | |
| float& sqrsum = mChannelData[2 * i + 1]; | |
| if (numSamples == 1) | |
| nova::peak_rms_vec(in, &level, &sqrsum, 1); | |
| else { | |
| if (simd) | |
| nova::peak_rms_vec_simd(in, &level, &sqrsum, numSamples); | |
| else | |
| nova::peak_rms_vec(in, &level, &sqrsum, numSamples); | |
| } | |
| } | |
| } | |
| void analyzePartialBlock(int firstSample, int samplesToAnalyze) { | |
| SendPeakRMS* unit = this; | |
| for (int i = 0; i != mChannelCount; ++i) { | |
| float* in = IN(signalStartIndex + i) + firstSample; | |
| int numSamples = INBUFLENGTH(signalStartIndex + i); | |
| float& level = mChannelData[2 * i]; | |
| float& sqrsum = mChannelData[2 * i + 1]; | |
| if (numSamples == 1) { | |
| if (firstSample == 0) | |
| nova::peak_rms_vec(in, &level, &sqrsum, 1); | |
| } else { | |
| if (!(samplesToAnalyze & 15) && !(firstSample & 3)) // check for unrolling and alignment | |
| nova::peak_rms_vec_simd(in, &level, &sqrsum, samplesToAnalyze); | |
| else | |
| nova::peak_rms_vec(in, &level, &sqrsum, samplesToAnalyze); | |
| } | |
| } | |
| } | |
| template <bool simd> inline void next_k(int inNumSamples) { | |
| mPhaseRemain -= 1; | |
| if (mPhaseRemain <= 0) { | |
| mPhaseRemain += mControlSamplesPerTick; | |
| sendReply(); | |
| } | |
| analyzeFullBlock<simd>(); | |
| } | |
| template <bool simd> inline void next_a(int inNumSamples) { | |
| if (mPhaseRemain >= inNumSamples) { | |
| mPhaseRemain -= inNumSamples; | |
| analyzeFullBlock<simd>(); | |
| } else { | |
| if (mPhaseRemain == 0) { | |
| sendReply(); | |
| mPhaseRemain = mAudioSamplesPerTick; | |
| } | |
| int startSample = 0; | |
| int samplesToAnalyze = std::min(mPhaseRemain, inNumSamples); | |
| int remain = inNumSamples; | |
| do { | |
| analyzePartialBlock(startSample, samplesToAnalyze); | |
| startSample += samplesToAnalyze; | |
| mPhaseRemain -= samplesToAnalyze; | |
| if (mPhaseRemain == 0) { | |
| sendReply(); | |
| mPhaseRemain = mAudioSamplesPerTick; | |
| } | |
| remain -= samplesToAnalyze; | |
| samplesToAnalyze = std::min(remain, mPhaseRemain); | |
| } while (remain); | |
| } | |
| } | |
| template <bool simd> static void perform_k(Unit* unit, int inNumSamples) { | |
| static_cast<SendPeakRMS*>(unit)->next_k<simd>(inNumSamples); | |
| } | |
| template <bool simd> static void perform_a(Unit* unit, int inNumSamples) { | |
| static_cast<SendPeakRMS*>(unit)->next_a<simd>(inNumSamples); | |
| } | |
| }; | |
| static void SendPeakRMS_Ctor(SendPeakRMS* unit) { new (unit) SendPeakRMS(); } | |
| static void SendPeakRMS_Dtor(SendPeakRMS* unit) { unit->~SendPeakRMS(); } | |
| //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
| PluginLoad(Trigger) { | |
| ft = inTable; | |
| DefineSimpleUnit(Trig1); | |
| DefineSimpleUnit(Trig); | |
| DefineSimpleUnit(SendTrig); | |
| DefineDtorUnit(SendReply); | |
| DefineDtorUnit(Poll); | |
| DefineSimpleUnit(ToggleFF); | |
| DefineSimpleUnit(SetResetFF); | |
| DefineSimpleUnit(Latch); | |
| DefineSimpleUnit(Gate); | |
| DefineSimpleUnit(Schmidt); | |
| DefineSimpleUnit(PulseDivider); | |
| DefineSimpleUnit(PulseCount); | |
| DefineSimpleUnit(Stepper); | |
| DefineSimpleUnit(TDelay); | |
| DefineSimpleUnit(ZeroCrossing); | |
| DefineSimpleUnit(Timer); | |
| DefineSimpleUnit(Sweep); | |
| DefineSimpleUnit(Phasor); | |
| DefineSimpleUnit(Peak); | |
| DefineSimpleUnit(RunningMin); | |
| DefineSimpleUnit(RunningMax); | |
| DefineSimpleUnit(PeakFollower); | |
| DefineSimpleUnit(MostChange); | |
| DefineSimpleUnit(LeastChange); | |
| DefineSimpleUnit(LastValue); | |
| DefineSimpleUnit(Done); | |
| DefineSimpleUnit(Pause); | |
| DefineSimpleUnit(FreeSelf); | |
| DefineSimpleUnit(PauseSelf); | |
| DefineSimpleUnit(Free); | |
| DefineSimpleUnit(FreeSelfWhenDone); | |
| DefineSimpleUnit(PauseSelfWhenDone); | |
| DefineDtorUnit(SendPeakRMS); | |
| } |