Factotum

Difficult to name. Pitchshifter, time-stretcher, play-rate adjuster (stretch+pitchshift), sampler, delay, granulizer... See inputs/controls for their functions (hoover above them)
Author: Remco van der most
License: BSD
Github: sss/delay/Factotum.axo

Inlets

frac32 sets start-phase when sync-input goes high.

frac32 sets the playback length in relation to the recorded buffer. If set to 0.5x, only plays half the buffer.

frac32 controls the playrate linearly. Set rate-control to x1 for normal response.

frac32 sets the window size of the pitchshifter/stretcher. Small window have faster response, but generate more distortion and pitching errors. Long windows will create delayed repeats.

frac32 wet

frac32.bipolar controls the playback speed, bot stretches and pitchshifts as normal tape-behavior. normal semitone response

frac32.bipolar ONLY pitchshifts the signal without stretching it. normal semitone response.

frac32.bipolar ONLY stretches the signal without pitchshifting it. normal semitone response.

frac32.bipolar controls the rate of the grain-offset generator. This one does NOT have a semitone response->negative is backwards shifting, positive is forwards shifting.

frac32.bipolar sets the amount of feedback when in "overwrite" mode.

int32 divides the rate at which the grainshift will be applied. (base rate is controlled by stretch/pitchshift controls, NOT the playspeed control!)

int32 quantizes the grain-offset in power of 2. 0=no offset, 1=2 positions, 2=4 positions, 3=8 positions, etc

int32 multiplies the grain-offset-position of the first of the two delay-lines after quantification

int32 multiplies the grain-offset-position of the second of the two delay-lines after quantification

frac32buffer audio input

bool32 when high, records to buffer

bool32 when high, restarts at "phase-position" of phase input+parameter

bool32 controls the playback direction in direction mode 3 (see on-module "dir" control)

bool32 when high, records the input continuously. There has to be a recorded buffer already! That one sets the buffersize!

Outlets

frac32buffer out

Parameters

bool32.tgl when high, records the input continuously. There has to be a recorded buffer already! That one sets the buffersize!

int32 sets crossfade length for de-clicking (has to be smaller then total recorded time)

int32 divides the rate at which the grainshift will be applied. (base rate is controlled by stretch/pitchshift controls, NOT the playspeed control!)

int32 quantizes the grain-offset in power of 2. 0=no offset, 1=2 positions, 2=4 positions, 3=8 positions, etc

int32 multiplies the grain-offset-position of the first of the two delay-lines after quantification

int32 multiplies the grain-offset-position of the second of the two delay-lines after quantification

frac32.u.map.gain sets start-phase when sync-input goes high.

frac32.u.map.gain sets the playback length in relation to the recorded buffer. If set to 0.5x, only plays half the buffer.

frac32.u.map.gain sets the window size of the pitchshifter/stretcher. Small window have faster response, but generate more distortion and pitching errors. Long windows will create delayed repeats.

frac32.u.map.gain sets dry input signal amount to output

frac32.u.map.gain sets wet effect signal amount to output

int32.hradio sets direction-mode: 0=normal, 1=reverse, 2=external control

frac32.s.map.pitch controls the playback speed, bot stretches and pitchshifts as normal tape-behavior. normal semitone response

frac32.s.map.pitch ONLY pitchshifts the signal without stretching it. normal semitone response.

frac32.s.map.pitch ONLY stretches the signal without pitchshifting it. normal semitone response.

frac32.s.map controls the playrate linearly. Set rate-control to x1 for normal response.

frac32.s.map controls the rate of the grain-offset generator. This one does NOT have a semitone response->negative is backwards shifting, positive is forwards shifting.

frac32.s.map sets the amount of feedback when in "overwrite" mode.

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);
int16_t *array;
uint32_t writepos;
int32_t out;
uint32_t phase;
uint32_t phs;
bool rec;
int32_t rate;
uint32_t length;
int32_t cnt;
int32_t fade;
int32_t fd;
float32_t ratio;
int32_t fBase;
int32_t fRate;
int32_t LNG;
int dir;
int32_t READ(int T, uint32_t R, uint32_t L) {
  int32_t tmp_a2;
  uint32_t tmp_di = T / R;
  uint32_t tmp_w1 = (T - tmp_di * R) * R >> 2;
  int32_t tmp_a1 = array[tmp_di];
  tmp_a1 =
      (tmp_a1 << 14) + ___SMMUL(array[(tmp_di + 1)] - tmp_a1 << 16, tmp_w1);
  if (tmp_di < fade) {
    tmp_a2 = array[tmp_di + L];
    tmp_a2 = (tmp_a2 << 14) +
             ___SMMUL(array[(tmp_di + 1) + L] - tmp_a2 << 16, tmp_w1);
    tmp_a1 += ___SMMUL(tmp_a2 - tmp_a1, __USAT(fade - tmp_di, 30) << (30 - fd))
              << 2;
  }

  return out = tmp_a1;
}
uint32_t prv;
bool Dr;
uint32_t grain1;
uint32_t grain2;
uint32_t CNT;
int32_t FD;
bool snc;
Init
static int16_t _array[attr_poly][1 << attr_size]
    __attribute__((section(".sdram")));
