Five

The waveform of the FiveSteps oscillator is controlled by five parameters: the five steps levels. It allows to generate waveforms reminiscent of old pseudo digital synths (such as the RMI and it's digit harmonics based on Walsh functions). It is **anti aliased** with an algorithm that is based on both BLEPs and DPWs... i think it is quite original and efficient with this kind of waveforms. (the steppy signal goes through a second order leaky "analytic" integrator, when a transient occurs the state variable of the integrator is updated taking account of the subsample time of the transient - much like BLEPs -... at the end the signal is high passed with a second order differentiator - like a second order DPW...) It has an accompanying help patch file you can play with.
Author: Smashed Transistors
License: LGPL
Github: tiar/osc/Steps/Five.axo

Inlets

frac32.bipolar pitch

Outlets

frac32buffer.bipolar out

Parameters

frac32.s.map level0

frac32.s.map level1

frac32.s.map level2

frac32.s.map level3

frac32.s.map level4

frac32.s.map.pitch pitch

Declaration
float x, y, z0, z_1, z_2, p, dp, _dp;
float w0, w_1, w_2;
int cpt;
float seq[7];
Init
cpt = 0;
x = y = z_2 = z_1 = z0 = 0;
p = 0;
Control Rate
int32_t idp;
MTOFEXTENDED(param_pitch + inlet_pitch, idp);
dp = 5.0f * (idp * (0.25f / (1 << 30)));
_dp = 1 / dp;
if (dp > 1)
  dp = 1;
float dc = seq[0] = (float)param_level0;
dc += seq[1] = (float)param_level1;
dc += seq[2] = (float)param_level2;
dc += seq[3] = (float)param_level3;
dc += seq[4] = (float)param_level4;
dc *= 1.0f / 5;
for (int i = 0; i < 5; i++)
  seq[i] -= dc;
Audio Rate
// phase increment
p += dp;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                                         transition ?
if (p > 1) {    // phase above 1
  cpt++;        // next step in sequence
  if (cpt >= 5) // above 5 => wrap to 0
    cpt = 0;
  p -= 1;                // reset phase
  float alpha = p * _dp; // subsample time since the transition
  //_  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
  //                           integrator evolution before the transition
  float _alpha = 1 - alpha;
  float alpha_x = _alpha * x;
  z0 += _alpha * (y + 0.5f * alpha_x);
  y += alpha_x;
  //_  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
  //                                                           transition
  x = seq[cpt];
  //_  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
  //                            integrator evolution after the transition
  alpha_x = alpha * x;
  z0 += alpha * (y + 0.5f * alpha_x);
  y += alpha_x;
} else {
  //_  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
  //                              integrator evolution without transition
  z0 += y + 0.5f * x;
  y += x;
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                                     integrator leaks
y *= 0.999f;
z0 *= 0.999f;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                            2nd order differenciation
outlet_out = (int32_t)(z0 + z_2 - 2 * z_1);
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                                      previous values
z_2 = z_1;
z_1 = z0;

Privacy

© 2024 Zrna Research