pwm dpw

PWM wave tonewheels The pwm oscillators are made by subtracting two DPW saw waves (against aliasing). Range is midi note 24 to 119.
Author: Johannes Taelman
License: BSD
Github: jt/tonewheels/pwm dpw.axo

Inlets

frac32 phase

frac32.bipolar pwm

Outlets

frac32buffer.bipolar sine wave

Parameters

frac32.u.map phase

frac32.s.map pwm

Attributes

objref Table containing the amplitudes (32bit)

objref Tuning table

Declaration
class osc {
public:
  void init();
};

class osc_one : public osc {
public:
  int32_t prev1;
  int32_t prev2;

  void init() {
    prev1 = 0;
    prev2 = 0;
  }

  void render(int32_t *pOut, int32_t amp, uint32_t freq, uint32_t phase,
              uint32_t pw, float invfreq) {
    // pOut: pointer to s32 output buffer, adds values
    // amp: s32 amplitude
    int32_t a = (int)(invfreq * amp);
    int32_t _prev1 = ___SMMUL(phase - freq, phase - freq);
    int32_t _prev2 = ___SMMUL(phase - freq + pw, phase - freq + pw);

    int i = BUFSIZE;
    while (i--) {
      int32_t out = *pOut;

      int32_t v1 = ___SMMUL(phase, phase);
      int32_t d1 = (v1 - _prev1);
      out = __SMMLA(d1, a, out);
      _prev1 = v1;

      int32_t phase2 = phase + pw;
      int32_t v2 = ___SMMUL(phase2, phase2);
      int32_t d2 = (v2 - _prev2);
      out = ___SMMLS(d2, a, out);
      _prev2 = v2;

      phase += freq;
      *pOut++ = out;
    }
    prev1 = _prev1;
    prev2 = _prev2;
  }
};

static const int n_octaves = 8;

class chroma {
  int phase;

public:
  osc_one octaves[n_octaves];

  void init() {
    phase = 0;
    int i;
    for (i = 0; i < n_octaves; i++) {
      octaves[i].init();
    }
  };

  void render(int freq, int32_t *pOut, int32_t *amp, uint32_t x, int32_t pwm) {
    amp += 24;
    phase += freq << 4;
    uint32_t p = phase;
    uint32_t f = freq;
    float invfreq = (1 << 25) / (float)freq;
    int i;
    for (i = 0; i < n_octaves; i++) {
      octaves[i].render(pOut, *amp, f, p + x, pwm, invfreq);
      amp += 12;
      p = p << 1;
      f = f << 1;
      invfreq = invfreq * 0.5f;
    }
  }
};

chroma chromas[12];
Init
int i;

for (i = 0; i < 12; i++) {
  chromas[i].init();
}
Control Rate
int i;

// clear
for (i = 0; i < BUFSIZE; i++) {
  outlet_wave[i] = 0;
}

// sum into output buffer
for (i = 0; i < 12; i++) {
  chromas[i].render(attr_tuning.array[i] >> 3, &outlet_wave[0],
                    &attr_amplitudes.array[i], (param_phase + inlet_phase) << 5,
                    0x80000000 + ((inlet_pwm + param_pwm) << 4));
}

// output gain
for (i = 0; i < BUFSIZE; i++) {
  outlet_wave[i] = outlet_wave[i] << 2;
}

Privacy

© 2024 Zrna Research