None
None
text function0
text function1
text function2
text function3
combo size
combo location
combo mode
combo normalize
#if attr_location == 0
#define LOCATION
#else
#define LOCATION __attribute__((section(".sdram")))
#endif
static const uint32_t NBWAVES = 4;
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
}
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);
}
prepare();