blepped

blepped multi-waveform oscillator Bandwith limited
Author: Remco van der Most
License: BSD
Github: sss/osc/blepped.axo

Inlets

frac32buffer mod

frac32buffer strike

frac32 env

frac32 self

int32 mode

frac32.bipolar pitch

Outlets

frac32buffer.bipolar triangle wave, anti-aliased

Parameters

int32 wave

int32 index2wave

int32 note2wave

frac32.s.map.pitch pitch

frac32.s.map self

frac32.s.map mod

bool32.tgl sync

Attributes

objref table

combo size

Declaration
static const uint32_t LENGTHPOW = attr_size;
static const uint32_t LENGTH = 1 << attr_size;
static const uint32_t LENGTHMASK = (1 << attr_size) - 1;
int32_t *array;
uint32_t writepos;
uint32_t Writepos;
uint32_t osc_p;
int32_t Osc_p;
bool trg;
int32_t preset;
int wave;
int k;
int32_t prev;
int32_t step;

static const int blepvoices = 8;
const int16_t *oscp[blepvoices];
int16_t *Oscp[blepvoices];
int16_t amp[blepvoices];
uint32_t nextvoice;
int32_t vgain[blepvoices];
int32_t i0;
int32_t sync;
int32_t max;
int32_t val;
int32_t dval1;
int32_t dval2;

int32_t in[attr_poly][BUFSIZE];
int32_t out[attr_poly][BUFSIZE];
int i;

int32_t SIN(int32_t pitch, int32_t fm, int32_t self) {

  uint32_t freq;
  MTOFEXTENDED(pitch, freq);
  int32_t FM;
  int32_t fM = ___SMMUL(fm << 4, freq) << 3;
  int32_t Fm = ___SMMUL(self << 2, freq);
  int j;
  for (j = 0; j < BUFSIZE; j++) {
    FM = ___SMMUL(in[parent->polyIndex][j] << 3, fM) +
             ___SMMUL(out[parent->polyIndex][j] << 3, Fm << 2)
         << 3;
    int32_t tfreq = freq + FM;
    if (((in[parent->polyIndex][j] > 0) && !trg) && sync) {
      trg = 1;
      osc_p = 0;
    } else if (in[parent->polyIndex][j] <= 0) {
      trg = 0;
    }
    osc_p += tfreq;
    int32_t sine;
    SINE2TINTERP(osc_p, sine)
    int32_t tmp = sine >> 5;
    val += (tmp - val) >> 10;
    out[parent->polyIndex][j] = tmp - val;
  }
}
int32_t TRI(int32_t pitch, int32_t fm, int32_t self) {

  uint32_t freq;
  MTOFEXTENDED(pitch, freq);
  int32_t FM;
  int32_t fM = ___SMMUL(fm << 4, freq) << 3;
  int32_t Fm = ___SMMUL(self << 2, freq);
  int j;
  const int16_t *lastblep = &blt[BLEPSIZE - 1];
  for (j = 0; j < BUFSIZE; j++) {
    FM = ___SMMUL(in[parent->polyIndex][j] << 3, fM) +
             ___SMMUL(out[parent->polyIndex][j] << 3, Fm << 2)
         << 3;
    int32_t tfreq = freq + FM;
    // tfreq=tfreq>0?tfreq:-tfreq+1;
    int i;
    uint32_t p;
    p = osc_p;
    int32_t p3 = p - 2 * tfreq;
    int32_t tri;
    if (p3 > 0) {
      tri = ((1 << 30) - (p3)) >> 4;
    } else {
      tri = (p3 + (1 << 30)) >> 4;
    }
    osc_p = p + tfreq;
    //
    int i1 = sync > 0 ? in[parent->polyIndex][j] >> 2 : 0;
    if ((i1 > 0) && !(i0 > 0)) { // phase reset
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = 64 - ((-i0 << 6) / (i1 - i0));
      oscp[nextvoice] = &blept[x];
      vgain[nextvoice] = vgain[nextvoice] =
          (((x * (tfreq >> 7)) + (((uint32_t)p) >> 1))) >> 18;
      osc_p = x * (tfreq >> 6);
    } else if ((osc_p > 0) && !(p > 0)) { // dispatch
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = osc_p / (tfreq >> 6);
      oscp[nextvoice] = &blept[x];
      vgain[nextvoice] = 1 << 13;
    }
    i0 = i1;
    //
    if ((((int32_t)osc_p) > 0) ^ (((int32_t)p) > 0)) { // dispatch
      if ((freq >> 6) > 0) {
        nextvoice = (nextvoice + 1) & (blepvoices - 1);
        int32_t x = (osc_p & 0x7FFFFFFF) / (((uint32_t)tfreq) >> 6);
        oscp[nextvoice] = &blt[x];
        amp[nextvoice] = (((int32_t)osc_p) < 0) ? tfreq >> 16 : -(tfreq >> 16);
      }
    }
    int32_t sum = 0;
    for (i = 0; i < blepvoices; i++) { // sample
      const int16_t *t = oscp[i];
      sum += (*t) * amp[i];
      t += 64;
      if (t >= lastblep)
        t = lastblep;
      oscp[i] = t;
    }
    int32_t tmp = tri + (sum >> 3);
    val += (tmp - val) >> 10;
    out[parent->polyIndex][j] = tmp - val;
  }
};

