SelfPM

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/osc/SelfPM.axo

Inlets

frac32.bipolar pitch

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

Outlets

frac32buffer.bipolar selfPM wave

Parameters

frac32.s.map.pitch pitch

frac32.s.map Feedback Range [fb0 fb1]

frac32.s.map Feedback Range [fb0 fb1]

Declaration
// _____________________________________________________________________
uint32_t p;       // phase
int32_t kFb;      // feedback coefficient
int32_t aFb, dFb; // interp Fb
int32_t y;        // raw (modulated)sine
int32_t fy;       // filtered output
// _____________________________________________________________________
Init
// _____________________________________________________________________
p = 0;
y = 0;
fy = 0;
aFb = dFb = 0;
// _____________________________________________________________________
Control Rate
// _____________________________________________________________________
int32_t dp; // delta phase aka freq
MTOFEXTENDED(param_pitch + inlet_pitch, dp);
// mapping:
// fbMod [0 64] -> [fb0 fb1] with scaling
int32_t fbMod = __USAT(inlet_fbMod, 27);
kFb = ___SMMUL(param_fb1 * 3, fbMod << 4);
kFb = ___SMMLA(param_fb0 * 3, (((1 << 27) - 1) - fbMod) << 4, kFb);
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                             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
    p += dp;
    // raw sine access with feedback (with low passed output "fy")
    y = sine2t[((uint32_t)(p + (___SMMUL(fy, aFb) << 4))) >> 20];
    // we can tolerate raw access to the sine table thanks to
    // this "anti hunting" low pass filter
    fy = (fy >> 1) + (y >> 1);
    outlet_wave[j] = fy >> 4;
    aFb += dFb;
  }
} else {
  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  //                                             Squared feedback variant
  int j;
  for (j = 0; j < BUFSIZE; j++) {
    // phase increment
    p += dp;
    // raw sine access with squared lp feedback
    y = sine2t[((uint32_t)(p + (___SMMUL(___SMMUL(fy, fy), aFb) << 5))) >> 20];
    // "anti hunting" low pass filter
    fy = (fy >> 1) + (y >> 1);
    outlet_wave[j] = fy >> 4;
    aFb += dFb;
  }
}
// _____________________________________________________________________

Privacy

© 2024 Zrna Research