paraEQ

2-pole resonant multimode filter (biquad) 0=thru 1=peak 2=lowshelf 4=highshelf mute bypasses the filter
Author: Remco van der Most
License: BSD
Github: sss/filter/paraEQ.axo

Inlets

int32 preset

frac32buffer filter input

bool32 save

bool32 load

Outlets

frac32buffer filter output

Parameters

frac32.s.map gain

bool32.mom save

bool32.mom load

int32 stage

int32 preset

bool32.tgl STorMS

int32.hradio mode

frac32.s.map.pitch freq

frac32.u.map.filterq reso

Attributes

spinner stages

Declaration
static const uint32_t LENGTH = attr_stages << 2;
int32_t *array;
biquad_state bs[attr_stages];
biquad_coefficients bc[attr_stages];
int32_t freq;
int32_t reso;
int stages = attr_stages;
int mode;
int i;
int j;
int32_t out[BUFSIZE];
int32_t TMP1[BUFSIZE];
// 0=mode
// 1=freq
// 2=reso
// 3=gain
int32_t gain;
int32_t filter(int32_t FREQ, int32_t RESO, int32_t MODE, int k) {
  switch (MODE > 0 ? MODE : 0) {
  case 0:
    biquad_bp_coefs(&bc[k], FREQ, INT_MAX - (__USAT(RESO, 27) << 4));
    break;
  case 1:
    biquad_bp_coefs(&bc[k], FREQ, INT_MAX - (__USAT(RESO, 27) << 4));
    break;
  case 2:
    biquad_lp_coefs(&bc[k], FREQ, INT_MAX - (__USAT(RESO, 27) << 4));
    break;
  case 3:
    biquad_hp_coefs(&bc[k], FREQ, INT_MAX - (__USAT(RESO, 27) << 4));
    break;
  }
};
int prev;
char c[64];
int offset;
int pval;
int strig;
int ltrig;
Init
static int32_t _array[LENGTH] __attribute__((section(".sdram")));
array = &_array[0];

for (i = 0; i < attr_stages; i++) {
  biquad_clearstate(&bs[i]);
  array[i << 2] = 1;
}

strcpy(&c[0], "0:/para000.tab");
offset = strlen("para");
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;
int 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;

int stage = (param_stage - 1) << 2;
if ((stage >> 2) < attr_stages) {
  if (!(stage + load == prev)) {
    PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_mode],
                       array[stage], 0xFFFD);
    PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_freq],
                       array[stage + 1], 0xFFFD);
    PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_reso],
                       array[stage + 2], 0xFFFD);
    PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_gain],
                       array[stage + 3], 0xFFFD);
  }

  array[stage] = param_mode;
  array[stage + 1] = param_freq;
  array[stage + 2] = param_reso;
  array[stage + 3] = param_gain;
}
for (i = 0; i < BUFSIZE; i++) {
  TMP1[i] = inlet_in[i];
}
for (j = 0; j < attr_stages; j++) {
  mode = array[j << 2];
  if (mode > 0) {
    MTOF(array[(j << 2) + 1], freq);
    reso = array[(j << 2) + 2];
    filter(freq, reso, mode, j);
    biquad_dsp(&bs[j], &bc[j], TMP1, outlet_out);
    gain = array[(j << 2) + 3] * (1 - (param_STorMS << 1));
    gain = gain > 0 ? gain : gain;
    for (i = 0; i < BUFSIZE; i++) {
      TMP1[i] += ___SMMUL(outlet_out[i] << 2, gain << 3);
    }
  }
}
for (i = 0; i < BUFSIZE; i++) {
  outlet_out[i] = TMP1[i];
}

prev = stage + load;

Privacy

© 2024 Zrna Research