r1r2

Two slope cyclic ramp/LFO
Author: SmashedTransistors
License: LGPL
Github: tiar/XT/r1r2.axo

Inlets

frac32.positive start

frac32.bipolar rate1

frac32.bipolar rate2

bool32.rising reset

int32 sync

Outlets

frac32.positive saw wave

Attributes

combo sync2limit

Declaration
float reScale(float x) {
  float y = fabsf(x) * 1.01f - 0.01f;
  if (y < 0)
    y = 0;                       // central zero
  y = y * y * (1 + y * (1 + y)); // y2+y3+y4
  y *= (5 / 3000.0f);
  return x >= 0 ? y : -y;
}

float r, v;
bool atrig;
int state;
Init
r = v = 0;
atrig = false;
state = 0;
Control Rate
float r1 = reScale(arm::q_to_float(inlet_rate1, 27));
float r2 = reScale(arm::q_to_float(inlet_rate2, 27));

bool trig = inlet_reset && !atrig;
atrig = inlet_reset;
int32_t sync = inlet_sync;
if (r1 > 0) {
  if (r2 > 0) {
    if (sync == 1) { // two rate ramp
      if (v >= 2)
        v -= 4;
      if (v < -2)
        v += 4;
      if (trig) {
        state = 0;
        v = 0;
      } // start segment
      // if(v > 1){state = 1;}
      state = ((int)(v + 4)) & 1;
      v += state == 0 ? r1 : r2;

    } else if (sync == 2) { // two rate ramp
      if (v < 0)
        v += 4;
      if (v < 0)
        v += 4;
      if (trig) {
        state = 0;
        v = 0;
      } // start segment
      if (v > 1) {
        state = 1;
      }
      v += state == 0 ? r1 : r2;
      float start = 4 * arm::q_to_float(inlet_start, 27);
      if (v >= attr_sync2limit - start)
        v = attr_sync2limit - start; // 4*63.0f/64.0f = 3.9375f
    } else {                         // free run alternating rates ramp
      if (v >= 2)
        v -= 4;
      if (v < -2)
        v += 4;
      state = ((int)(v + 4)) & 1;
      v += state == 0 ? r1 : r2;
    }
  } else { // r1>0 r2<=0
    if (v >= 2)
      v -= 4;
    if (v < -2)
      v += 4;
    if (sync > 0) { // synched LFO
      if (trig) {
        state = 0;
        v = 0;
      } // start segment
      if (v >= 1) {
        state = 1;
        v = 1;
      }
      if (v <= 0) {
        state = 0;
        v = 0;
      }
      v += state == 0 ? r1 : r2;
    } else { // free run LFO
      if (v >= 1) {
        state = 1;
        v = 1;
      }
      if (v < 0) {
        state = 0;
        v = 0;
      }
      v += state == 0 ? r1 : r2;
    }
  }
} else {
  if (r2 > 0) {
    if (sync >= 1) { // synched neg LFO
      if (v >= 2)
        v -= 4;
      if (v < -2)
        v += 4;
      if (trig) {
        state = 0;
        v = 0;
      } // start segment
      if (v <= -1) {
        state = 1;
        v = -1;
      }
      if (v > 0) {
        state = 0;
        v = 0;
      }
      v += state == 0 ? r1 : r2;
    } else { // free un neg LFO
      if (v >= 2)
        v -= 4;
      if (v < -2)
        v += 4;
      if (v <= -1) {
        state = 1;
        v = -1;
      }
      if (v > 0) {
        state = 0;
        v = 0;
      }
      v += state == 0 ? r1 : r2;
    }
  } else {
    if (sync == 1) { // two rate neg ramp
      if (v >= 2)
        v -= 4;
      if (v < -2)
        v += 4;
      if (trig) {
        v = 0;
      } // start segment
      // if(v < -1){state = 1;}
      state = ((int)(v + 4)) & 1;
      v += state == 0 ? r2 : r1;

    } else if (sync == 2) { // two rate neg ramp
      if (v > 0)
        v -= 4;
      if (v > 0)
        v -= 4;
      if (trig) {
        state = 0;
        v = 0;
      } // start segment
      if (v < -1) {
        state = 1;
      }
      v += state == 0 ? r1 : r2;
      float start = 4 * arm::q_to_float(inlet_start, 27);
      if (v <= -start)
        v = -start;

    } else { // free run alternating rates neg ramp
      if (v >= 2)
        v -= 4;
      if (v < -2)
        v += 4;
      state = ((int)(v + 4)) & 1;
      v += state == 0 ? r1 : r2;
    }
  }
}

float s = 16 + 4 * arm::q_to_float(inlet_start, 27);
float fv = (v + s) * 0.25f;
outlet_out = arm::float_to_q((fv - floorf(fv)), 27);

Privacy

© 2024 Zrna Research