chainFX

Main effect chaining module. Uses the fx modules contained in the same folder (sss/fx/chainer/...) (or if other developers jump in to make their own chainable effects, there might be more fx folders later on) Loads up to 12 different effects of which 4 are used. The "routing" input can order the selected effects in all possible combination (using each effect only once). Each effect has a dry/wet-mix, mixing the output of the effect with the input of the effect. This could be used to layer effects on top of the original signal. Effect 2,3 and 4 also have a mix control to mix between the last effect and the former effect input. This could be used for parallel effects fx1->(fx2&fx3)->fx4 Each effect in the chain has two CV inputs that alter the fx that is currently loaded at that position in the chain. The effects themselves (modules containing the effect functions) can also have their own parameter inputs for fx-dedicated control (eg. tempo synced delay/lfo) All effects are stereo for lots of spatial effects
Author: Remco van der Most
License: BSD
Github: sss/fx/chainer/chainFX.axo

Inlets

frac32buffer audio input left

frac32buffer audio input right

frac32 control voltage 1 for 1st effect in chain

frac32 control voltage 2 for 1st effect in chain

frac32 control voltage 1 for 2nd effect in chain

frac32 control voltage 2 for 2nd effect in chain

frac32 control voltage 1 for 3rd effect in chain

frac32 control voltage 2 for 3rd effect in chain

frac32 control voltage 1 for 4th effect in chain

frac32 control voltage 2 for 4th effect in chain

int32 sets routing order for the 4 selected effects

int32 selects 1st effect in chain (use permuList module for easy control and excluding duplicate use of the same effect)

int32 selects 2nd effect in chain (use permuList module for easy control and excluding duplicate use of the same effect)

int32 selects 3rd effect in chain (use permuList module for easy control and excluding duplicate use of the same effect)

int32 selects 4th effect in chain (use permuList module for easy control and excluding duplicate use of the same effect)

Outlets

frac32buffer audio output left

frac32buffer audio output right

Parameters

int32 sets the routing order of the 4 effects

frac32.u.map.gain mixes from original to output of 1st effect to use as input for the 2nd effect (parallel fx)

frac32.u.map.gain mixes from output of 1st effect to output of 2nd effect to use as input for the 3rd effect (parallel fx)

frac32.u.map.gain mixes from output of 2st effect to output of 3nd effect to use as input for the 4th effect (parallel fx)

frac32.u.map.gain sets wet-mix of the 1st effect in the chain (layering)

frac32.u.map.gain sets wet-mix of the 2nd effect in the chain (layering)

frac32.u.map.gain sets wet-mix of the 3rd effect in the chain (layering)

frac32.u.map.gain sets wet-mix of the 4th effect in the chain (layering)

frac32.u.map.gain sets volume of audio that went through the fx-chain

frac32.u.map.gain sets dry volume of original audio

Attributes

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

objref enter the name of the effect module you're refering to

Declaration
int32_t CV[4][2], inL, inR;
int SEL[4], i;
int chain[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, 1, 0, 3}, {2, 1, 3, 0}, {2, 0, 1, 3}, {2, 0, 3, 1},
                    {2, 3, 1, 0}, {2, 3, 0, 1}, {3, 1, 2, 0}, {3, 1, 0, 2},
                    {3, 2, 1, 0}, {3, 2, 0, 1}, {3, 0, 1, 2}, {3, 0, 2, 1}};

int AV[45][4] = {
    {0, 1, 2, 3}, {0, 1, 2, 4}, {0, 1, 2, 5}, {0, 1, 2, 6}, {0, 1, 2, 7},
    {0, 1, 3, 4}, {0, 1, 3, 5}, {0, 1, 3, 6}, {0, 1, 3, 7}, {0, 2, 3, 4},
    {0, 2, 3, 5}, {0, 2, 3, 6}, {0, 2, 3, 7}, {0, 2, 4, 5}, {0, 2, 4, 6},
    {0, 2, 4, 7}, {0, 3, 4, 5}, {0, 3, 4, 6}, {0, 3, 4, 7}, {0, 4, 5, 6},
    {0, 4, 5, 7}, {0, 4, 6, 7}, {0, 5, 6, 7}, {1, 2, 3, 4}, {1, 2, 3, 5},
    {1, 2, 3, 6}, {1, 2, 3, 7}, {1, 2, 4, 5}, {1, 2, 4, 6}, {1, 2, 4, 7},
    {1, 3, 4, 5}, {1, 3, 4, 6}, {1, 3, 4, 7}, {2, 3, 4, 5}, {2, 3, 4, 6},
    {2, 3, 4, 7}, {2, 4, 5, 6}, {2, 4, 5, 7}, {2, 4, 6, 7}, {2, 5, 6, 7},
    {3, 4, 5, 6}, {3, 4, 5, 7}, {3, 4, 6, 7}, {3, 5, 6, 7}, {4, 5, 6, 7},
};

