WeightedFollow

WeightedFollow calculates the chance that certain notes will follow up on previous played notes. The internal array can be set externally with the WeightedFolRec module. WITHOUT THIS, THE MODULE WON'T WORK! Sending note and gate data to the WeightedFolRec will record for each note (48 notes, 4 octaves, wrapped when going over) which notes have a chance to follow up on it (each time a note is played after a certain note, that weight gets +1). Sending a gate/trigger to this module (WeightedFollow) will make it step through notes. The chance-array can be saved to a fixed filename with preset-index.
Author: Remco van der Most
License: BSD
Github: sss/patt/WeightedFollow.axo

Inlets

int32 preset

bool32 trig

bool32 save

bool32 load

Outlets

int32 note

int32 chance

int32 max

Parameters

bool32.mom save

bool32.mom load

int32 preset

Declaration
static const uint32_t LENGTH = 48 * 48;
int16_t *array;
int note;
int i;
int prev;
int ntrig;
int32_t max;
int32_t chance;
int select;
int T;
int strig;
int ltrig;
char c[64];
int offset;
int pval;
int load;
Init
static int16_t _array[LENGTH] __attribute__((section(".sdram")));
array = &_array[0];

strcpy(&c[0], "0:/chc000.tab");
offset = strlen("0:/chc");
pval = 0;
Control Rate
int16_t preset = param_preset + inlet_preset;
if (preset != pval) {
  pval = preset;
  int i = preset;
  int i0 = i / 10;
  c[offset + 2] = '0' + i - 10 * i0;
  i = i0;
  i0 = i / 10;
  c[offset + 1] = '0' + i - 10 * i0;
  i = i0;
  i0 = i / 10;
  c[offset + 0] = '0' + i - 10 * i0;
}

int save = inlet_save + param_save;
load = inlet_load + param_load;
if ((save > 0) && !strig) {
  strig = 1;
  FIL FileObject;
  FRESULT err;
  UINT bytes_written;
  err = f_open(&FileObject, &c[0], FA_WRITE | FA_CREATE_ALWAYS);
  if (err != FR_OK) {
    report_fatfs_error(err, &c[0]);
    return;
  }
  int rem_sz = sizeof(*array) * LENGTH;
  int offset = 0;
  while (rem_sz > 0) {
    if (rem_sz > sizeof(fbuff)) {
      memcpy((char *)fbuff, (char *)(&array[0]) + offset, sizeof(fbuff));
      err = f_write(&FileObject, fbuff, sizeof(fbuff), &bytes_written);
      rem_sz -= sizeof(fbuff);
      offset += sizeof(fbuff);
    } else {
      memcpy((char *)fbuff, (char *)(&array[0]) + offset, rem_sz);
      err = f_write(&FileObject, fbuff, rem_sz, &bytes_written);
      rem_sz = 0;
    }
  }
  if (err != FR_OK)
    report_fatfs_error(err, &c[0]);
  err = f_close(&FileObject);
  if (err != FR_OK)
    report_fatfs_error(err, &c[0]);
} else if (!(save > 0))
  strig = 0;

if ((load > 0) && !ltrig) {
  ltrig = 1;
  FIL FileObject;
  FRESULT err;
  UINT bytes_read;
  err = f_open(&FileObject, &c[0], FA_READ | FA_OPEN_EXISTING);
  if (err != FR_OK) {
    report_fatfs_error(err, &c[0]);
    return;
  }
  int rem_sz = sizeof(*array) * LENGTH;
  int offset = 0;
  while (rem_sz > 0) {
    if (rem_sz > sizeof(fbuff)) {
      err = f_read(&FileObject, fbuff, sizeof(fbuff), &bytes_read);
      if (bytes_read == 0)
        break;
      memcpy((char *)(&array[0]) + offset, (char *)fbuff, bytes_read);
      rem_sz -= bytes_read;
      offset += bytes_read;
    } else {
      err = f_read(&FileObject, fbuff, rem_sz, &bytes_read);
      memcpy((char *)(&array[0]) + offset, (char *)fbuff, bytes_read);
      rem_sz = 0;
    }
  }
  if (err != FR_OK) {
    report_fatfs_error(err, &c[0]);
    return;
  };
  err = f_close(&FileObject);
  if (err != FR_OK) {
    report_fatfs_error(err, &c[0]);
    return;
  };
} else if (!(load > 0))
  ltrig = 0;

if ((inlet_trig > 0) && !ntrig) {
  ntrig = 1;
  max = array[note * 48 + 47];
  chance = (int32_t)(GenerateRandomNumber() >> 5);
  chance = chance - chance / max * max;
  chance = chance < 0 ? chance + max : chance;

  T = -1;
  for (i = 0; i < 48; i++) {
    if (T == -1) {
      T = (array[note * 48 + i] >= chance) ? i : -1;
    }
  }
  note = T;
  note = note - note / 48 * 48;
  note = note < 0 ? note + 48 : note;
} else if (inlet_trig == 0) {
  ntrig = 0;
}

outlet_note = note;
outlet_chance = chance;
outlet_max = max;

// prev=note;

Privacy

© 2024 Zrna Research