fold 2

Wavefolding wavefolder waveshaper distortion based on polynomial waveshaping, with some attempts to make it mildly antialiased by integration. Sounds like sinefolding, but danker.
Author: Sputnki
License: BSD
Github: sptnk/effect/fold 2.axo

Inlets

frac32 shape parameter

frac32 "rule" for m parameter in chained units

frac32 global feedback

frac32buffer input

Outlets

frac32buffer out

Parameters

frac32.u.map shape parameter

frac32.s.map "rule" for m parameter in chained units

frac32.s.map global feedback

Attributes

spinner chain

Declaration
// defining some data structures and functions for the object. Hackable.
typedef struct {
  int32_t k0 = 0;
  int32_t k1 = 0;
  int32_t k2 = 0;
  int32_t k0_2 = 0;
  int32_t k1_4 = 0;
  int32_t k2_6 = 0;
} sinefolder_coefs;

typedef struct {
  int32_t x_old = 0;
  int32_t Y_old = 0;
} sinefolder_state;

void sinefolder_setcoefs(sinefolder_state *state, sinefolder_coefs *coefs,
                         int32_t xp) {
  int32_t xp1 = ___SMMLA(__USAT(xp, 27) << 3, 70317507 << 2, 43683676);
  int32_t xp2 = ___SMMUL(xp1 << 2, xp1 << 3);
  int32_t xp3 = ___SMMUL(xp2 << 2, xp1 << 3);
  int32_t xp4 = ___SMMUL(xp3 << 2, xp1 << 3);
  int32_t xp5 = ___SMMUL(xp4 << 2, xp1 << 3);
  int32_t xp7 = ___SMMUL(xp5 << 2, xp2 << 3);

  float D_rec = 1.0f / ((float)((xp7 << 1) - (xp5 << 2) + (xp3 << 1)));
  float Nk1 = 5 * xp4 - (1 << 27);
  float Nk2 = (1 << 27) - 3 * xp2;

  // k in Q25 format. This way i can go up to k = 64 (massive wavefolding)

  int32_t k1 = (1 << 25) * Nk1 * D_rec;
  int32_t k2 = (1 << 25) * Nk2 * D_rec;
  int32_t k0 = -k1 - k2;
  int32_t k0_2 = k0 >> 1;
  int32_t k1_4 = k1 >> 2;
  int32_t k2_6 = k2 / 6;

  (coefs->k0) = k0;
  (coefs->k1) = k1;
  (coefs->k2) = k2;
  (coefs->k0_2) = k0_2;
  (coefs->k1_4) = k1_4;
  (coefs->k2_6) = k2_6;

  int32_t x_old = (state->x_old);

  int32_t x1 = x_old;
  int32_t x2 = ___SMMUL(x1 << 2, x1 << 3);
  int32_t x4 = ___SMMUL(x2 << 2, x2 << 3);
  int32_t x6 = ___SMMUL(x2 << 2, x4 << 3);

  // x_n are in Q27 format. k_m are in Q25 format. I want to come out in Q24
  // format

  int32_t Y =
      ___SMMUL(x2 << 3, k0_2) + ___SMMUL(x4 << 3, k1_4) +
      ___SMMUL(x6 << 3, k2_6); // 0.5*k0*x2 + 0.25*k1*x4 + 1.f/6.f*k2*x6;

  (state->Y_old) = Y;
}

int32_t sinefolder_process(sinefolder_state *state, sinefolder_coefs *coefs,
                           int32_t input_Q27) {
  int32_t x1 = __SSAT(input_Q27, 28);
  int32_t x2 = ___SMMUL(x1 << 2, x1 << 3);
  int32_t x3 = ___SMMUL(x1 << 2, x2 << 3);
  int32_t x4 = ___SMMUL(x1 << 2, x3 << 3);
  int32_t x5 = ___SMMUL(x1 << 2, x4 << 3);
  int32_t x6 = ___SMMUL(x1 << 2, x5 << 3);

  int32_t k0 = (coefs->k0);
  int32_t k1 = (coefs->k1);
  int32_t k2 = (coefs->k2);
  int32_t k0_2 = (coefs->k0_2);
  int32_t k1_4 = (coefs->k1_4);
  int32_t k2_6 = (coefs->k2_6);

  int32_t x_old = (state->x_old);
  int32_t Y_old = (state->Y_old);

  // x_n are in Q27 format. k_m are in Q25 format. I want to come out in Q24
  // format

  int32_t y = ___SMMUL(x1 << 3, k0) + ___SMMUL(x3 << 3, k1) +
              ___SMMUL(x5 << 3, k2); // x1*k0 + x3*k1 + x5*k2;
  int32_t Y =
      ___SMMUL(x2 << 3, k0_2) + ___SMMUL(x4 << 3, k1_4) +
      ___SMMUL(x6 << 3, k2_6); // 0.5*k0*x2 + 0.25*k1*x4 + 1.f/6.f*k2*x6;

  int32_t dx = x1 - x_old;
  int32_t dY = Y - Y_old;

  int32_t dx_abs = dx > 0 ? dx : -dx;

  (state->Y_old) = Y;
  (state->x_old) = x1;

  int32_t dY_dx = dY * 134217728.0f / ((float)dx);
  int32_t out;

  if (dx_abs > 1 << 8)
    out = dY_dx;
  else
    out = y;

  return out << 4;
}

sinefolder_coefs wf_c[attr_chain];
sinefolder_state wf_s[attr_chain];
int32_t buffer[attr_chain + 1];
Control Rate
for (int i = 0; i < attr_chain; i++)
  sinefolder_setcoefs(&wf_s[i], &wf_c[i],
                      param_m + inlet_m + (i * (param_chain / attr_chain)));
Audio Rate
buffer[0] = inlet_in + ___SMMUL(param_feed << 2, buffer[attr_chain] << 3);
for (int i = 0; i < attr_chain; i++)
  buffer[i + 1] = sinefolder_process(&wf_s[i], &wf_c[i], buffer[i]);
outlet_out = buffer[attr_chain];

Privacy

© 2024 Zrna Research