int32_t SQR(int32_t pitch, int32_t fm, int32_t self) {

  int32_t freq;
  MTOFEXTENDED(pitch, freq);
  int32_t FM;
  int32_t fM = ___SMMUL(fm << 4, freq) << 3;
  int32_t Fm = ___SMMUL(self << 2, freq);
  int j;
  int16_t *lastblep = &blept[BLEPSIZE - 1];
  for (j = 0; j < BUFSIZE; j++) {
    FM = ___SMMUL(in[parent->polyIndex][j] << 3, fM) +
             ___SMMUL(out[parent->polyIndex][j] << 3, Fm << 2)
         << 3;
    int32_t tfreq = freq + FM;
    tfreq = tfreq > 0 ? tfreq : -tfreq + 1;
    int i;
    int p;
    p = Osc_p;
    Osc_p = p + (tfreq << 1);
    int32_t sum = 0;
    int i1 = sync > 0 ? in[parent->polyIndex][j] >> 2 : 0;
    if ((i1 > 0) && !(i0 > 0)) { // phase reset
      int32_t x = 64 - ((-i0 << 6) / (i1 - i0));
      Osc_p = x * (tfreq >> 6);
      if (nextvoice & 1) {
        nextvoice = (nextvoice + 1) & (blepvoices - 1);
        oscp[nextvoice] = &blept[x];
      }
    } else if ((Osc_p > 0) && !(p > 0)) { // dispatch
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = Osc_p / (tfreq >> 5);
      Oscp[nextvoice] = &blept[x];
    }
    i0 = i1;
    for (i = 0; i < blepvoices; i++) { // sample
      int16_t *t = Oscp[i];
      if (i & 1)
        sum += *t;
      else
        sum -= *t;
      t += 64;
      if (t >= lastblep)
        t = lastblep;
      Oscp[i] = t;
    }
    sum -= ((((nextvoice + 1) & 1) << 1) - 1) << 13;
    int32_t tmp = sum << 13;
    val += (tmp - val) >> 10;
    out[parent->polyIndex][j] = tmp - val;
  }
}

int32_t SAW(int32_t pitch, int32_t fm, int32_t self, int dir) {

  int32_t freq;
  MTOFEXTENDED(pitch, freq);
  int32_t FM;
  int32_t fM = ___SMMUL(fm << 4, freq) << 3;
  int32_t Fm = ___SMMUL(self << 2, freq);
  int j;
  int16_t *lastblep = &blept[BLEPSIZE - 1];
  for (j = 0; j < BUFSIZE; j++) {
    int i;
    int p;
    FM = ___SMMUL(in[parent->polyIndex][j] << 3, fM) +
             ___SMMUL(out[parent->polyIndex][j] << 3, Fm << 2)
         << 3;
    int32_t tfreq = freq + FM;
    tfreq = tfreq > 0 ? tfreq : -tfreq + 1;
    p = Osc_p;
    Osc_p = p + tfreq;
    int32_t sum = 0;
    int i1 = sync > 0 ? in[parent->polyIndex][j] >> 2 : 0;
    if ((i1 > 0) && !(i0 > 0)) { // phase reset
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = 64 - ((-i0 << 6) / (i1 - i0));
      Oscp[nextvoice] = &blept[x];
      vgain[nextvoice] = vgain[nextvoice] =
          (((x * (tfreq >> 7)) + (((uint32_t)p) >> 1))) >> 18;
      Osc_p = x * (tfreq >> 6);
    } else if ((Osc_p > 0) && !(p > 0)) { // dispatch
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = Osc_p / (tfreq >> 6);
      Oscp[nextvoice] = &blept[x];
      vgain[nextvoice] = 1 << 13;
    }
    i0 = i1;

    for (i = 0; i < blepvoices; i++) { // sample
      int16_t *t = Oscp[i];
      sum += (16384 - (*t)) * vgain[i];
      t += 64;
      if (t >= lastblep)
        t = lastblep;
      Oscp[i] = t;
    }
    // sum = -sum;
    uint32_t g = Osc_p;
    int32_t tmp = ((g >> 5) + sum - (1 << 26)) * dir;
    val += (tmp - val) >> 10;
    out[parent->polyIndex][j] = tmp - val;
  }
}

