gen8

Author: Smashed Transistors
License: LGPL
Github: tiar/XT/gen8.axo

Inlets

None

Outlets

None

Attributes

text function0

text function1

text function2

text function3

text function4

text function5

text function6

text function7

combo size

combo location

combo mode

combo normalize

Declaration
#if attr_location == 0
#define LOCATION
#else
#define LOCATION __attribute__((section(".sdram")))
#endif
static const uint32_t NBWAVES = 8;
static const uint32_t LENGTHPOW = attr_size;
static const uint32_t LENGTH = 1 << attr_size;
static const uint32_t LENGTHMASK = (1 << attr_size) - 1;
static const uint32_t BITS = 32;
static const uint32_t GAIN = 7;         // q20 to q27
static const uint32_t MODE = attr_mode; // 0 interp, 1 vintage, 2 dirty
uint32_t TSAL[16] = {0x0000FFFFU,
                     0xFF00FF00U,
                     0x0FF0F00FU,
                     0xF0F0F0F0U,
                     0b00111100001111001100001111000011U,
                     0b11000011001111001100001100111100U,
                     0b00110011110011001100110000110011U,
                     0b11001100110011001100110011001100U,
                     0b01100110011001101001100110011001U,
                     0b10011001011001101001100101100110U,
                     0b01101001100101101001011001101001U,
                     0b10010110100101101001011010010110U,
                     0b01011010010110101010010110100101U,
                     0b10100101010110101010010101011010U,
                     0b01010101101010101010101001010101U,
                     0b10101010101010101010101010101010U};
int32_t *v;
float *fv; // in place
int32_t *array;
int32_t *Iv;

static float rnd(float x) {
  return (((((int32_t)(x)) * 69069 + 1) * 69069 + 1) * 69069) > 0 ? 1 : -1;
}
static float rndf(float x) {
  return arm::q_to_float(
      ((arm::float_to_q(x, 31) * 69069 + 1) * 69069 + 1) * 69069, 31);
}
static float mod1(float x) { return (x + 100) - ((int)(x + 100)); }
static float saw(float x) { return 2 * mod1(x) - 1; }
static float rect(float x, float r) {
  x = mod1(x);
  return x < r ? -1 : 1;
}
static float sqr(float x) { return rect(x, 0.5f); }
static float tri(float x, float r) { // r: cyclic ratio 0.5f => middle
  x = mod1(x);
  if (x < r)
    return -1 + (2 * x / r);
  else
    return 1 - 2 * (x - r) / (1.0f - r);
}
static float tri(float x) { return tri(x, 0.5f); }
// cos with phase distorsion
static float cos1(float x, float r) {
  x = tri(x, r);
  return -x * (1.5708f + x * x * (-0.6422f + 0.0714f * x * x));
}
static float cos1(float x) { return cos1(x, 0.5f); }
static float sin1(float x) { return cos1(x - 0.25f); }

