swelldelay

Swell-delay with a precise feedback-time control. delay-time functions the same as the other normal delays, but.. the tailtime is a direct representation of the time (in seconds) the feedback will take to die out, whatever the delaytime. So when you set to control to 30, it will take 30 seconds die out, whether it's at a delaytime of 100ms or 2 seconds.. As it's a "swell" delay, it features two audio-buffers using the exact same timing of writing/reading, but using different feedback times. As one is subtracted by the other, a volume peak in the delay will happen when either one dies out while the other rings on. As we know both the tailtimes, we can also calculate what the volume-drop will be at the moment of the volume-peak (remaining volume of the signal that hasn't died out yet). So this is internally normalised to input level and goes through a gain stage. A switch is added so you can have up to 2x gain for the delay, making it up to 4 times the volume of the input level (so watch it!) As last, an input-attenuator is added to control the dry amount.
Author: Remco van der Most
License: BSD
Github: sss/delay/swelldelay.axo

Inlets

frac32buffer delay time (fraction of total delayline size)

frac32 time

frac32 tailtime1

frac32 tailtime2

Outlets

frac32buffer wave

Parameters

frac32.u.map time

frac32.u.map tailtime1

frac32.u.map tailtime2

frac32.u.map peak

frac32.u.map dry

bool32.tgl x2

Attributes

combo size

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);
int32_t *array1;
int32_t *array2;
uint32_t writepos;
int32_t feed;
int32_t Time;
int32_t val1;
int32_t val2;
int32_t T1ime;
Init
static int32_t _array1[1 << attr_size] __attribute__((section(".sdram")));
array1 = &_array1[0];
static int32_t _array2[1 << attr_size] __attribute__((section(".sdram")));
array2 = &_array2[0];
int i;
writepos = 0;
for (i = 0; i < LENGTH; i++) {
  array1[i] = 0;
  array2[i] = 0;
}
Control Rate
int32_t TMP = __USAT(inlet_time + param_time, 27);
Time = TMP >> 27 - LENGTHPOW;
float32_t tailtime1 = __USAT(param_tailtime1 + inlet_tailtime1, 27) >> 5;

float32_t ratio1 = (float32_t)(Time << 2) / (tailtime1 * 7);
float32_t dB1 = (float32_t)(-10) * ratio1;
dB1 = powf(2, dB1) * 4;
float32_t tailtime2 = __USAT(param_tailtime2 + inlet_tailtime2, 27) >> 5;
float32_t ratio2 = (float32_t)(Time << 2) / (tailtime2 * 7);
float32_t dB2 = (float32_t)(-10) * ratio2;
dB2 = powf(2, dB2) * 4;

uint32_t tmp_w1 = (TMP << (LENGTHPOW + 3)) & 0x3FFFFFFF;
uint32_t tmp_w2 = (1 << 30) - tmp_w1;

float32_t ttime1 = tailtime1 <= tailtime2 ? tailtime1 : tailtime2;
float32_t ttime2 = tailtime1 <= tailtime2 ? tailtime2 : tailtime1;

float32_t tratio = ttime1 / ttime2;
ttime1 = powf(2, 1 * tratio) * 2 * (1 + param_x2);
Audio Rate
writepos = (writepos + 1) & LENGTHMASK;
uint32_t tmp_di1 = writepos - (Time)-1;
int32_t tmp_a1 = array1[tmp_di1 & LENGTHMASK];
int32_t tmp_a2 = array1[(tmp_di1 + 1) & LENGTHMASK];
int32_t tmp_r1 = ___SMMUL(tmp_a1, tmp_w1);
tmp_r1 = ___SMMLA(tmp_a2, tmp_w2, tmp_r1);
int32_t lp1 = tmp_r1 * dB1;
array1[writepos] = -lp1 + inlet_in;
int32_t tmp_a3 = array2[tmp_di1 & LENGTHMASK];
int32_t tmp_a4 = array2[(tmp_di1 + 1) & LENGTHMASK];
int32_t tmp_r2 = ___SMMUL(tmp_a3, tmp_w1);
tmp_r2 = ___SMMLA(tmp_a4, tmp_w2, tmp_r2);
int32_t lp2 = tmp_r2 * dB2;
array2[writepos] = -lp2 + inlet_in;

outlet_out =
    ___SMMUL(((int32_t)((-lp1 + lp2) * ttime1)) << 2, param_peak << 3) +
    ___SMMUL(inlet_in << 2, param_dry << 3);

Privacy

© 2024 Zrna Research