From 031b5a21e5c788f0dc10acc638fb16acb4b8070c Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Mon, 8 Jun 2015 01:14:48 -0700 Subject: [PATCH] another rewrite (segfaults currently) --- crap/mugi4.hpp | 336 +++++++++++++++++++++---------------------------- 1 file changed, 142 insertions(+), 194 deletions(-) diff --git a/crap/mugi4.hpp b/crap/mugi4.hpp index 4d7d6da..e16efc6 100644 --- a/crap/mugi4.hpp +++ b/crap/mugi4.hpp @@ -1,9 +1,6 @@ -#define ID (0xD8D0D8D0) -#define LABEL "crap_mugi4" -#define NAME "crap mugi4 (moog-like)" -#define AUTHOR "Connor Olding" -#define COPYRIGHT "MIT" -#define PARAMETERS 3 +#define BLOCK_SIZE 256 +#define OVERSAMPLING 2 +#define FULL_SIZE (BLOCK_SIZE*OVERSAMPLING) /* 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 */ -#define OVERSAMPLING 2 -#define BLOCK_SIZE 256 -#define FULL_SIZE (BLOCK_SIZE*OVERSAMPLING) - #include #include #include "util.hpp" -#include "param.hpp" +#include "Param.hpp" +#include "Crap.hpp" #include "os2piir.hpp" +#include "BufferOS2.hpp" #define VT 0.026 #define N 4 #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 { v2df sum, sumback, dout; } stage; @@ -43,25 +48,7 @@ typedef struct { v2df L_r1; } freqdata; -typedef struct { - ulong fs; - halfband_t 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; -} - +// TODO: namespace TEMPLATE INNER T process_stage(stage *s, freqdata fd, T in) { @@ -73,174 +60,135 @@ process_stage(stage *s, freqdata fd, T in) return out; } -TEMPLATE INNER T -process_one(T in, personal *data) -{ - freqdata fd = data->fd; +struct Crap_mugi4 +:public AdjustAll> { + static constexpr ulong id = 0xD8D0D8D0; + 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; - - T sum = in + data->sumback1; - T pre = -fd.p0*sum; - process_stage(&data->s1, fd, tanh2(pre/VT2)); - process_stage(&data->s2, fd, data->s1.dout); - process_stage(&data->s3, fd, data->s2.dout); - T out = process_stage(&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 -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 *hb_up = &data->hb_up; - halfband_t *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)); - memset(&data->hb_down, 0, sizeof(halfband_t)); -} - -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); + static constexpr ulong parameters = 3; freqdata fd; - #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); + stage s1, s2, s3, s4; + v2df sumback1, sumback2, sumback3, sumback4; + v2df drive, feedback; - 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); + inline + Crap_mugi4() + { + // FIXME + //memset(data, 0, sizeof(personal)); + } - fd_set(L_p0, 1/(1 + g)); - fd_set(L_q0, 1 - g); - fd_set(L_r1, -g); - #undef fd_set + TEMPLATE inline T + process_one(T in) + { + in *= drive; - data->fd = fd; -} + T sum = in + sumback1; + T pre = -fd.p0*sum; + process_stage(&s1, fd, tanh2(pre/VT2)); + process_stage(&s2, fd, s1.dout); + process_stage(&s3, fd, s2.dout); + T out = process_stage(&s4, fd, s3.dout); -INNER void -adjust_one(personal *data, param *params, unsigned int index) -{ - adjust(data, params, data->fs); -} + T back = feedback*out; + sumback1 = fd.r1*in + fd.q0*back + sumback2; + sumback2 = fd.r2*in + fd.q1*back + sumback3; + 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)); + memset(&hb_down, 0, sizeof(halfband_t)); + } + + 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[];