4 self PM oscs

Self PM oscillator (Very low cost) Generates a band controlled sawtooth like wave form. A square like wave form is obtained with negative kFb (negative kFb triggers kFb by squared signal). fb0 and fb1 controls the range of the feedback depth. fbMod modulates the feedback in the range [fb0 fb1]
Author: Smashed Transistors
License: LGPL
Github: tiar/dev/fourSelfPM.axo

Inlets

frac32.bipolar pitch

frac32.positive Feedback mod : [0 64] -> [fb0 fb1]

frac32.positive Gain

Outlets

frac32buffer.bipolar selfPM wave0

frac32buffer.bipolar selfPM wave1

frac32buffer.bipolar selfPM wave2

frac32buffer.bipolar selfPM wave3

Parameters

int32 detune

frac32.s.map.pitch pitch

frac32.s.map Feedback Range [fb0 fb1]

frac32.s.map Feedback Range [fb0 fb1]

Displays

frac32.s.dial Modulated feedback

Declaration
// _____________________________________________________________________
uint32_t p0, p1, p2, p3;    // phase
int32_t kFb;                // feedback coefficient
int32_t y0, y1, y2, y3;     // raw (modulated)sine
int32_t fy0, fy1, fy2, fy3; // filtered output
int32_t of0, of1, of2, of3; // pitch offsets
int32_t aGain, dGain;       // interp gain
int32_t aFb, dFb;           // interp Fb
// _____________________________________________________________________
Init
// _____________________________________________________________________
p0 = p1 = p2 = p3 = 0;
y0 = y1 = y2 = y3 = 0;
fy0 = fy1 = fy2 = fy3 = 0;
of0 = 0;
aGain = dGain = 0;
aFb = dFb = 0;
// _____________________________________________________________________
Control Rate
if (param_detune == 1) {
  of0 = (int32_t)(-0.0023f * (1 << (27 - 6)));
  of1 = (int32_t)(0.0016f * (1 << (27 - 6)));
  of2 = (int32_t)(-0.0007f * (1 << (27 - 6)));
  of3 = (int32_t)(0.0020f * (1 << (27 - 6)));
} else if (param_detune == 2) {
  of0 = (int32_t)(-0.023f * (1 << (27 - 6)));
  of1 = (int32_t)(0.015f * (1 << (27 - 6)));
  of2 = (int32_t)(-0.007f * (1 << (27 - 6)));
  of3 = (int32_t)(-0.005f * (1 << (27 - 6)));
} else if (param_detune == 3) {
  of0 = (int32_t)(-0.0023f * (1 << (27 - 6)));
  of1 = (int32_t)(0.0015f * (1 << (27 - 6)));
  of2 = (int32_t)(12.007f * (1 << (27 - 6)));
  of3 = (int32_t)(11.995f * (1 << (27 - 6)));
} else if (param_detune == 4) {
  of0 = (int32_t)(-0.023f * (1 << (27 - 6)));
  of1 = (int32_t)(0.015f * (1 << (27 - 6)));
  of2 = (int32_t)(12.013f * (1 << (27 - 6)));
  of3 = (int32_t)(11.981f * (1 << (27 - 6)));
} else if (param_detune == 5) {
  of0 = (int32_t)(-0.0023f * (1 << (27 - 6)));
  of1 = (int32_t)(7.0015f * (1 << (27 - 6)));
  of2 = (int32_t)(19.007f * (1 << (27 - 6)));
  of3 = (int32_t)(11.995f * (1 << (27 - 6)));
} else {
  of0 = (int32_t)(-0.023f * (1 << (27 - 6)));
  of1 = (int32_t)(7.015f * (1 << (27 - 6)));
  of2 = (int32_t)(19.013f * (1 << (27 - 6)));
  of3 = (int32_t)(11.981f * (1 << (27 - 6)));
}

