frac32 4Feet
frac32 8Feet
frac32 16Feet
frac32 Attack
frac32 Release
frac32 RevLevel
frac32 RevDuration
frac32 Vibrato
frac32.bipolar lfo
frac32buffer.bipolar out
frac32.positive keys
#define NB_OCT 6
int32_t outLP;
int32_t phi[12];
int32_t dPhi[12];
// 6 octaves + one note (C to C)
int32_t envMix[12 * NB_OCT + 13];
int32_t env[12 * NB_OCT + 13];
int32_t envRev[12 * NB_OCT + 13];
int32_t envTarget[12 * NB_OCT + 13];
int32_t coefEnv[12 * NB_OCT + 13];
for (int n12 = 0; n12 < 12; n12++) {
int32_t dp;
MTOFEXTENDED((-40 << 21) + (n12 << 21), dp)
dPhi[n12] = -dp;
for (int oct = 0; oct < NB_OCT + (n12 == 0); oct++) {
int32_t note = 12 * oct + n12;
int32_t coef;
MTOFEXTENDED(-note << 21, coef)
coefEnv[note] = coef;
env[note] = 0;
envTarget[note] = 0;
envRev[note] = 0;
}
}
outLP = 0;
int32_t coefA = inlet_Attack * 2 - (64 << 21);
MTOF(-coefA, coefA);
int32_t coefR = inlet_Release * 2 - (64 << 21);
MTOF(-coefR, coefR);
int32_t coefRevA = inlet_RevDuration - (24 << 21);
MTOF(-coefRevA, coefRevA);
int32_t coefRevR = inlet_RevDuration - (0 << 21);
MTOF(-coefRevR, coefRevR);
int32_t revLevel = inlet_RevLevel << 4;
for (int i = 0; i < 12 * NB_OCT + 1; i++) {
int32_t delta = envTarget[i] - env[i];
env[i] = ___SMMLA(delta > 0 ? coefA : coefR, delta, env[i]);
delta = ___SMMLA(envTarget[i] << 1, revLevel, -envRev[i]);
envRev[i] = ___SMMLA(delta > 0 ? coefRevA : coefRevR, delta, envRev[i]);
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
int32_t coef8Feet = __SSAT(inlet_8Feet, 28) << 4; // q31
for (int i = 0; i < 12 * NB_OCT + 1; i++) {
envMix[i] = ___SMMUL(env[i] + envRev[i], coef8Feet) << 1;
}
// we add coef4Feet*env to the mix env above
int32_t coef4Feet = __SSAT(inlet_4Feet, 28) << 3; // q31
for (int i = 0; i < 12 * NB_OCT + 1 - 12; i++) {
envMix[i + 12] = ___SMMLA(env[i] + envRev[i], coef4Feet, envMix[i + 12] >> 1)
<< 1;
}
// we add coef4Feet*env to the mix env below
int32_t coef16Feet = __SSAT(inlet_16Feet, 28) << 4; // q31
for (int i = 12; i < 12 * NB_OCT + 1; i++) {
envMix[i - 12] =
___SMMLA((env[i] + envRev[i]) << 1, coef16Feet, envMix[i - 12] >> 1) << 1;
}
int32_t keys = 0;
for (int i = 0; i < 12 * NB_OCT + 1; i++) {
keys += envTarget[i] != 0 ? 1 << 21 : 0;
}
outlet_keys = keys;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
int32_t y1;
int32_t y0 = 0;
for (int n12 = 0; n12 < 12; n12++) {
int32_t *e = envMix + n12;
int32_t p = phi[n12];
for (int oct = 0; oct < NB_OCT + (n12 == 0); oct++) {
/* int32_t x = p & 0x7FFFFFFF; //q31
int32_t y = ___SMMUL(x, x)<<1; //q30
y = ___SMMUL(y, y); //q30
y = ___SMMLS(y, y, x>>3);//q28
y0 = ___SMMLA(y, *e, y0);
*/
int32_t x = __USAT(p, 31);
x = ___SMMUL(x, x); // q30
x = ___SMMLS(x, x, x >> 2); // q28
y0 = ___SMMLA(x, *e, y0);
e += 12;
p -= 1 << 30;
p <<= 1;
}
}
int32_t dPhiM[12];
int32_t lfo = ___SMMUL(inlet_lfo, inlet_Vibrato) << 5;
for (int n12 = 0; n12 < 12; n12++) {
dPhiM[n12] = ___SMMLA(lfo, dPhi[n12], dPhi[n12]);
}
for (int i = 0; i < BUFSIZE; i++) {
for (int n12 = 0; n12 < 12; n12++) {
phi[n12] += dPhiM[n12];
}
y1 = y0;
y0 = 0;
for (int n12 = 0; n12 < 12; n12++) {
int32_t *e = envMix + n12;
int32_t p = phi[n12];
for (int oct = 0; oct < NB_OCT + (n12 == 0); oct++) {
/* int32_t x = p & 0x7FFFFFFF; //q31
int32_t y = ___SMMUL(x, x)<<1; //q30
y = ___SMMUL(y, y); //q30
y = ___SMMLS(y, y, x>>3);//q28
y0 = ___SMMLA(y, *e, y0);
*/
int32_t x = __USAT(p, 31);
x = ___SMMUL(x, x); // q30
x = ___SMMLS(x, x, x >> 2); // q28
y0 = ___SMMLA(x, *e, y0);
e += 12;
p -= 1 << 30;
p <<= 1;
}
}
int32_t out = (y0 - y1) << 13;
outLP = ___SMMLA(0x10000000, out - outLP, outLP);
// outlet_out[i] = __SSAT(outLP, 27)+__SSAT(out-outLP, 27);
outlet_out[i] = __SSAT(out / 2 + __SSAT(out, 28), 30);
}
if (status == MIDI_NOTE_ON + attr_midichannel) {
int n = ((data1 & 0x7F) - 24);
if (n >= 0 && n < 12 * NB_OCT + 1) {
envTarget[n] = data2 != 0 ? coefEnv[n] : 0;
}
// gates[data1 & 0x7F] = data2 * coef1[data1];
} else if (status == MIDI_NOTE_OFF + attr_midichannel) {
int n = ((data1 & 0x7F) - 24);
if (n >= 0 && n < 12 * NB_OCT + 1) {
envTarget[n] = 0;
}
// gates[data1 & 0x7F] = 0;
} else if ((status == attr_midichannel + MIDI_CONTROL_CHANGE) &&
(data1 == MIDI_C_ALL_NOTES_OFF)) {
for (int i = 0; i < 12 * NB_OCT + 1; i++)
envTarget[i] = 0;
}