osc

XT osc, needs to connect to a XT.
Author: Smashed Transistors
License: LGPL
Github: tiar/XT/osc.axo

Inlets

frac32.bipolar pitch

frac32.bipolar freq offset

frac32.bipolar disto offset

frac32buffer.bipolar pm

bool32 disables the object

bool32 use the waveform as a distortion

frac32 wave

Outlets

frac32buffer.bipolar wave

Parameters

frac32.s.map.pitch pitch

Attributes

objref xt

Declaration
uint32_t p; // phase
int32_t dp; // delta phase aka freq
int32_t x0, x1;
int32_t I1_1_0;
int32_t I1_1_1;
int32_t kMI;      // Modulation Index
int32_t aMI, dMI; // interp Modulation Index
int32_t alpha;
int iw0, iw1;
int32_t *v0;
int32_t *Iv0;
int32_t *v1;
int32_t *Iv1;
Init
p = 0;
dp = 1;
x0 = 0;
x1 = 1;
aMI = dMI = kMI = 0;
I1_1_0 = 0;
I1_1_1 = 0;
iw0 = -1;
iw1 = -1;
alpha = 0;
Control Rate
if (!inlet_disable) {
  MTOFEXTENDED(param_pitch + inlet_pitch, dp);
  dp += ___SMMUL(0x01000000, inlet_freq_space_offset);
  dp >>= 32 - 20 - attr_xt.LENGTHPOW;
  // (need to calculate x0 - x1 even with over modulation)
  const int rightShiftPM = 9 - attr_xt.LENGTHPOW;
  const int shiftDisto = attr_xt.LENGTHPOW - 4;

  int32_t w0 = ((inlet_wave & 0x07FFFFFF) >> 6) * attr_xt.NBWAVES; // q21
  int newIw0 = w0 >> 21;

  if (newIw0 == iw0) { // continuity
    int32_t dAlpha = (((w0 & ((1 << 21) - 1)) << (31 - 21)) - alpha) >> 4; // q31
    for (int j = 0; j < BUFSIZE; j++) {
      alpha += dAlpha;
      if (inlet_disto) {
        p = (inlet_disto_space_offset >> 4) << shiftDisto;
      } else {
        p += dp; // phase increment
        if (p >= 0x40000000) {
          p -= attr_xt.LENGTH << 20;  // length of one cycle
          x0 -= attr_xt.LENGTH << 20; // p, x0 and x1 must be consistent
        }
      }
      x1 = x0;
      x0 = p + ((inlet_pm[j] << 3) >> rightShiftPM);

      int32_t _a = (x0 & 0x000FFFFF) << 11;
      uint32_t _i = (x0 & (attr_xt.LENGTHMASK << 20)) >> 20;
      if (abs(x0 - x1) < 256) {
        int32_t val0 = attr_xt.I0p30(v0, _i, _a);
        int32_t val1 = attr_xt.I0p30(v1, _i, _a);
        outlet_wave[j] = ___SMMLA(alpha, val1 - val0, val0 >> 1) << 1;
        I1_1_0 = attr_xt.I1p30(v0, Iv0, _i, _a);
        I1_1_1 = attr_xt.I1p30(v1, Iv1, _i, _a);
      } else {
        float inv = ((float)(1 << 27)) / ((float)(x0 - x1));
        int32_t I1_0_0 = attr_xt.I1p30(v0, Iv0, _i, _a);
        int32_t diff0 = I1_0_0 - I1_1_0;
        I1_1_0 = I1_0_0;
        int32_t I1_0_1 = attr_xt.I1p30(v1, Iv1, _i, _a);
        int32_t diff1 = I1_0_1 - I1_1_1;
        I1_1_1 = I1_0_1;
        //                        q31      q27           q26
        int32_t diff = ___SMMLA(alpha, diff1 - diff0, diff0 >> 1) << 1;
        outlet_wave[j] = (int32_t)(diff * inv);
      }
    }
  } else { // table change
    iw0 = newIw0;
    v0 = attr_xt.getV(iw0);
    Iv0 = attr_xt.getIv(iw0);
    iw1 = (iw0 + 1) % attr_xt.NBWAVES;
    v1 = attr_xt.getV(iw1);
    Iv1 = attr_xt.getIv(iw1);

    alpha = (w0 & ((1 << 21) - 1)) << (31 - 21);
    I1_1_0 = attr_xt.I1p30(v0, Iv0, x0);
    I1_1_1 = attr_xt.I1p30(v1, Iv1, x0);
    for (int j = 0; j < BUFSIZE; j++) {
      if (inlet_disto) {
        p = (inlet_disto_space_offset >> 4) << shiftDisto;
      } else {
        p += dp; // phase increment
        if (p >= 0x40000000) {
          p -= attr_xt.LENGTH << 20;  // length of one cycle
          x0 -= attr_xt.LENGTH << 20; // p, x0 and x1 must be consistent
        }
      }
      x1 = x0;
      x0 = p + ((inlet_pm[j] << 3) >> rightShiftPM);

      int32_t _a = (x0 & 0x000FFFFF) << 11;
      uint32_t _i = (x0 & (attr_xt.LENGTHMASK << 20)) >> 20;
      if (abs(x0 - x1) < 256) {
        int32_t val0 = attr_xt.I0p30(v0, _i, _a);
        int32_t val1 = attr_xt.I0p30(v1, _i, _a);
        outlet_wave[j] = ___SMMLA(alpha, val1 - val0, val0 >> 1) << 1;
        I1_1_0 = attr_xt.I1p30(v0, Iv0, _i, _a);
        I1_1_1 = attr_xt.I1p30(v1, Iv1, _i, _a);
      } else {
        float inv = ((float)(1 << 27)) / ((float)(x0 - x1));
        int32_t I1_0_0 = attr_xt.I1p30(v0, Iv0, _i, _a);
        int32_t diff0 = I1_0_0 - I1_1_0;
        I1_1_0 = I1_0_0;
        int32_t I1_0_1 = attr_xt.I1p30(v1, Iv1, _i, _a);
        int32_t diff1 = I1_0_1 - I1_1_1;
        I1_1_1 = I1_0_1;
        //                        q31      q27           q26
        int32_t diff = ___SMMLA(alpha, diff1 - diff0, diff0 >> 1) << 1;
        outlet_wave[j] = (int32_t)(diff * inv);
      }
    }
  }
} else { // disabled
  if (inlet_disto) {
    for (int j = 0; j < BUFSIZE; j++) {
      outlet_wave[j] = inlet_pm[j];
    }
  } else {
    for (int j = 0; j < BUFSIZE; j++) {
      outlet_wave[j] = 0;
    }
  }
}

Privacy

© 2024 Zrna Research