ctrlRec16

Continous control recorder for 16 outputs. 2 inputs for dual recording (x/y), recording starts when either "rec" of "dub" input is high and stops when it goes low. (use a clock-synced latch before the gate input to tempo-sync recording) Before "dub" can be used, a recording has to be made using the "rec" input. Rec can be any length up to the maximum length of the channel's buffer (buffer=size/16) Dub can overwrite the recording at any position while looping at the rec-length. Individual record channel selection ("channel" input), steps-per-record quantizer ("steps" input. Set to a high number to have a smooth output). Also features a more or less "smooth" randomiser for all channels. This continuously adds a smoothed out random bipolar offset to the buffer depending on change and chance controls. If you have a midicontroller that can both send out "touch" information next to the midiCC, connect this to the "rec" input to automatically start recording when you touch the controller and stop when you release it.
Author: Johannes Taelman
License: BSD
Github: sss/patt/ctrlRec16.axo

Inlets

frac32 CV1

frac32 CV2

int32 channel1

int32 channel2

int32 steps1

int32 steps2

bool32 trg

bool32 rec1

bool32 dub1

bool32 rec2

bool32 dub2

bool32 rnd

bool32 sync

Outlets

frac32 o1

frac32 o2

frac32 o3

frac32 o4

frac32 o5

frac32 o6

frac32 o7

frac32 o8

frac32 o9

frac32 o10

frac32 o11

frac32 o12

frac32 o13

frac32 o14

frac32 o15

frac32 o16

Parameters

frac32.u.map change

frac32.u.map chance

frac32.s.map.lfopitch damp

Attributes

combo size

Displays

int32.label count

int32.label length

int32.label rnd

Declaration
static const uint32_t LENGTHPOW = (attr_size - 4);
static const uint32_t LENGTH = (1 << attr_size - 4);
static const uint32_t LENGTHMASK = ((1 << attr_size - 4) - 1);
static const uint32_t BITS = 16;
static const uint32_t GAIN = 12;
int16_t *array;
uint32_t cnt[16];
uint32_t CNT[16];
uint32_t steps[16];
uint32_t LE[16];
bool rec1;
bool rec2;
uint32_t C1;
uint32_t C2;
uint32_t prv1;
uint32_t prv2;
bool trg;
int i;
uint32_t L01 = LENGTH;
uint32_t L02 = LENGTH * 2;
uint32_t L03 = LENGTH * 3;
uint32_t L04 = LENGTH * 4;
uint32_t L05 = LENGTH * 5;
uint32_t L06 = LENGTH * 6;
uint32_t L07 = LENGTH * 7;
uint32_t L08 = LENGTH * 8;
uint32_t L09 = LENGTH * 9;
uint32_t L10 = LENGTH * 10;
uint32_t L11 = LENGTH * 11;
uint32_t L12 = LENGTH * 12;
uint32_t L13 = LENGTH * 13;
uint32_t L14 = LENGTH * 14;
uint32_t L15 = LENGTH * 15;
bool DO = 1;
int32_t rnd;
int32_t v27 = (1 << 27);
int32_t v30 = (1 << 30);
int32_t tmp[16];
bool snc;
int32_t RND;
int32_t vl[16];
int32_t VL[16];
Init
static int16_t _array[1 << attr_size] __attribute__((section(".sdram")));
array = &_array[0];
{

  for (i = 0; i < LENGTH; i++)
    array[i] = 0;
}
for (i = 0; i < 16; i++) {
  LE[i] = 512;
  steps[i] = 512;
}
rnd = 0;
Control Rate
if ((inlet_sync > 0) && !snc) {
  snc = 1;
  for (i = 0; i < 16; i++) {
    cnt[i] = 0;
  }
} else if (inlet_sync == 0) {
  snc = 0;
}
int32_t damp;
MTOF(param_damp, damp)
int chn1 = inlet_channel1;
int chn2 = inlet_channel2;
int32_t CV1 = __SSAT(inlet_CV1, 28) >> GAIN;
int32_t CV2 = __SSAT(inlet_CV2, 28) >> GAIN;
int32_t change = ___SMMUL(param_change << 3, param_change << 2) << 2;
int32_t chance = ___SMMUL(param_chance << 3, param_chance << 2);
if (DO == 1) {
  prv1 = inlet_steps1;
  prv2 = inlet_steps2;
}

