2facedFilter

Dual allpass/phaser and dual SVF multi-filter. Filter-modes are LP1 - HP1 - BP1 - BR1 - LP2 - HP2 - BP2 - BR2. Depending on being filter 1 or 2, the 2nd filter-mode is a different combination of allpass/phaser, crossover/filter and serial/parallel processing settings. Use 2FacedCtrl-module for easy time/frequency modulations (randomisable presets).
Author: Remco van der Most
License: BSD
Github: sss/filter/2facedFilter.axo

Inlets

int32 filter1

int32 filter2

frac32buffer wave input

frac32 time1

frac32 cutoff1

frac32 resonance1

frac32 drive1

frac32 time2

frac32 cutoff2

frac32 resonance2

frac32 drive2

Outlets

frac32buffer out

int32 filter1

int32 filter2

Parameters

frac32.u.map.gain feed1

frac32.u.map.gain gain1

frac32.u.map.gain drive1

frac32.u.map.gain feed2

frac32.u.map.gain gain2

frac32.u.map.gain drive2

int32.hradio filter1

int32.hradio filter2

frac32.u.map.filterq resonance1

frac32.u.map.filterq resonance2

frac32.s.map.pitch time1

frac32.s.map.pitch cutoff1

frac32.s.map.pitch time2

frac32.s.map.pitch cutoff2

Declaration
static const uint32_t LENGTHPOW = 11;
static const uint32_t LENGTH = (1 << 11);
static const uint32_t LENGTHMASK = ((1 << 11) - 1);
int32_t *array;
uint32_t writepos;
uint32_t v30 = 1 << 30;
int32_t feed1;
int32_t feed2;
int32_t main;
int32_t PHASER(int32_t in, uint32_t tmp_d, int I) {
  uint32_t LT = LENGTH * I;
  array[writepos + LT] = __SSAT(in, 28) << 2;
  uint32_t tmp_di = writepos - (tmp_d >> 16) - 1;
  uint32_t tmp_w1 = (tmp_d << (14)) & 0x3FFFFFFF;
  uint32_t tmp_w2 = v30 - tmp_w1;
  int32_t tmp_a1 = array[(tmp_di & LENGTHMASK) + LT];
  int32_t tmp_a2 = array[((tmp_di + 1) & LENGTHMASK) + LT];
  int32_t tmp_r = tmp_a1 + ___SMMUL(tmp_a2 - tmp_a1, tmp_w1);
  return tmp_r;
}

int32_t band[2];
int32_t low[2];
int32_t SVF(int32_t in, int32_t frq, int32_t res, int32_t gain, int32_t drv,
            int flt, int I) {
  int32_t notch = in - (___SMMUL(res, band[I]) << 1);
  low[I] = low[I] + (___SMMUL(frq, band[I]) << 1);
  int32_t high = notch - low[I];
  band[I] = __SSAT(band[I], 28);
  band[I] += ___SMMUL(band[I], gain) >> 1;
  int32_t tband = __SSAT(band[I], 28);
  tband = ___SMMUL(___SMMUL(tband << 3, tband << 2) << 2, tband << 3);
  band[I] = (___SMMUL(frq, high) << 1) + band[I] - (___SMMUL(tband, drv) << 2);
  int32_t out1;
  switch (flt) {
  case 0:
    out1 = low[I];
    break;
  case 1:
    out1 = high;
    break;
  case 2:
    out1 = band[I];
    break;
  case 3:
    out1 = notch;
    break;
  }
  return out1;
}

int32_t SOFT(int32_t in) {
  int32_t ts = __SSAT(in, 28);
  int32_t tsq31 = ts << 3;
  int32_t tsq31p3 = ___SMMUL(tsq31, ___SMMUL(tsq31, tsq31));
  return ts = ts + (ts >> 1) - (tsq31p3);
}
Init
static int32_t _array[1 << 12] __attribute__((section(".sdram")));
array = &_array[0];
int i;
writepos = 0;
for (i = 0; i < (LENGTH << 1); i++)
  array[i] = 0;