int32_t TAB(int32_t pitch, int32_t fm, int32_t self, int32_t pst) {

  uint32_t freq;
  MTOFEXTENDED(pitch, freq);
  uint32_t damp;
  MTOFEXTENDED(-pitch, damp)
  int32_t FM;
  int32_t fM = ___SMMUL(fm << 4, freq) << 3;
  int32_t Fm = ___SMMUL(self << 2, freq);
  int j;
  const int16_t *lastblep = &blt[BLEPSIZE - 1];
  for (j = 0; j < BUFSIZE; j++) {
    writepos = (writepos + 1) & LENGTHMASK;
    dval1 += ___SMMUL(attr_table.array[writepos + pst] - dval1, damp);
    dval2 += ___SMMUL(dval1 - dval2, damp);
    array[writepos] += dval2 - array[writepos] >> 1;
    FM = ___SMMUL(in[parent->polyIndex][j] << 3, fM) +
             ___SMMUL(out[parent->polyIndex][j] << 3, Fm << 2)
         << 3;
    int32_t tfreq = freq + FM;
    // tfreq=tfreq>0?tfreq:-tfreq+1;
    int i;
    uint32_t p;
    p = osc_p;
    uint32_t p3 = p - 2 * tfreq;
    int32_t tri;
    uint32_t tmp_d = p3 >> 5;
    uint32_t tmp_di = (tmp_d >> (27 - LENGTHPOW));
    uint32_t tmp_w1 = (tmp_d << (LENGTHPOW + 3)) & 0x3FFFFFFF;
    uint32_t tmp_w2 = (1 << 30) - tmp_w1;
    int32_t tmp_a1 = array[(tmp_di & LENGTHMASK)];
    int32_t tmp_a2 = array[((tmp_di + 1) & LENGTHMASK)];
    int32_t tmp_r = ___SMMUL(tmp_a1, tmp_w1);
    tmp_r = ___SMMLA(tmp_a2, tmp_w2, tmp_r);
    tri = (tmp_r << 1) + (1 << 27);

    osc_p = p + tfreq;
    //
    int i1 = sync > 0 ? in[parent->polyIndex][j] >> 2 : 0;
    if ((i1 > 0) && !(i0 > 0)) { // phase reset
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = 64 - ((-i0 << 6) / (i1 - i0));
      oscp[nextvoice] = &blept[x];
      vgain[nextvoice] = vgain[nextvoice] =
          (((x * (tfreq >> 7)) + (((uint32_t)p) >> 1))) >> 18;
      osc_p = x * (tfreq >> 6);
    } else if ((osc_p > 0) && !(p > 0)) { // dispatch
      nextvoice = (nextvoice + 1) & (blepvoices - 1);
      int32_t x = osc_p / (tfreq >> 6);
      oscp[nextvoice] = &blept[x];
      vgain[nextvoice] = 1 << 13;
    }
    i0 = i1;
    //
    if ((((int32_t)osc_p) > 0) ^ (((int32_t)p) > 0)) { // dispatch
      if ((freq >> 6) > 0) {
        nextvoice = (nextvoice + 1) & (blepvoices - 1);
        int32_t x = (osc_p & 0x7FFFFFFF) / (((uint32_t)tfreq) >> 6);
        oscp[nextvoice] = &blt[x];
        amp[nextvoice] = (((int32_t)osc_p) < 0) ? tfreq >> 16 : -(tfreq >> 16);
      }
    }
    int32_t sum = 0;
    for (i = 0; i < blepvoices; i++) { // sample
      const int16_t *t = oscp[i];
      sum += (*t) * amp[i];
      t += 64;
      if (t >= lastblep)
        t = lastblep;
      oscp[i] = t;
    }
    int32_t tmp = tri + (sum >> 3);
    val += (tmp - val) >> 10;
    tmp = tmp - val;
    max = __USAT(max - (6 << 11), 31);
    int32_t Abs = tmp > 0 ? tmp : -tmp;
    if (Abs > max) {
      max = Abs;
    }
    float32_t ratio = (float32_t)(1 << 26) / max;
    out[parent->polyIndex][j] = tmp * ratio;
  }
};

