Flooper

Friendly 4 channel looper module with seperate ins/outs/triggers/looptime BPM-syncable with global overdub mode.
Author: Remco van der Most
License: BSD
Github: sss/delay/Flooper.axo

Inlets

frac32buffer audio input for channel 1

frac32buffer audio input for channel 2

frac32buffer audio input for channel 3

frac32buffer audio input for channel 4

bool32 records in1 to channel 1 buffer when high

bool32 records in2 to channel 2 buffer when high

bool32 records in3 to channel 3 buffer when high

bool32 records in4 to channel 4 buffer when high

bool32 when high, goes in "overdub" mode (length stays the same as first recording)

bool32 when high, syncs to host BPM (syncIn inlet)

bool32 connect clock to sync

Outlets

frac32buffer audio output for channel 1

frac32buffer audio output for channel 2

frac32buffer audio output for channel 3

frac32buffer audio output for channel 4

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);
uint32_t L2 = LENGTH << 1;
uint32_t L3 = LENGTH * 3;
int32_t *array;
int i;

uint32_t writepos[4];
uint32_t countmax[4];
bool ttrg[4];
int32_t in[4];
uint32_t cnt;
bool ttrig;
uint32_t timer;
uint32_t ttmp[4];
Init
static int32_t _array[LENGTH * 4] __attribute__((section(".sdram")));
array = &_array[0];
for (i = 0; i < 4; i++) {
  writepos[i] = 0;
}
for (i = 0; i < LENGTH; i++)
  array[i] = 0;
Control Rate
bool tap[4];
tap[0] = inlet_tap1;
tap[1] = inlet_tap2;
tap[2] = inlet_tap3;
tap[3] = inlet_tap4;
for (i = 0; i < 4; i++) {
  if ((tap[i] > 0) && !ttrg[i]) {
    ttrg[i] = 1;
    if (inlet_overdub == 0) {
      writepos[i] = 0;
    }
  } else if ((tap[i] == 0) && ttrg[i]) {
    ttrg[i] = 0;
    if (inlet_overdub == 0) {
      countmax[i] = writepos[i];
      writepos[i] = 0;
    }
  }

  if (inlet_syncOn > 0) {
    ttmp[i] = countmax[i] / timer * timer;
  } else {
    ttmp[i] = countmax[i];
  }
}
Audio Rate
if ((inlet_syncIn > 0) && (!(ttrig))) {
  ttrig = 1;
  timer = cnt;
  cnt = 0;
} else if (!(inlet_syncIn > 0)) {
  ttrig = 0;
}
cnt += 1;

in[0] = inlet_in1;
in[1] = inlet_in2;
in[2] = inlet_in3;
in[3] = inlet_in4;
for (i = 0; i < 4; i++) {
  writepos[i] += 1;
  if (tap[i] == 1) {
    if (inlet_overdub == 0) {
      array[writepos[i] + i * LENGTH] = in[i];
    }
    if (inlet_overdub == 1) {
      array[writepos[i] + i * LENGTH] =
          __SSAT(in[i] + array[writepos[i] + i * LENGTH], 30);
      writepos[i] = writepos[i] >= ttmp[i] ? 0 : writepos[i];
    }
  } else if (tap[i] == 0) {
    writepos[i] = writepos[i] >= ttmp[i] ? 0 : writepos[i];
  }
}
outlet_out1 = array[writepos[0]];
outlet_out2 = array[writepos[1] + LENGTH];
outlet_out3 = array[writepos[2] + L2];
outlet_out4 = array[writepos[3] + L3];

Privacy

© 2024 Zrna Research