Control Rate
uint32_t TM[2];
MTOF(-param_time1 - inlet_time1, TM[0])
TM[0] = TM[0] >> 3;
MTOF(-param_time2 - inlet_time2, TM[1])
TM[1] = TM[1] >> 3;

int filter1 = (param_filter1 + inlet_filter1) & 15;
int filter2 = (param_filter2 + inlet_filter2) & 15;
int mode3 = filter1 >> 3;
mode3 = mode3;
int mode1 = (filter1 & 7) >> 2;

int mode2 = filter2 >> 2;
outlet_filter1 = filter1 = filter1 & 3;
outlet_filter2 = filter2 = filter2 & 3;
uint32_t GN1 = ___SMMUL(param_drive1, param_gain1) << 1;
uint32_t GN2 = ___SMMUL(param_drive2, param_gain2) << 1;
int32_t damp1 =
    (0x80 << 24) - (__USAT(inlet_resonance1 + param_resonance1, 27) << 4);
damp1 = ___SMMUL(damp1, damp1);
int32_t alpha;
int32_t freq1;
MTOFEXTENDED(param_cutoff1 + inlet_cutoff1, alpha);
SINE2TINTERP(alpha, freq1);
int32_t drive1 = __USAT((param_drive1 >> 1) + (inlet_drive1 << 3), 30) << 1;

int32_t damp2 =
    (0x80 << 24) - (__USAT(inlet_resonance2 + param_resonance2, 27) << 4);
damp2 = ___SMMUL(damp2, damp2);
int32_t freq2;
MTOFEXTENDED(param_cutoff2 + inlet_cutoff2, alpha);
SINE2TINTERP(alpha, freq2);
int32_t drive2 = __USAT((param_drive2 >> 1) + (inlet_drive2 << 3), 30) << 1;
Audio Rate
writepos = (writepos + 1) & LENGTHMASK;
int32_t out1;
int32_t out2;
out1 = PHASER(inlet_in - feed1, TM[0], 0);
feed1 = ___SMMUL(out1, param_feed1) >> 1;
switch (mode1) {
case 0:
  out2 = SVF(out1 + inlet_in >> 1, freq1, damp1, GN1, drive1, filter1, 0);
  break;
case 1:
  out2 = SVF(out1, freq1, damp1, GN1, drive1, filter1, 0) + inlet_in >> 1;
  break;
}
out2 = out2 >> 1; // SOFT(out2>>1);
if (mode3 == 0) {

  main = PHASER(out2 - feed2, TM[1], 1);
  feed2 = ___SMMUL(main, param_feed2) >> 1;
  switch (mode2) {
  case 0:
    out2 = SVF(main + out2 >> 1, freq2, damp2, GN2, drive2, filter2, 1);
    break;
  case 1:
    out2 = SVF(main, freq2, damp2, GN2, drive2, filter2, 1) + out2 >> 1;
    break;
  case 2:
    out2 = SVF(inlet_in - (main + out2 >> 1) >> 1, freq2, damp2, GN2, drive2,
               filter2, 1);
    break;
  case 3:
    out2 = inlet_in -
               (SVF(main, freq2, damp2, GN2, drive2, filter2, 1) + out2 >> 1) >>
           1;
    break;
  }
} else if (mode3 == 1) {
  main = PHASER(inlet_in, TM[1], 1);
  switch (mode2) {
  case 0:
    out2 = SVF(main + out2 >> 1, freq2, damp2, GN2, drive2, filter2, 1);
    break;
  case 1:
    out2 = SVF(main, freq2, damp2, GN2, drive2, filter2, 1) + out2 >> 1;
    break;
  case 2:
    out2 = SVF(inlet_in - (main + out2 >> 1) >> 1, freq2, damp2, GN2, drive2,
               filter2, 1);
    break;
  case 3:
    out2 = inlet_in -
               (SVF(main, freq2, damp2, GN2, drive2, filter2, 1) + out2 >> 1) >>
           1;
    break;
  }
}
out2 = out2 >> 1;
// out2=SOFT(out2>>1);
outlet_out = out2;

Privacy

© 2024 Zrna Research