// _____________________________________________________________________
int32_t dp0, dp1, dp2, dp3; // delta phase aka freq
MTOFEXTENDED(param_pitch + inlet_pitch + of0, dp0);
MTOFEXTENDED(param_pitch + inlet_pitch + of1, dp1);
MTOFEXTENDED(param_pitch + inlet_pitch + of2, dp2);
MTOFEXTENDED(param_pitch + inlet_pitch + of3, dp3);
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                           kRate -> aRate gain interp
dGain = (inlet_gain - aGain) >> 4;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// mapping:
// fbMod [0 64] -> [fb0 fb1] with scaling
kFb = ___SMMUL(param_fb1 * 3, inlet_fbMod << 4);
kFb = ___SMMLA(param_fb0 * 3, (((1 << 27) - 1) - inlet_fbMod) << 4, kFb);
disp_fb = kFb >> 1;
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                             kRate -> aRate FB interp
dFb = (kFb - aFb) >> 4;
// _____________________________________________________________________
//                                                     Audio rate loops
if (kFb > 0) {
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  //                                                      Simple feedback
  int j;
  for (j = 0; j < BUFSIZE; j++) {
    // phase increment
    p0 += dp0;
    p1 += dp1;
    p2 += dp2;
    p3 += dp3;
    // raw sine access with feedback (with low passed output "fy")
    y0 = sine2t[((uint32_t)(p0 + (___SMMUL(fy0, aFb) << 4))) >> 20];
    y1 = sine2t[((uint32_t)(p1 + (___SMMUL(fy1, aFb) << 4))) >> 20];
    y2 = sine2t[((uint32_t)(p2 + (___SMMUL(fy2, aFb) << 4))) >> 20];
    y3 = sine2t[((uint32_t)(p3 + (___SMMUL(fy3, aFb) << 4))) >> 20];
    // we can tolerate raw access to the sine table thanks to
    // this "anti hunting" low pass filter
    fy0 = (fy0 >> 1) + (y0 >> 1);
    fy1 = (fy1 >> 1) + (y1 >> 1);
    fy2 = (fy2 >> 1) + (y2 >> 1);
    fy3 = (fy3 >> 1) + (y3 >> 1);
    outlet_wave0[j] = ___SMMUL(aGain, fy0);
    outlet_wave1[j] = ___SMMUL(aGain, fy1);
    outlet_wave2[j] = ___SMMUL(aGain, fy2);
    outlet_wave3[j] = ___SMMUL(aGain, fy3);
    aGain += dGain;
    aFb += dFb;
  }
} else {
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  //                                             Squared feedback variant
  int j;
  for (j = 0; j < BUFSIZE; j++) {
    // phase increment
    p0 += dp0;
    p1 += dp1;
    p2 += dp2;
    p3 += dp3;
    // raw sine access with squared lp feedback
    y0 = sine2t[((uint32_t)(p0 + (___SMMUL(___SMMUL(fy0, fy0), aFb) << 5))) >>
                20];
    y1 = sine2t[((uint32_t)(p1 + (___SMMUL(___SMMUL(fy1, fy1), aFb) << 5))) >>
                20];
    y2 = sine2t[((uint32_t)(p2 + (___SMMUL(___SMMUL(fy2, fy2), aFb) << 5))) >>
                20];
    y3 = sine2t[((uint32_t)(p3 + (___SMMUL(___SMMUL(fy3, fy3), aFb) << 5))) >>
                20];
    // "anti hunting" low pass filter
    fy0 = (fy0 >> 1) + (y0 >> 1);
    fy1 = (fy1 >> 1) + (y1 >> 1);
    fy2 = (fy2 >> 1) + (y2 >> 1);
    fy3 = (fy3 >> 1) + (y3 >> 1);
    outlet_wave0[j] = ___SMMUL(aGain, fy0);
    outlet_wave1[j] = ___SMMUL(aGain, fy1);
    outlet_wave2[j] = ___SMMUL(aGain, fy2);
    outlet_wave3[j] = ___SMMUL(aGain, fy3);
    aGain += dGain;
    aFb += dFb;
  }
}
// _____________________________________________________________________

Privacy

© 2024 Zrna Research