frac32buffer input signal
frac32buffer 16 coefficient buffer, these represent the shape of a curve in several points
frac32 amount of feedback
frac32buffer out
frac32.s.map feedback
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;
}
int32_t out = 0;
int32_t buffer[attr_chain + 1];
waveshaper_coefs wsc[attr_chain];
waveshaper_state wss[attr_chain];
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);
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], buffer[i]);
outlet_out = buffer[attr_chain];