polyWaveform

4-voice "chord" oscillator with multiple waveforms connect a positive saw-LFO (non-bandlimited) to the morph input for normal operation connect an attenuatable LFO to the mofs input to "swing" the morphing connect note patterns to the note(1-4) inputs, these will be scaled to the selected key internally "PW" controls an exponential shaping of the phase, generating PW-modulation for all waveform-options "waveform" controls the selected "base-start" waveform "wChg" sets different waveforms for each voice, one knob for all possible combinations **use shift+ctrl to get to smaller bits "detune" offsets the pitch between the 4 voices. "key" sets the key of the scale. (negative values for minor scales)
Author: Remco van der Most
License: BSD
Github: sss/osc/polyWaveform.axo

Inlets

frac32 morph

frac32 mofs

frac32 note1

frac32 note2

frac32 note3

frac32 note4

frac32 PW

int32 waveform

bool32 active

Outlets

frac32buffer out

Parameters

frac32.s.map.pitch pitch

frac32.s.map detune

frac32.s.map PW

int32 key

int32 waveform

frac32.u.map wChg

Declaration
uint32_t phase[8];
uint32_t phose[8];
uint32_t phise[8];
int32_t wave[8];
int32_t freq[8];
int form[8];
int i;
int32_t base[12] = {0, 0, 2, 2, 4, 5, 5, 7, 7, 9, 9, 11};
int32_t sum;
int m1trig[4];
int m2trig[4];
int note[4];
int octave[4];
int32_t marph[4];
int32_t mirph[4];
int32_t morph[4];
int32_t LP1;
int32_t LP2;
int32_t HP;
int32_t PW;
Control Rate
if (inlet_active > 0) {
  for (i = 0; i < 4; i++) {
    int32_t a;
    a = (inlet_morph + i * inlet_mofs) & ((1 << 27) - 1);
    morph[i] = a < (1 << 26) ? a << 1 : (1 << 27) - ((a - (1 << 26)) << 1);
    morph[i] = (morph[i] - (1 << 26)) * 8 / 6 + (1 << 26);
    marph[i] = marph[i] + ((morph[i] - marph[i]) >> 1);
    morph[i] = marph[i] < 0 ? 0 : marph[i];
    morph[i] = morph[i] > (1 << 27) ? (1 << 27) : morph[i];
  }

  note[0] = (inlet_note1 + param_pitch) >> 21;
  note[1] = (inlet_note2 + param_pitch) >> 21;
  note[2] = (inlet_note3 + param_pitch) >> 21;
  note[3] = (inlet_note4 + param_pitch) >> 21;
  int key = (param_key * 7) - (param_key * 7) / 12 * 12;
  for (i = 0; i < 4; i++) {
    octave[i] = note[i] / 12;
    note[i] = note[i] - octave[i] * 12;
    note[i] = note[i] < 0 ? note[i] + 11 : note[i];

    if ((morph[i] == 0) && (!(m1trig[i]))) {
      MTOFEXTENDED((((base[note[i]] + octave[i] * 12)) << 21) + (key << 21) +
                       i * 53,
                   freq[i * 2])
      form[i * 2] =
          (inlet_waveform + param_waveform + (param_wChg >> (i * 2) * 3 + 8)) &
          7;
      m1trig[i] = 1;
    } else if (!(morph[i] == 0)) {
      m1trig[i] = 0;
    }

    if (!(morph[i] == (1 << 27)) && (!(m2trig[i]))) {
      MTOFEXTENDED((((base[note[i]] + octave[i] * 12)) << 21) + (key << 21) +
                       i * 47,
                   freq[i * 2 + 1])
      form[i * 2 + 1] = (inlet_waveform + param_waveform +
                         (param_wChg >> (i * 2 + 1) * 3 + 8)) &
                        7;
      m2trig[i] = 1;
    } else if ((morph[i] == (1 << 27))) {
      m2trig[i] = 0;
    }
  }
}
Audio Rate
if (inlet_active > 0) {
  PW = PW +
       (((((param_PW + inlet_PW + (1 << 27)) & ((1 << 28) - 1)) - (1 << 27)) -
         PW) >>
        8);
  sum = 0;
  for (i = 0; i < 4; i++) {
    mirph[i] = mirph[i] + ((marph[i] - mirph[i]) >> 8);
    morph[i] = mirph[i] < 0 ? 0 : mirph[i];
    morph[i] = morph[i] > (1 << 27) ? (1 << 27) : morph[i];
  }
  for (i = 0; i < 8; i++) {
    phase[i] += freq[i] + ((i * param_detune) >> 11);

    if (PW >= 0) {
      phose[i] = (___SMMUL(phase[i] >> 1, phase[i] >> 1) << 2);
    } else if (PW < 0) {
      phose[i] = ((1 << 32) - 1) - phase[i];
      phose[i] = ___SMMUL(phose[i] >> 1, phose[i] >> 1) << 2;
      phose[i] = (((1 << 32) - 1) - phose[i]);
    }

    phise[i] =
        ((___SMMUL(phase[i] >> 2, ((1 << 27) - (PW >= 0 ? PW : -PW)) << 3)
          << 3) +
         ((___SMMUL(phose[i] >> 1, (PW > 0 ? PW : -PW) << 3) << 2)))
        << 1;
    switch (form[i] > 0 ? form[i] : 0) {
    case 0:
      SINE2TINTERP(phise[i], wave[i]);
      break;
    case 1:
      wave[i] = phise[i] < (1 << 31)
                    ? ((phise[i] - (1 << 30)) << 1)
                    : ((1 << 31) - (phise[i] - (1 << 30))) << 1;
      break;
    case 2:
      wave[i] = phise[i] < (1 << 31) ? ((phise[i] - (1 << 30)) << 1)
                                     : ((1 << 31) - (phise[i] - (1 << 30)));
      break;
    case 3:
      wave[i] = phise[i] < (1 << 31) ? ((phise[i] - (1 << 30)) << 1)
                                     : ((1 << 30) - (phise[i] - (1 << 30)));
      break;
    case 4:
      wave[i] = phise[i] < (1 << 31)
                    ? ((phise[i] - (1 << 30)) << 1) - (1 << 27)
                    : -((1 << 30) - (phise[i] - (1 << 30))) - (1 << 27);
      break;
    case 5:
      wave[i] = phise[i] < (1 << 31) ? ((phise[i])) << 1
                                     : (-(phise[i] - (1 << 30))) << 1;
      break;
    case 6:
      wave[i] = phise[i] - (1 << 31);
      break;
    case 7:
      wave[i] = (phise[i]) > ((((PW > 0 ? PW : -PW) << 5) / (1 + i)) &
                              ((1 << 31) - 1))
                    ? (1 << 30)
                    : -(1 << 30);
      break;
    }
  }

  for (i = 0; i < 4; i++) {
    sum += ___SMMUL(morph[i], wave[i * 2]) +
           ___SMMUL((1 << 27) - morph[i], wave[i * 2 + 1]);
  }
  LP1 = LP1 + (((sum >> 2) - LP1) >> 2);
  HP = HP + ((LP1 - HP) >> 12);
  outlet_out = LP1 - HP;
  // outlet_out=wave[0]>>5;
}

Privacy

© 2024 Zrna Research