array = &_array[parent->polyIndex][0];
int i;
writepos = 0;
for (i = 0; i < LENGTH; i++)
  array[i] = 0;
dir = 1;
Control Rate
fade = 1 << param_fade;
fd = param_fade;
int32_t playspeed = param_playspeed + inlet_playspeed;
int32_t stretch = param_stretch + inlet_stretch;
int32_t pitchshift = param_pitchshift + inlet_pitchshift;
int32_t LnG = __USAT((param_length >> 1) + (inlet_length << 3), 30) << 1;
int32_t Window = __USAT((param_window >> 1) + (inlet_window << 3), 30) << 1;
int32_t shiftsize = param_shiftsize + inlet_shiftsize;
int32_t ratedivisor = param_ratedivisor + inlet_ratedivisor;
int32_t step1 = param_step1 + inlet_step1;
int32_t step2 = param_step2 + inlet_step2;
bool overwrite = param_overwrite || inlet_overwrite;
uint32_t PHS = __USAT((inlet_phase << 3) + (param_phase >> 1), 30) << 1;
int32_t RT = __SSAT(param_rate + inlet_rate, 29);
if ((inlet_sync > 0) && !snc) {
  phase = PHS;
  phs = 0;
  snc = 1;
} else if (inlet_sync == 0) {
  snc = 0;
}

MTOFEXTENDED(0, fBase);
MTOFEXTENDED(playspeed + stretch, fRate)
ratio = (float32_t)fRate / fBase;
int32_t feed = __SSAT(param_feedback + inlet_feedback, 28) << 4;
if ((inlet_rec > 0) && !rec) {
  rec = 1;

  writepos = 0;
  cnt = 0;
} else if ((inlet_rec == 0) && rec) {
  rec = 0;
  length = writepos;
  cnt = fade;
}
LNG = ___SMMUL(length, LnG) << 1;

rate = ((uint64_t)1 << 32) / LNG;
int32_t RATE = rate * ratio;

int32_t grate;

grate = shiftsize;
grate = grate > 0 ? grate : -grate;
grate = ___SMMUL(grate << 3, shiftsize << 2);
grate = grate << 3;
int row = (ratedivisor << 1) + 1;
int32_t qnt = 32 - __USAT(param_qnt + inlet_qnt, 5);

int32_t prate;
MTOFEXTENDED(pitchshift - stretch, prate)
float32_t pratio = (float32_t)prate / fBase;
int32_t window = ((uint64_t)Window << 12) / length;
float32_t wratio = (float32_t)(1 << 30) / (window >> 1);
prate = (int64_t)((int64_t)RATE * pratio - RATE) * wratio;
if (param_dir < 2) {
  dir = param_dir < 1 ? 1 : -1;
} else {
  dir = inlet_dir > 0 ? -1 : 1;
}
int32_t wet = __USAT((inlet_wet << 3) + (param_wet >> 1), 30) << 1;
Audio Rate
int32_t FRQ = ___SMMUL(prate * dir << 2, RT << 3);
phase += ___SMMUL(RATE * dir << 2, RT << 3);
phs += FRQ;
uint32_t P3 = phs;
if (!((phs > (1 << 31)) == (prv > (1 << 31)))) {
  if (CNT == 0) {
    if ((phs > (1 << 30)) && (P3 < (3 << 30))) {
      grain2 += grate;
    } else {
      grain1 += grate;
    }
  }
  CNT += 1;
  CNT = CNT - CNT / row * row;
}

if ((overwrite > 0) && !rec) {
  array[writepos] = __SSAT(inlet_in + FD >> 14, 16);
  writepos = writepos >= length + fade ? 0 : writepos;
}
if (rec > 0) {
  array[writepos] = __SSAT(inlet_in >> 14, 16);
}
if (cnt > 0) {
  array[writepos] = __SSAT(inlet_in >> 14, 16);
  cnt -= 1;
}
writepos = (writepos + 1) & LENGTHMASK;

uint32_t P1 = ((uint32_t)phs) >> 1;
uint32_t P2 = ((uint32_t)phs + (1 << 31)) >> 1;
int32_t tmp1 =
    READ(phase + ((grain1 >> qnt) << qnt) * step1 + (___SMMUL(P1, window) << 2),
         rate, LNG);
int32_t tmp2 =
    READ(phase + ((grain2 >> qnt) << qnt) * step2 + (___SMMUL(P2, window) << 2),
         rate, LNG);
int32_t mp;
SINE2TINTERP(phs - (1 << 30), mp)
mp = (mp >> 2) + (1 << 29);
int32_t out = tmp2 + (___SMMUL(tmp1 - tmp2, mp) << 2);
outlet_out = __SSAT(___SMMUL(out, wet) + ___SMMUL(inlet_in, param_dry), 27)
             << 1;
FD = ___SMMUL(out, feed) << 1;
prv = phs;

Privacy

© 2024 Zrna Research