another rewrite (segfaults currently)
This commit is contained in:
parent
7035102ab1
commit
031b5a21e5
336
crap/mugi4.hpp
336
crap/mugi4.hpp
|
@ -1,9 +1,6 @@
|
||||||
#define ID (0xD8D0D8D0)
|
#define BLOCK_SIZE 256
|
||||||
#define LABEL "crap_mugi4"
|
#define OVERSAMPLING 2
|
||||||
#define NAME "crap mugi4 (moog-like)"
|
#define FULL_SIZE (BLOCK_SIZE*OVERSAMPLING)
|
||||||
#define AUTHOR "Connor Olding"
|
|
||||||
#define COPYRIGHT "MIT"
|
|
||||||
#define PARAMETERS 3
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
an implementation of:
|
an implementation of:
|
||||||
|
@ -14,21 +11,29 @@ vol. 22, no. 12, pp. 1873 1883, December 2014.
|
||||||
https://aaltodoc.aalto.fi/bitstream/handle/123456789/14420/article6.pdf
|
https://aaltodoc.aalto.fi/bitstream/handle/123456789/14420/article6.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define OVERSAMPLING 2
|
|
||||||
#define BLOCK_SIZE 256
|
|
||||||
#define FULL_SIZE (BLOCK_SIZE*OVERSAMPLING)
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "param.hpp"
|
#include "Param.hpp"
|
||||||
|
#include "Crap.hpp"
|
||||||
#include "os2piir.hpp"
|
#include "os2piir.hpp"
|
||||||
|
#include "BufferOS2.hpp"
|
||||||
|
|
||||||
#define VT 0.026
|
#define VT 0.026
|
||||||
#define N 4
|
#define N 4
|
||||||
#define VT2 T(2.*VT)
|
#define VT2 T(2.*VT)
|
||||||
|
|
||||||
|
TEMPLATE INNER PURE T
|
||||||
|
tanh2(T x)
|
||||||
|
{
|
||||||
|
//return T(tanh(x[0]), tanh(x[1]));
|
||||||
|
T xx = x*x;
|
||||||
|
T a = ((xx + T(378))*xx + T(17325))*xx + T(135135);
|
||||||
|
T b = ((T(28)*xx + T(3150))*xx + T(62370))*xx + T(135135);
|
||||||
|
return x*a/b;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
v2df sum, sumback, dout;
|
v2df sum, sumback, dout;
|
||||||
} stage;
|
} stage;
|
||||||
|
@ -43,25 +48,7 @@ typedef struct {
|
||||||
v2df L_r1;
|
v2df L_r1;
|
||||||
} freqdata;
|
} freqdata;
|
||||||
|
|
||||||
typedef struct {
|
// TODO: namespace
|
||||||
ulong fs;
|
|
||||||
halfband_t<v2df> hb_up, hb_down;
|
|
||||||
freqdata fd;
|
|
||||||
stage s1, s2, s3, s4;
|
|
||||||
v2df sumback1, sumback2, sumback3, sumback4;
|
|
||||||
v2df drive, feedback;
|
|
||||||
} personal;
|
|
||||||
|
|
||||||
TEMPLATE INNER PURE T
|
|
||||||
tanh2(T x)
|
|
||||||
{
|
|
||||||
//return T(tanh(x[0]), tanh(x[1]));
|
|
||||||
T xx = x*x;
|
|
||||||
T a = ((xx + T(378))*xx + T(17325))*xx + T(135135);
|
|
||||||
T b = ((T(28)*xx + T(3150))*xx + T(62370))*xx + T(135135);
|
|
||||||
return x*a/b;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEMPLATE INNER T
|
TEMPLATE INNER T
|
||||||
process_stage(stage *s, freqdata fd, T in)
|
process_stage(stage *s, freqdata fd, T in)
|
||||||
{
|
{
|
||||||
|
@ -73,174 +60,135 @@ process_stage(stage *s, freqdata fd, T in)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEMPLATE INNER T
|
struct Crap_mugi4
|
||||||
process_one(T in, personal *data)
|
:public AdjustAll<BufferOS2<Crap>> {
|
||||||
{
|
static constexpr ulong id = 0xD8D0D8D0;
|
||||||
freqdata fd = data->fd;
|
static constexpr char label[] = "crap_mugi4";
|
||||||
|
static constexpr char name[] = "crap mugi4 (moog-like)";
|
||||||
|
static constexpr char author[] = "Connor Olding";
|
||||||
|
static constexpr char copyright[] = "MIT";
|
||||||
|
|
||||||
in *= data->drive;
|
static constexpr ulong parameters = 3;
|
||||||
|
|
||||||
T sum = in + data->sumback1;
|
|
||||||
T pre = -fd.p0*sum;
|
|
||||||
process_stage<T>(&data->s1, fd, tanh2<T>(pre/VT2));
|
|
||||||
process_stage<T>(&data->s2, fd, data->s1.dout);
|
|
||||||
process_stage<T>(&data->s3, fd, data->s2.dout);
|
|
||||||
T out = process_stage<T>(&data->s4, fd, data->s3.dout);
|
|
||||||
|
|
||||||
T back = data->feedback*out;
|
|
||||||
data->sumback1 = fd.r1*in + fd.q0*back + data->sumback2;
|
|
||||||
data->sumback2 = fd.r2*in + fd.q1*back + data->sumback3;
|
|
||||||
data->sumback3 = fd.r3*in + fd.q2*back + data->sumback4;
|
|
||||||
data->sumback4 = fd.r4*in + fd.q3*back;
|
|
||||||
|
|
||||||
T compensate = -(data->feedback + T(1));
|
|
||||||
return out/data->drive*compensate;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static void
|
|
||||||
process(personal *data,
|
|
||||||
T *in_L, T *in_R,
|
|
||||||
T *out_L, T *out_R,
|
|
||||||
ulong count)
|
|
||||||
{
|
|
||||||
disable_denormals();
|
|
||||||
v2df buf[BLOCK_SIZE];
|
|
||||||
v2df over[FULL_SIZE];
|
|
||||||
|
|
||||||
halfband_t<v2df> *hb_up = &data->hb_up;
|
|
||||||
halfband_t<v2df> *hb_down = &data->hb_down;
|
|
||||||
|
|
||||||
for (ulong pos = 0; pos < count; pos += BLOCK_SIZE) {
|
|
||||||
ulong rem = BLOCK_SIZE;
|
|
||||||
if (pos + BLOCK_SIZE > count)
|
|
||||||
rem = count - pos;
|
|
||||||
|
|
||||||
ulong rem2 = rem*OVERSAMPLING;
|
|
||||||
|
|
||||||
for (ulong i = 0; i < rem; i++) {
|
|
||||||
buf[i][0] = in_L[i];
|
|
||||||
buf[i][1] = in_R[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ulong i = 0; i < rem; i++) {
|
|
||||||
over[i*2+0] = interpolate_a(hb_up, buf[i]);
|
|
||||||
over[i*2+1] = interpolate_b(hb_up, buf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ulong i = 0; i < rem2; i++) {
|
|
||||||
over[i] = process_one(over[i], data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ulong i = 0; i < rem; i++) {
|
|
||||||
decimate_a(hb_down, over[i*2+0]);
|
|
||||||
buf[i] = decimate_b(hb_down, over[i*2+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ulong i = 0; i < rem; i++) {
|
|
||||||
out_L[i] = buf[i][0];
|
|
||||||
out_R[i] = buf[i][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
in_L += BLOCK_SIZE;
|
|
||||||
in_R += BLOCK_SIZE;
|
|
||||||
out_L += BLOCK_SIZE;
|
|
||||||
out_R += BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INNER void
|
|
||||||
construct(personal *data)
|
|
||||||
{
|
|
||||||
memset(data, 0, sizeof(personal));
|
|
||||||
}
|
|
||||||
|
|
||||||
INNER void
|
|
||||||
construct_params(param *params)
|
|
||||||
{
|
|
||||||
sprintf(params[0].name, "Frequency");
|
|
||||||
params[0].min = 20;
|
|
||||||
params[0].max = 20000;
|
|
||||||
params[0].scale = SCALE_HZ;
|
|
||||||
params[0].def = DEFAULT_MAX;
|
|
||||||
|
|
||||||
sprintf(params[1].name, "Drive");
|
|
||||||
params[1].min = -40;
|
|
||||||
params[1].max = 0;
|
|
||||||
params[1].scale = SCALE_DB;
|
|
||||||
params[1].def = DEFAULT_MIN;
|
|
||||||
|
|
||||||
sprintf(params[2].name, "Feedback");
|
|
||||||
params[2].min = 0;
|
|
||||||
params[2].max = 1;
|
|
||||||
params[2].scale = SCALE_FLOAT;
|
|
||||||
params[2].def = DEFAULT_MIN;
|
|
||||||
|
|
||||||
param_reset(¶ms[0]);
|
|
||||||
param_reset(¶ms[1]);
|
|
||||||
param_reset(¶ms[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
INNER void
|
|
||||||
destruct(personal *data)
|
|
||||||
{}
|
|
||||||
|
|
||||||
INNER void
|
|
||||||
resume(personal *data)
|
|
||||||
{
|
|
||||||
memset(&data->hb_up, 0, sizeof(halfband_t<v2df>));
|
|
||||||
memset(&data->hb_down, 0, sizeof(halfband_t<v2df>));
|
|
||||||
}
|
|
||||||
|
|
||||||
INNER void
|
|
||||||
pause(personal *data)
|
|
||||||
{}
|
|
||||||
|
|
||||||
INNER void
|
|
||||||
adjust(personal *data, param *params, ulong fs_long)
|
|
||||||
{
|
|
||||||
double fs = fs_long;
|
|
||||||
data->fs = fs_long;
|
|
||||||
double f = params[0].value;
|
|
||||||
if (f < 20) f = 20;
|
|
||||||
if (f > fs/6*OVERSAMPLING) f = fs/6*OVERSAMPLING;
|
|
||||||
double drive = DB2LIN(params[1].value);
|
|
||||||
double k = params[2].value*N;
|
|
||||||
data->drive = (v2df){drive, drive};
|
|
||||||
data->feedback = (v2df){k, k};
|
|
||||||
|
|
||||||
double bc1 = -4; //-binomial(N, 1);
|
|
||||||
double bc2 = -6; //-binomial(N, 2);
|
|
||||||
double bc3 = -4; //-binomial(N, 3);
|
|
||||||
double bc4 = -1; //-binomial(N, 4);
|
|
||||||
|
|
||||||
freqdata fd;
|
freqdata fd;
|
||||||
#define fd_set(L, R) double L = R; fd.L = (v2df){L, L}
|
stage s1, s2, s3, s4;
|
||||||
fd_set(g, tan(M_PI*f/fs/OVERSAMPLING));
|
v2df sumback1, sumback2, sumback3, sumback4;
|
||||||
double gg1 = g/(g + 1);
|
v2df drive, feedback;
|
||||||
double gg1Nk = k*gg1*gg1*gg1*gg1;
|
|
||||||
double g1g1 = (g - 1)/(g + 1);
|
|
||||||
|
|
||||||
fd_set(p0, 1/(1 + gg1Nk));
|
inline
|
||||||
fd_set(r1, bc1*gg1Nk);
|
Crap_mugi4()
|
||||||
fd_set(r2, bc2*gg1Nk);
|
{
|
||||||
fd_set(r3, bc3*gg1Nk);
|
// FIXME
|
||||||
fd_set(r4, bc4*gg1Nk);
|
//memset(data, 0, sizeof(personal));
|
||||||
fd_set(q0, r1 + bc1*g1g1);
|
}
|
||||||
fd_set(q1, r2 + bc2*g1g1*g1g1);
|
|
||||||
fd_set(q2, r3 + bc3*g1g1*g1g1*g1g1);
|
|
||||||
fd_set(q3, r4 + bc4*g1g1*g1g1*g1g1*g1g1);
|
|
||||||
|
|
||||||
fd_set(L_p0, 1/(1 + g));
|
TEMPLATE inline T
|
||||||
fd_set(L_q0, 1 - g);
|
process_one(T in)
|
||||||
fd_set(L_r1, -g);
|
{
|
||||||
#undef fd_set
|
in *= drive;
|
||||||
|
|
||||||
data->fd = fd;
|
T sum = in + sumback1;
|
||||||
}
|
T pre = -fd.p0*sum;
|
||||||
|
process_stage<T>(&s1, fd, tanh2<T>(pre/VT2));
|
||||||
|
process_stage<T>(&s2, fd, s1.dout);
|
||||||
|
process_stage<T>(&s3, fd, s2.dout);
|
||||||
|
T out = process_stage<T>(&s4, fd, s3.dout);
|
||||||
|
|
||||||
INNER void
|
T back = feedback*out;
|
||||||
adjust_one(personal *data, param *params, unsigned int index)
|
sumback1 = fd.r1*in + fd.q0*back + sumback2;
|
||||||
{
|
sumback2 = fd.r2*in + fd.q1*back + sumback3;
|
||||||
adjust(data, params, data->fs);
|
sumback3 = fd.r3*in + fd.q2*back + sumback4;
|
||||||
}
|
sumback4 = fd.r4*in + fd.q3*back;
|
||||||
|
|
||||||
|
T compensate = -(feedback + T(1));
|
||||||
|
return out/drive*compensate;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual inline v2df
|
||||||
|
process2(v2df in)
|
||||||
|
{
|
||||||
|
return process_one(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
construct_params(Param *params)
|
||||||
|
{
|
||||||
|
sprintf(params[0].name, "Frequency");
|
||||||
|
params[0].min = 20;
|
||||||
|
params[0].max = 20000;
|
||||||
|
params[0].scale = SCALE_HZ;
|
||||||
|
params[0].def = DEFAULT_MAX;
|
||||||
|
|
||||||
|
sprintf(params[1].name, "Drive");
|
||||||
|
params[1].min = -40;
|
||||||
|
params[1].max = 0;
|
||||||
|
params[1].scale = SCALE_DB;
|
||||||
|
params[1].def = DEFAULT_MIN;
|
||||||
|
|
||||||
|
sprintf(params[2].name, "Feedback");
|
||||||
|
params[2].min = 0;
|
||||||
|
params[2].max = 1;
|
||||||
|
params[2].scale = SCALE_FLOAT;
|
||||||
|
params[2].def = DEFAULT_MIN;
|
||||||
|
|
||||||
|
params[0].reset();
|
||||||
|
params[1].reset();
|
||||||
|
params[2].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
pause()
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
resume()
|
||||||
|
{
|
||||||
|
memset(&hb_up, 0, sizeof(halfband_t<v2df>));
|
||||||
|
memset(&hb_down, 0, sizeof(halfband_t<v2df>));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
adjust_all(Param *params)
|
||||||
|
{
|
||||||
|
double f = params[0].value;
|
||||||
|
if (f < 20) f = 20;
|
||||||
|
if (f > fs/6*OVERSAMPLING) f = fs/6*OVERSAMPLING;
|
||||||
|
double _drive = DB2LIN(params[1].value);
|
||||||
|
double k = params[2].value*N;
|
||||||
|
drive = v2df(_drive, _drive);
|
||||||
|
feedback = v2df(k, k);
|
||||||
|
|
||||||
|
double bc1 = -4; //-binomial(N, 1);
|
||||||
|
double bc2 = -6; //-binomial(N, 2);
|
||||||
|
double bc3 = -4; //-binomial(N, 3);
|
||||||
|
double bc4 = -1; //-binomial(N, 4);
|
||||||
|
|
||||||
|
#define fd_set(L, R) double L = R; fd.L = (v2df){L, L}
|
||||||
|
fd_set(g, tan(M_PI*f/fs/OVERSAMPLING));
|
||||||
|
double gg1 = g/(g + 1);
|
||||||
|
double gg1Nk = k*gg1*gg1*gg1*gg1;
|
||||||
|
double g1g1 = (g - 1)/(g + 1);
|
||||||
|
|
||||||
|
fd_set(p0, 1/(1 + gg1Nk));
|
||||||
|
fd_set(r1, bc1*gg1Nk);
|
||||||
|
fd_set(r2, bc2*gg1Nk);
|
||||||
|
fd_set(r3, bc3*gg1Nk);
|
||||||
|
fd_set(r4, bc4*gg1Nk);
|
||||||
|
fd_set(q0, r1 + bc1*g1g1);
|
||||||
|
fd_set(q1, r2 + bc2*g1g1*g1g1);
|
||||||
|
fd_set(q2, r3 + bc3*g1g1*g1g1*g1g1);
|
||||||
|
fd_set(q3, r4 + bc4*g1g1*g1g1*g1g1*g1g1);
|
||||||
|
|
||||||
|
fd_set(L_p0, 1/(1 + g));
|
||||||
|
fd_set(L_q0, 1 - g);
|
||||||
|
fd_set(L_r1, -g);
|
||||||
|
#undef fd_set
|
||||||
|
|
||||||
|
fd = fd;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr char Crap_mugi4::label[];
|
||||||
|
constexpr char Crap_mugi4::name[];
|
||||||
|
constexpr char Crap_mugi4::author[];
|
||||||
|
constexpr char Crap_mugi4::copyright[];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user