frac32.bipolar lfo1
frac32.bipolar lfo2
frac32.bipolar lfo3
frac32buffer.bipolar out
frac32.u.map lfoDepth
frac32.s.map.kdecaytime.exp Attack
frac32.s.map.kdecaytime.exp Release
int32 Max Key
int32 Min Key
combo type
combo algo
float dp[128]; // delta phase
float p[128];
float coef1[128]; // for gain compensation in DPW algo
float gates[128];
float env[128];
float z[BUFSIZE];
float z1, z2, fz;
float lfo[12];
const float type_l[11] = {0.0f, 0.0f, 0.2f, 0.2f, 0.75f, 0.5f,
0.25f, 1.0f, 0.0f, 0.0f, -1.0f};
const float type_r[11] = {0.0f, 0.25f, 0.25f, 0.5f, 0.25f, 0.5f,
0.75f, 0.5f, 1.0f, 0.11f, 0.5f};
const float l = type_l[attr_type];
const float r = type_r[attr_type];
const float a = (l - 1) / r;
const float K = -0.5f * (l + 1) * r;
const float b = 1.0f + K;
const float A = 0.5 * (l - 1) / r;
const float C = -((1.0f / 3) * A * r * r * r + 0.5 * r * r - 0.5f * K + K * r);
const float C_K = C - K;
int syncRefresh = 0;
// _____________________________________________________________________
int i, j;
for (i = 0; i < 128; i++) {
p[i] = gates[i] = env[i] = 0.0f;
}
z1 = z2 = fz = 0.0f;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
dp[0] = 1.7032914407591056E-4f;
dp[1] = 1.804574420422344E-4f;
dp[2] = 1.9118799994622893E-4f;
dp[3] = 2.0255663002739644E-4f;
dp[4] = 2.1460127403181634E-4f;
dp[5] = 2.2736212983919527E-4f;
dp[6] = 2.4088178561955362E-4f;
dp[7] = 2.5520536196728464E-4f;
dp[8] = 2.703806624869435E-4f;
dp[9] = 2.8645833333333333E-4f;
dp[10] = 3.0349203223833975E-4f;
dp[11] = 3.2153860758862255E-4f;
for (i = 12; i <= 127; i++) {
dp[i] = 2 * dp[i - 12];
if (attr_algo == 3) {
coef1[i] = ((1 << 24) / 127.0f) / (dp[i]);
} else if (attr_algo == 2) {
coef1[i] = ((1 << 25) / 127.0f) / (dp[i]);
} else {
coef1[i] = ((1 << 25) / 127.0f);
}
}
int minKey = param_Min_space_Key < param_Max_space_Key ? param_Min_space_Key
: param_Max_space_Key;
int maxKey = param_Min_space_Key >= param_Max_space_Key ? param_Min_space_Key
: param_Max_space_Key;
float attack = 1.0f - param_Attack / ((float)((1UL << 31) - 1));
float release = 1.0f - param_Release / ((float)((1UL << 31) - 1));
// attack = attack>1?1:attack;
// release = release>1?1:release;
// _____________________________________________________________________
int i, j;
for (j = 0; j < BUFSIZE; j++) {
z[j] = 0;
}
float lfoDepth = param_lfoDepth * (1.0f / (1 << 27));
lfo[0] = 1.0f + lfoDepth * inlet_lfo1 * (0.03f / (1 << 27));
lfo[1] = 1.0f - lfoDepth * inlet_lfo1 * (0.021f / (1 << 27));
lfo[2] = 1.0f + lfoDepth * inlet_lfo1 * (0.023f / (1 << 27));
lfo[3] = 1.0f - lfoDepth * inlet_lfo2 * (0.029f / (1 << 27));
lfo[4] = 1.0f + lfoDepth * inlet_lfo2 * (0.02f / (1 << 27));
lfo[5] = 1.0f + lfoDepth * inlet_lfo3 * (0.015f / (1 << 27));
lfo[6] = 1.0f - lfoDepth * inlet_lfo3 * (0.02f / (1 << 27));
lfo[7] = 1.0f + lfoDepth * inlet_lfo1 * (0.029f / (1 << 27));
lfo[8] = 1.0f - lfoDepth * inlet_lfo3 * (0.022f / (1 << 27));
lfo[9] = 1.0f + lfoDepth * inlet_lfo1 * (0.021f / (1 << 27));
lfo[10] = 1.0f + lfoDepth * inlet_lfo2 * (0.03f / (1 << 27));
lfo[11] = 1.0f - lfoDepth * inlet_lfo2 * (0.027f / (1 << 27));
// resync (lock) of phases to avoid drift caused by calc inaccuracies
/*float pRef = p[minKey + syncRefresh];
for(i = syncRefresh + 12; i<= maxKey; i+=12){
pRef*=2;
if(pRef>=1)
pRef -= 1;
p[i] = pRef;
}
syncRefresh++;
if(syncRefresh>=12)
syncRefresh = 0;
*/
// DPW anti ali
if (attr_algo == 2) {
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
int i12 = 0;
for (i = minKey; i <= maxKey; i++) {
float _env = env[i];
env[i] += (gates[i] > env[i] ? attack : release) * (gates[i] - env[i]);
// if(env[i]<0.01f) continue;
float denv = (env[i] - _env) * (1.0f / BUFSIZE);
float _dp = dp[i] * lfo[i12];
i12++;
if (i12 >= 12)
i12 = 0;
float _p = p[i];
for (j = 0; j < BUFSIZE; j++) {
_env += denv;
_p += _dp;
// branchless code, more cpu but constant 72% for 61 notes
_p -= (_p > 1);
z[j] += _env * (K * _p + C_K + (_p < r) * (K + _p * (1 + A * _p)));
/*
// code with branching => less cpu but cpu variations => glitches
// 74% for 61+24 notes
if(_p>1) _p--;
float tmp;
if(_p>r)
tmp = K * _p + C_K;
else
tmp = C + _p * (1+K + A * _p);
z[j] += _env * tmp;*/
}
p[i] = _p;
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
for (j = 0; j < BUFSIZE; j++) {
outlet_out[j] = (int32_t)(z[j] - z1);
z1 = z[j];
}
} else
{
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
int i12 = 0;
for (i = minKey; i <= maxKey; i++) {
float _env = env[i];
env[i] += (gates[i] > env[i] ? attack : release) * (gates[i] - env[i]);
float denv = (env[i] - _env) * (1.0f / BUFSIZE);
float _p = p[i];
float _dp = dp[i] * lfo[i12];
i12++;
if (i12 >= 12)
i12 = 0;
for (j = 0; j < BUFSIZE; j++) {
_env += denv;
_p += _dp;
_p -= (_p > 1);
z[j] += _env * (K + (_p < r) * (1 + a * _p));
}
p[i] = _p;
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
for (j = 0; j < BUFSIZE; j++) {
outlet_out[j] = (int32_t)(z[j]);
}
}
if (status == MIDI_NOTE_ON + attr_midichannel) {
// gates[data1 & 0x7F] = data2 * coef1[data1];
gates[data1 & 0x7F] =
data2 == 0 ? 0
: 100 * coef1[data1]; // <---------------------Fixed velocity
} else if (status == MIDI_NOTE_OFF + attr_midichannel) {
gates[data1 & 0x7F] = 0;
} else if ((status == attr_midichannel + MIDI_CONTROL_CHANGE) &&
(data1 == MIDI_C_ALL_NOTES_OFF)) {
for (int i = 0; i < 128; i++)
gates[data1 & 0x7F] = 0;
}