BLITstringFilter3

Author: Smashed Transistors
License: LGPL
Github: tiar/oscBnk/BLITstringFilter3.axo

Inlets

frac32.bipolar vib0

frac32.bipolar vib1

frac32.bipolar vib2

Outlets

frac32buffer.bipolar out

Parameters

frac32.s.map.kdecaytime.exp A

frac32.s.map.kdecaytime.exp R1

frac32.s.map.kdecaytime.exp R2

frac32.u.map L

Declaration
int32_t y[8], v, integ;
uint8_t i;

int8_t gates[128];
int32_t envs[8 * 12];
int32_t envc[8 * 12];
uint16_t spl;
int32_t d[256];
uint8_t w = 0;

class BLIT {
public:
  int32_t env[8];
  uint32_t per = 5 << 10;
  uint16_t nextSpl = 0;
  uint32_t next = 0;
  uint8_t cpt = 0;
  void setF(float f) { per = (uint32_t)(48000.0f * (1 << (6 + 10)) / f); }
  void init(float f) {
    setF(f);
    for (int i = 0; i < 8; i++) {
      env[i] = 0;
    }
  }
  void proc(uint16_t spl, int32_t *y, int i) {
    if (spl == nextSpl) {

      int32_t ampli = env[7]; // all cycles
      if ((cpt & 1))
        ampli += env[6];
      if ((cpt & 3) == 0)
        ampli += env[5];
      if ((cpt & 7) == 4)
        ampli += env[4];
      if ((cpt & 15) == 9)
        ampli += env[3];
      if ((cpt & 31) == 11)
        ampli += env[2];
      if ((cpt & 63) == 37)
        ampli += env[1];
      if ((cpt & 127) == 0)
        ampli += env[0];

      // select the band limited pulse according to subsample time since the
      // transition
      const int16_t *t = tiar_bli_8_64 + 8 * (((next >> 10) & 63));
      // add the selected band limited pulse to the output 8 taps
      for (int j = 0; j <= 7; j++) {
        y[(i - j) & 7] += ampli * t[j];
      }

      next += per;
      cpt++;
      nextSpl = (next >> (6 + 10)) & 65535;
    }
  }
};

BLIT blit[12];
Init
y[0] = y[1] = y[2] = y[3] = y[4] = y[5] = y[6] = y[7] = v = integ = 0;
i = 0;

spl = 0;

float f = 4186.009f * 4;
for (int i = 0; i < 12; i++) {
  blit[i].init(f);
  f *= 1.059463094f;
}

for (int i = 0; i < 128; i++) {
  gates[i] = 0;
}
for (int i = 0; i < 8 * 12; i++) {
  envs[i] = 0;
}

for (int i = 0; i < 256; i++) {
  d[i] = 0;
}
Control Rate
float vib0 = inlet_vib0 * 1e-10f;
float vib1 = inlet_vib1 * 1e-10f;
float vib2 = inlet_vib2 * 1e-10f;
float f = 4186.009f;
blit[0].setF(f *vib0 + f);
f *= 1.059463094f;
blit[1].setF(0.5f * f * vib0 + f);
f *= 1.059463094f;
blit[2].setF(-f *vib0 + f);
f *= 1.059463094f;
blit[3].setF(f *vib1 + f);
f *= 1.059463094f;
blit[4].setF(-f *vib1 + f);
f *= 1.059463094f;
blit[5].setF(-f *vib2 + f);
f *= 1.059463094f;
blit[6].setF(0.9f * f * vib2 + f);
f *= 1.059463094f;
blit[7].setF(-0.9f * f * vib1 + f);
f *= 1.059463094f;
blit[8].setF(f *vib1 + f);
f *= 1.059463094f;
blit[9].setF(-f *vib0 + f);
f *= 1.059463094f;
blit[10].setF(0.7f * f * vib2 + f);
f *= 1.059463094f;
blit[11].setF(0.5f * f * vib2 + f);

float envTot = 0;
for (int i = 0; i < 8 * 12; i++) {
  int32_t b = envs[i];
  if (gates[24 + i] > 10)
    envs[i] = ___SMMLA(0x7FFFFFFF - param_A, (100 << 20) - b, b >> 1)
              << 1; // ascending
  else if (b > param_L)
    envs[i] = ___SMMUL(b, param_R1) << 1;
  else
    envs[i] = ___SMMUL(b, param_R2) << 1;
  envTot += envs[i];
}
int32_t comp = arm::float_to_q(10000000 / sqrtf(envTot + (1 << 27)), 27);
for (int i = 0; i < 8 * 12; i++) {
  envc[i] = ___SMMUL(envs[i], comp);
}

for (int i = 0; i < 12; i++) {
  for (int oct = 0; oct < 8; oct++) {
    blit[i].env[oct] = (envc[i + 12 * oct] >> 12);
  }
}
Audio Rate
for (int note = 0; note < 12; note++) {
  blit[note].proc(spl, y, i);
}

spl++;

w--;

d[w] = y[i];
integ = ___SMMUL(integ, 0x7F800000) << 1;
int32_t filter =
    d[w] - d[(uint8_t)(w + (uint8_t)1)] + d[(uint8_t)(w + (uint8_t)6)] -
    d[(uint8_t)(w + (uint8_t)28)] - d[(uint8_t)(w + (uint8_t)69)] +
    d[(uint8_t)(w + (uint8_t)98)] - d[(uint8_t)(w + (uint8_t)99)] +
    d[(uint8_t)(w + (uint8_t)105)] - d[(uint8_t)(w + (uint8_t)130)] +
    d[(uint8_t)(w + (uint8_t)135)] - d[(uint8_t)(w + (uint8_t)194)] +
    d[(uint8_t)(w + (uint8_t)197)] + d[(uint8_t)(w + (uint8_t)212)] -
    d[(uint8_t)(w + (uint8_t)234)] - d[(uint8_t)(w + (uint8_t)253)] +
    d[(uint8_t)(w + (uint8_t)255)]

    ;
integ += filter;
outlet_out = integ;

y[i] = 0;
i = (i + 1) & 7;
Midi Handler
if (status == MIDI_NOTE_ON + attr_midichannel) {
  gates[data1 & 0x7F] = data2 ? 100 : 0;
} else if (status == MIDI_NOTE_OFF + attr_midichannel) {
  gates[data1 & 0x7F] = 0;
} else if ((status == attr_midichannel + MIDI_CONTROL_CHANGE) &&
           (data1 == MIDI_C_ALL_NOTES_OFF)) {
  for (int i = 0; i < 128; i++)
    gates[data1 & 0x7F] = 0;
}

Privacy

© 2024 Zrna Research