multiPatt

Generates 8 patterns based on euclidian functions. Each pattern can have multiple "parts"(attribute) that influence the pattern. Using "pattern", you select which pattern to adjust. Using "part" (parameter) you select which part of the selected pattern you'ld like to adjust. (max set by attribute) "qnt" sets the amount of steps it takes before a new value will be generated. "lng" sets the length of the part after which it will repeat itself until count restarts. "rng" sets the maximum level that the part can reach. Note also, that the individual parts get summed, thus total range is the sum of the ranges of all parts. "stp" sets the stepsize of each step, skipping intermediate steps. (wrapped by "rng") with these 4 controls and the pattern and part controls, you can set all parts of all patterns. Combing different "qnt" values will result in interesting rhythms. This module combines very well with the "songnotes" module.
Author: Remco van der Most
License: BSD
Github: sss/patt/multiPatt.axo

Inlets

int32 count

bool32 trig

bool32 save

bool32 load

charptr32 filename

Outlets

int32 patt1

int32 patt2

int32 patt3

int32 patt4

int32 patt5

int32 patt6

int32 patt7

int32 patt8

Parameters

int32.hradio pattern

bool32.mom save

bool32.mom load

int32 qnt

int32 lng

int32 rng

int32 part

frac32.u.map stp

Attributes

spinner parts

Declaration
static const uint32_t LENGTH = 32 * attr_parts;
int32_t *array;
int gtrig;
int32_t prev;
int i;
int j;
int32_t count;
int32_t COUNTER(int32_t cnt, int qnt, int lng, int rng, int stp) {
  count = cnt / qnt;
  count = count - count / lng * lng;
  stp = ___SMMUL(stp << 3, rng << 18);
  count = count * stp;
  count = count >> 16;
  count = count - count / rng * rng;
  count = count < 0 ? count + rng : count;
}
int32_t temp[8];
int strig;
int ltrig;
Init
static int32_t _array[LENGTH] __attribute__((section(".sdram")));
array = &_array[0];
// for(i=0;i<LENGTH;i++){array[i]=1;}
Control Rate
int save = inlet_save + param_save;
if ((save > 0) && !strig) {
  strig = 1;
  FIL FileObject;
  FRESULT err;
  UINT bytes_written;
  err = f_open(&FileObject, inlet_filename, FA_WRITE | FA_CREATE_ALWAYS);
  if (err != FR_OK) {
    report_fatfs_error(err, "inlet_filename");
    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, "inlet_filename");
  err = f_close(&FileObject);
  if (err != FR_OK)
    report_fatfs_error(err, "inlet_filename");
} else if (!(save > 0)) {
  strig = 0;
}
int load = param_load + inlet_load;
if ((load > 0) && !ltrig) {
  ltrig = 1;
  FIL FileObject;
  FRESULT err;
  UINT bytes_read;
  err = f_open(&FileObject, inlet_filename, FA_READ | FA_OPEN_EXISTING);
  if (err != FR_OK) {
    report_fatfs_error(err, inlet_filename);
    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, inlet_filename);
    return;
  };
  err = f_close(&FileObject);
  if (err != FR_OK) {
    report_fatfs_error(err, inlet_filename);
    return;
  };
} else if (!(load > 0)) {
  ltrig = 0;
}

if (param_part >= attr_parts) {
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_part],
                     attr_parts - 1, 0xFFFD);
}
int32_t part = param_part * 32;
int32_t param = param_pattern << 2;
int32_t patt = param + part;
if (!(prev == patt)) {
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_qnt],
                     array[patt], 0xFFFD);
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_lng],
                     array[patt + 1], 0xFFFD);
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_rng],
                     array[patt + 2], 0xFFFD);
  PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_stp],
                     array[patt + 3], 0xFFFD);
}
if ((inlet_trig > 0) && !gtrig) {
  array[patt] = param_qnt;
  array[patt + 1] = param_lng;
  array[patt + 2] = param_rng;
  array[patt + 3] = param_stp;
  for (i = 0; i < 8; i++) {
    temp[i] = 0;
  }
  for (j = 0; j < 8; j++) {
    for (i = 0; i < attr_parts; i++) {
      COUNTER(inlet_count, array[(j << 2) + (i << 5)],
              array[(j << 2) + (i << 5) + 1], array[(j << 2) + (i << 5) + 2],
              array[(j << 2) + (i << 5) + 3]);
      temp[j] += count;
    }
  }
  gtrig = 1;
} else if (inlet_trig == 0) {
  gtrig = 0;
}
outlet_patt1 = temp[0];
outlet_patt2 = temp[1];
outlet_patt3 = temp[2];
outlet_patt4 = temp[3];
outlet_patt5 = temp[4];
outlet_patt6 = temp[5];
outlet_patt7 = temp[6];
outlet_patt8 = temp[7];
prev = patt;

Privacy

© 2024 Zrna Research