if (!(inlet_steps1 == prv1)) {
  steps[chn1] = inlet_steps1;
}
if (!(inlet_steps2 == prv2)) {
  steps[chn2] = inlet_steps2;
}

if ((((int32_t)(GenerateRandomNumber() >> 5)) < chance) && inlet_rnd) {
  rnd += (v30 - rnd) >> 14;
} else {
  rnd -= rnd >> 7;
  for (i = 0; i < 16; i++) {
    tmp[i] -= tmp[i] >> 10;
  }
}
RND += (rnd - RND) >> 10;

if ((inlet_trg > 0) && !trg) {
  trg = 1;
  for (i = 0; i < 16; i++) {
    cnt[i] += 1;
    if (cnt[i] >= LE[i]) {
      cnt[i] = 0;
    }
    cnt[i] = cnt[i] & LENGTHMASK;
    if (RND > 128) {
      int32_t k = (i << LENGTHPOW) + cnt[i];
      tmp[i] = __SSAT(
          (int32_t)tmp[i] +
              ___SMMUL((((int32_t)GenerateRandomNumber()) >> 16) - tmp[i] << 2,
                       ___SMMUL(change, RND) << 4),
          16);
      array[k] = __USAT((int32_t)tmp[i] + array[k], 15);
    }
  }
} else if (inlet_trg == 0) {
  trg = 0;
}

if (inlet_rec1 > 0) {
  if (!rec1) {
    rec1 = 1;
    cnt[chn1] = 0;
  }
  array[cnt[chn1] + (chn1 << LENGTHPOW)] = CV1;
  LE[chn1] = cnt[chn1] + 2;
} else if ((inlet_rec1 == 0) && rec1) {
  rec1 = 0;
  LE[chn1] = cnt[chn1];
}

if (inlet_rec2 > 0) {
  if (!rec2) {
    rec2 = 1;
    cnt[chn2] = 0;
  }
  array[cnt[chn2] + (chn2 << LENGTHPOW)] = CV2;
  LE[chn2] = cnt[chn2] + 2;
} else if ((inlet_rec2 == 0) && rec2) {
  rec2 = 0;
  LE[chn2] = cnt[chn2];
}

if (inlet_dub1 > 0) {
  array[cnt[chn1] + (chn1 << LENGTHPOW)] = CV1;
}
if (inlet_dub2 > 0) {
  array[cnt[chn2] + (chn2 << LENGTHPOW)] = CV2;
}
for (i = 0; i < 16; i++) {
  CNT[i] = (cnt[i] * steps[i] / LE[i]) * LE[i] / steps[i];
}

for (i = 0; i < 16; i++) {
  VL[i] = ___SMMLA(((array[CNT[i] + (i << LENGTHPOW)] << GAIN) - VL[i]) << 1,
                   damp, VL[i]);
  vl[i] = ___SMMLA((VL[i] - vl[i]) << 1, damp, vl[i]);
}

outlet_o1 = vl[0];
outlet_o2 = vl[1];
outlet_o3 = vl[2];
outlet_o4 = vl[3];
outlet_o5 = vl[4];
outlet_o6 = vl[5];
outlet_o7 = vl[6];
outlet_o8 = vl[7];
outlet_o9 = vl[8];
outlet_o10 = vl[9];
outlet_o11 = vl[10];
outlet_o12 = vl[11];
outlet_o13 = vl[12];
outlet_o14 = vl[13];
outlet_o15 = vl[14];
outlet_o16 = vl[15];

disp_count = cnt[0];
disp_length = LE[0];
disp_rnd = RND;

prv1 = inlet_steps1;
prv2 = inlet_steps2;
DO = 0;

Privacy

© 2024 Zrna Research