int32_t mode(int sel, int I) {
  I = I & 3;
  switch (sel) {
  case 0:
    attr_fx01.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx01.outL;
    inR = attr_fx01.outR;
    break;
  case 1:
    attr_fx02.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx02.outL;
    inR = attr_fx02.outR;
    break;
  case 2:
    attr_fx03.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx03.outL;
    inR = attr_fx03.outR;
    break;
  case 3:
    attr_fx04.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx04.outL;
    inR = attr_fx04.outR;
    break;
  case 4:
    attr_fx05.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx05.outL;
    inR = attr_fx05.outR;
    break;
  case 5:
    attr_fx06.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx06.outL;
    inR = attr_fx06.outR;
    break;
  case 6:
    attr_fx07.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx07.outL;
    inR = attr_fx07.outR;
    break;
  case 7:
    attr_fx08.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx08.outL;
    inR = attr_fx08.outR;
    break;
  case 8:
    attr_fx09.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx09.outL;
    inR = attr_fx09.outR;
    break;
  case 9:
    attr_fx10.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx10.outL;
    inR = attr_fx10.outR;
    break;
  case 10:
    attr_fx11.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx11.outL;
    inR = attr_fx11.outR;
    break;
  case 11:
    attr_fx12.FX(inL, inR, CV[I][0], CV[I][1]);
    inL = attr_fx12.outL;
    inR = attr_fx12.outR;
    break;
  }
}
Control Rate
CV[0][0] = inlet_CVa1;
CV[0][1] = inlet_CVa2;
CV[1][0] = inlet_CVb1;
CV[1][1] = inlet_CVb2;
CV[2][0] = inlet_CVc1;
CV[2][1] = inlet_CVc2;
CV[3][0] = inlet_CVd1;
CV[3][1] = inlet_CVd2;
int pst = param_routing + inlet_routing;
pst = pst - pst / 24 * 24;
pst += pst < 0 ? 24 : 0;
// int FXsel=param_FXselect+inlet_FXselect;
// FXsel=FXsel-FXsel/45*45;
// FXsel+=FXsel<0?45:0;
int SEL[4];
// for(i=0;i<4;i++){
// SEL[i]=AV[FXsel][i];
//}
SEL[0] = inlet_fx1;
SEL[1] = inlet_fx2;
SEL[2] = inlet_fx3;
SEL[3] = inlet_fx4;
bool solo = attr_fx01.solo || attr_fx02.solo || attr_fx03.solo ||
            attr_fx04.solo || attr_fx05.solo || attr_fx06.solo ||
            attr_fx07.solo || attr_fx08.solo || attr_fx09.solo ||
            attr_fx10.solo || attr_fx11.solo || attr_fx12.solo;
Audio Rate
int32_t TL[4];
int32_t TR[4];
TL[0] = inL = inlet_leftI;
TR[0] = inR = inlet_rightI;

if (solo < 1) {
  mode(SEL[chain[pst][0]], 0);

  TL[1] = TL[0] + ___SMMUL(inL - TL[0] << 1, param_wet1);
  TR[1] = TR[0] + ___SMMUL(inR - TR[0] << 1, param_wet1);
  inL = TL[0] + ___SMMUL(TL[1] - TL[0] << 1, param_mix2);
  inR = TR[0] + ___SMMUL(TR[1] - TR[0] << 1, param_mix2);

  mode(SEL[chain[pst][1]], 1);

  TL[2] = TL[1] + ___SMMUL(inL - TL[1] << 1, param_wet2);
  TR[2] = TR[1] + ___SMMUL(inR - TR[1] << 1, param_wet2);
  inL = TL[1] + ___SMMUL(TL[2] - TL[1] << 1, param_mix3);
  inR = TR[1] + ___SMMUL(TR[2] - TR[1] << 1, param_mix3);

  mode(SEL[chain[pst][2]], 2);

  TL[3] = TL[2] + ___SMMUL(inL - TL[2] << 1, param_wet3);
  TR[3] = TR[2] + ___SMMUL(inR - TR[2] << 1, param_wet3);
  inL = TL[2] + ___SMMUL(TL[3] - TL[2] << 1, param_mix4);
  inR = TR[2] + ___SMMUL(TR[3] - TR[2] << 1, param_mix4);

  mode(SEL[chain[pst][3]], 3);

  inL = TL[3] + ___SMMUL(inL - TL[3] << 1, param_wet4);
  inR = TR[3] + ___SMMUL(inR - TR[3] << 1, param_wet4);
}
int TP = 0;

if (attr_fx01.solo > 0) {
  mode(0, TP);
  TP += 1;
}
if (attr_fx02.solo > 0) {
  mode(1, TP);
  TP += 1;
}
if (attr_fx03.solo > 0) {
  mode(2, TP);
  TP += 1;
}
if (attr_fx04.solo > 0) {
  mode(3, TP);
  TP += 1;
}
if (attr_fx05.solo > 0) {
  mode(4, TP);
  TP += 1;
}
if (attr_fx06.solo > 0) {
  mode(5, TP);
  TP += 1;
}
if (attr_fx07.solo > 0) {
  mode(6, TP);
  TP += 1;
}
if (attr_fx08.solo > 0) {
  mode(7, TP);
  TP += 1;
}
if (attr_fx09.solo > 0) {
  mode(8, TP);
  TP += 1;
}
if (attr_fx10.solo > 0) {
  mode(9, TP);
  TP += 1;
}
if (attr_fx11.solo > 0) {
  mode(10, TP);
  TP += 1;
}
if (attr_fx12.solo > 0) {
  mode(11, TP);
  TP += 1;
}

outlet_leftO = (___SMMUL(inL, param_wetVol) << 1) +
               (___SMMUL(inlet_leftI, param_dry) << 1);
outlet_rightO = (___SMMUL(inR, param_wetVol) << 1) +
                (___SMMUL(inlet_rightI, param_dry) << 1);

/*
if(param_Freroute>0){
int32_t tmp1=attr_fx1.F1>>1;
int32_t tmp2=attr_fx1.F2>>1;
attr_fx1.F1=attr_fx2.F2>>1;
attr_fx1.F2=attr_fx2.F1>>1;
attr_fx2.F1=tmp1;
attr_fx2.F2=tmp2;
};
*/

Privacy

© 2024 Zrna Research