multifx

chorus effect from the rings dsp code open sourced by mutable instruments. any bugs/issues you find are our own, report on the axoloti forum. Thanks to Olivier Gillet from Mutable Instruments for open sourcing their code. http://mutable-instruments.com
Author:
License: GPL
Github: sss/MI/FX/multifx.axo

Inlets

frac32buffer l

frac32buffer r

int32 order

frac32 Cmix

frac32 Pmix

frac32 Emix

frac32 Rmix

frac32 Pfrequency

frac32 Pshift

Outlets

frac32buffer l

frac32buffer r

Parameters

frac32.u.map mix amount chorus

frac32.u.map mix amount phaser/delay

frac32.u.map mix amount ensemble

frac32.u.map mix amount reverb

frac32.u.map chorus amount

frac32.u.map chorus depth

frac32.u.map pingpong delay feedback amount

frac32.u.map ensemble amount

frac32.u.map ensemble depth

frac32.u.map reverb mix amount

frac32.u.map reverb time size/decay

frac32.u.map reverb diffusion

frac32.u.map reverb gain

frac32.u.map reverb lowpass

frac32.u.map main delay feedback amount

int32 the order of the four main effects

frac32.s.map pingpong delay time

frac32.s.map pingpong delay left/right time shift

frac32.s.map main delay time (records from left/right outputs and inserts feedback path to the start of the main fx)

frac32.s.map main delay time left/right shift

bool32.tgl pingpong

Attributes

combo size

Declaration
rings_fx::Chorus chorus;
rings_fx::Ensemble ensemble;
rings_fx::Reverb reverb;
static const uint32_t LENGTHPOW = (attr_size);
static const uint32_t LENGTH = (1 << attr_size);
static const uint32_t LENGTHMASK = ((1 << attr_size) - 1);
int16_t *a1;
int16_t *a2;
int16_t *a3;
int16_t *a4;
uint32_t writepos, wp;
int32_t cm, pm, em, rm;
int32_t TM1, TM2, FD, f1, f2, prv1, prv2, stp1, stp2, T1, T2, fd1[BUFSIZE],
    fd2[BUFSIZE];
int32_t L[4][BUFSIZE], R[4][BUFSIZE];
int32_t hp1, hp2;
int i;
int SL;
int sel[24][4] = {{0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1},
                  {0, 3, 1, 2}, {0, 3, 2, 1}, {1, 0, 2, 3}, {1, 0, 3, 2},
                  {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0},
                  {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0},
                  {2, 3, 0, 1}, {2, 3, 1, 0}, {3, 0, 1, 2}, {3, 0, 2, 1},
                  {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}};
int32_t Chorus(int I) {
  static float left[BUFSIZE];
  static float right[BUFSIZE];
  for (i = 0; i < BUFSIZE; i++) {
    left[i] = q27_to_float(L[I][i]);
    right[i] = q27_to_float(R[I][i]);
  }
  chorus.Process(left, right, BUFSIZE);
  for (i = 0; i < BUFSIZE; i++) {
    L[I][i] += ___SMMUL((float_to_q27(left[i])) - L[I][i], cm) << 1;
    R[I][i] += ___SMMUL((float_to_q27(right[i])) - R[I][i], cm) << 1;
  }
}

int32_t Ensemble(int I) {
  static float left[BUFSIZE];
  static float right[BUFSIZE];
  for (i = 0; i < BUFSIZE; i++) {
    left[i] = q27_to_float(L[I][i]);
    right[i] = q27_to_float(R[I][i]);
  }

  ensemble.Process(left, right, BUFSIZE);

  for (i = 0; i < BUFSIZE; i++) {
    L[I][i] += ___SMMUL((float_to_q27(left[i])) - L[I][i], em) << 1;
    R[I][i] += ___SMMUL((float_to_q27(right[i])) - R[I][i], em) << 1;
  }
}

int32_t Reverb(int I) {
  static float left[BUFSIZE];
  static float right[BUFSIZE];
  for (i = 0; i < BUFSIZE; i++) {
    left[i] = q27_to_float(L[I][i]);
    right[i] = q27_to_float(R[I][i]);
  }
  reverb.Process(left, right, BUFSIZE);
  for (i = 0; i < BUFSIZE; i++) {
    L[I][i] += ___SMMUL((float_to_q27(left[i])) - L[I][i], rm) << 1;
    R[I][i] += ___SMMUL((float_to_q27(right[i])) - R[I][i], rm) << 1;
  }
}

int32_t Phaser(int I) {
  for (i = 0; i < BUFSIZE; i++) {
    writepos = (writepos + 1) & LENGTHMASK;
    a1[writepos] = __SSAT(L[I][i] + f2 >> 14, 16); //+fd2[i]>>14,16);
    a2[writepos] = __SSAT(R[I][i] + f1 >> 14, 16); //+fd1[i]>>14,16);

    uint32_t tmp_di = writepos - (T1 >> (27 - LENGTHPOW)) - 1;
    uint32_t tmp_w1 = (T1 << (LENGTHPOW + 3)) & 0x3FFFFFFF;
    uint32_t tmp_w2 = (1 << 30) - tmp_w1;
    int32_t tmp_a1 = a1[tmp_di & LENGTHMASK] << 16;
    int32_t tmp_a2 = a1[(tmp_di + 1) & LENGTHMASK] << 16;
    int32_t tmp_r = ___SMMUL(tmp_a1, tmp_w1);
    f1 = ___SMMLA(tmp_a2, tmp_w2, tmp_r);

    tmp_di = writepos - (T2 >> (27 - LENGTHPOW)) - 1;
    tmp_w1 = (T2 << (LENGTHPOW + 3)) & 0x3FFFFFFF;
    tmp_w2 = (1 << 30) - tmp_w1;
    tmp_a1 = a1[tmp_di & LENGTHMASK] << 16;
    tmp_a2 = a1[(tmp_di + 1) & LENGTHMASK] << 16;
    tmp_r = ___SMMUL(tmp_a1, tmp_w1);
    f2 = ___SMMLA(tmp_a2, tmp_w2, tmp_r);
    f1 = ___SMMUL(FD, f1) << 5;
    f2 = ___SMMUL(FD, f2) << 5;
    L[I][i] += ___SMMUL(f2 - L[I][i] << 1, pm);
    R[I][i] += ___SMMUL(f1 - R[I][i] << 1, pm);
    T1 += stp1;
    T2 += stp2;
  }
}

