blepSlaveS

Multi wave oscillator with sync and FM modulation Bandwith limited
Author: Remco van der Most
License: BSD
Github: sss/osc/blepSlaveS.axo

Inlets

frac32 fm

frac32 mix

frac32buffer sync, resets oscillator phase on rising zero-crossing

frac32buffer mod

int32 wave

int32 Sstep

int32 Sstart

int32 syncs

int32 hrmPst

int32 octPst

frac32.bipolar pitch

frac32.bipolar SPofs

Outlets

frac32 pitch

frac32 frq

frac32buffer.bipolar saw wave, anti-aliased

Parameters

frac32.s.map SPofs

frac32.s.map fm

frac32.s.map SFMofs

frac32.s.map defm

frac32.u.map detune

frac32.u.map mix

frac32.u.map demix

int32.hradio wave

int32 Wstep

int32 Sstart

int32 Sstep

int32 syncs

int32 stack

bool32.tgl selectM

bool32.tgl selectS

frac32.s.map.pitch pitch

Attributes

objref core

spinner maxStack

Declaration
static const int stack = attr_maxStack;
int32_t osc_p[stack];
uint32_t uosc_p[stack];
static const int blepvoices = 8;
const int16_t *uoscp[stack][blepvoices];
int16_t *oscp[stack][blepvoices];
int32_t vgain[stack][blepvoices];
uint32_t nextvoice[stack];
int32_t i0[stack];
int32_t sync[BUFSIZE];
int32_t mix[stack];
int i;
int k;
int wave[stack];
int32_t pitch[stack];
bool snc[stack];
int32_t fm[stack];
int32_t v27 = 1 << 27;
int32_t SQRT(int32_t in) {
  int32_t ai = in;
  float aif = ai;
  aif *= (1 << 27);
  aif = _VSQRTF(aif);
  return (int)aif;
}

int Pst;

int32_t octPst[8][8] = {
    {0, 0, 0, 0, 0, 0, 0, 0},        {0, -1, 0, -1, 0, -1, 0, -1},
    {0, -1, 0, -1, -2, 0, -1, -2},   {0, 1, -1, 0, 1, -1, 0, -2},
    {0, 1, 2, -1, -2, 0, 1, -1},     {0, 1, -1, -2, -1, -2, -3, -4},
    {0, -1, -2, -3, -4, -5, -6, -7}, {-3, -2, -1, 0, 1, 2, 1, -4}};
Init
int j;
for (i = 0; i < stack; i++) {
  for (j = 0; j < blepvoices; j++) {
    oscp[i][j] = &blept[BLEPSIZE - 1];
    nextvoice[i] = 0;
    i0[i] = 0;
  }
  for (j = 0; j < 8; j++) {
    octPst[j][i] = (octPst[j][i] * 12) << 21;
  }
}
Control Rate
if (param_stack > attr_maxStack) {
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_stack],
                     attr_maxStack, 0xFFFD);
}
if (param_syncs > attr_maxStack) {
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_syncs],
                     attr_maxStack, 0xFFFD);
}
int stack = param_stack > attr_maxStack ? attr_maxStack : param_stack;
attr_core.pst = inlet_hrmPst & 15;

int32_t mx = __USAT(param_mix + inlet_mix, 27);
for (i = 0; i < stack; i++) {
  attr_core.core = i & 7;
  int m = (i * (param_Wstep + (inlet_wave >> 2)));
  wave[i] = (param_wave + inlet_wave + m + (m >> 2) + (m >> 4)) & 3;
  pitch[i] = param_pitch + inlet_pitch + i * (param_detune >> 8) +
             (octPst[inlet_octPst & 7][i & 7]);
  snc[i] = 0;
  fm[i] = param_fm + inlet_fm + param_defm * i / stack;
  mix[i] = SQRT(
      SQRT((__USAT(mx - ___SMMUL(((v27 - param_demix) / param_stack) * i << 3,
                                 mx << 2),
                   27)
            << 3) /
           param_stack));
}

int syncs = param_syncs + inlet_syncs;
syncs = syncs - syncs / stack * stack;
syncs += syncs < 0 ? stack : 0;
int Sstep = param_Sstep + inlet_Sstep;
int Sstart = param_Sstart + inlet_Sstart;
int selectM = (param_selectM + (inlet_Sstep >> 3)) & 1;
int selectS = (param_selectS + (inlet_Sstart >> 3)) & 1;
for (i = 0; i < syncs; i++) {
  int tmp = i * Sstep + Sstart;
  tmp += tmp >> 3;
  tmp = tmp - tmp / stack * stack;
  snc[tmp] = 1;
  pitch[tmp] += param_SPofs + inlet_SPofs;
  fm[tmp] += param_SFMofs;
}

for (k = 0; k < param_stack; k++) {
  for (i = 0; i < blepvoices; i++) {
    attr_core.oscp[i] = oscp[k][i];
    attr_core.uoscp[i] = uoscp[k][i];
    attr_core.vgain[i] = vgain[k][i];
  }
  for (i = 0; i < BUFSIZE; i++) {
    attr_core.sync[i] = snc[k] > 0 ? (k > 0 ? sync[i] : inlet_sync[i]) : 0;
    attr_core.mod[i] =
        ___SMMUL((k > 0 ? (selectM > 0 ? inlet_mod[i] : attr_core.wave[i])
                        : inlet_mod[i] << 2)
                     << 2,
                 fm[k]);
  }
  attr_core.i0 = i0[k];
  attr_core.osc_p = osc_p[k];
  attr_core.uosc_p = uosc_p[k];
  attr_core.nextvoice = nextvoice[k];

  switch (wave[k]) {
  case 0:
    attr_core.OSC_SIN(pitch[k]);
    break;
  case 1:
    attr_core.OSC_TRI(pitch[k]);
    break;
  case 2:
    attr_core.OSC_SAW(pitch[k]);
    break;
  case 3:
    attr_core.OSC_SQR(pitch[k]);
    break;
  }
  for (i = 0; i < BUFSIZE; i++) {
    if (k == 0) {
      outlet_wave[i] = ___SMMUL(attr_core.wave[i] << 2, mix[k]);
      sync[i] = selectS > 0 ? inlet_sync[i] : attr_core.wave[i];
    } else {
      outlet_wave[i] += ___SMMUL(attr_core.wave[i] << 2, mix[k]);
    }
  }
  for (i = 0; i < blepvoices; i++) {
    oscp[k][i] = attr_core.oscp[i];
    uoscp[k][i] = attr_core.uoscp[i];
    vgain[k][i] = attr_core.vgain[i];
  }
  i0[k] = attr_core.i0;
  osc_p[k] = attr_core.osc_p;
  uosc_p[k] = attr_core.uosc_p;
  nextvoice[k] = attr_core.nextvoice;
}
outlet_pitch = param_pitch + inlet_pitch;
int32_t frq;
MTOFEXTENDED(outlet_pitch, frq)
outlet_frq = frq;

Privacy

© 2024 Zrna Research