Skip to content
Permalink
f806ace7bd
Go to file
 
 
Cannot retrieve contributors at this time
3582 lines (2988 sloc) 112 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 "function_attributes.h"
#include <limits>
#include <string.h>
static InterfaceTable* ft;
struct BufUnit : public Unit {
SndBuf* m_buf;
float m_fbufnum;
};
struct TableLookup : public BufUnit {
double m_cpstoinc, m_radtoinc;
int32 mTableSize;
int32 m_lomask;
};
struct DegreeToKey : public BufUnit {
int32 mPrevIndex;
float mPrevKey;
int32 mOctave;
};
struct Select : public Unit {};
struct TWindex : public Unit {
int32 m_prevIndex;
float m_trig;
};
struct Index : public BufUnit {};
struct IndexL : public BufUnit {};
struct WrapIndex : public BufUnit {};
struct FoldIndex : public BufUnit {};
struct IndexInBetween : public BufUnit {};
struct DetectIndex : public BufUnit {
float mPrev;
float mPrevIn;
};
struct Shaper : public BufUnit {
float mOffset;
float mPrevIn;
};
struct FSinOsc : public Unit {
double m_b1, m_y1, m_y2, m_freq;
};
struct PSinGrain : public Unit {
double m_b1, m_y1, m_y2;
double m_level, m_slope, m_curve;
int32 mCounter;
};
struct Osc : public TableLookup {
int32 m_phase;
float m_phasein;
};
struct SinOsc : public TableLookup {
int32 m_phase;
float m_phasein;
};
struct SinOscFB : public TableLookup {
int32 m_phase;
float m_prevout, m_feedback;
};
struct OscN : public TableLookup {
int32 m_phase;
float m_phasein;
};
struct COsc : public TableLookup {
int32 m_phase1, m_phase2;
};
struct VOsc : public Unit {
double m_cpstoinc, m_radtoinc;
int32 mTableSize;
int32 m_lomask;
int32 m_phase, m_phaseoffset;
float m_phasein, m_bufpos;
};
struct VOsc3 : public Unit {
double m_cpstoinc;
int32 mTableSize;
int32 m_lomask;
int32 m_phase1, m_phase2, m_phase3;
float m_bufpos;
};
struct Formant : public Unit {
int32 m_phase1, m_phase2, m_phase3;
double m_cpstoinc;
};
struct Blip : public Unit {
int32 m_phase, m_numharm, m_N;
float m_freqin, m_scale;
double m_cpstoinc;
};
struct Saw : public Unit {
int32 m_phase, m_N;
float m_freqin, m_scale, m_y1;
double m_cpstoinc;
};
struct Pulse : public Unit {
int32 m_phase, m_phaseoff, m_N;
float m_freqin, m_scale, m_y1;
double m_cpstoinc;
};
struct Klang : public Unit {
float* m_coefs;
int32 m_numpartials;
};
struct Klank : public Unit {
float* m_coefs;
float* m_buf;
float m_x1, m_x2;
int32 m_numpartials;
};
#define xlomask8 0x000003FC
#define xlomask9 0x000007FC
#define xlomask10 0x00000FFC
#define xlomask11 0x00001FFC
#define xlomask12 0x00003FFC
#define xlomask13 0x00007FFC
#define xlomask8i 0x000007F8
#define xlomask9i 0x00000FF8
#define xlomask10i 0x00001FF8
#define xlomask11i 0x00003FF8
#define xlomask12i 0x00007FF8
#define xlomask13i 0x0000FFF8
#define onecyc13 0x20000000
//////////////////////////////////////////////////////////////////////////////////////////////////
extern "C" {
void DegreeToKey_Ctor(DegreeToKey* unit);
void DegreeToKey_next_1(DegreeToKey* unit, int inNumSamples);
void DegreeToKey_next_k(DegreeToKey* unit, int inNumSamples);
void DegreeToKey_next_a(DegreeToKey* unit, int inNumSamples);
void Select_Ctor(Select* unit);
void Select_next_1(Select* unit, int inNumSamples);
void Select_next_k(Select* unit, int inNumSamples);
void Select_next_a(Select* unit, int inNumSamples);
void TWindex_Ctor(TWindex* unit);
void TWindex_next_k(TWindex* unit, int inNumSamples);
void TWindex_next_ak(TWindex* unit, int inNumSamples);
void Index_Ctor(Index* unit);
void Index_next_1(Index* unit, int inNumSamples);
void Index_next_k(Index* unit, int inNumSamples);
void Index_next_a(Index* unit, int inNumSamples);
void IndexL_Ctor(IndexL* unit);
void IndexL_next_1(IndexL* unit, int inNumSamples);
void IndexL_next_k(IndexL* unit, int inNumSamples);
void IndexL_next_a(IndexL* unit, int inNumSamples);
void FoldIndex_Ctor(FoldIndex* unit);
void FoldIndex_next_1(FoldIndex* unit, int inNumSamples);
void FoldIndex_next_k(FoldIndex* unit, int inNumSamples);
void FoldIndex_next_a(FoldIndex* unit, int inNumSamples);
void WrapIndex_Ctor(WrapIndex* unit);
void WrapIndex_next_1(WrapIndex* unit, int inNumSamples);
void WrapIndex_next_k(WrapIndex* unit, int inNumSamples);
void WrapIndex_next_a(WrapIndex* unit, int inNumSamples);
void Shaper_Ctor(Shaper* unit);
void Shaper_next_1(Shaper* unit, int inNumSamples);
void Shaper_next_k(Shaper* unit, int inNumSamples);
void Shaper_next_a(Shaper* unit, int inNumSamples);
void DetectIndex_Ctor(DetectIndex* unit);
void DetectIndex_next_1(DetectIndex* unit, int inNumSamples);
void DetectIndex_next_k(DetectIndex* unit, int inNumSamples);
void DetectIndex_next_a(DetectIndex* unit, int inNumSamples);
void IndexInBetween_Ctor(IndexInBetween* unit);
void IndexInBetween_next_1(IndexInBetween* unit, int inNumSamples);
void IndexInBetween_next_k(IndexInBetween* unit, int inNumSamples);
void IndexInBetween_next_a(IndexInBetween* unit, int inNumSamples);
void FSinOsc_Ctor(FSinOsc* unit);
void FSinOsc_next(FSinOsc* unit, int inNumSamples);
void FSinOsc_next_i(FSinOsc* unit, int inNumSamples);
void PSinGrain_Ctor(PSinGrain* unit);
void PSinGrain_next(PSinGrain* unit, int inNumSamples);
void SinOsc_Ctor(SinOsc* unit);
void SinOsc_next_ikk(SinOsc* unit, int inNumSamples);
void SinOsc_next_ika(SinOsc* unit, int inNumSamples);
void SinOsc_next_iak(SinOsc* unit, int inNumSamples);
void SinOsc_next_iaa(SinOsc* unit, int inNumSamples);
void Osc_Ctor(Osc* unit);
void Osc_next_ikk(Osc* unit, int inNumSamples);
void Osc_next_ika(Osc* unit, int inNumSamples);
void Osc_next_iak(Osc* unit, int inNumSamples);
void Osc_next_iaa(Osc* unit, int inNumSamples);
void OscN_Ctor(OscN* unit);
void OscN_next_nkk(OscN* unit, int inNumSamples);
void OscN_next_nka(OscN* unit, int inNumSamples);
void OscN_next_nak(OscN* unit, int inNumSamples);
void OscN_next_naa(OscN* unit, int inNumSamples);
void COsc_Ctor(COsc* unit);
void COsc_next(COsc* unit, int inNumSamples);
void VOsc_Ctor(VOsc* unit);
void VOsc_next_ikk(VOsc* unit, int inNumSamples);
void VOsc_next_ika(VOsc* unit, int inNumSamples);
void VOsc3_Ctor(VOsc3* unit);
void VOsc3_next_ik(VOsc3* unit, int inNumSamples);
void Formant_Ctor(Formant* unit);
void Formant_next(Formant* unit, int inNumSamples);
void Blip_Ctor(Blip* unit);
void Blip_next(Blip* unit, int inNumSamples);
void Saw_Ctor(Saw* unit);
void Saw_next(Saw* unit, int inNumSamples);
void Pulse_Ctor(Pulse* unit);
void Pulse_next(Pulse* unit, int inNumSamples);
void Klang_Dtor(Klang* unit);
void Klang_Ctor(Klang* unit);
void Klang_next(Klang* unit, int inNumSamples);
void Klank_Dtor(Klank* unit);
void Klank_Ctor(Klank* unit);
void Klank_next(Klank* unit, int inNumSamples);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
force_inline bool UnitGetTable(BufUnit* unit, int inNumSamples, const SndBuf*& buf, const float*& bufData,
int& tableSize) {
float fbufnum = ZIN0(0);
if (fbufnum != unit->m_fbufnum) {
uint32 bufnum = (uint32)fbufnum;
World* world = unit->mWorld;
if (bufnum >= world->mNumSndBufs) {
uint32 localBufNum = bufnum - world->mNumSndBufs;
Graph* parent = unit->mParent;
if (localBufNum <= parent->localBufNum)
unit->m_buf = parent->mLocalSndBufs + localBufNum;
else {
bufnum = 0;
unit->m_buf = world->mSndBufs + bufnum;
}
} else
unit->m_buf = world->mSndBufs + bufnum;
unit->m_fbufnum = fbufnum;
}
buf = unit->m_buf;
if (!buf) {
ClearUnitOutputs(unit, inNumSamples);
return false;
}
bufData = buf->data;
if (!bufData) {
ClearUnitOutputs(unit, inNumSamples);
return false;
}
tableSize = buf->samples;
return true;
}
#define GET_TABLE \
const SndBuf* buf; \
const float* bufData; \
int tableSize; \
do { \
bool tableValid = UnitGetTable(unit, inNumSamples, buf, bufData, tableSize); \
if (!tableValid) \
return; \
} while (0);
static inline bool verify_wavetable(Unit* unit, const char* name, int tableSize, int inNumSamples) {
// phase computation is not precise for large wavetables.
if (tableSize > 131072) {
if (unit->mWorld->mVerbosity >= -1)
Print("Warning: wave table too big (%s)\n", name);
ClearUnitOutputs(unit, inNumSamples);
return false;
}
if (!ISPOWEROFTWO(tableSize)) {
if (unit->mWorld->mVerbosity >= -1)
Print("Warning: size of wavetable not a power of two (%s)\n", name);
ClearUnitOutputs(unit, inNumSamples);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
void TableLookup_SetTable(TableLookup* unit, int32 inSize, float* inTable)
{
unit->mTable0 = inTable;
unit->mTable1 = inTable + 1;
unit->mTableSize = inSize;
unit->mMaxIndex = unit->mTableSize - 1;
unit->mFMaxIndex = unit->mMaxIndex;
unit->m_radtoinc = unit->mTableSize * (rtwopi * 65536.);
unit->m_cpstoinc = unit->mTableSize * SAMPLEDUR * 65536.;
//Print("TableLookup_SetTable unit->m_radtoinc %g %d %g\n", m_radtoinc, unit->mTableSize, rtwopi);
}
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////
void DegreeToKey_Ctor(DegreeToKey* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(DegreeToKey_next_1);
} else if (INRATE(0) == calc_FullRate) {
SETCALC(DegreeToKey_next_a);
} else {
SETCALC(DegreeToKey_next_k);
}
unit->mOctave = (int32)ZIN0(2);
unit->mPrevIndex = std::numeric_limits<int32>::max();
unit->mPrevKey = 0.;
DegreeToKey_next_1(unit, 1);
}
void DegreeToKey_next_1(DegreeToKey* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
int32 key, oct;
int32 octave = unit->mOctave;
float val;
int32 index = (int32)floor(ZIN0(1));
if (index == unit->mPrevIndex) {
val = unit->mPrevKey;
} else if (index < 0) {
unit->mPrevIndex = index;
key = tableSize + index % tableSize;
oct = (index + 1) / tableSize - 1;
val = unit->mPrevKey = table[key] + octave * oct;
} else if (index > maxindex) {
unit->mPrevIndex = index;
key = index % tableSize;
oct = index / tableSize;
val = unit->mPrevKey = table[key] + octave * oct;
} else {
unit->mPrevIndex = index;
val = unit->mPrevKey = table[index];
}
ZOUT0(0) = val;
}
void DegreeToKey_next_k(DegreeToKey* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
int32 key, oct;
float octave = unit->mOctave;
float val;
int32 index = (int32)floor(ZIN0(1));
if (index == unit->mPrevIndex) {
val = unit->mPrevKey;
} else if (index < 0) {
unit->mPrevIndex = index;
key = tableSize + index % tableSize;
oct = (index + 1) / tableSize - 1;
val = unit->mPrevKey = table[key] + octave * oct;
} else if (index > maxindex) {
unit->mPrevIndex = index;
key = index % tableSize;
oct = index / tableSize;
val = unit->mPrevKey = table[key] + octave * oct;
} else {
unit->mPrevIndex = index;
val = unit->mPrevKey = table[index];
}
LOOP1(inNumSamples, ZXP(out) = val;);
}
void DegreeToKey_next_a(DegreeToKey* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
int32 previndex = unit->mPrevIndex;
float prevkey = unit->mPrevKey;
int32 key, oct;
float octave = unit->mOctave;
LOOP1(
inNumSamples, int32 index = (int32)floor(ZXP(in));
if (index == previndex) { ZXP(out) = prevkey; } else if (index < 0) {
previndex = index;
key = tableSize + index % tableSize;
oct = (index + 1) / tableSize - 1;
ZXP(out) = prevkey = table[key] + octave * oct;
} else if (index > maxindex) {
previndex = index;
key = index % tableSize;
oct = index / tableSize;
ZXP(out) = prevkey = table[key] + octave * oct;
} else {
previndex = index;
ZXP(out) = prevkey = table[index];
});
unit->mPrevIndex = previndex;
unit->mPrevKey = prevkey;
}
////////////////////////////////////////////////////////////////////////////////////
void Select_Ctor(Select* unit) {
if (BUFLENGTH == 1) {
SETCALC(Select_next_1);
} else if (INRATE(0) == calc_FullRate) {
SETCALC(Select_next_a);
} else {
SETCALC(Select_next_k);
}
Select_next_1(unit, 1);
}
void Select_next_1(Select* unit, int inNumSamples) {
int32 maxindex = unit->mNumInputs - 1;
int32 index = (int32)ZIN0(0) + 1;
index = sc_clip(index, 1, maxindex);
ZOUT0(0) = ZIN0(index);
}
void Select_next_k(Select* unit, int inNumSamples) {
int32 maxindex = unit->mNumInputs - 1;
int32 index = (int32)ZIN0(0) + 1;
index = sc_clip(index, 1, maxindex);
float* out = OUT(0);
float* in = IN(index);
Copy(inNumSamples, out, in);
}
void Select_next_a(Select* unit, int inNumSamples) {
int32 maxindex = unit->mNumInputs - 1;
float* out = ZOUT(0);
float* in0 = ZIN(0);
float** in = unit->mInBuf;
for (int i = 0; i < inNumSamples; ++i) {
int32 index = (int32)ZXP(in0) + 1;
index = sc_clip(index, 1, maxindex);
ZXP(out) = in[index][i];
}
}
////////////////////////////////////////////////////////////////////////////////////
void TWindex_Ctor(TWindex* unit) {
if (INRATE(0) == calc_FullRate) {
SETCALC(TWindex_next_ak); // todo : ar
} else {
SETCALC(TWindex_next_k);
}
unit->m_prevIndex = 0;
unit->m_trig = -1.f; // make it trigger the first time
TWindex_next_k(unit, 1);
}
void TWindex_next_k(TWindex* unit, int inNumSamples) {
int maxindex = unit->mNumInputs;
int32 index = maxindex;
float sum = 0.f;
float maxSum = 0.f;
float normalize = ZIN0(1); // switch normalisation on or off
float trig = ZIN0(0);
float* out = ZOUT(0);
if (trig > 0.f && unit->m_trig <= 0.f) {
if (normalize == 1) {
for (int32 k = 2; k < maxindex; ++k) {
maxSum += ZIN0(k);
}
} else {
maxSum = 1.f;
}
RGen& rgen = *unit->mParent->mRGen;
float max = maxSum * rgen.frand();
for (int32 k = 2; k < maxindex; ++k) {
sum += ZIN0(k);
if (sum >= max) {
index = k - 2;
break;
}
}
unit->m_prevIndex = index;
} else {
index = unit->m_prevIndex;
}
LOOP1(inNumSamples, ZXP(out) = index;)
unit->m_trig = trig;
}
void TWindex_next_ak(TWindex* unit, int inNumSamples) {
int maxindex = unit->mNumInputs;
int32 index = maxindex;
float sum = 0.f;
float maxSum = 0.f;
float normalize = ZIN0(1); // switch normalisation on or off
float* trig = ZIN(0);
float* out = ZOUT(0);
float curtrig;
if (normalize == 1) {
for (int32 k = 2; k < maxindex; ++k) {
maxSum += ZIN0(k);
}
} else
maxSum = 1.f;
RGen& rgen = *unit->mParent->mRGen;
LOOP1(
inNumSamples, curtrig = ZXP(trig); if (curtrig > 0.f && unit->m_trig <= 0.f) {
float max = maxSum * rgen.frand();
for (int32 k = 2; k < maxindex; ++k) {
sum += ZIN0(k);
if (sum >= max) {
index = k - 2;
break;
}
}
unit->m_prevIndex = index;
} else index = unit->m_prevIndex;
ZXP(out) = index; unit->m_trig = curtrig;)
}
////////////////////////////////////////////////////////////////////////////////////
void Index_Ctor(Index* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(Index_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(Index_next_a);
} else {
SETCALC(Index_next_k);
}
Index_next_1(unit, 1);
}
void Index_next_1(Index* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
int32 index = (int32)ZIN0(1);
index = sc_clip(index, 0, maxindex);
ZOUT0(0) = table[index];
}
void Index_next_k(Index* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
int32 index = (int32)ZIN0(1);
index = sc_clip(index, 0, maxindex);
float val = table[index];
LOOP1(inNumSamples, ZXP(out) = val;);
}
void Index_next_a(Index* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
LOOP1(inNumSamples, int32 index = (int32)ZXP(in); index = sc_clip(index, 0, maxindex); ZXP(out) = table[index];);
}
////////////////////////////////////////////////////////////////////////////////////
void IndexL_Ctor(IndexL* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(IndexL_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(IndexL_next_a);
} else {
SETCALC(IndexL_next_k);
}
IndexL_next_1(unit, 1);
}
void IndexL_next_1(IndexL* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float findex = ZIN0(1);
float frac = sc_frac(findex);
int32 index = (int32)findex;
index = sc_clip(index, 0, maxindex);
float a = table[index];
float b = table[sc_clip(index + 1, 0, maxindex)];
ZOUT0(0) = lininterp(frac, a, b);
}
void IndexL_next_k(IndexL* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float findex = ZIN0(1);
float frac = sc_frac(findex);
int32 index = (int32)findex;
index = sc_clip(index, 0, maxindex);
float a = table[index];
float b = table[sc_clip(index + 1, 0, maxindex)];
float val = lininterp(frac, a, b);
LOOP1(inNumSamples, ZXP(out) = val;);
}
void IndexL_next_a(IndexL* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
LOOP1(inNumSamples, float findex = ZXP(in); float frac = sc_frac(findex);
int32 i1 = sc_clip((int32)findex, 0, maxindex); int32 i2 = sc_clip(i1 + 1, 0, maxindex); float a = table[i1];
float b = table[i2]; ZXP(out) = lininterp(frac, a, b););
}
////////////////////////////////////////////////////////////////////////////////////
void FoldIndex_Ctor(FoldIndex* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(FoldIndex_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(FoldIndex_next_a);
} else {
SETCALC(FoldIndex_next_k);
}
FoldIndex_next_1(unit, 1);
}
void FoldIndex_next_1(FoldIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
int32 index = (int32)ZIN0(1);
index = sc_fold(index, 0, maxindex);
ZOUT0(0) = table[index];
}
void FoldIndex_next_k(FoldIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
int32 index = (int32)ZIN0(1);
float* out = ZOUT(0);
index = sc_fold(index, 0, maxindex);
float val = table[index];
LOOP1(inNumSamples, ZXP(out) = val;);
}
void FoldIndex_next_a(FoldIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
LOOP1(inNumSamples, int32 index = (int32)ZXP(in); index = sc_fold(index, 0, maxindex); ZXP(out) = table[index];);
}
////////////////////////////////////////////////////////////////////////////////////
void WrapIndex_Ctor(WrapIndex* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(WrapIndex_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(WrapIndex_next_a);
} else {
SETCALC(WrapIndex_next_k);
}
WrapIndex_next_1(unit, 1);
}
void WrapIndex_next_1(WrapIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
int32 index = (int32)floor(ZIN0(1));
index = sc_wrap(index, 0, maxindex);
ZOUT0(0) = table[index];
}
void WrapIndex_next_k(WrapIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
int32 index = (int32)ZIN0(1);
index = sc_wrap(index, 0, maxindex);
float val = table[index];
LOOP1(inNumSamples, ZXP(out) = val;);
}
void WrapIndex_next_a(WrapIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
LOOP1(inNumSamples, int32 index = (int32)ZXP(in); index = sc_wrap(index, 0, maxindex); ZXP(out) = table[index];);
}
////////////////////////////////////////////////////////////////////////////////////
static float IndexInBetween_FindIndex(const float* table, float in, int32 maxindex) {
for (int32 i = 0; i <= maxindex; i++) {
if (table[i] > in) {
if (i == 0) {
return 0.f;
} else {
return ((in - table[i - 1]) / (table[i] - table[i - 1]) + i - 1);
}
}
}
return (float)maxindex;
}
void IndexInBetween_Ctor(IndexInBetween* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(IndexInBetween_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(IndexInBetween_next_a);
} else {
SETCALC(IndexInBetween_next_k);
}
IndexInBetween_next_1(unit, 1);
}
void IndexInBetween_next_1(IndexInBetween* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float in = ZIN0(1);
ZOUT0(0) = IndexInBetween_FindIndex(table, in, maxindex);
}
void IndexInBetween_next_k(IndexInBetween* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float in = ZIN0(1);
float val = IndexInBetween_FindIndex(table, in, maxindex);
LOOP1(inNumSamples, ZXP(out) = val;);
}
void IndexInBetween_next_a(IndexInBetween* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
LOOP1(inNumSamples, ZXP(out) = IndexInBetween_FindIndex(table, ZXP(in), maxindex););
}
////////////////////////////////////////////////////////////////////////////////////
static int32 DetectIndex_FindIndex(const float* table, float in, int32 maxindex) {
int32 index;
for (index = 0; index <= maxindex; index += 1) {
if (table[index] == in) {
return index;
}
}
return -1;
}
void DetectIndex_Ctor(DetectIndex* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(DetectIndex_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(DetectIndex_next_a);
} else {
SETCALC(DetectIndex_next_k);
}
unit->mPrev = -1.f;
DetectIndex_next_1(unit, 1);
}
void DetectIndex_next_1(DetectIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float in = ZIN0(1);
int32 index;
if (in == unit->mPrevIn) {
index = (int32)unit->mPrev;
} else {
index = DetectIndex_FindIndex(table, in, maxindex);
unit->mPrev = index;
unit->mPrevIn = in;
}
ZOUT0(0) = (float)index;
}
void DetectIndex_next_k(DetectIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float in = ZIN0(1);
int32 index;
float val;
if (in == unit->mPrevIn) {
index = (int32)unit->mPrev;
} else {
index = DetectIndex_FindIndex(table, in, maxindex);
unit->mPrev = index;
unit->mPrevIn = in;
};
val = (float)index;
LOOP1(inNumSamples, ZXP(out) = val;);
}
void DetectIndex_next_a(DetectIndex* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
int32 maxindex = tableSize - 1;
float* out = ZOUT(0);
float* in = ZIN(1);
float prev = unit->mPrevIn;
int32 prevIndex = (int32)unit->mPrev;
float inval;
LOOP1(
inNumSamples, inval = ZXP(in);
if (inval != prev) { prevIndex = DetectIndex_FindIndex(table, inval, maxindex); } prev = inval;
ZXP(out) = (float)prevIndex;);
unit->mPrev = prevIndex;
unit->mPrevIn = inval;
}
////////////////////////////////////////////////////////////////////////////////////
void Shaper_Ctor(Shaper* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
if (BUFLENGTH == 1) {
SETCALC(Shaper_next_1);
} else if (INRATE(1) == calc_FullRate) {
SETCALC(Shaper_next_a);
} else {
SETCALC(Shaper_next_k);
}
unit->mPrevIn = ZIN0(0);
Shaper_next_1(unit, 1);
}
float force_inline ShaperPerform(const float* table0, const float* table1, float in, float offset, float fmaxindex) {
float findex = offset + in * offset;
findex = sc_clip(findex, 0.f, fmaxindex);
int32 index = (int32)findex;
float pfrac = findex - (index - 1);
index <<= 3;
float val1 = *(const float*)((const char*)table0 + index);
float val2 = *(const float*)((const char*)table1 + index);
float val = val1 + val2 * pfrac;
return val;
}
void Shaper_next_1(Shaper* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table0 = bufData;
const float* table1 = table0 + 1;
float fmaxindex = (float)(tableSize >> 1) - 0.001;
float offset = tableSize * 0.25;
ZOUT0(0) = ShaperPerform(table0, table1, ZIN0(1), offset, fmaxindex);
}
void Shaper_next_k(Shaper* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table0 = bufData;
const float* table1 = table0 + 1;
float fmaxindex = (float)(tableSize >> 1) - 0.001;
float offset = tableSize * 0.25;
float* out = ZOUT(0);
float fin = ZIN0(1);
if (fin == unit->mPrevIn) {
LOOP1(inNumSamples, ZXP(out) = ShaperPerform(table0, table1, fin, offset, fmaxindex););
} else {
float phaseinc = (fin - unit->mPrevIn) * offset;
unit->mPrevIn = fin;
LOOP1(inNumSamples, ZXP(out) = ShaperPerform(table0, table1, fin, offset, fmaxindex); fin += phaseinc;);
}
}
void Shaper_next_a(Shaper* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table0 = bufData;
const float* table1 = table0 + 1;
float fmaxindex = (float)(tableSize >> 1) - 0.001;
float offset = tableSize * 0.25;
float* out = ZOUT(0);
const float* in = ZIN(1);
LOOP1(inNumSamples, float fin = ZXP(in); ZXP(out) = ShaperPerform(table0, table1, fin, offset, fmaxindex););
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSinOsc_Ctor(FSinOsc* unit) {
if (INRATE(0) == calc_ScalarRate)
SETCALC(FSinOsc_next_i);
else
SETCALC(FSinOsc_next);
unit->m_freq = ZIN0(0);
float iphase = ZIN0(1);
float w = unit->m_freq * unit->mRate->mRadiansPerSample;
unit->m_b1 = 2. * cos(w);
unit->m_y1 = sin(iphase);
unit->m_y2 = sin(iphase - w);
ZOUT0(0) = unit->m_y1;
}
void FSinOsc_next(FSinOsc* unit, int inNumSamples) {
float* out = ZOUT(0);
double freq = ZIN0(0);
double b1;
if (freq != unit->m_freq) {
unit->m_freq = freq;
double w = freq * unit->mRate->mRadiansPerSample;
unit->m_b1 = b1 = 2.f * cos(w);
} else {
b1 = unit->m_b1;
}
double y0;
double y1 = unit->m_y1;
double y2 = unit->m_y2;
// Print("y %g %g b1 %g\n", y1, y2, b1);
// Print("%d %d\n", unit->mRate->mFilterLoops, unit->mRate->mFilterRemain);
LOOP(unit->mRate->mFilterLoops, ZXP(out) = y0 = b1 * y1 - y2; ZXP(out) = y2 = b1 * y0 - y1;
ZXP(out) = y1 = b1 * y2 - y0;);
LOOP(unit->mRate->mFilterRemain, ZXP(out) = y0 = b1 * y1 - y2; y2 = y1; y1 = y0;);
// Print("y %g %g b1 %g\n", y1, y2, b1);
unit->m_y1 = y1;
unit->m_y2 = y2;
}
void FSinOsc_next_i(FSinOsc* unit, int inNumSamples) {
float* __restrict__ out = ZOUT(0);
double b1 = unit->m_b1;
double y0;
double y1 = unit->m_y1;
double y2 = unit->m_y2;
// Print("y %g %g b1 %g\n", y1, y2, b1);
// Print("%d %d\n", unit->mRate->mFilterLoops, unit->mRate->mFilterRemain);
LOOP(unit->mRate->mFilterLoops, y0 = b1 * y1 - y2; y2 = b1 * y0 - y1; y1 = b1 * y2 - y0; ZXP(out) = y0;
ZXP(out) = y2; ZXP(out) = y1;);
LOOP(unit->mRate->mFilterRemain, ZXP(out) = y0 = b1 * y1 - y2; y2 = y1; y1 = y0;);
// Print("y %g %g b1 %g\n", y1, y2, b1);
unit->m_y1 = y1;
unit->m_y2 = y2;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void PSinGrain_Ctor(PSinGrain* unit) {
SETCALC(PSinGrain_next);
float freq = ZIN0(0);
float dur = ZIN0(1);
float amp = ZIN0(2);
float w = freq * unit->mRate->mRadiansPerSample;
float sdur = SAMPLERATE * dur;
float rdur = 1.f / sdur;
float rdur2 = rdur * rdur;
unit->m_level = 0.f;
unit->m_slope = 4.0 * (rdur - rdur2); // ampslope
unit->m_curve = -8.0 * rdur2; // ampcurve
unit->mCounter = (int32)(sdur + .5);
/* calc feedback param and initial conditions */
unit->m_b1 = 2. * cos(w);
unit->m_y1 = 0.f;
unit->m_y2 = -sin(w) * amp;
ZOUT0(0) = 0.f;
}
void PSinGrain_next(PSinGrain* unit, int inNumSamples) {
float* out = ZOUT(0);
float y0;
float y1 = unit->m_y1;
float y2 = unit->m_y2;
float b1 = unit->m_b1;
float level = unit->m_level;
float slope = unit->m_slope;
float curve = unit->m_curve;
int32 counter = unit->mCounter;
int32 remain = inNumSamples;
int32 nsmps;
do {
if (counter <= 0) {
nsmps = remain;
remain = 0;
LOOP(nsmps, ZXP(out) = 0.f;); // can't use Clear bcs might not be aligned
} else {
nsmps = sc_min(remain, counter);
remain -= nsmps;
counter -= nsmps;
if (nsmps == inNumSamples) {
nsmps = unit->mRate->mFilterLoops;
LOOP(nsmps, y0 = b1 * y1 - y2; ZXP(out) = y0 * level; level += slope; slope += curve; y2 = b1 * y0 - y1;
ZXP(out) = y2 * level; level += slope; slope += curve; y1 = b1 * y2 - y0; ZXP(out) = y1 * level;
level += slope; slope += curve;);
nsmps = unit->mRate->mFilterRemain;
LOOP(nsmps, y0 = b1 * y1 - y2; y2 = y1; y1 = y0; ZXP(out) = y0 * level; level += slope;
slope += curve;);
} else {
LOOP(nsmps, y0 = b1 * y1 - y2; y2 = y1; y1 = y0; ZXP(out) = y0 * level; level += slope;
slope += curve;);
}
if (counter == 0) {
NodeEnd(&unit->mParent->mNode);
}
}
} while (remain > 0);
unit->mCounter = counter;
unit->m_level = level;
unit->m_slope = slope;
unit->m_y1 = y1;
unit->m_y2 = y2;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename OscType, int FreqInputIndex>
force_inline void Osc_ikk_perform(OscType* unit, const float* table0, const float* table1, int inNumSamples) {
float* out = ZOUT(0);
float freqin = ZIN0(FreqInputIndex);
float phasein = ZIN0(FreqInputIndex + 1);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
int32 freq = (int32)(unit->m_cpstoinc * freqin);
int32 phaseinc = freq + (int32)(CALCSLOPE(phasein, unit->m_phasein) * unit->m_radtoinc);
unit->m_phasein = phasein;
LOOP1(inNumSamples, ZXP(out) = lookupi1(table0, table1, phase, lomask); phase += phaseinc;);
unit->m_phase = phase;
}
void SinOsc_next_ikk(SinOsc* unit, int inNumSamples) {
float* table0 = ft->mSineWavetable;
float* table1 = table0 + 1;
Osc_ikk_perform<SinOsc, 0>(unit, table0, table1, inNumSamples);
}
template <typename OscType, int FreqInputIndex>
force_inline void Osc_ika_perform(OscType* unit, const float* table0, const float* table1, int inNumSamples) {
float* out = ZOUT(0);
float freqin = ZIN0(FreqInputIndex);
float* phasein = ZIN(FreqInputIndex + 1);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
int32 freq = (int32)(unit->m_cpstoinc * freqin);
float radtoinc = unit->m_radtoinc;
LOOP1(inNumSamples, int32 phaseoffset = phase + (int32)(radtoinc * ZXP(phasein));
ZXP(out) = lookupi1(table0, table1, phaseoffset, lomask); phase += freq;);
unit->m_phase = phase;
}
void SinOsc_next_ika(SinOsc* unit, int inNumSamples) {
const float* table0 = ft->mSineWavetable;
const float* table1 = table0 + 1;
Osc_ika_perform<SinOsc, 0>(unit, table0, table1, inNumSamples);
}
template <typename OscType, int FreqInputIndex>
force_inline void Osc_iaa_perform(OscType* unit, const float* table0, const float* table1, int inNumSamples) {
float* out = ZOUT(0);
float* freqin = ZIN(FreqInputIndex);
float* phasein = ZIN(FreqInputIndex + 1);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
float cpstoinc = unit->m_cpstoinc;
float radtoinc = unit->m_radtoinc;
LOOP1(inNumSamples, float phaseIn = ZXP(phasein); float freqIn = ZXP(freqin);
int32 phaseoffset = phase + (int32)(radtoinc * phaseIn);
float z = lookupi1(table0, table1, phaseoffset, lomask); phase += (int32)(cpstoinc * freqIn); ZXP(out) = z;);
unit->m_phase = phase;
}
void SinOsc_next_iaa(SinOsc* unit, int inNumSamples) {
const float* table0 = ft->mSineWavetable;
const float* table1 = table0 + 1;
Osc_iaa_perform<SinOsc, 0>(unit, table0, table1, inNumSamples);
}
template <typename OscType, int FreqInputIndex>
force_inline void Osc_iak_perform(OscType* unit, const float* table0, const float* table1, int inNumSamples) {
float* out = ZOUT(0);
float* freqin = ZIN(FreqInputIndex);
float phasein = ZIN0(FreqInputIndex + 1);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
float cpstoinc = unit->m_cpstoinc;
float radtoinc = unit->m_radtoinc;
float phasemod = unit->m_phasein;
if (phasein != phasemod) {
float phaseslope = CALCSLOPE(phasein, phasemod);
LOOP1(inNumSamples, int32 pphase = phase + (int32)(radtoinc * phasemod); phasemod += phaseslope;
float z = lookupi1(table0, table1, pphase, lomask); phase += (int32)(cpstoinc * ZXP(freqin));
ZXP(out) = z;);
} else {
LOOP1(inNumSamples, int32 pphase = phase + (int32)(radtoinc * phasemod);
float z = lookupi1(table0, table1, pphase, lomask); phase += (int32)(cpstoinc * ZXP(freqin));
ZXP(out) = z;);
}
unit->m_phase = phase;
unit->m_phasein = phasein;
}
void SinOsc_next_iak(SinOsc* unit, int inNumSamples) {
float* table0 = ft->mSineWavetable;
float* table1 = table0 + 1;
Osc_iak_perform<SinOsc, 0>(unit, table0, table1, inNumSamples);
}
template <typename OscType, int FreqInputIndex>
force_inline void Osc_iai_perform(OscType* unit, const float* table0, const float* table1, int inNumSamples) {
float* out = ZOUT(0);
float* freqin = ZIN(FreqInputIndex);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
float cpstoinc = unit->m_cpstoinc;
float radtoinc = unit->m_radtoinc;
float phasemod = unit->m_phasein;
LOOP1(inNumSamples, int32 pphase = phase + (int32)(radtoinc * phasemod);
float z = lookupi1(table0, table1, pphase, lomask); phase += (int32)(cpstoinc * ZXP(freqin)); ZXP(out) = z;);
unit->m_phase = phase;
}
void SinOsc_next_iai(SinOsc* unit, int inNumSamples) {
float* table0 = ft->mSineWavetable;
float* table1 = table0 + 1;
Osc_iai_perform<SinOsc, 0>(unit, table0, table1, inNumSamples);
}
void SinOsc_Ctor(SinOsc* unit) {
int tableSize2 = ft->mSineSize;
unit->m_phasein = ZIN0(1);
unit->m_radtoinc = tableSize2 * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize2 * SAMPLEDUR * 65536.;
unit->m_lomask = (tableSize2 - 1) << 3;
if (INRATE(0) == calc_FullRate) {
if (INRATE(1) == calc_FullRate)
SETCALC(SinOsc_next_iaa);
else if (INRATE(1) == calc_BufRate)
SETCALC(SinOsc_next_iak);
else
SETCALC(SinOsc_next_iai);
unit->m_phase = 0;
} else {
if (INRATE(1) == calc_FullRate) {
// Print("next_ika\n");
SETCALC(SinOsc_next_ika);
unit->m_phase = 0;
} else {
SETCALC(SinOsc_next_ikk);
unit->m_phase = (int32)(unit->m_phasein * unit->m_radtoinc);
}
}
SinOsc_next_ikk(unit, 1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////!!!
void SinOscFB_next_kk(SinOscFB* unit, int inNumSamples) {
float* out = ZOUT(0);
float freqin = ZIN0(0);
float feedback = unit->m_feedback;
float nextFeedback = ZIN0(1) * unit->m_radtoinc;
float* table0 = ft->mSineWavetable;
float* table1 = table0 + 1;
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
float prevout = unit->m_prevout;
float feedback_slope = CALCSLOPE(nextFeedback, feedback);
int32 freq = (int32)(unit->m_cpstoinc * freqin);
LooP(inNumSamples) {
prevout = lookupi1(table0, table1, phase + (int32)(feedback * prevout), lomask);
ZXP(out) = prevout;
phase += freq;
feedback += feedback_slope;
}
unit->m_phase = phase;
unit->m_prevout = prevout;
unit->m_feedback = feedback;
}
void SinOscFB_Ctor(SinOscFB* unit) {
// Print("next_ik\n");
SETCALC(SinOscFB_next_kk);
int tableSize2 = ft->mSineSize;
unit->m_lomask = (tableSize2 - 1) << 3;
unit->m_radtoinc = tableSize2 * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize2 * SAMPLEDUR * 65536.;
unit->m_prevout = 0.;
unit->m_feedback = ZIN0(1) * unit->m_radtoinc;
unit->m_phase = 0;
SinOscFB_next_kk(unit, 1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Osc_Ctor(Osc* unit) {
unit->mTableSize = -1;
float fbufnum = ZIN0(0);
uint32 bufnum = (uint32)fbufnum;
World* world = unit->mWorld;
SndBuf* buf;
if (bufnum >= world->mNumSndBufs) {
int localBufNum = bufnum - world->mNumSndBufs;
Graph* parent = unit->mParent;
if (localBufNum <= parent->localBufNum) {
buf = unit->m_buf = parent->mLocalSndBufs + localBufNum;
} else {
buf = unit->m_buf = world->mSndBufs;
}
} else {
buf = unit->m_buf = world->mSndBufs + bufnum;
}
int tableSize = buf->samples;
int tableSize2 = tableSize >> 1;
unit->m_radtoinc = tableSize2 * (rtwopi * 65536.); // Osc, OscN, PMOsc
unit->m_phasein = ZIN0(2);
if (INRATE(1) == calc_FullRate) {
if (INRATE(2) == calc_FullRate) {
// Print("next_iaa\n");
SETCALC(Osc_next_iaa);
unit->m_phase = 0;
} else {
// Print("next_iak\n");
SETCALC(Osc_next_iak);
unit->m_phase = 0;
}
} else {
if (INRATE(2) == calc_FullRate) {
// Print("next_ika\n");
SETCALC(Osc_next_ika);
unit->m_phase = 0;
} else {
// Print("next_ikk\n");
SETCALC(Osc_next_ikk);
unit->m_phase = (int32)(unit->m_phasein * unit->m_radtoinc);
}
}
Osc_next_ikk(unit, 1);
}
force_inline bool Osc_get_table(Osc* unit, const float*& table0, const float*& table1, int inNumSamples) {
const SndBuf* buf;
const float* bufData;
int tableSize;
bool tableValid = UnitGetTable(unit, inNumSamples, buf, bufData, tableSize);
if (!tableValid)
return false;
table0 = bufData;
table1 = table0 + 1;
if (tableSize != unit->mTableSize) {
unit->mTableSize = tableSize;
int tableSize2 = tableSize >> 1;
unit->m_lomask = (tableSize2 - 1) << 3; // Osc, OscN, COsc, COsc, COsc2, OscX4, OscX2
unit->m_radtoinc = tableSize2 * (rtwopi * 65536.); // Osc, OscN, PMOsc
// Osc, OscN, PMOsc, COsc, COsc2, OscX4, OscX2
unit->m_cpstoinc = tableSize2 * SAMPLEDUR * 65536.;
}
if (!verify_wavetable(unit, "Osc", tableSize, inNumSamples))
return false;
return true;
}
void Osc_next_ikk(Osc* unit, int inNumSamples) {
const float* table0;
const float* table1;
bool tableValid = Osc_get_table(unit, table0, table1, inNumSamples);
if (!tableValid)
return;
Osc_ikk_perform<Osc, 1>(unit, table0, table1, inNumSamples);
}
void Osc_next_ika(Osc* unit, int inNumSamples) {
const float* table0;
const float* table1;
bool tableValid = Osc_get_table(unit, table0, table1, inNumSamples);
if (!tableValid)
return;
Osc_ika_perform<Osc, 1>(unit, table0, table1, inNumSamples);
}
void Osc_next_iaa(Osc* unit, int inNumSamples) {
const float* table0;
const float* table1;
bool tableValid = Osc_get_table(unit, table0, table1, inNumSamples);
if (!tableValid)
return;
Osc_iaa_perform<Osc, 1>(unit, table0, table1, inNumSamples);
}
void Osc_next_iak(Osc* unit, int inNumSamples) {
const float* table0;
const float* table1;
bool tableValid = Osc_get_table(unit, table0, table1, inNumSamples);
if (!tableValid)
return;
Osc_iak_perform<Osc, 1>(unit, table0, table1, inNumSamples);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OscN_Ctor(OscN* unit) {
unit->mTableSize = -1;
float fbufnum = ZIN0(0);
uint32 bufnum = (uint32)fbufnum;
World* world = unit->mWorld;
SndBuf* buf;
if (bufnum >= world->mNumSndBufs) {
int localBufNum = bufnum - world->mNumSndBufs;
Graph* parent = unit->mParent;
if (localBufNum <= parent->localBufNum) {
buf = unit->m_buf = parent->mLocalSndBufs + localBufNum;
} else {
buf = unit->m_buf = world->mSndBufs;
}
} else {
buf = unit->m_buf = world->mSndBufs + bufnum;
}
int tableSize = buf->samples;
unit->m_radtoinc = tableSize * (rtwopi * 65536.);
unit->m_phasein = ZIN0(2);
// Print("OscN_Ctor\n");
if (INRATE(1) == calc_FullRate) {
if (INRATE(2) == calc_FullRate) {
// Print("next_naa\n");
SETCALC(OscN_next_naa);
unit->m_phase = 0;
} else {
// Print("next_nak\n");
SETCALC(OscN_next_nak);
unit->m_phase = 0;
}
} else {
if (INRATE(2) == calc_FullRate) {
// Print("next_nka\n");
SETCALC(OscN_next_nka);
unit->m_phase = 0;
} else {
// Print("next_nkk\n");
SETCALC(OscN_next_nkk);
unit->m_phase = (int32)(unit->m_phasein * unit->m_radtoinc);
}
}
OscN_next_nkk(unit, 1);
}
void OscN_next_nkk(OscN* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
if (tableSize != unit->mTableSize) {
unit->mTableSize = tableSize;
unit->m_lomask = (tableSize - 1) << 2;
unit->m_radtoinc = tableSize * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize * SAMPLEDUR * 65536.;
}
if (!verify_wavetable(unit, "OscN", tableSize, inNumSamples))
return;
float* out = ZOUT(0);
float freqin = ZIN0(1);
float phasein = ZIN0(2);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
int32 freq = (int32)(unit->m_cpstoinc * freqin);
int32 phaseinc = freq + (int32)(CALCSLOPE(phasein, unit->m_phasein) * unit->m_radtoinc);
unit->m_phasein = phasein;
LOOP1(inNumSamples, ZXP(out) = *(float*)((char*)table + ((phase >> xlobits) & lomask)); phase += phaseinc;);
unit->m_phase = phase;
}
void OscN_next_nka(OscN* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
if (tableSize != unit->mTableSize) {
unit->mTableSize = tableSize;
unit->m_lomask = (tableSize - 1) << 2;
unit->m_radtoinc = tableSize * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize * SAMPLEDUR * 65536.;
}
if (!verify_wavetable(unit, "OscN", tableSize, inNumSamples))
return;
float* out = ZOUT(0);
float freqin = ZIN0(1);
float* phasein = ZIN(2);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
int32 freq = (int32)(unit->m_cpstoinc * freqin);
float radtoinc = unit->m_radtoinc;
LOOP1(inNumSamples, int32 pphase = phase + (int32)(radtoinc * ZXP(phasein));
ZXP(out) = *(float*)((char*)table + ((pphase >> xlobits) & lomask)); phase += freq;);
unit->m_phase = phase;
}
void OscN_next_naa(OscN* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
if (tableSize != unit->mTableSize) {
unit->mTableSize = tableSize;
unit->m_lomask = (tableSize - 1) << 2;
unit->m_radtoinc = tableSize * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize * SAMPLEDUR * 65536.;
}
if (!verify_wavetable(unit, "OscN", tableSize, inNumSamples))
return;
float* out = ZOUT(0);
float* freqin = ZIN(1);
float* phasein = ZIN(2);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
float cpstoinc = unit->m_cpstoinc;
float radtoinc = unit->m_radtoinc;
LOOP1(inNumSamples, int32 pphase = phase + (int32)(radtoinc * ZXP(phasein));
float z = *(float*)((char*)table + ((pphase >> xlobits) & lomask)); phase += (int32)(cpstoinc * ZXP(freqin));
ZXP(out) = z;);
unit->m_phase = phase;
}
void OscN_next_nak(OscN* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table = bufData;
if (tableSize != unit->mTableSize) {
unit->mTableSize = tableSize;
unit->m_lomask = (tableSize - 1) << 2;
unit->m_radtoinc = tableSize * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize * SAMPLEDUR * 65536.;
}
if (!verify_wavetable(unit, "OscN", tableSize, inNumSamples))
return;
float* out = ZOUT(0);
float* freqin = ZIN(1);
float phasein = ZIN0(2);
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
float cpstoinc = unit->m_cpstoinc;
float radtoinc = unit->m_radtoinc;
float phasemod = unit->m_phasein;
float phaseslope = CALCSLOPE(phasein, phasemod);
LOOP1(inNumSamples, int32 pphase = phase + (int32)(radtoinc * phasemod); phasemod += phaseslope;
float z = *(float*)((char*)table + ((pphase >> xlobits) & lomask)); phase += (int32)(cpstoinc * ZXP(freqin));
ZXP(out) = z;);
unit->m_phase = phase;
unit->m_phasein = phasein;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void COsc_Ctor(COsc* unit) {
unit->m_fbufnum = std::numeric_limits<float>::quiet_NaN();
SETCALC(COsc_next);
unit->m_phase1 = 0;
unit->m_phase2 = 0;
unit->mTableSize = -1;
COsc_next(unit, 1);
}
void COsc_next(COsc* unit, int inNumSamples) {
// get table
GET_TABLE
const float* table0 = bufData;
const float* table1 = table0 + 1;
if (tableSize != unit->mTableSize) {
unit->mTableSize = tableSize;
int tableSize2 = tableSize >> 1;
unit->m_lomask = (tableSize2 - 1) << 3; // Osc, OscN, COsc, COsc, COsc2, OscX4, OscX2
// Osc, OscN, PMOsc, COsc, COsc2, OscX4, OscX2
unit->m_cpstoinc = tableSize2 * SAMPLEDUR * 65536.;
}
if (!verify_wavetable(unit, "COsc", tableSize, inNumSamples))
return;
float* out = ZOUT(0);
float freqin = ZIN0(1);
float beats = ZIN0(2) * 0.5f;
int32 phase1 = unit->m_phase1;
int32 phase2 = unit->m_phase2;
int32 lomask = unit->m_lomask;
int32 cfreq = (int32)(unit->m_cpstoinc * freqin);
int32 beatf = (int32)(unit->m_cpstoinc * beats);
int32 freq1 = cfreq + beatf;
int32 freq2 = cfreq - beatf;
LOOP1(inNumSamples, float a = lookupi1(table0, table1, phase1, lomask);
float b = lookupi1(table0, table1, phase2, lomask); ZXP(out) = a + b; phase1 += freq1; phase2 += freq2;);
unit->m_phase1 = phase1;
unit->m_phase2 = phase2;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static inline const SndBuf* VOscGetBuf(int& bufnum, World* world, Unit* unit) {
if (bufnum < 0)
bufnum = 0;
const SndBuf* bufs;
if (bufnum + 1 >= world->mNumSndBufs) {
int localBufNum = bufnum - world->mNumSndBufs;
Graph* parent = unit->mParent;
if (localBufNum <= parent->localBufNum) {
bufs = parent->mLocalSndBufs + localBufNum;
} else {
bufnum = 0;
bufs = world->mSndBufs + bufnum;
}
} else {
if (bufnum >= world->mNumSndBufs)
bufnum = 0;
bufs = world->mSndBufs + sc_max(0, bufnum);
}
return bufs;
}
void VOsc_Ctor(VOsc* unit) {
float nextbufpos = ZIN0(0);
unit->m_bufpos = nextbufpos;
int bufnum = sc_floor(nextbufpos);
World* world = unit->mWorld;
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
int tableSize = bufs[0].samples;
unit->mTableSize = tableSize;
int tableSize2 = tableSize >> 1;
unit->m_lomask = (tableSize2 - 1) << 3;
unit->m_radtoinc = tableSize2 * (rtwopi * 65536.);
unit->m_cpstoinc = tableSize2 * SAMPLEDUR * 65536.;
unit->m_phasein = ZIN0(2);
unit->m_phaseoffset = (int32)(unit->m_phasein * unit->m_radtoinc);
if (INRATE(2) == calc_FullRate) {
SETCALC(VOsc_next_ika);
unit->m_phase = 0;
} else {
SETCALC(VOsc_next_ikk);
unit->m_phase = unit->m_phaseoffset;
}
VOsc_next_ikk(unit, 1);
}
void VOsc_next_ikk(VOsc* unit, int inNumSamples) {
float* out = ZOUT(0);
float nextbufpos = ZIN0(0);
float freqin = ZIN0(1);
float phasein = ZIN0(2);
float prevbufpos = unit->m_bufpos;
float bufdiff = nextbufpos - prevbufpos;
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
int32 freq = (int32)(unit->m_cpstoinc * freqin);
int32 phaseinc = freq + (int32)(CALCSLOPE(phasein, unit->m_phasein) * unit->m_radtoinc);
unit->m_phasein = phasein;
int tableSize = unit->mTableSize;
float cur = prevbufpos;
World* world = unit->mWorld;
if (bufdiff == 0.f) {
float level = cur - sc_floor(cur);
int32 bufnum = (int)sc_floor(cur);
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
if (!verify_wavetable(unit, "VOsc", tableSize, inNumSamples))
return;
const float* table0 = bufs[0].data;
const float* table2 = bufs[1].data;
if (!table0 || !table2 || tableSize != bufs[0].samples || tableSize != bufs[1].samples) {
ClearUnitOutputs(unit, inNumSamples);
return;
}
const float* table1 = table0 + 1;
const float* table3 = table2 + 1;
LOOP1(inNumSamples, float pfrac = PhaseFrac1(phase); uint32 index = ((phase >> xlobits1) & lomask);
float val0 = *(float*)((char*)table0 + index); float val1 = *(float*)((char*)table1 + index);
float val2 = *(float*)((char*)table2 + index); float val3 = *(float*)((char*)table3 + index);
float a = val0 + val1 * pfrac; float b = val2 + val3 * pfrac; ZXP(out) = a + level * (b - a);
phase += phaseinc;);
} else {
int nsmps;
int donesmps = 0;
int remain = inNumSamples;
while (remain) {
float level = cur - sc_floor(cur);
float cut;
if (bufdiff > 0.) {
cut = sc_min(nextbufpos, sc_floor(cur + 1.f));
} else {
cut = sc_max(nextbufpos, sc_ceil(cur - 1.f));
}
float sweepdiff = cut - cur;
if (cut == nextbufpos)
nsmps = remain;
else {
float sweep = (float)inNumSamples / bufdiff;
nsmps = (int)sc_floor(sweep * sweepdiff + 0.5f) - donesmps;
nsmps = sc_clip(nsmps, 1, remain);
}
float slope = sweepdiff / (float)nsmps;
int32 bufnum = (int32)sc_floor(cur);
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
if (!verify_wavetable(unit, "VOsc", tableSize, inNumSamples))
return;
const float* table0 = bufs[0].data;
const float* table2 = bufs[1].data;
if (!table0 || !table2 || tableSize != bufs[0].samples || tableSize != bufs[1].samples) {
ClearUnitOutputs(unit, inNumSamples);
return;
}
const float* table1 = table0 + 1;
const float* table3 = table2 + 1;
LOOP(nsmps, float pfrac = PhaseFrac1(phase); uint32 index = ((phase >> xlobits1) & lomask);
float val0 = *(float*)((char*)table0 + index); float val1 = *(float*)((char*)table1 + index);
float val2 = *(float*)((char*)table2 + index); float val3 = *(float*)((char*)table3 + index);
float a = val0 + val1 * pfrac; float b = val2 + val3 * pfrac; ZXP(out) = a + level * (b - a);
phase += phaseinc; level += slope;);
donesmps += nsmps;
remain -= nsmps;
cur = cut;
}
}
unit->m_bufpos = nextbufpos;
unit->m_phase = phase;
}
void VOsc_next_ika(VOsc* unit, int inNumSamples) {
float* out = ZOUT(0);
float nextbufpos = ZIN0(0);
float freqin = ZIN0(1);
float* phasein = ZIN(2);
float prevbufpos = unit->m_bufpos;
float bufdiff = nextbufpos - prevbufpos;
int32 phase = unit->m_phase;
int32 lomask = unit->m_lomask;
int32 freq = (int32)(unit->m_cpstoinc * freqin);
int32 phaseinc = freq;
int tableSize = unit->mTableSize;
float cur = prevbufpos;
World* world = unit->mWorld;
if (bufdiff == 0.f) {
float level = cur - sc_floor(cur);
int32 bufnum = (int)sc_floor(cur);
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
if (!verify_wavetable(unit, "VOsc", tableSize, inNumSamples))
return;
const float* table0 = bufs[0].data;
const float* table2 = bufs[1].data;
if (!table0 || !table2 || tableSize != bufs[0].samples || tableSize != bufs[1].samples) {
ClearUnitOutputs(unit, inNumSamples);
return;
}
const float* table1 = table0 + 1;
const float* table3 = table2 + 1;
LOOP1(inNumSamples, int32 pphase = phase + (int32)(ZXP(phasein) * unit->m_radtoinc);
float pfrac = PhaseFrac1(pphase); uint32 index = ((pphase >> xlobits1) & lomask);
float val0 = *(float*)((char*)table0 + index); float val1 = *(float*)((char*)table1 + index);
float val2 = *(float*)((char*)table2 + index); float val3 = *(float*)((char*)table3 + index);
float a = val0 + val1 * pfrac; float b = val2 + val3 * pfrac; ZXP(out) = a + level * (b - a);
phase += phaseinc;);
} else {
int nsmps;
int donesmps = 0;
int remain = inNumSamples;
while (remain) {
float level = cur - sc_floor(cur);
float cut;
if (bufdiff > 0.) {
cut = sc_min(nextbufpos, sc_floor(cur + 1.f));
} else {
cut = sc_max(nextbufpos, sc_ceil(cur - 1.f));
}
float sweepdiff = cut - cur;
if (cut == nextbufpos)
nsmps = remain;
else {
float sweep = (float)inNumSamples / bufdiff;
nsmps = (int)sc_floor(sweep * sweepdiff + 0.5f) - donesmps;
nsmps = sc_clip(nsmps, 1, remain);
}
float slope = sweepdiff / (float)nsmps;
int32 bufnum = (int32)sc_floor(cur);
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
if (!verify_wavetable(unit, "VOsc", tableSize, inNumSamples))
return;
const float* table0 = bufs[0].data;
const float* table2 = bufs[1].data;
if (!table0 || !table2 || tableSize != bufs[0].samples || tableSize != bufs[1].samples) {
ClearUnitOutputs(unit, inNumSamples);
return;
}
const float* table1 = table0 + 1;
const float* table3 = table2 + 1;
LOOP(nsmps, int32 pphase = phase + (int32)(ZXP(phasein) * unit->m_radtoinc);
float pfrac = PhaseFrac1(pphase); uint32 index = ((pphase >> xlobits1) & lomask);
float val0 = *(float*)((char*)table0 + index); float val1 = *(float*)((char*)table1 + index);
float val2 = *(float*)((char*)table2 + index); float val3 = *(float*)((char*)table3 + index);
float a = val0 + val1 * pfrac; float b = val2 + val3 * pfrac; ZXP(out) = a + level * (b - a);
phase += phaseinc; level += slope;);
donesmps += nsmps;
remain -= nsmps;
cur = cut;
}
}
unit->m_bufpos = nextbufpos;
unit->m_phase = phase;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void VOsc3_Ctor(VOsc3* unit) {
SETCALC(VOsc3_next_ik);
float nextbufpos = ZIN0(0);
unit->m_bufpos = nextbufpos;
int32 bufnum = (int32)sc_floor(nextbufpos);
World* world = unit->mWorld;
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
int tableSize = bufs[0].samples;
unit->mTableSize = tableSize;
int tableSize2 = tableSize >> 1;
unit->m_lomask = (tableSize2 - 1) << 3;
unit->m_cpstoinc = tableSize2 * SAMPLEDUR * 65536.;
unit->m_phase1 = 0;
unit->m_phase2 = 0;
unit->m_phase3 = 0;
VOsc3_next_ik(unit, 1);
}
void VOsc3_next_ik(VOsc3* unit, int inNumSamples) {
float* out = ZOUT(0);
float nextbufpos = ZIN0(0);
float freq1in = ZIN0(1);
float freq2in = ZIN0(2);
float freq3in = ZIN0(3);
float prevbufpos = unit->m_bufpos;
float bufdiff = nextbufpos - prevbufpos;
int32 phase1 = unit->m_phase1;
int32 phase2 = unit->m_phase2;
int32 phase3 = unit->m_phase3;
int32 freq1 = (int32)(unit->m_cpstoinc * freq1in);
int32 freq2 = (int32)(unit->m_cpstoinc * freq2in);
int32 freq3 = (int32)(unit->m_cpstoinc * freq3in);
int32 lomask = unit->m_lomask;
int tableSize = unit->mTableSize;
float cur = prevbufpos;
World* world = unit->mWorld;
if (bufdiff == 0.f) {
float level = cur - (int)cur;
int bufnum = (int)cur;
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
if (!verify_wavetable(unit, "VOsc3", tableSize, inNumSamples))
return;
const float* table0 = bufs[0].data;
const float* table2 = bufs[1].data;
if (!table0 || !table2 || tableSize != bufs[0].samples || tableSize != bufs[1].samples) {
ClearUnitOutputs(unit, inNumSamples);
return;
}
const float* table1 = table0 + 1;
const float* table3 = table2 + 1;
LOOP1(inNumSamples,
float pfrac1 = PhaseFrac1(phase1);
float pfrac2 = PhaseFrac1(phase2); float pfrac3 = PhaseFrac1(phase3);
int index1 = ((phase1 >> xlobits1) & lomask); int index2 = ((phase2 >> xlobits1) & lomask);
int index3 = ((phase3 >> xlobits1) & lomask);
phase1 += freq1; phase2 += freq2; phase3 += freq3;
float val10 = *(float*)((char*)table0 + index1); float val11 = *(float*)((char*)table1 + index1);
float val12 = *(float*)((char*)table2 + index1); float val13 = *(float*)((char*)table3 + index1);
float a = val10 + val11 * pfrac1; float b = val12 + val13 * pfrac1;
float val20 = *(float*)((char*)table0 + index2); float val21 = *(float*)((char*)table1 + index2);
float val22 = *(float*)((char*)table2 + index2); float val23 = *(float*)((char*)table3 + index2);
a += val20 + val21 * pfrac2; b += val22 + val23 * pfrac2;
float val30 = *(float*)((char*)table0 + index3); float val31 = *(float*)((char*)table1 + index3);
float val32 = *(float*)((char*)table2 + index3); float val33 = *(float*)((char*)table3 + index3);
a += val30 + val31 * pfrac3; b += val32 + val33 * pfrac3;
ZXP(out) = a + level * (b - a););
} else {
int nsmps;
int donesmps = 0;
int remain = inNumSamples;
do {
float level = cur - sc_trunc(cur);
float cut;
if (bufdiff >= 0.)
cut = sc_min(nextbufpos, sc_trunc(cur + 1.f));
else
cut = sc_max(nextbufpos, sc_ceil(cur - 1.f));
float sweepdiff = cut - cur;
if (cut == nextbufpos)
nsmps = remain;
else {
float sweep = (float)inNumSamples / bufdiff;
nsmps = sc_floor(sweep * sweepdiff + 0.5f) - donesmps;
nsmps = sc_clip(nsmps, 1, remain);
}
float slope = sweepdiff / (float)nsmps;
int bufnum = (int)cur;
const SndBuf* bufs = VOscGetBuf(bufnum, world, unit);
if (!verify_wavetable(unit, "VOsc3", tableSize, inNumSamples))
return;
const float* table0 = bufs[0].data;
const float* table2 = bufs[1].data;
if (!table0 || !table2 || tableSize != bufs[0].samples || tableSize != bufs[1].samples) {
ClearUnitOutputs(unit, inNumSamples);
return;
}
const float* table1 = table0 + 1;
const float* table3 = table2 + 1;
LOOP(nsmps,
float pfrac1 = PhaseFrac1(phase1);
float pfrac2 = PhaseFrac1(phase2); float pfrac3 = PhaseFrac1(phase3);
int index1 = ((phase1 >> xlobits1) & lomask); int index2 = ((phase2 >> xlobits1) & lomask);
int index3 = ((phase3 >> xlobits1) & lomask);
phase1 += freq1; phase2 += freq2; phase3 += freq3;
float val10 = *(float*)((char*)table0 + index1); float val11 = *(float*)((char*)table1 + index1);
float val12 = *(float*)((char*)table2 + index1); float val13 = *(float*)((char*)table3 + index1);
float a = val10 + val11 * pfrac1; float b = val12 + val13 * pfrac1;
float val20 = *(float*)((char*)table0 + index2); float val21 = *(float*)((char*)table1 + index2);
float val22 = *(float*)((char*)table2 + index2); float val23 = *(float*)((char*)table3 + index2);
a += val20 + val21 * pfrac2; b += val22 + val23 * pfrac2;
float val30 = *(float*)((char*)table0 + index3); float val31 = *(float*)((char*)table1 + index3);
float val32 = *(float*)((char*)table2 + index3); float val33 = *(float*)((char*)table3 + index3);
a += val30 + val31 * pfrac3; b += val32 + val33 * pfrac3;
ZXP(out) = a + level * (b - a); level += slope;);
donesmps += nsmps;
remain -= nsmps;
cur = cut;
} while (remain);
}
unit->m_bufpos = nextbufpos;
unit->m_phase1 = phase1;
unit->m_phase2 = phase2;
unit->m_phase3 = phase3;
}
//////////////////////////////////////////////////////////////////////////////////////////
void Formant_Ctor(Formant* unit) {
SETCALC(Formant_next);
unit->m_cpstoinc = ft->mSineSize * SAMPLEDUR * 65536.;
unit->m_phase1 = 0;
unit->m_phase2 = 0;
unit->m_phase3 = 0;
Formant_next(unit, 1);
}
#define tqcyc13 0x18000000
void Formant_next(Formant* unit, int inNumSamples) {
float* out = ZOUT(0);
float freq1in = ZIN0(0);
float freq2in = ZIN0(1);
float freq3in = ZIN0(2);
int32 phase1 = unit->m_phase1;
int32 phase2 = unit->m_phase2;
int32 phase3 = unit->m_phase3;
float cpstoinc = unit->m_cpstoinc;
int32 freq1 = (int32)(cpstoinc * freq1in);
int32 freq2 = (int32)(cpstoinc * freq2in);
int32 freq3 = (int32)(cpstoinc * freq3in);
float* sine = ft->mSine;
int32 formfreq = sc_max(freq1, freq3);
LOOP1(
inNumSamples,
if (phase3 < onecyc13) {
ZXP(out) = (*(float*)((char*)sine + (((phase3 + tqcyc13) >> xlobits) & xlomask13)) + 1.f)
* *(float*)((char*)sine + ((phase2 >> xlobits) & xlomask13));
phase3 += formfreq;
} else { ZXP(out) = 0.f; } phase1 += freq1;
phase2 += freq2; if (phase1 > onecyc13) {
phase1 -= onecyc13;
phase2 = phase1 * freq2 / freq1;
phase3 = phase1 * freq3 / freq1;
});
unit->m_phase1 = phase1;
unit->m_phase2 = phase2;
unit->m_phase3 = phase3;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
inline float lookup13(float* table, int32 pphase) {
float pfrac = PhaseFrac(pphase);
float* tbl = (float*)((char*)table + ((pphase >> xlobits) & xlomask13));
return lininterp(pfrac, tbl[0], tbl[1]);
}
void Blip_Ctor(Blip* unit) {
SETCALC(Blip_next);
unit->m_freqin = ZIN0(0);
unit->m_numharm = (int32)ZIN0(1);
unit->m_cpstoinc = ft->mSineSize * SAMPLEDUR * 65536. * 0.5;
int32 N = unit->m_numharm;
int32 maxN = (int32)((SAMPLERATE * 0.5) / unit->m_freqin);
if (N > maxN)
N = maxN;
if (N < 1)
N = 1;
unit->m_N = N;
unit->m_scale = 0.5 / N;
unit->m_phase = 0;
Blip_next(unit, 1);
}
void Blip_next(Blip* unit, int inNumSamples) {
float* out = ZOUT(0);
float freqin = ZIN0(0);
int numharm = (int32)ZIN0(1);
int32 phase = unit->m_phase;
float* numtbl = ft->mSine;
float* dentbl = ft->mCosecant;
int32 freq, N, prevN;
float scale, prevscale;
bool crossfade;
if (numharm != unit->m_numharm || freqin != unit->m_freqin) {
N = numharm;
int32 maxN = (int32)((SAMPLERATE * 0.5) / freqin);
if (N > maxN) {
float maxfreqin;
N = maxN;
maxfreqin = sc_max(unit->m_freqin, freqin);
freq = (int32)(unit->m_cpstoinc * maxfreqin);
} else {
if (N < 1) {
N = 1;
}
freq = (int32)(unit->m_cpstoinc * freqin);
}
crossfade = N != unit->m_N;
prevN = unit->m_N;
prevscale = unit->m_scale;
unit->m_N = N;
unit->m_scale = scale = 0.5 / N;
} else {
N = unit->m_N;
freq = (int32)(unit->m_cpstoinc * freqin);
scale = unit->m_scale;
crossfade = false;
}
int32 N2 = 2 * N + 1;
if (crossfade) {
int32 prevN2 = 2 * prevN + 1;
float xfade_slope = unit->mRate->mSlopeFactor;
float xfade = 0.f;
LOOP1(
inNumSamples, float* tbl = (float*)((char*)dentbl + ((phase >> xlobits) & xlomask13)); float t0 = tbl[0];
float t1 = tbl[1]; if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
ZXP(out) = 1.f;
} else {
int32 rphase = phase * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer / denom - 1.f) * prevscale;
rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer / denom - 1.f) * scale;
ZXP(out) = lininterp(xfade, n1, n2);
}
} else {
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase * prevN2;
pfrac = PhaseFrac(rphase);
float* tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer * denom - 1.f) * prevscale;
rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer * denom - 1.f) * scale;
ZXP(out) = lininterp(xfade, n1, n2);
} phase += freq;
xfade += xfade_slope;);
} else {
// hmm, if freq is above sr/4 then revert to sine table osc w/ no interpolation ?
// why bother, it isn't a common choice for a fundamental.
LOOP1(
inNumSamples, float* tbl = (float*)((char*)dentbl + ((phase >> xlobits) & xlomask13)); float t0 = tbl[0];
float t1 = tbl[1]; if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
ZXP(out) = 1.f;
} else {
int32 rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
ZXP(out) = (numer / denom - 1.f) * scale;
}
} else {
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
ZXP(out) = (numer * denom - 1.f) * scale;
} phase += freq;);
}
unit->m_phase = phase;
unit->m_freqin = freqin;
unit->m_numharm = numharm;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Saw_Ctor(Saw* unit) {
SETCALC(Saw_next);
unit->m_freqin = ZIN0(0);
unit->m_cpstoinc = ft->mSineSize * SAMPLEDUR * 65536. * 0.5;
unit->m_N = (int32)((SAMPLERATE * 0.5) / unit->m_freqin);
unit->m_scale = 0.5 / unit->m_N;
unit->m_phase = 0;
unit->m_y1 = -0.46f;
ZOUT0(0) = 0.f;
}
void Saw_next(Saw* unit, int inNumSamples) {
float* out = ZOUT(0);
float freqin = ZIN0(0);
int32 phase = unit->m_phase;
float y1 = unit->m_y1;
float* numtbl = ft->mSine;
float* dentbl = ft->mCosecant;
int32 freq, N, prevN;
float scale, prevscale;
bool crossfade;
if (freqin != unit->m_freqin) {
N = (int32)((SAMPLERATE * 0.5) / freqin);
if (N != unit->m_N) {
float maxfreqin;
maxfreqin = sc_max(unit->m_freqin, freqin);
freq = (int32)(unit->m_cpstoinc * maxfreqin);
crossfade = true;
} else {
freq = (int32)(unit->m_cpstoinc * freqin);
crossfade = false;
}
prevN = unit->m_N;
prevscale = unit->m_scale;
unit->m_N = N;
unit->m_scale = scale = 0.5 / N;
} else {
N = unit->m_N;
freq = (int32)(unit->m_cpstoinc * freqin);
scale = unit->m_scale;
crossfade = false;
}
int32 N2 = 2 * N + 1;
if (crossfade) {
int32 prevN2 = 2 * prevN + 1;
float xfade_slope = unit->mRate->mSlopeFactor;
float xfade = 0.f;
LOOP1(
inNumSamples, float* tbl = (float*)((char*)dentbl + ((phase >> xlobits) & xlomask13)); float t0 = tbl[0];
float t1 = tbl[1]; if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
ZXP(out) = y1 = 1.f + 0.999f * y1;
} else {
int32 rphase = phase * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer / denom - 1.f) * prevscale;
rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer / denom - 1.f) * scale;
ZXP(out) = y1 = n1 + xfade * (n2 - n1) + 0.999f * y1;
}
} else {
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer * denom - 1.f) * prevscale;
rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer * denom - 1.f) * scale;
ZXP(out) = y1 = n1 + xfade * (n2 - n1) + 0.999f * y1;
} phase += freq;
xfade += xfade_slope;);
} else {
// hmm, if freq is above sr/4 then revert to sine table osc ?
// why bother, it isn't a common choice for a fundamental.
LOOP1(
inNumSamples, float* tbl = (float*)((char*)dentbl + ((phase >> xlobits) & xlomask13)); float t0 = tbl[0];
float t1 = tbl[1]; if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
ZXP(out) = y1 = 1.f + 0.999f * y1;
} else {
int32 rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
ZXP(out) = y1 = (numer / denom - 1.f) * scale + 0.999f * y1;
}
} else {
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase * N2;
pfrac = PhaseFrac(rphase);
float* tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
ZXP(out) = y1 = (numer * denom - 1.f) * scale + 0.999f * y1;
} phase += freq;);
}
unit->m_y1 = y1;
unit->m_phase = phase;
unit->m_freqin = freqin;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void Pulse_Ctor(Pulse* unit) {
SETCALC(Pulse_next);
unit->m_freqin = ZIN0(0);
unit->m_cpstoinc = ft->mSineSize * SAMPLEDUR * 65536. * 0.5;
unit->m_N = (int32)((SAMPLERATE * 0.5) / unit->m_freqin);
unit->m_scale = 0.5 / unit->m_N;
unit->m_phase = 0;
unit->m_phaseoff = 0;
unit->m_y1 = 0.f;
ZOUT0(0) = 0.f;
}
void Pulse_next(Pulse* unit, int inNumSamples) {
float* out = ZOUT(0);
float freqin = ZIN0(0);
float duty = ZIN0(1);
int32 phase = unit->m_phase;
float y1 = unit->m_y1;
float* numtbl = ft->mSine;
float* dentbl = ft->mCosecant;
int32 freq, N, prevN;
float scale, prevscale;
bool crossfade;
if (freqin != unit->m_freqin) {
N = (int32)((SAMPLERATE * 0.5) / freqin);
if (N != unit->m_N) {
float maxfreqin;
maxfreqin = sc_max(unit->m_freqin, freqin);
freq = (int32)(unit->m_cpstoinc * maxfreqin);
crossfade = true;
} else {
freq = (int32)(unit->m_cpstoinc * freqin);
crossfade = false;
}
prevN = unit->m_N;
prevscale = unit->m_scale;
unit->m_N = N;
unit->m_scale = scale = 0.5 / N;
} else {
N = unit->m_N;
freq = (int32)(unit->m_cpstoinc * freqin);
scale = unit->m_scale;
crossfade = false;
}
int32 N2 = 2 * N + 1;
int32 phaseoff = unit->m_phaseoff;
int32 next_phaseoff = (int32)(duty * (1L << 28));
int32 phaseoff_slope = (int32)((next_phaseoff - phaseoff) * unit->mRate->mSlopeFactor);
unit->m_phaseoff = next_phaseoff;
float rscale = 1.f / scale + 1.f;
float pul1, pul2;
if (crossfade) {
int32 prevN2 = 2 * prevN + 1;
float xfade_slope = unit->mRate->mSlopeFactor;
float xfade = 0.f;
LOOP1(
inNumSamples, float* tbl = (float*)((char*)dentbl + ((phase >> xlobits) & xlomask13)); float t0 = tbl[0];
float t1 = tbl[1]; if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
pul1 = 1.f;
} else {
int32 rphase = phase * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer / denom - 1.f) * prevscale;
rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer / denom - 1.f) * scale;
pul1 = lininterp(xfade, n1, n2);
}
} else {
float pfrac = PhaseFrac(phase);
float denom = lininterp(pfrac, t0, t1);
int32 rphase = phase * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer * denom - 1.f) * prevscale;
rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer * denom - 1.f) * scale;
pul1 = lininterp(xfade, n1, n2);
}
int32 phase2 = phase + phaseoff;
tbl = (float*)((char*)dentbl + ((phase2 >> xlobits) & xlomask13)); t0 = tbl[0]; t1 = tbl[1];
if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase2 >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase2);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
pul2 = 1.f;
} else {
int32 rphase = phase2 * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer / denom - 1.f) * prevscale;
rphase = phase2 * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer / denom - 1.f) * scale;
pul2 = lininterp(xfade, n1, n2);
}
} else {
float pfrac = PhaseFrac(phase2);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase2 * prevN2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
float n1 = (numer * denom - 1.f) * prevscale;
rphase = phase2 * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
numer = lininterp(pfrac, tbl[0], tbl[1]);
float n2 = (numer * denom - 1.f) * scale;
pul2 = lininterp(xfade, n1, n2);
}
ZXP(out) = y1 = pul1 - pul2 + 0.999f * y1;
phase += freq; phaseoff += phaseoff_slope; xfade += xfade_slope;);
} else {
LOOP1(
inNumSamples, float* tbl = (float*)((char*)dentbl + ((phase >> xlobits) & xlomask13)); float t0 = tbl[0];
float t1 = tbl[1]; if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
pul1 = rscale;
} else {
int32 rphase = phase * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
pul1 = numer / denom;
}
} else {
float pfrac = PhaseFrac(phase);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase * N2;
pfrac = PhaseFrac(rphase);
float* tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
pul1 = (numer * denom);
}
int32 phase2 = phase + phaseoff;
tbl = (float*)((char*)dentbl + ((phase2 >> xlobits) & xlomask13)); t0 = tbl[0]; t1 = tbl[1];
if (t0 == kBadValue || t1 == kBadValue) {
tbl = (float*)((char*)numtbl + ((phase2 >> xlobits) & xlomask13));
t0 = tbl[0];
t1 = tbl[1];
float pfrac = PhaseFrac(phase2);
float denom = t0 + (t1 - t0) * pfrac;
if (std::abs(denom) < 0.0005f) {
pul2 = rscale;
} else {
int32 rphase = phase2 * N2;
pfrac = PhaseFrac(rphase);
tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
pul2 = numer / denom;
}
} else {
float pfrac = PhaseFrac(phase2);
float denom = t0 + (t1 - t0) * pfrac;
int32 rphase = phase2 * N2;
pfrac = PhaseFrac(rphase);
float* tbl = (float*)((char*)numtbl + ((rphase >> xlobits) & xlomask13));
float numer = lininterp(pfrac, tbl[0], tbl[1]);
pul2 = (numer * denom);
}
ZXP(out) = y1 = (pul1 - pul2) * scale + 0.999f * y1;
phase += freq; phaseoff += phaseoff_slope;);
}
unit->m_y1 = y1;
unit->m_phase = phase;
unit->m_freqin = freqin;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static float Klang_SetCoefs(Klang* unit) {
unit->m_numpartials = (unit->mNumInputs - 2) / 3;
int numcoefs = unit->m_numpartials * 3;
unit->m_coefs = (float*)RTAlloc(unit->mWorld, numcoefs * sizeof(float));
if (!unit->m_coefs) {
Print("Klang: RT memory allocation failed\n");
SETCALC(ClearUnitOutputs);
return 0.f;
}
float freqscale = ZIN0(0) * unit->mRate->mRadiansPerSample;
float freqoffset = ZIN0(1) * unit->mRate->mRadiansPerSample;
float outf = 0.;
float* coefs = unit->m_coefs - 1;
for (int i = 0, j = 2; i < unit->m_numpartials; ++i, j += 3) {
float w = ZIN0(j) * freqscale + freqoffset;
float level = ZIN0(j + 1);
float phase = ZIN0(j + 2);
if (phase != 0.f) {
outf += * ++coefs = level * sin(phase); // y1
*++coefs = level * sin(phase - w); // y2
} else {
outf += * ++coefs = 0.f; // y1
*++coefs = level * -sin(w); // y2
}
*++coefs = 2. * cos(w); // b1
}
return outf;
}
void Klang_Ctor(Klang* unit) {
SETCALC(Klang_next);
ZOUT0(0) = Klang_SetCoefs(unit);
}
void Klang_Dtor(Klang* unit) { RTFree(unit->mWorld, unit->m_coefs); }
void Klang_next(Klang* unit, int inNumSamples) {
float* out0 = ZOUT(0);
float* out;
float y0_0, y1_0, y2_0, b1_0;
float y0_1, y1_1, y2_1, b1_1;
float y0_2, y1_2, y2_2, b1_2;
float y0_3, y1_3, y2_3, b1_3;
float outf;
float* coefs = unit->m_coefs - 1;
int32 numpartials = unit->m_numpartials;
switch (numpartials & 3) {
case 3:
y1_0 = *++coefs;
y2_0 = *++coefs;
b1_0 = *++coefs;
y1_1 = *++coefs;
y2_1 = *++coefs;
b1_1 = *++coefs;
y1_2 = *++coefs;
y2_2 = *++coefs;
b1_2 = *++coefs;
out = out0;
LOOP(unit->mRate->mFilterLoops, outf = y0_0 = b1_0 * y1_0 - y2_0; outf += y0_1 = b1_1 * y1_1 - y2_1;
outf += y0_2 = b1_2 * y1_2 - y2_2; ZXP(out) = outf;
outf = y2_0 = b1_0 * y0_0 - y1_0; outf += y2_1 = b1_1 * y0_1 - y1_1; outf += y2_2 = b1_2 * y0_2 - y1_2;
ZXP(out) = outf;
outf = y1_0 = b1_0 * y2_0 - y0_0; outf += y1_1 = b1_1 * y2_1 - y0_1; outf += y1_2 = b1_2 * y2_2 - y0_2;
ZXP(out) = outf;);
LOOP(unit->mRate->mFilterRemain, outf = y0_0 = b1_0 * y1_0 - y2_0; outf += y0_1 = b1_1 * y1_1 - y2_1;
outf += y0_2 = b1_2 * y1_2 - y2_2; y2_0 = y1_0; y1_0 = y0_0; y2_1 = y1_1; y1_1 = y0_1; y2_2 = y1_2;
y1_2 = y0_2; ZXP(out) = outf;);
coefs -= 9;
*++coefs = y1_0;
*++coefs = y2_0;
++coefs;
*++coefs = y1_1;
*++coefs = y2_1;
++coefs;
*++coefs = y1_2;
*++coefs = y2_2;
++coefs;
break;
case 2:
y1_0 = *++coefs;
y2_0 = *++coefs;
b1_0 = *++coefs;
y1_1 = *++coefs;
y2_1 = *++coefs;
b1_1 = *++coefs;
out = out0;
LOOP(unit->mRate->mFilterLoops, outf = y0_0 = b1_0 * y1_0 - y2_0; outf += y0_1 = b1_1 * y1_1 - y2_1;
ZXP(out) = outf;
outf = y2_0 = b1_0 * y0_0 - y1_0; outf += y2_1 = b1_1 * y0_1 - y1_1; ZXP(out) = outf;
outf = y1_0 = b1_0 * y2_0 - y0_0; outf += y1_1 = b1_1 * y2_1 - y0_1; ZXP(out) = outf;);
LOOP(unit->mRate->mFilterRemain, outf = y0_0 = b1_0 * y1_0 - y2_0; outf += y0_1 = b1_1 * y1_1 - y2_1;
y2_0 = y1_0; y1_0 = y0_0; y2_1 = y1_1; y1_1 = y0_1; ZXP(out) = outf;);
coefs -= 6;
*++coefs = y1_0;
*++coefs = y2_0;
++coefs;
*++coefs = y1_1;
*++coefs = y2_1;
++coefs;
break;
case 1:
y1_0 = *++coefs;
y2_0 = *++coefs;
b1_0 = *++coefs;
out = out0;
LOOP(unit->mRate->mFilterLoops, ZXP(out) = y0_0 = b1_0 * y1_0 - y2_0;
ZXP(out) = y2_0 = b1_0 * y0_0 - y1_0;
ZXP(out) = y1_0 = b1_0 * y2_0 - y0_0;);
LOOP(unit->mRate->mFilterRemain, ZXP(out) = y0_0 = b1_0 * y1_0 - y2_0; y2_0 = y1_0; y1_0 = y0_0;);
coefs -= 3;
*++coefs = y1_0;
*++coefs = y2_0;
++coefs;
break;
case 0:
out = out0;
ZClear(inNumSamples, out);
break;
}
int32 imax = numpartials >> 2;
for (int i = 0; i < imax; ++i) {
y1_0 = *++coefs;
y2_0 = *++coefs;
b1_0 = *++coefs;
y1_1 = *++coefs;
y2_1 = *++coefs;
b1_1 = *++coefs;
y1_2 = *++coefs;
y2_2 = *++coefs;
b1_2 = *++coefs;
y1_3 = *++coefs;
y2_3 = *++coefs;
b1_3 = *++coefs;
out = out0;
LOOP(unit->mRate->mFilterLoops, outf = y0_0 = b1_0 * y1_0 - y2_0; outf += y0_1 = b1_1 * y1_1 - y2_1;
outf += y0_2 = b1_2 * y1_2 - y2_2; outf += y0_3 = b1_3 * y1_3 - y2_3; ZXP(out) += outf;
outf = y2_0 = b1_0 * y0_0 - y1_0; outf += y2_1 = b1_1 * y0_1 - y1_1; outf += y2_2 = b1_2 * y0_2 - y1_2;
outf += y2_3 = b1_3 * y0_3 - y1_3; ZXP(out) += outf;
outf = y1_0 = b1_0 * y2_0 - y0_0; outf += y1_1 = b1_1 * y2_1 - y0_1; outf += y1_2 = b1_2 * y2_2 - y0_2;
outf += y1_3 = b1_3 * y2_3 - y0_3; ZXP(out) += outf;);
LOOP(unit->mRate->mFilterRemain, outf = y0_0 = b1_0 * y1_0 - y2_0; outf += y0_1 = b1_1 * y1_1 - y2_1;
outf += y0_2 = b1_2 * y1_2 - y2_2; outf += y0_3 = b1_3 * y1_3 - y2_3; y2_0 = y1_0; y1_0 = y0_0;
y2_1 = y1_1; y1_1 = y0_1; y2_2 = y1_2; y1_2 = y0_2; y2_3 = y1_3; y1_3 = y0_3; ZXP(out) += outf;);
coefs -= 12;
*++coefs = y1_0;
*++coefs = y2_0;
++coefs;
*++coefs = y1_1;
*++coefs = y2_1;
++coefs;
*++coefs = y1_2;
*++coefs = y2_2;
++coefs;
*++coefs = y1_3;
*++coefs = y2_3;
++coefs;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static void Klank_SetCoefs(Klank* unit) {
int numpartials = (unit->mNumInputs - 4) / 3;
unit->m_numpartials = numpartials;
int numcoefs = ((unit->m_numpartials + 3) & ~3) * 5;
unit->m_coefs = (float*)RTAlloc(unit->mWorld, (numcoefs + unit->mWorld->mBufLength) * sizeof(float));
if (!unit->m_coefs) {
Print("Klang: RT memory allocation failed\n");
SETCALC(ClearUnitOutputs);
return;
}
unit->m_buf = unit->m_coefs + numcoefs;
float freqscale = ZIN0(1) * unit->mRate->mRadiansPerSample;
float freqoffset = ZIN0(2) * unit->mRate->mRadiansPerSample;
float decayscale = ZIN0(3);
float* coefs = unit->m_coefs;
float sampleRate = SAMPLERATE;
for (int i = 0, j = 4; i < numpartials; ++i, j += 3) {
float w = ZIN0(j) * freqscale + freqoffset;
float level = ZIN0(j + 1);
float time = ZIN0(j + 2) * decayscale;
float R = time == 0.f ? 0.f : exp(log001 / (time * sampleRate));
float twoR = 2.f * R;
float R2 = R * R;
float cost = (twoR * cos(w)) / (1.f + R2);
int k = 20 * (i >> 2) + (i & 3);
coefs[k + 0] = 0.f; // y1
coefs[k + 4] = 0.f; // y2
coefs[k + 8] = twoR * cost; // b1
coefs[k + 12] = -R2; // b2
coefs[k + 16] = level * 0.25; // a0
// Print("coefs %d %g %g %g\n", i, twoR * cost, -R2, ampf * 0.25);
}
}
void Klank_Ctor(Klank* unit) {
SETCALC(Klank_next);
unit->m_x1 = unit->m_x2 = 0.f;
Klank_SetCoefs(unit);
ZOUT0(0) = 0.f;
}
void Klank_Dtor(Klank* unit) { RTFree(unit->mWorld, unit->m_coefs); }
void Klank_next(Klank* unit, int inNumSamples) {
float* out0 = ZOUT(0);
float* in0 = ZIN(0);
float *in, *out;
float inf;
float y0_0, y1_0, y2_0, a0_0, b1_0, b2_0;
float y0_1, y1_1, y2_1, a0_1, b1_1, b2_1;
float y0_2, y1_2, y2_2, a0_2, b1_2, b2_2;
float y0_3, y1_3, y2_3, a0_3, b1_3, b2_3;
int32 numpartials = unit->m_numpartials;
int32 imax = numpartials >> 2;
float* coefs = unit->m_coefs + imax * 20;
switch (numpartials & 3) {
case 3:
y1_0 = coefs[0];
y2_0 = coefs[4];
b1_0 = coefs[8];
b2_0 = coefs[12];
a0_0 = coefs[16];
y1_1 = coefs[1];
y2_1 = coefs[5];
b1_1 = coefs[9];
b2_1 = coefs[13];
a0_1 = coefs[17];
y1_2 = coefs[2];
y2_2 = coefs[6];
b1_2 = coefs[10];
b2_2 = coefs[14];
a0_2 = coefs[18];
in = in0;
out = unit->m_buf - 1;
LooP(unit->mRate->mFilterLoops) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
y0_1 = inf + b1_1 * y1_1 + b2_1 * y2_1;
y0_2 = inf + b1_2 * y1_2 + b2_2 * y2_2;
*++out = a0_0 * y0_0 + a0_1 * y0_1 + a0_2 * y0_2;
inf = *++in;
y2_0 = inf + b1_0 * y0_0 + b2_0 * y1_0;
y2_1 = inf + b1_1 * y0_1 + b2_1 * y1_1;
y2_2 = inf + b1_2 * y0_2 + b2_2 * y1_2;
*++out = a0_0 * y2_0 + a0_1 * y2_1 + a0_2 * y2_2;
inf = *++in;
y1_0 = inf + b1_0 * y2_0 + b2_0 * y0_0;
y1_1 = inf + b1_1 * y2_1 + b2_1 * y0_1;
y1_2 = inf + b1_2 * y2_2 + b2_2 * y0_2;
*++out = a0_0 * y1_0 + a0_1 * y1_1 + a0_2 * y1_2;
}
LooP(unit->mRate->mFilterRemain) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
y0_1 = inf + b1_1 * y1_1 + b2_1 * y2_1;
y0_2 = inf + b1_2 * y1_2 + b2_2 * y2_2;
*++out = a0_0 * y0_0 + a0_1 * y0_1 + a0_2 * y0_2;
y2_0 = y1_0;
y1_0 = y0_0;
y2_1 = y1_1;
y1_1 = y0_1;
y2_2 = y1_2;
y1_2 = y0_2;
}
coefs[0] = zapgremlins(y1_0);
coefs[4] = zapgremlins(y2_0);
coefs[1] = zapgremlins(y1_1);
coefs[5] = zapgremlins(y2_1);
coefs[2] = zapgremlins(y1_2);
coefs[6] = zapgremlins(y2_2);
break;
case 2:
y1_0 = coefs[0];
y2_0 = coefs[4];
b1_0 = coefs[8];
b2_0 = coefs[12];
a0_0 = coefs[16];
y1_1 = coefs[1];
y2_1 = coefs[5];
b1_1 = coefs[9];
b2_1 = coefs[13];
a0_1 = coefs[17];
in = in0;
out = unit->m_buf - 1;
LooP(unit->mRate->mFilterLoops) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
y0_1 = inf + b1_1 * y1_1 + b2_1 * y2_1;
*++out = a0_0 * y0_0 + a0_1 * y0_1;
inf = *++in;
y2_0 = inf + b1_0 * y0_0 + b2_0 * y1_0;
y2_1 = inf + b1_1 * y0_1 + b2_1 * y1_1;
*++out = a0_0 * y2_0 + a0_1 * y2_1;
inf = *++in;
y1_0 = inf + b1_0 * y2_0 + b2_0 * y0_0;
y1_1 = inf + b1_1 * y2_1 + b2_1 * y0_1;
*++out = a0_0 * y1_0 + a0_1 * y1_1;
}
LooP(unit->mRate->mFilterRemain) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
y0_1 = inf + b1_1 * y1_1 + b2_1 * y2_1;
*++out = a0_0 * y0_0 + a0_1 * y0_1;
y2_0 = y1_0;
y1_0 = y0_0;
y2_1 = y1_1;
y1_1 = y0_1;
}
coefs[0] = zapgremlins(y1_0);
coefs[4] = zapgremlins(y2_0);
coefs[1] = zapgremlins(y1_1);
coefs[5] = zapgremlins(y2_1);
break;
case 1:
y1_0 = coefs[0];
y2_0 = coefs[4];
b1_0 = coefs[8];
b2_0 = coefs[12];
a0_0 = coefs[16];
// Print("rcoefs %g %g %g %g %g\n", y1_0, y2_0, b1_0, b2_0, a0_0);
in = in0;
out = unit->m_buf - 1;
LooP(unit->mRate->mFilterLoops) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
*++out = a0_0 * y0_0;
inf = *++in;
y2_0 = inf + b1_0 * y0_0 + b2_0 * y1_0;
*++out = a0_0 * y2_0;
inf = *++in;
y1_0 = inf + b1_0 * y2_0 + b2_0 * y0_0;
*++out = a0_0 * y1_0;
// Print("out %g %g %g\n", y0_0, y2_0, y1_0);
}
LooP(unit->mRate->mFilterRemain) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
*++out = a0_0 * y0_0;
y2_0 = y1_0;
y1_0 = y0_0;
// Print("out %g\n", y0_0);
}
/*
coefs[0] = y1_0; coefs[4] = y2_0;
*/
coefs[0] = zapgremlins(y1_0);
coefs[4] = zapgremlins(y2_0);
break;
case 0:
out = unit->m_buf - 1;
LooP(inNumSamples) { *++out = 0.f; }
break;
}
coefs = unit->m_coefs;
for (int i = 0; i < imax; ++i) {
y1_0 = coefs[0];
y2_0 = coefs[4];
b1_0 = coefs[8];
b2_0 = coefs[12];
a0_0 = coefs[16];
y1_1 = coefs[1];
y2_1 = coefs[5];
b1_1 = coefs[9];
b2_1 = coefs[13];
a0_1 = coefs[17];
y1_2 = coefs[2];
y2_2 = coefs[6];
b1_2 = coefs[10];
b2_2 = coefs[14];
a0_2 = coefs[18];
y1_3 = coefs[3];
y2_3 = coefs[7];
b1_3 = coefs[11];
b2_3 = coefs[15];
a0_3 = coefs[19];
in = in0;
out = unit->m_buf - 1;
LooP(unit->mRate->mFilterLoops) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
y0_1 = inf + b1_1 * y1_1 + b2_1 * y2_1;
y0_2 = inf + b1_2 * y1_2 + b2_2 * y2_2;
y0_3 = inf + b1_3 * y1_3 + b2_3 * y2_3;
*++out += a0_0 * y0_0 + a0_1 * y0_1 + a0_2 * y0_2 + a0_3 * y0_3;
inf = *++in;
y2_0 = inf + b1_0 * y0_0 + b2_0 * y1_0;
y2_1 = inf + b1_1 * y0_1 + b2_1 * y1_1;
y2_2 = inf + b1_2 * y0_2 + b2_2 * y1_2;
y2_3 = inf + b1_3 * y0_3 + b2_3 * y1_3;
*++out += a0_0 * y2_0 + a0_1 * y2_1 + a0_2 * y2_2 + a0_3 * y2_3;
inf = *++in;
y1_0 = inf + b1_0 * y2_0 + b2_0 * y0_0;
y1_1 = inf + b1_1 * y2_1 + b2_1 * y0_1;
y1_2 = inf + b1_2 * y2_2 + b2_2 * y0_2;
y1_3 = inf + b1_3 * y2_3 + b2_3 * y0_3;
*++out += a0_0 * y1_0 + a0_1 * y1_1 + a0_2 * y1_2 + a0_3 * y1_3;
}
LooP(unit->mRate->mFilterRemain) {
inf = *++in;
y0_0 = inf + b1_0 * y1_0 + b2_0 * y2_0;
y0_1 = inf + b1_1 * y1_1 + b2_1 * y2_1;
y0_2 = inf + b1_2 * y1_2 + b2_2 * y2_2;
y0_3 = inf + b1_3 * y1_3 + b2_3 * y2_3;
*++out += a0_0 * y0_0 + a0_1 * y0_1 + a0_2 * y0_2 + a0_3 * y0_3;
y2_0 = y1_0;
y1_0 = y0_0;
y2_1 = y1_1;
y1_1 = y0_1;
y2_2 = y1_2;
y1_2 = y0_2;
y2_3 = y1_3;
y1_3 = y0_3;
}
coefs[0] = zapgremlins(y1_0);
coefs[4] = zapgremlins(y2_0);
coefs[1] = zapgremlins(y1_1);
coefs[5] = zapgremlins(y2_1);
coefs[2] = zapgremlins(y1_2);
coefs[6] = zapgremlins(y2_2);
coefs[3] = zapgremlins(y1_3);
coefs[7] = zapgremlins(y2_3);
coefs += 20;
}
float x0;
float x1 = unit->m_x1;
float x2 = unit->m_x2;
in = unit->m_buf - 1;
out = out0;
LooP(unit->mRate->mFilterLoops) {
x0 = *++in;
*++out = x0 - x2;
x2 = *++in;
*++out = x2 - x1;
x1 = *++in;
*++out = x1 - x0;
}
LooP(unit->mRate->mFilterRemain) {
x0 = *++in;
*++out = x0 - x2;
x2 = x1;
x1 = x0;
}
unit->m_x1 = x1;
unit->m_x2 = x2;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
static void normalize_samples(int size, float* data, float peak) {
float maxamp = 0.f;
for (int i = 0; i < size; ++i) {
float absamp = std::abs(data[i]);
if (absamp > maxamp)
maxamp = absamp;
}
if (maxamp != 0.f && maxamp != peak) {
float ampfac = peak / maxamp;
for (int i = 0; i < size; ++i) {
data[i] *= ampfac;
}
}
}
static void normalize_wsamples(int size, float* data, float peak) {
float maxamp = 0.f;
for (int i = 0; i < size; i += 2) {
float absamp = std::abs(data[i] + data[i + 1]);
if (absamp > maxamp)
maxamp = absamp;
}
if (maxamp != 0.f && maxamp != peak) {
float ampfac = peak / maxamp;
for (int i = 0; i < size; ++i) {
data[i] *= ampfac;
}
}
}
static void add_partial(int size, float* data, double partial, double amp, double phase) {
if (amp == 0.0)
return;
double w = (partial * 2.0 * 3.1415926535897932384626433832795) / (double)size;
for (int i = 0; i < size; ++i) {
data[i] += amp * sin(phase);
phase += w;
}
}
static void add_wpartial(int size, float* data, double partial, double amp, double phase) {
if (amp == 0.0)
return;
int size2 = size >> 1;
double w = (partial * 2.0 * 3.1415926535897932384626433832795) / (double)size2;
double cur = amp * sin(phase);
phase += w;
for (int i = 0; i < size; i += 2) {
double next = amp * sin(phase);
data[i] += 2 * cur - next;
data[i + 1] += next - cur;
cur = next;
phase += w;
}
}
static void add_chebyshev(int size, float* data, double partial, double amp) {
if (amp == 0.0)
return;
double w = 2.0 / (double)size;
double phase = -1.0;
double offset = -amp * cos(partial * pi2);
for (int i = 0; i < size; ++i) {
data[i] += amp * cos(partial * acos(phase)) + offset;
phase += w;
}
}
static void add_wchebyshev(int size, float* data, double partial, double amp) {
if (amp == 0.0)
return;
int size2 = size >> 1;
double w = 2.0 / (double)size2;
double phase = -1.0;
double offset = -amp * cos(partial * pi2);
double cur = amp * cos(partial * acos(phase)) + offset;
phase += w;
for (int i = 0; i < size; i += 2) {
double next = amp * cos(partial * acos(phase)) + offset;
data[i] += 2 * cur - next;
data[i + 1] += next - cur;
cur = next;
phase += w;
}
}
static void cantorFill(int size, float* data) // long offset, double amp)
{
// if (amp == 0.0) return;
for (int i = 0; i < (size); ++i) {
int j = i;
float flag = 1.f;
while ((j > 0) && (flag == 1.f)) {
if (j % 3 == 1) {
flag = 0.f;
}
j = j / 3;
}
if (flag) {
data[i] += 1.f;
}
}
}
enum { flag_Normalize = 1, flag_Wavetable = 2, flag_Clear = 4 };
void ChebyFill(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
if (buf->channels != 1)
return;
int flags = msg->geti();
int size = buf->samples;
int byteSize = size * sizeof(float);
float* data = (float*)malloc(byteSize);
if (flags & flag_Clear)
Fill(size, data, 0.);
else
memcpy(data, buf->data, byteSize);
for (int partial = 1; msg->remain(); partial++) {
double amp = msg->getf();
if (flags & flag_Wavetable)
add_wchebyshev(size, data, partial, amp);
else
add_chebyshev(size, data, partial, amp);
}
if (flags & flag_Normalize) {
if (flags & flag_Wavetable)
normalize_wsamples(size, data, 1.);
else
normalize_samples(size, data, 1.);
}
memcpy(buf->data, data, byteSize);
free(data);
}
void SineFill1(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
if (buf->channels != 1)
return;
int flags = msg->geti();
int size = buf->samples;
int byteSize = size * sizeof(float);
float* data = (float*)malloc(byteSize);
if (flags & flag_Clear)
Fill(size, data, 0.);
else
memcpy(data, buf->data, byteSize);
for (int partial = 1; msg->remain(); partial++) {
double amp = msg->getf();
if (flags & flag_Wavetable)
add_wpartial(size, data, partial, amp, 0.);
else
add_partial(size, data, partial, amp, 0.);
}
if (flags & flag_Normalize) {
if (flags & flag_Wavetable)
normalize_wsamples(size, data, 1.);
else
normalize_samples(size, data, 1.);
}
memcpy(buf->data, data, byteSize);
free(data);
}
void SineFill2(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
if (buf->channels != 1)
return;
int flags = msg->geti();
int size = buf->samples;
int byteSize = size * sizeof(float);
float* data = (float*)malloc(byteSize);
if (flags & flag_Clear)
Fill(size, data, 0.);
else
memcpy(data, buf->data, byteSize);
while (msg->remain()) {
double partial = msg->getf();
double amp = msg->getf();
if (flags & flag_Wavetable)
add_wpartial(size, data, partial, amp, 0.);
else
add_partial(size, data, partial, amp, 0.);
}
if (flags & flag_Normalize) {
if (flags & flag_Wavetable)
normalize_wsamples(size, data, 1.);
else
normalize_samples(size, data, 1.);
}
memcpy(buf->data, data, byteSize);
free(data);
}
void SineFill3(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
if (buf->channels != 1)
return;
int flags = msg->geti();
int size = buf->samples;
int byteSize = size * sizeof(float);
float* data = (float*)malloc(byteSize);
if (flags & flag_Clear)
Fill(size, data, 0.);
else
memcpy(data, buf->data, byteSize);
while (msg->remain()) {
double partial = msg->getf();
double amp = msg->getf();
double phase = msg->getf();
if (flags & flag_Wavetable)
add_wpartial(size, data, partial, amp, phase);
else
add_partial(size, data, partial, amp, phase);
}
if (flags & flag_Normalize) {
if (flags & flag_Wavetable)
normalize_wsamples(size, data, 1.);
else
normalize_samples(size, data, 1.);
}
memcpy(buf->data, data, byteSize);
free(data);
}
void NormalizeBuf(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
float newmax;
if (msg->remain() != 0) {
newmax = msg->getf();
} else {
newmax = 1.f;
}
float* data = buf->data;
int size = buf->samples;
normalize_samples(size, data, newmax);
}
void NormalizeWaveBuf(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
float newmax;
if (msg->remain() != 0) {
newmax = msg->getf();
} else {
newmax = 1.f;
}
float* data = buf->data;
int size = buf->samples;
normalize_wsamples(size, data, newmax);
}
void CopyBuf(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
int frames1 = buf->frames;
int channels1 = buf->channels;
int toPos = msg->geti();
uint32 bufnum2 = msg->geti();
int fromPos = msg->geti();
int length = msg->geti();
if (bufnum2 >= world->mNumSndBufs)
bufnum2 = 0;
SndBuf* buf2 = world->mSndBufs + bufnum2;
int frames2 = buf2->frames;
int channels2 = buf2->channels;
if (channels1 != channels2)
return;
fromPos = sc_clip(fromPos, 0, frames2 - 1);
toPos = sc_clip(toPos, 0, frames1 - 1);
int maxLength = sc_min(frames2 - fromPos, frames1 - toPos);
if (length < 0) {
length = maxLength;
} else {
length = sc_min(length, maxLength);
}
if (length <= 0)
return;
int numbytes = length * sizeof(float) * channels1;
float* data1 = buf->data + toPos * channels1;
float* data2 = buf2->data + fromPos * channels2;
if ((((char*)data1 + numbytes) > (char*)data2) || (((char*)data2 + numbytes) > (char*)data1)) {
memmove(data1, data2, numbytes);
} else {
memcpy(data1, data2, numbytes);
}
}
void CantorFill(World* world, struct SndBuf* buf, struct sc_msg_iter* msg) {
float* data = buf->data;
int size = buf->samples;
// double offset = msg->getf();
// double amp = msg->getf();
// long offs = (long) offset;
cantorFill(size, data);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
PluginLoad(Osc) {
ft = inTable;
DefineSimpleUnit(DegreeToKey);
DefineSimpleUnit(Select);
DefineSimpleUnit(TWindex);
DefineSimpleUnit(Index);
DefineSimpleUnit(IndexL);
DefineSimpleUnit(FoldIndex);
DefineSimpleUnit(WrapIndex);
DefineSimpleUnit(IndexInBetween);
DefineSimpleUnit(DetectIndex);
DefineSimpleUnit(Shaper);
DefineSimpleUnit(FSinOsc);
DefineSimpleUnit(PSinGrain);
DefineSimpleUnit(SinOsc);
DefineSimpleUnit(SinOscFB);
DefineSimpleUnit(VOsc);
DefineSimpleUnit(VOsc3);
DefineSimpleUnit(Osc);
DefineSimpleUnit(OscN);
DefineSimpleUnit(COsc);
DefineSimpleUnit(Formant);
DefineSimpleUnit(Blip);
DefineSimpleUnit(Saw);
DefineSimpleUnit(Pulse);
DefineDtorUnit(Klang);
DefineDtorUnit(Klank);
DefineBufGen("cheby", ChebyFill);
DefineBufGen("sine1", SineFill1);
DefineBufGen("sine2", SineFill2);
DefineBufGen("sine3", SineFill3);
DefineBufGen("normalize", NormalizeBuf);
DefineBufGen("wnormalize", NormalizeWaveBuf);
DefineBufGen("copy", CopyBuf);
DefineBufGen("cantorFill", CantorFill);
}
//////////////////////////////////////////////////////////////////////////////////////////////////