int32_t COPY(int I) {
  for (i = 0; i < BUFSIZE; i++) {
    L[I + 1][i] = __SSAT(L[I][i], 28);
    R[I + 1][i] = __SSAT(R[I][i], 28);
  }
}

int32_t SEL(int I) {
  switch (sel[SL][I]) {
  case 0:
    Chorus(I);
    break;
  case 1:
    Phaser(I);
    break;
  case 2:
    Ensemble(I);
    break;
  case 3:
    Reverb(I);
    break;
  }
}
Init
static int16_t _a1[1 << attr_size] __attribute__((section(".sdram")));
a1 = &_a1[0];
static int16_t _a2[1 << attr_size] __attribute__((section(".sdram")));
a2 = &_a2[0];
static int16_t _a3[1 << attr_size] __attribute__((section(".sdram")));
a3 = &_a3[0];
static int16_t _a4[1 << attr_size] __attribute__((section(".sdram")));
a4 = &_a4[0];
writepos = 0;
for (i = 0; i < LENGTH; i++) {
  a1[i] = 0;
  a2[i] = 0;
  a3[i] = 0;
  a4[i] = 0;
}

chorus.Init((uint16_t *)sdram_malloc(32768));

reverb.Init((uint16_t *)sdram_malloc(32768));

ensemble.Init((uint16_t *)sdram_malloc(32768));
Control Rate
for (i = 0; i < BUFSIZE; i++) {
  L[0][i] = __SSAT(inlet_l[i] + (param_pingpong > 0 ? fd2[i] : fd1[i]), 28);
  R[0][i] = __SSAT(inlet_r[i] + (param_pingpong > 0 ? fd1[i] : fd2[i]), 28);
}
cm = __USAT(param_Cmix + inlet_Cmix, 27) << 4;
pm = __USAT(param_Pmix + inlet_Pmix, 27) << 4;
em = __USAT(param_Emix + inlet_Emix, 27) << 4;
rm = __USAT(param_Rmix + inlet_Rmix, 27) << 4;
chorus.set_amount(q27_to_float(param_Camount));
chorus.set_depth(q27_to_float(param_Cdepth));

MTOF(-param_Pfrequency - inlet_Pfrequency, TM1)
TM1 = TM1 >> 1;
int32_t Pshift = __SSAT(param_Pshift + inlet_Pshift, 28);
Pshift = (___SMMUL(Pshift, TM1) << 5);
TM2 = __USAT(TM1 + Pshift, 27);
TM1 = __USAT(TM1 - Pshift, 27);

int32_t at1, at2;
MTOF(-param_Alltime, at1)
at1 = at1 >> 1;
int32_t Ashift = ___SMMUL(__SSAT(param_Allshift, 28), at1) << 5;
at2 = __USAT(at1 + Ashift, 27);
at1 = __USAT(at1 - Ashift, 27);

stp1 = TM1 - prv1 >> 4;
T1 = prv1;
prv1 = TM1;
stp2 = TM2 - prv2 >> 4;
T2 = prv2;
prv2 = TM2;

FD = param_Pfeedback;

ensemble.set_amount(q27_to_float(param_Eamount));
ensemble.set_depth(q27_to_float(param_Edepth));

reverb.set_amount(q27_to_float(param_Ramount));
reverb.set_input_gain(q27_to_float(param_Rgain));
reverb.set_time(q27_to_float(param_Rtime));
reverb.set_diffusion(q27_to_float(param_Rdiffusion));
reverb.set_lp(q27_to_float(param_Rlowpass));

SL = param_order + inlet_order;
SL = SL - SL / 24 * 24;
SL += SL < 0 ? 24 : 0;

SEL(0);
COPY(0);
SEL(1);
COPY(1);
SEL(2);
COPY(2);
SEL(3);

for (i = 0; i < BUFSIZE; i++) {
  int32_t tl, tr;
  tl = L[3][i];
  tr = R[3][i];

  hp1 += tl - hp1 >> 9;
  hp2 += tr - hp2 >> 9;
  tl -= hp1;
  tr -= hp2;
  outlet_l[i] = tl << 1;
  outlet_r[i] = tr << 1;
  wp = (wp + 1) & LENGTHMASK;
  a3[wp] = __SSAT(tl >> 14, 15);
  a4[wp] = __SSAT(tr >> 14, 15);
  fd1[i] = -___SMMUL(param_Allfeed, a3[(wp - at1 + BUFSIZE) & LENGTHMASK] << 14)
           << 5;
  fd2[i] = -___SMMUL(param_Allfeed, a4[(wp - at2 + BUFSIZE) & LENGTHMASK] << 14)
           << 5;
}

Privacy

© 2024 Zrna Research