wavetable play

play a wavetable, which has been loaded by wave/wavetable load/ crossfade will fade beween waves. (~ double cpu load). note: you can use as a single wave oscillator by just loadng 1 wave
Author: Mark Harris
License: GPL
Github: tb/wave/wavetable play.axo

Inlets

frac32buffer frequency

frac32.bipolar pitch

frac32.positive wave index

Outlets

frac32buffer wave

Parameters

frac32.u.map wavetable index

bool32.tgl crossfade between waves

frac32.s.map.pitch pitch

Attributes

objref wavetable load object

Declaration
uint32_t phase;
uint32_t lastPhase;
uint32_t WAVESMASK, WAVESZ;

uint32_t wt1, new_wt1;
uint32_t wt2, new_wt2;
uint32_t mwt, new_mwt;
uint32_t cwt, new_cwt;
uint32_t wt1m, new_wt1m;
uint32_t wt2m, new_wt2m;
Init
WAVESMASK = (~((1 << (21 - (attr_table.WAVESPOW - 6))) - 1));
WAVESZ = (1 << (21 - (attr_table.WAVESPOW - 6)));

phase = 0;
lastPhase = 1 << 31;
new_wt1 = 0;
new_wt2 = 0;
new_wt1m = (1 << attr_table.SIZEPOW) - 1;
new_wt2m = (1 << attr_table.SIZEPOW) - 1;
new_mwt = 0;
new_cwt = 64 << 21;

wt1 = new_wt1;
wt2 = new_wt2;
mwt = new_mwt;
cwt = new_cwt;
wt1m = new_wt1m;
wt2m = new_wt2m;
Control Rate
uint32_t freq;
MTOFEXTENDED(param_pitch + inlet_pitch, freq);

uint32_t w = inlet_windex + param_windex;
w = w > (64 << 21) ? (64 << 21) - (w - (64 << 21)) : w;

new_wt1 = w & WAVESMASK;
uint32_t wsi = __USAT(new_wt1, 27) >> (27 - attr_table.LENGTHPOW);
new_wt1m = (wsi + (1 << attr_table.SIZEPOW)) - 1;

if (param_xfade) {
  new_wt2 = new_wt1 + WAVESZ;

  if (new_wt2 >= (64 << 21)) {
    new_wt2 = new_wt1;
    new_mwt = 128 << 20;
    new_cwt = 0;

  } else {
    uint32_t d = w - (w & WAVESMASK);
    uint32_t dp = d << attr_table.WAVESPOW;
    new_mwt = ((128 << 20) - dp);
    new_cwt = dp;
  }
  uint32_t wsi = __USAT(new_wt2, 27) >> (27 - attr_table.LENGTHPOW);
  new_wt2m = (wsi + (1 << attr_table.SIZEPOW)) - 1;
}
Audio Rate
// phasor
int32_t phasor;
phase += (freq >> 0) + inlet_freq;
phasor = phase >> 5;

// trig at new cycle
if (lastPhase > phase) {
  wt1 = new_wt1;
  wt2 = new_wt2;
  wt1m = new_wt1m;
  wt2m = new_wt2m;
  mwt = new_mwt;
  cwt = new_cwt;
}
lastPhase = phase;

// div number of entries
phasor = phasor >> attr_table.WAVESPOW;

// read interp - wt1
int32_t swt1;
{
  uint32_t asat = __USAT(phasor + wt1, 27);
  int index = asat >> (27 - attr_table.LENGTHPOW);
  int32_t y1 = attr_table.array[index] << attr_table.GAIN;
  int32_t y2 = attr_table.array[(index + 1) & wt1m] << attr_table.GAIN;
  int frac = (asat - (index << (27 - attr_table.LENGTHPOW)))
             << (attr_table.LENGTHPOW + 3);
  swt1 = ___SMMUL(y1, (1 << 30) - frac);
  swt1 = ___SMMLA(y2, frac, swt1);
}

if (param_xfade) {
  int32_t swt2;

  // read interp wt2
  uint32_t asat = __USAT(phasor + wt2, 27);
  int index = asat >> (27 - attr_table.LENGTHPOW);
  int32_t y1 = attr_table.array[index] << attr_table.GAIN;
  int32_t y2 = attr_table.array[(index + 1) & wt2m] << attr_table.GAIN;
  int frac = (asat - (index << (27 - attr_table.LENGTHPOW)))
             << (attr_table.LENGTHPOW + 3);
  swt2 = ___SMMUL(y1, (1 << 30) - frac);
  swt2 = ___SMMLA(y2, frac, swt2);

  // xfade between swt1 swt2
  int64_t a = (int64_t)swt2 * cwt;
  a += (int64_t)swt1 * mwt;
  outlet_o = a >> (27 - 2);
} else {
  outlet_o = swt1 << 2;
}

Privacy

© 2024 Zrna Research