Skip to content
Permalink
develop
Go to file
 
 
Cannot retrieve contributors at this time
2619 lines (2171 sloc) 74.4 KB
/*
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);
}