over5tap

A five tap 32bit delay line with internal oversampling to limit unwanted interpolation filtering. Useful for choruses
Author: SmashedTransistors
License: LGPL
Github: tiar/delay/over5tap.axo

Inlets

frac32 d1

frac32 d2

frac32 d3

frac32 d4

frac32 d5

frac32buffer wave input

Outlets

frac32buffer out1

frac32buffer out2

frac32buffer out3

frac32buffer out4

frac32buffer out5

Attributes

combo size

combo Over

Declaration
static const uint32_t LENGTHPOW = (attr_size);
static const uint32_t LENGTH = (1 << attr_size);
static const uint32_t LENGTHMASK = ((1 << attr_size) - 1);
static const uint32_t MINDD = (32 << (27 - LENGTHPOW));
static const uint32_t MAXDD = (1 << 27) - (32 << (27 - LENGTHPOW));
int32_t *d;

int32_t interp(uint32_t ind, int32_t p) {
  // int32_t a = p&((1<<(27-LOG2))-1); //q27-LOG2
  // a <<= 31-(27-LOG2); //q31
  int32_t a = (p << (31 - (27 - LENGTHPOW))) & 0x7FFFFFFF; // q31
  int32_t i = p >> (27 - LENGTHPOW);                       // int
  i = (ind + i) & LENGTHMASK;
  int32_t d0 = d[i];
  return ___SMMLA(a, (d[(i + 1) & LENGTHMASK] - d0) << 1, d0);
}
void calcOut(int32_t in_d, int32_t &d, int32_t &fd, int32_t *out) {
  // local copies -> registers
  int32_t ld = d;
  int32_t lfd = fd;

  int i = ind;
  int32_t dd = in_d;
  if (dd < MINDD)
    dd = MINDD;
  else if (dd > MAXDD)
    dd = MAXDD;

  dd = (dd - ld) >> 4;
  for (int smp = 0; smp < BUFSIZE; smp++) {
    ld += dd;                                  // interpolation
    lfd = ___SMMLA(0x10000000, ld - lfd, lfd); // smooth
    out[smp] = interp(i, lfd);
    i -= 2;
    i &= LENGTHMASK;
  }
  d = ld;
  fd = lfd;
}
uint32_t ind;
int32_t x, y;
int32_t d1, fd1, d2, fd2, d3, fd3, d4, fd4, d5, fd5;

float x0, x1, x2, x3, x4, x5, y0, y1;
Init
static int32_t _d[attr_poly][1 << attr_size] __attribute__((section(".sdram")));
d = &_d[parent->polyIndex][0];

for (int i = 0; i < LENGTH; i++)
  d[i] = 0;
ind = 0;
d1 = fd1 = d2 = fd2 = d3 = fd3 = d4 = fd4 = d5 = fd5 = x = y = 0;
x0 = x1 = x2 = x3 = x4 = x5 = y0 = y1 = 0;
Control Rate
// writer
if (attr_Over == 1) {
  for (int smp = 0; smp < BUFSIZE; smp++) {
    // interp -> LP1
    ind--;
    ind &= LENGTHMASK;
    d[ind] = y = (((inlet_in[smp] + x) >> 1) + y) >> 1;
    // nointerp ->LP1
    x = inlet_in[smp];
    ind--;
    ind &= LENGTHMASK;
    d[ind] = y =
        ___SMMLA(1004378102, x - y,
                 y); // 0.4677q31 same gain as one zero one pole 0.5 at Sr/8
  }
}
if (attr_Over == 2) {
  for (int smp = 0; smp < BUFSIZE; smp++) {
    ind--;
    ind &= LENGTHMASK;
    d[ind] = inlet_in[smp];
    ind--;
    ind &= LENGTHMASK;
    d[ind] = inlet_in[smp];
  }
}
// use interpolator
if (attr_Over == 3) {
  for (int smp = 0; smp < BUFSIZE; smp++) {
    x0 = x1;
    x1 = x2;
    x2 = x3;
    x3 = x4;
    x4 = x5;
    x5 = (float)inlet_in[smp];
    /*outlet_y1 = (int32_t)x2;
    outlet_y0 = (int32_t)(
             (x5 + x0) * 0.025665914601895386f
         + (x4 + x1) * -0.04277652433649233f
         + (x3 + x2) * 0.517110609734597f
         );
            */
    ind--;
    ind &= LENGTHMASK;
    d[ind] = (int32_t)x2;
    ind--;
    ind &= LENGTHMASK;
    d[ind] = (int32_t)((x5 + x0) * 0.025665914601895386f +
                       (x4 + x1) * -0.04277652433649233f +
                       (x3 + x2) * 0.517110609734597f);
  }
}
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// readers
calcOut(inlet_d1, d1, fd1, outlet_out1);
calcOut(inlet_d2, d2, fd2, outlet_out2);
calcOut(inlet_d3, d3, fd3, outlet_out3);
calcOut(inlet_d4, d4, fd4, outlet_out4);
calcOut(inlet_d5, d5, fd5, outlet_out5);

Privacy

© 2024 Zrna Research