frac32buffer input signal
frac32buffer 16 coefficient buffer, these represent the shape of a curve in several points
frac32 amount of feedback
frac32 filter cutoff pitch
frac32 "rule" for cutoff pitch in chained units
frac32buffer out
frac32.s.map feedback
frac32.s.map "rule" for cutoff pitch in chained units
frac32.s.map.pitch filter cutoff pitch
spinner number of individual waveshaper units chained together
typedef struct {
int32_t q[17]; // actual coefficients
int32_t Q[17]; // integral values
} waveshaper_coefs;
// the positive semiperiod of the wave is subdivided in 16 segments. I want to
// do pre integration, hoping to have a mild antialiasing
typedef struct {
int32_t x_old; // old x value
int32_t Y_old; // old integrated value
} waveshaper_state;
int32_t integrate_segment(int32_t dx, int32_t yi, int32_t yi_1) {
int32_t dy = yi - yi_1;
int32_t dx_sq = ___SMMUL(dx << 2, dx << 3);
return ___SMMUL(yi_1 << 2, dx << 3) + (___SMMUL(dx_sq << 2, dy << 3) << 3);
}
int32_t integrate_fullseg(int32_t yi, int32_t yi_1) { return yi_1 + yi >> 5; }
void waveshaper_setcoefs(waveshaper_coefs *coefs, waveshaper_state *state,
int32_t *ybuf) {
(coefs->Q[0]) = 0;
(coefs->q[0]) = 0;
for (int i = 1; i < 17; i++) {
(coefs->q[i]) = ybuf[i - 1];
(coefs->Q[i]) =
(coefs->Q[i - 1]) + integrate_fullseg((coefs->q[i]), (coefs->q[i - 1]));
}
int32_t x = (state->x_old);
int32_t x_abs = x > 0 ? x : -x;
int32_t i = (x_abs >> 23);
int32_t z = x_abs & 0x7FFFFF;
int32_t q_i = coefs->q[i + 1];
int32_t q_i_1 = coefs->q[i];
int32_t Q_i_1 = coefs->Q[i];
int32_t Y = Q_i_1 + integrate_segment(z, q_i, q_i_1);
state->Y_old = Y;
}
int32_t waveshaper_process(waveshaper_coefs *coefs, waveshaper_state *state,
int32_t input) {
int32_t x = __SSAT(input, 28);
int32_t x_sign = x > 0 ? 1 : -1;
int32_t x_abs = x * x_sign;
int32_t i = (x_abs >> 23);
int32_t z = x_abs & 0x7FFFFF;
int32_t q_i = coefs->q[i + 1];
int32_t q_i_1 = coefs->q[i];
int32_t Q_i_1 = coefs->Q[i];
int32_t y = ___SMMLA(q_i - q_i_1 << 2, z << 7, q_i_1) * x_sign;
int32_t Y = Q_i_1 + integrate_segment(z, q_i, q_i_1);
int32_t dx = x - (state->x_old);
int32_t dx_abs = dx > 0 ? dx : -dx;
int32_t dY = Y - (state->Y_old);
int32_t dY_dx = 134217728.0f * ((float)dY) / ((float)dx);
state->x_old = x;
state->Y_old = Y;
return (dx_abs > (1 << 10)) ? dY_dx : y;
}
typedef struct {
int32_t f = 0;
int32_t val = 0;
} filter_state;
void filter_setpitch(filter_state *state, int32_t pitch) {
MTOF(pitch, state->f);
}
int32_t lowpass_process(filter_state *state, int32_t input) {
state->val = ___SMMLA((input - (state->val)) << 1, state->f, state->val);
return (state->val);
}
filter_state lps[attr_chain - 1];
int32_t out = 0;
int32_t buffer[attr_chain + 1];
waveshaper_coefs wsc[attr_chain];
waveshaper_state wss[attr_chain];
for (int i = 0; i < attr_chain; i++)
filter_setpitch(&lps[i], 1 << 27);
int i;
int32_t coefs[BUFSIZE];
for (i = 0; i < BUFSIZE; i++) {
coefs[i] = inlet_coefs[i];
}
for (int i = 0; i < attr_chain; i++) {
waveshaper_setcoefs(&wsc[i], &wss[i], coefs);
filter_setpitch(&lps[i],
inlet_pitch + param_pitch + (i * (param_chain / attr_chain)));
}
int32_t feed = __SSAT(inlet_feed + param_feed, 28);
buffer[0] = inlet_in + ___SMMUL(feed << 2, buffer[attr_chain] << 3);
for (int i = 0; i < attr_chain; i++)
buffer[i + 1] =
waveshaper_process(&wsc[i], &wss[i], lowpass_process(&lps[i], buffer[i]));
outlet_out = buffer[attr_chain];