int32_t STR(int32_t pitch, int32_t fm, int32_t self) {
  int32_t Tim;
  uint32_t tmp_d;
  int32_t Time;
  int32_t tailtime;
  float32_t ratio;
  float32_t dB;
  int32_t damp;
  int32_t ptmp;
  MTOFEXTENDED(0 - pitch, Tim);
  tmp_d = __USAT(Tim >> 1, 27);
  Time = Tim;
  MTOF(fm << 1, tailtime)
  tailtime = tailtime;
  ratio = (float32_t)(Time << 2) / (tailtime);
  dB = (float32_t)(-10) * ratio;
  dB = (powf(2, (dB / 2000)));
  MTOF(self, damp)
  ptmp = tmp_d >> 16;

  for (i = 0; i < BUFSIZE; i++) {
    Writepos = (Writepos + 1) & 2047;
    array[Writepos] = __SSAT(
        (((int32_t)((out[parent->polyIndex][(i - 1) & (BUFSIZE - 1)] * dB)))),
        30);
    uint32_t tmp_di = Writepos - (ptmp);
    uint32_t tmp_w1 = (tmp_d << (16)) & 0x3FFFFFFF;
    uint32_t tmp_w2 = (1 << 30) - tmp_w1;
    int32_t tmp_a1 = array[tmp_di & 2047] << 2;
    int32_t tmp_a2 = array[(tmp_di + 1) & 2047] << 2;
    out[parent->polyIndex][i] = ___SMMUL(tmp_a1, tmp_w1);
    out[parent->polyIndex][i] =
        in[parent->polyIndex][i] +
        ___SMMLA(tmp_a2, tmp_w2, out[parent->polyIndex][i]);
    val = ___SMMLA((out[parent->polyIndex][i] - val) << 1, damp, val);
    out[parent->polyIndex][i] =
        out[parent->polyIndex][i] - ((out[parent->polyIndex][i] - val) >> 9);
  }
}
Init
static int32_t _array[attr_poly][LENGTH << 3]
    __attribute__((section(".sdram")));
array = &_array[parent->polyIndex][0];
int j;
for (j = 0; j < blepvoices; j++) {
  oscp[j] = &blt[BLEPSIZE - 1];
  Oscp[j] = &blept[BLEPSIZE - 1];
  amp[j] = 0;
  i0 = 0;
}
nextvoice = 0;
for (i = 0; i < LENGTH << 3; i++) {
  array[i] = 0;
}
Control Rate
sync = param_sync;
int32_t offset = (parent->polyIndex) * param_index2wave;
int32_t MAX = attr_table.Waveforms + 6;
preset = (param_wave + offset + inlet_mode);
preset = preset - preset / MAX * MAX;
wave = preset > 6 ? 6 : preset;
int32_t Pitch = param_pitch + inlet_pitch;
int32_t Not = (Pitch >> 21) & 255;

preset = preset >= 6 ? preset + Not * param_note2wave - 6 : 0;

preset = (preset - preset / attr_table.Waveforms * attr_table.Waveforms)
         << attr_table.LENGTHPOW;

step = (inlet_env - prev) >> 4;
int32_t I = prev;
prev = inlet_env;

for (i = 0; i < BUFSIZE; i++) {
  if (!(wave == 5)) {
    in[parent->polyIndex][i] = inlet_mod[i];
  } else {
    in[parent->polyIndex][i] = inlet_strike[i];
  }
}

int32_t P2 = Pitch + ((39 << 21) / 100);
int32_t Self = param_self + inlet_self << 1;
if (wave == 0) {
  SIN(Pitch, param_mod, Self);
}
if (wave == 1) {
  TRI(Pitch, param_mod, Self);
}
if (wave == 2) {
  SAW(Pitch, param_mod, Self, 1);
}
if (wave == 3) {
  SAW(Pitch, param_mod, Self, -1);
}
if (wave == 4) {
  SQR(Pitch, param_mod, Self);
}
if (wave == 5) {
  STR(P2, param_mod, Self);
}
if (wave == 6) {
  TAB(Pitch, param_mod, Self, preset);
}
for (i = 0; i < BUFSIZE; i++) {
  outlet_wave[i] = ___SMMUL(out[parent->polyIndex][i], I) << 5;
  I += step;
}

Privacy

© 2024 Zrna Research