// additive Synth from 3 to 10 harmonics
// ex: addSynth(x, 0.2f,0.5f,0.33f,0.25f,0.2f,0.1667f, 1.0f, 0.125f)
static float addSynth(float x, float h1, float h2, float h3) {
  return h1 * sin1(x) + h2 * sin1(2 * x) + h3 * sin1(3 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4) {
  return addSynth(x, h1, h2, h3) + h4 * sin1(4 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4,
                      float h5) {
  return addSynth(x, h1, h2, h3, h4) + h5 * sin1(5 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4, float h5,
                      float h6) {
  return addSynth(x, h1, h2, h3, h4, h5) + h6 * sin1(6 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4, float h5,
                      float h6, float h7) {
  return addSynth(x, h1, h2, h3, h4, h5, h6) + h7 * sin1(7 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4, float h5,
                      float h6, float h7, float h8) {
  return addSynth(x, h1, h2, h3, h4, h5, h6, h7) + h8 * sin1(8 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4, float h5,
                      float h6, float h7, float h8, float h9) {
  return addSynth(x, h1, h2, h3, h4, h5, h6, h7, h8) + h9 * sin1(9 * x);
}
static float addSynth(float x, float h1, float h2, float h3, float h4, float h5,
                      float h6, float h7, float h8, float h9, float h10) {
  return addSynth(x, h1, h2, h3, h4, h5, h6, h7, h8, h9) + h10 * sin1(10 * x);
}

static float clip(float x) { return x > 1.0f ? 1.0f : x < -1.0f ? -1.0f : x; }
static float sat(float x) {
  x = clip(x);
  return x * (1.5f - 0.5f * x * x);
}
static float pow(float x, int N) {
  float y = 1.0f;
  if (N >= 0)
    for (int i = 0; i < N; i++)
      y *= x;
  else {
    float _x = 1.0f / x;
    for (int i = 0; i < -N; i++)
      y *= _x;
  }
  return y;
}
static float exp1(float x) {
  x = 1 + x * (1 / 256.0f);
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  x *= x;
  return x;
}
static float exp(float x) {
  float coef = 1;
  while (x < -4) {
    x += 8.0f;
    coef *= 1 / 2980.9579870f;
  }
  // [-4 inf]
  if (x < 0) {
    x += 4.0f;
    coef *= 1 / 54.598150033f;
  }
  // [0 inf]
  while (x > 8) {
    x -= 8.0f;
    coef *= 2980.9579870f;
  }
  // [0 8]
  if (x > 4) {
    x -= 4.0f;
    coef *= 54.598150033f;
  }
  if (x > 2) {
    x -= 2.0f;
    coef *= 7.389056099f;
  }
  if (x > 1) {
    x -= 1.0f;
    coef *= 2.718281828f;
  }
  // [0 1]
  return exp1(x) * coef;
}
static float hann(float x) { return 0.5f - 0.5f * cos1(x); }
static float quant(float x, float step) {
  return (((int)(x / step + 100.5f)) - 100) * step;
}
/*
 xfade(w, tri(x*(1+5*w)), sin1(x*(1+5*w)))
 higher order can be used for segments
 xfade(x,1,0.1f,0,0,0) // pulsaw
*/
static float xf(float x, float v0, float v1) { return v0 + x * (v1 - v0); }
static float xfade(float x, float v0, float v1) {
  if (x <= 0)
    return v0;
  if (x >= 1)
    return v1;
  return v0 + x * (v1 - v0);
}
static float xfade(float x, float v0, float v1, float v2) {
  if (x <= 0)
    return v0;
  if (x >= 1)
    return v2;
  return x < 0.5f ? xf(x * 2, v0, v1) : xf((x - 0.5f) * 2, v1, v2);
}
static float xfade(float x, float v0, float v1, float v2, float v3) {
  if (x <= 0)
    return v0;
  if (x >= 1)
    return v3;
  return x < 1.0f / 3 ? xf(x * 3, v0, v1)
                      : (x < 2.0f / 3 ? xf((x - 1.0f / 3) * 3, v1, v2)
                                      : xf((x - 2.0f / 3) * 3, v2, v3));
}
static float xfade(float x, float v0, float v1, float v2, float v3, float v4) {
  if (x <= 0)
    return v0;
  if (x >= 1)
    return v4;
  if (x < 0.25f)
    return xf(x * 4, v0, v1);
  if (x < 0.50f)
    return xf((x - 0.25f) * 4, v1, v2);
  if (x < 0.75f)
    return xf((x - 0.50f) * 4, v2, v3);
  return xf((x - 0.75f) * 4, v3, v4);
}
static float xfade(float x, float v0, float v1, float v2, float v3, float v4,
                   float v5) {
  if (x <= 0)
    return v0;
  if (x >= 1)
    return v5;
  if (x < 0.2f)
    return xf(x * 5, v0, v1);
  if (x < 0.4f)
    return xf((x - 0.2f) * 5, v1, v2);
  if (x < 0.6f)
    return xf((x - 0.4f) * 5, v2, v3);
  if (x < 0.8f)
    return xf((x - 0.6f) * 5, v3, v4);
  return xf((x - 0.8f) * 5, v4, v5);
}
static float bt(float x, uint32_t bin) {
  return ((bin >> (arm::float_to_q(x, 5) & 31)) & 1) == 0 ? -1 : 1;
}
// n [1,16]
float sal(float x, int n) {
  if (n > 16)
    n = 16;
  else if (n < 1)
    n = 1;
  return bt(x, TSAL[n - 1]);
}
float sal(float x, float a1, float a2, float a3, float a4, float a5, float a6,
          float a7, float a8) {
  int o = arm::float_to_q(x, 5) & 31;
  float a;
  a = ((TSAL[0] >> o) & 1) == 0 ? -a1 : a1;
  a += ((TSAL[1] >> o) & 1) == 0 ? -a2 : a2;
  a += ((TSAL[2] >> o) & 1) == 0 ? -a3 : a3;
  a += ((TSAL[3] >> o) & 1) == 0 ? -a4 : a4;
  a += ((TSAL[4] >> o) & 1) == 0 ? -a5 : a5;
  a += ((TSAL[5] >> o) & 1) == 0 ? -a6 : a6;
  a += ((TSAL[6] >> o) & 1) == 0 ? -a7 : a7;
  a += ((TSAL[7] >> o) & 1) == 0 ? -a8 : a8;
  return a;
}
float sal(float x, float a1, float a2, float a3, float a4, float a5, float a6,
          float a7, float a8, float a9, float a10, float a11, float a12,
          float a13, float a14, float a15, float a16) {
  int o = arm::float_to_q(x, 5) & 31;
  float a;
  a = ((TSAL[0] >> o) & 1) == 0 ? -a1 : a1;
  a += ((TSAL[1] >> o) & 1) == 0 ? -a2 : a2;
  a += ((TSAL[2] >> o) & 1) == 0 ? -a3 : a3;
  a += ((TSAL[3] >> o) & 1) == 0 ? -a4 : a4;
  a += ((TSAL[4] >> o) & 1) == 0 ? -a5 : a5;
  a += ((TSAL[5] >> o) & 1) == 0 ? -a6 : a6;
  a += ((TSAL[6] >> o) & 1) == 0 ? -a7 : a7;
  a += ((TSAL[7] >> o) & 1) == 0 ? -a8 : a8;
  a += ((TSAL[8] >> o) & 1) == 0 ? -a9 : a9;
  a += ((TSAL[9] >> o) & 1) == 0 ? -a10 : a10;
  a += ((TSAL[10] >> o) & 1) == 0 ? -a11 : a11;
  a += ((TSAL[11] >> o) & 1) == 0 ? -a12 : a12;
  a += ((TSAL[12] >> o) & 1) == 0 ? -a13 : a13;
  a += ((TSAL[13] >> o) & 1) == 0 ? -a14 : a14;
  a += ((TSAL[14] >> o) & 1) == 0 ? -a15 : a15;
  a += ((TSAL[15] >> o) & 1) == 0 ? -a16 : a16;
  return a;
}

// usage
// sal(x,(int)(w*16+1.0f))
//        1    2    3    4    5    6    7    8    9   10   11   12   13   14 15
//        16
// sal(x, 16,   8,   0,   4,   0,   0,   0,   2,   0,   0,   0,   0, 3*w,   0,
// 0,   1)

void prepare(void) {
  for (int n = 0; n < NBWAVES; n++) {
    float *_fv = fv + (n * (LENGTH + 1));
    // pre integrate
    float moy = 0.0f;
    for (int i = 0; i < LENGTH; i++) {
      moy += _fv[i];
    }
    moy *= 1.0f / LENGTH;
    float M = 0.0f;
    for (int i = 0; i < LENGTH; i++) {
      _fv[i] -= moy;
      if (fabs(_fv[i]) > M)
        M = fabs(_fv[i]);
    }
    // normalize
    if (attr_normalize == 1 && M != 0.0f) {
      M = 1.0f / M;
      for (int i = 0; i < LENGTH; i++) {
        _fv[i] *= M;
      }
    }
    // convert
    int32_t *_v = v + (n * (LENGTH + 1));
    int32_t *_Iv = Iv + (n * (LENGTH));
    for (int i = 0; i < LENGTH; i++) {
      _v[i] = arm::float_to_q(_fv[i], 27 - GAIN);
    }
    _v[LENGTH] = _v[0]; // for easy dv: dv = v[i+1] - v[i]
    // integrate (checked)
    int32_t I1 = 0;
    for (int i = 0; i < LENGTH; i++) {
      _Iv[i] = I1;
#if attr_mode == 0
      I1 += _v[i] + (_v[i + 1] - _v[i]) / 2;
#elif attr_mode == 1
      I1 += _v[i];
#else
      I1 += _v[i] - (_v[i + 1] - _v[i]) / 2;
#endif
    }
  }
}
// used by tiar/PIXWT/oscLight
int32_t I1p32(int32_t n, uint32_t p) {
  // the interpolation coefficient
  int32_t a = (p & 0x003FFFFF) << 9; // 0 -> 1 q31
  // the segment number
  uint32_t i = (p & (LENGTHMASK << 22)) >> 22; // [0 LENGTH-1]
  // polynomial calc of the integrand on segment i at position a
  // the polynomial is
  // I1_0 = Iv + a * v + (a^2/2) dv
  // it is the integrand of v + a*dv
  //                                         a2/2 q31            I1_0
  int32_t *_v = v + (n * (LENGTH + 1));
  int32_t *_Iv = Iv + (n * (LENGTH));
#if attr_mode == 0
  return _Iv[i] +
         (___SMMLA(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#elif attr_mode == 1
  return _Iv[i] + (___SMMUL(_v[i], a) << 1);
#else
  return _Iv[i] +
         (___SMMLS(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#endif
}
int32_t *getV(int n) { return v + (n * (LENGTH + 1)); }
int32_t *getIv(int n) { return Iv + (n * (LENGTH)); }
// used by tiar/PIXWT/oscLight
int32_t I1p32(int32_t *_v, int32_t *_Iv, uint32_t p) {
  // the interpolation coefficient
  int32_t a = (p & 0x003FFFFF) << 9; // 0 -> 1 q31
  // the segment number
  uint32_t i = (p & (LENGTHMASK << 22)) >> 22; // [0 LENGTH-1]
// polynomial calc of the integrand on segment i at position a
// the polynomial is
// I1_0 = Iv + a * v + (a^2/2) dv
// it is the integrand of v + a*dv
//                                         a2/2 q31            I1_0
#if attr_mode == 0
  return _Iv[i] +
         (___SMMLA(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#elif attr_mode == 1
  return _Iv[i] + (___SMMUL(_v[i], a) << 1);
#else
  return _Iv[i] +
         (___SMMLS(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#endif
}
// used by tiar/PIXWT/osc
int32_t I1p30(int32_t *_v, int32_t *_Iv, uint32_t p) {
  // the interpolation coefficient
  int32_t a = (p & 0x000FFFFF) << 11; // 0 -> 1 q31
  // the segment number
  uint32_t i = (p & (LENGTHMASK << 20)) >> 20; // [0 LENGTH-1]
// polynomial calc of the integrand on segment i at position a
// the polynomial is
// I1_0 = Iv + a * v + (a^2/2) dv
// it is the integrand of v + a*dv
//                                         a2/2 q31            I1_0
#if attr_mode == 0
  return _Iv[i] +
         (___SMMLA(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#elif attr_mode == 1
  return _Iv[i] + (___SMMUL(_v[i], a) << 1);
#else
  return _Iv[i] +
         (___SMMLS(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#endif
}
int32_t I0p30(int32_t *_v, uint32_t p) {
  // the interpolation coefficient
  int32_t a = (p & 0x000FFFFF) << 11; // 0 -> 1 q31
  // the segment number
  uint32_t i = (p & (LENGTHMASK << 20)) >> 20; // [0 LENGTH-1]
// polynomial calc of the integrand on segment i at position a
// the polynomial is
// I1_0 = Iv + a * v + (a^2/2) dv
// it is the integrand of v + a*dv
//                                         a2/2 q31            I1_0
#if attr_mode == 0
  return ___SMMLA(a, _v[i + 1] - _v[i], _v[i] >> 1) << (GAIN + 1);
#elif attr_mode == 1
  return _v[i] << GAIN;
#else
  return ___SMMLS(a, _v[i + 1] - _v[i], _v[i] >> 1) << (GAIN + 1);
#endif
}

// used by tiar/PIXWT/osc
int32_t I1p30(int32_t *_v, int32_t *_Iv, uint32_t i, int32_t a) {
#if attr_mode == 0
  return _Iv[i] +
         (___SMMLA(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#elif attr_mode == 1
  return _Iv[i] + (___SMMUL(_v[i], a) << 1);
#else
  return _Iv[i] +
         (___SMMLS(_v[i + 1] - _v[i], ___SMMUL(a, a), ___SMMUL(_v[i], a)) << 1);
#endif
}
int32_t I0p30(int32_t *_v, uint32_t i, int32_t a) {
#if attr_mode == 0
  return ___SMMLA(a, _v[i + 1] - _v[i], _v[i] >> 1) << (GAIN + 1);
#elif attr_mode == 1
  return _v[i] << GAIN;
#else
  return ___SMMLS(a, _v[i + 1] - _v[i], _v[i] >> 1) << (GAIN + 1);
#endif
}
Init
static int32_t v_[attr_poly][NBWAVES * (LENGTH + 1)] LOCATION;
static int32_t Iv_[attr_poly][NBWAVES * (LENGTH)] LOCATION;
#undef LOCATION
v = &v_[parent->polyIndex][0];
fv = (float *)v; // in place
array = v;
Iv = &Iv_[parent->polyIndex][0];

for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[i] = (float)(attr_function0 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[1 * (LENGTH + 1) + i] = (float)(attr_function1 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[2 * (LENGTH + 1) + i] = (float)(attr_function2 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[3 * (LENGTH + 1) + i] = (float)(attr_function3 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[4 * (LENGTH + 1) + i] = (float)(attr_function4 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[5 * (LENGTH + 1) + i] = (float)(attr_function5 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[6 * (LENGTH + 1) + i] = (float)(attr_function6 + 0.0f);
}
for (int i = 0; i < LENGTH; i++) {
  float x = arm::q_to_float(i, LENGTHPOW);
  float sx = x < 0.5f ? 2 * x : 2 * (x - 1.0f); // for distos
  fv[7 * (LENGTH + 1) + i] = (float)(attr_function7 + 0.0f);
}
prepare();

Privacy

© 2024 Zrna Research