Unified · Split
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -25,23 +25,23 @@ extern "C" { · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | typedef struct _tLockhartWavefolder | 26 | typedef struct _tLockhartWavefolder |
| 27 | { | 27 | { |
| 28 | float Ln1; | 28 | double Ln1; |
| 29 | float Fn1; | 29 | double Fn1; |
| 30 | float xn1; | 30 | float xn1; |
| 31 | |||
| 32 | float RL; | ||
| 33 | float R; | ||
| 34 | float VT; | ||
| 35 | float Is; | ||
| 36 | 31 | ||
| 37 | float a; | 32 | double RL; |
| 38 | float b; | 33 | double R; |
| 39 | float d; | 34 | double VT; |
| 35 | double Is; | ||
| 36 | |||
| 37 | double a; | ||
| 38 | double b; | ||
| 39 | double d; | ||
| 40 | 40 | ||
| 41 | // Antialiasing error threshold | 41 | // Antialiasing error threshold |
| 42 | float thresh; | 42 | double thresh; |
| 43 | float half_a; | 43 | double half_a; |
| 44 | float longthing; | 44 | double longthing; |
| 45 | 45 | ||
| 46 | } _tLockhartWavefolder; | 46 | } _tLockhartWavefolder; |
| 47 | 47 | ||
| @@ -54,6 +54,27 @@ extern "C" { · 6 unmodified lines | |||
| 54 | 54 | ||
| 55 | //============================================================================== | 55 | //============================================================================== |
| 56 | 56 | ||
| 57 | |||
| 58 | |||
| 59 | typedef struct _tSampleReducer | ||
| 60 | { | ||
| 61 | float invRatio; | ||
| 62 | float hold; | ||
| 63 | uint32_t count; | ||
| 64 | } _tSampleReducer; | ||
| 65 | |||
| 66 | typedef _tSampleReducer* tSampleReducer; | ||
| 67 | |||
| 68 | void tSampleReducer_init (tSampleReducer* const); | ||
| 69 | void tSampleReducer_free (tSampleReducer* const); | ||
| 70 | |||
| 71 | float tSampleReducer_tick (tSampleReducer* const, float input); | ||
| 72 | |||
| 73 | // sampling ratio | ||
| 74 | void tSampleReducer_setRatio (tSampleReducer* const, float ratio); | ||
| 75 | |||
| 76 | //============================================================================== | ||
| 77 | |||
| 57 | typedef struct _tCrusher | 78 | typedef struct _tCrusher |
| 58 | { | 79 | { |
| 59 | float srr; | 80 | float srr; |
| @@ -63,6 +84,7 @@ extern "C" { · 3 unmodified lines | |||
| 63 | uint32_t op; //which bitwise operation (0-7) | 84 | uint32_t op; //which bitwise operation (0-7) |
| 64 | 85 | ||
| 65 | float gain; | 86 | float gain; |
| 87 | tSampleReducer sReducer; | ||
| 66 | 88 | ||
| 67 | } _tCrusher; | 89 | } _tCrusher; |
| 68 | 90 | ||
| @@ -85,7 +107,9 @@ extern "C" { · 16 unmodified lines | |||
| 85 | // sampling ratio | 107 | // sampling ratio |
| 86 | void tCrusher_setSamplingRatio (tCrusher* const, float ratio); | 108 | void tCrusher_setSamplingRatio (tCrusher* const, float ratio); |
| 87 | 109 | ||
| 110 | |||
| 88 | //============================================================================== | 111 | //============================================================================== |
| 112 | |||
| 89 | 113 | ||
| 90 | typedef struct _tOversampler | 114 | typedef struct _tOversampler |
| 91 | { | 115 | { |
Binary file not shown.
| @@ -16,11 +16,17 @@ · 15 unmodified lines | |||
| 16 | #include "../Inc/leaf-distortion.h" | 16 | #include "../Inc/leaf-distortion.h" |
| 17 | #include "../Inc/leaf-tables.h" | 17 | #include "../Inc/leaf-tables.h" |
| 18 | 18 | ||
| 19 | |||
| 19 | #endif | 20 | #endif |
| 20 | 21 | ||
| 21 | //============================================================================================================ | 22 | //============================================================================================================ |
| 22 | // WAVEFOLDER | 23 | // WAVEFOLDER |
| 23 | //============================================================================================================ | 24 | //============================================================================================================ |
| 25 | |||
| 26 | |||
| 27 | //from the paper: Virtual Analog Model of the Lockhart Wavefolder | ||
| 28 | //by Fabián Esqueda, Henri Pöntynen, Julian D. Parker and Stefan Bilbao | ||
| 29 | |||
| 24 | void tLockhartWavefolder_init(tLockhartWavefolder* const wf) | 30 | void tLockhartWavefolder_init(tLockhartWavefolder* const wf) |
| 25 | { | 31 | { |
| 26 | _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder)); | 32 | _tLockhartWavefolder* w = *wf = (_tLockhartWavefolder*) leaf_alloc(sizeof(_tLockhartWavefolder)); |
| @@ -37,9 +43,10 @@ void tLockhartWavefolder_init(tLockhartWavefolder* const wf) · 10 unmodified lines | |||
| 37 | w->a = 2.0*w->RL/w->R; | 43 | w->a = 2.0*w->RL/w->R; |
| 38 | w->b = (w->R+2.0*w->RL)/(w->VT*w->R); | 44 | w->b = (w->R+2.0*w->RL)/(w->VT*w->R); |
| 39 | w->d = (w->RL*w->Is)/w->VT; | 45 | w->d = (w->RL*w->Is)/w->VT; |
| 40 | w->half_a = 0.5f * w->a; | 46 | w->half_a = 0.5 * w->a; |
| 41 | w->longthing = (0.5*w->VT/w->b); | 47 | w->longthing = (0.5*w->VT/w->b); |
| 42 | 48 | ||
| 49 | |||
| 43 | // Antialiasing error threshold | 50 | // Antialiasing error threshold |
| 44 | w->thresh = 10e-10; | 51 | w->thresh = 10e-10; |
| 45 | } | 52 | } |
| @@ -55,28 +62,26 @@ double tLockhartWavefolderLambert(double x, double ln) · 9 unmodified lines | |||
| 55 | { | 62 | { |
| 56 | double thresh, w, expw, p, r, s, err; | 63 | double thresh, w, expw, p, r, s, err; |
| 57 | // Error threshold | 64 | // Error threshold |
| 58 | thresh = 10e-6; | 65 | thresh = 10e-10; |
| 59 | // Initial guess (use previous value) | 66 | // Initial guess (use previous value) |
| 60 | w = ln; | 67 | w = ln; |
| 61 | 68 | ||
| 62 | // Haley's method (Sec. 4.2 of the paper) | 69 | // Haley's method (Sec. 4.2 of the paper) |
| 63 | for(int i=0; i<100; i+=1) { | 70 | for(int i=0; i<1000; i+=1) { |
| 64 | 71 | ||
| 65 | expw = exp(w); | 72 | expw = exp(w); |
| 66 | 73 | ||
| 67 | p = w*expw - x; | 74 | p = w*expw - x; |
| 68 | r = (w+1.0)*expw; | 75 | r = (w+1.0)*expw; |
| 69 | s = (w+2.0)/(2.0*(w+1.0)); err = (p/(r-(p*s))); | 76 | s = (w+2.0)/(2.0*(w+1.0)); |
| 77 | err = (p/(r-(p*s))); | ||
| 70 | 78 | ||
| 71 | if (fabs(err)<thresh) { | 79 | if (fabs(err)<thresh) { |
| 72 | break; | 80 | break; |
| 73 | } | ||
| 74 | if (isnan(err)) | ||
| 75 | { | ||
| 76 | break; | ||
| 77 | } | 81 | } |
| 78 | 82 | ||
| 79 | w = w - err; | 83 | w = w - err; |
| 84 | |||
| 80 | } | 85 | } |
| 81 | return w; | 86 | return w; |
| 82 | } | 87 | } |
| @@ -86,11 +91,9 @@ float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp) · 3 unmodified lines | |||
| 86 | _tLockhartWavefolder* w = *wf; | 91 | _tLockhartWavefolder* w = *wf; |
| 87 | 92 | ||
| 88 | float out = 0.0f; | 93 | float out = 0.0f; |
| 89 | // Constants | ||
| 90 | |||
| 91 | 94 | ||
| 92 | // Compute Antiderivative | 95 | // Compute Antiderivative |
| 93 | int l = (samp > 0) - (samp < 0); | 96 | int l = (samp > 0.0f) - (samp < 0.0f); |
| 94 | double u = w->d*exp(l*w->b*samp); | 97 | double u = w->d*exp(l*w->b*samp); |
| 95 | double Ln = tLockhartWavefolderLambert(u,w->Ln1); | 98 | double Ln = tLockhartWavefolderLambert(u,w->Ln1); |
| 96 | double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp; | 99 | double Fn = w->longthing*(Ln*(Ln + 2.0)) - w->half_a*samp*samp; |
| @@ -99,24 +102,16 @@ float tLockhartWavefolder_tick(tLockhartWavefolder* const wf, float samp) · 2 unmodified lines | |||
| 99 | if (fabs(samp-w->xn1)<w->thresh) { | 102 | if (fabs(samp-w->xn1)<w->thresh) { |
| 100 | 103 | ||
| 101 | // Compute Averaged Wavefolder Output | 104 | // Compute Averaged Wavefolder Output |
| 102 | double xn = 0.5*(samp+w->xn1); | 105 | float xn = 0.5f*(samp+w->xn1); |
| 103 | u = w->d*exp(l*w->b*xn); | 106 | u = w->d*exp(l*w->b*xn); |
| 104 | Ln = tLockhartWavefolderLambert(u,w->Ln1); | 107 | Ln = tLockhartWavefolderLambert(u,w->Ln1); |
| 105 | out = (float) (l*w->VT*Ln - w->a*xn); | 108 | out = (float) (l*w->VT*Ln - w->a*xn); |
| 106 | if (isnan(out)) | ||
| 107 | { | ||
| 108 | ; | ||
| 109 | } | ||
| 110 | 109 | ||
| 111 | } | 110 | } |
| 112 | else { | 111 | else { |
| 113 | 112 | ||
| 114 | // Apply AA Form | 113 | // Apply AA Form |
| 115 | out = (float) ((Fn-w->Fn1)/(samp-w->xn1)); | 114 | out = (float) ((Fn-w->Fn1)/(samp-w->xn1)); |
| 116 | if (isnan(out)) | ||
| 117 | { | ||
| 118 | ; | ||
| 119 | } | ||
| 120 | } | 115 | } |
| 121 | 116 | ||
| 122 | // Update States | 117 | // Update States |
| @@ -140,14 +135,14 @@ void tCrusher_init (tCrusher* const cr) · 17 unmodified lines | |||
| 140 | c->div = SCALAR; | 135 | c->div = SCALAR; |
| 141 | c->rnd = 0.25f; | 136 | c->rnd = 0.25f; |
| 142 | c->srr = 0.25f; | 137 | c->srr = 0.25f; |
| 143 | 138 | tSampleReducer_init(&c->sReducer); | |
| 144 | c->gain = (c->div / SCALAR) * 0.7f + 0.3f; | 139 | c->gain = (c->div / SCALAR) * 0.7f + 0.3f; |
| 145 | } | 140 | } |
| 146 | 141 | ||
| 147 | void tCrusher_free (tCrusher* const cr) | 142 | void tCrusher_free (tCrusher* const cr) |
| 148 | { | 143 | { |
| 149 | _tCrusher* c = *cr; | 144 | _tCrusher* c = *cr; |
| 150 | 145 | tSampleReducer_free(&c->sReducer); | |
| 151 | leaf_free(c); | 146 | leaf_free(c); |
| 152 | } | 147 | } |
| 153 | 148 | ||
| @@ -169,7 +164,7 @@ float tCrusher_tick (tCrusher* const cr, float input) · 15 unmodified lines | |||
| 169 | 164 | ||
| 170 | sample = LEAF_round(sample, c->rnd); | 165 | sample = LEAF_round(sample, c->rnd); |
| 171 | 166 | ||
| 172 | sample = LEAF_reduct(sample, c->srr); | 167 | sample = tSampleReducer_tick(&c->sReducer, sample); |
| 173 | 168 | ||
| 174 | return sample * c->gain; | 169 | return sample * c->gain; |
| 175 | 170 | ||
| @@ -204,8 +199,55 @@ void tCrusher_setSamplingRatio (tCrusher* const cr, float ratio) · 28 unmodified lines | |||
| 204 | { | 199 | { |
| 205 | _tCrusher* c = *cr; | 200 | _tCrusher* c = *cr; |
| 206 | c->srr = ratio; | 201 | c->srr = ratio; |
| 202 | tSampleReducer_setRatio(&c->sReducer, ratio); | ||
| 203 | |||
| 207 | } | 204 | } |
| 208 | 205 | ||
| 206 | //============================================================================================================ | ||
| 207 | // Sample-Rate reducer | ||
| 208 | //============================================================================================================ | ||
| 209 | |||
| 210 | |||
| 211 | void tSampleReducer_init(tSampleReducer* const sr) | ||
| 212 | { | ||
| 213 | _tSampleReducer* s = *sr = (_tSampleReducer*) leaf_alloc(sizeof(_tSampleReducer)); | ||
| 214 | |||
| 215 | |||
| 216 | |||
| 217 | s->invRatio = 1.0f; | ||
| 218 | s->hold = 0.0f; | ||
| 219 | s->count = 0; | ||
| 220 | |||
| 221 | } | ||
| 222 | |||
| 223 | void tSampleReducer_free (tSampleReducer* const sr) | ||
| 224 | { | ||
| 225 | _tSampleReducer* s = *sr; | ||
| 226 | |||
| 227 | leaf_free(s); | ||
| 228 | } | ||
| 229 | |||
| 230 | float tSampleReducer_tick(tSampleReducer* const sr, float input) | ||
| 231 | { | ||
| 232 | _tSampleReducer* s = *sr; | ||
| 233 | if (s->count > s->invRatio) | ||
| 234 | { | ||
| 235 | s->hold = input; | ||
| 236 | s->count = 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | s->count++; | ||
| 240 | return s->hold; | ||
| 241 | } | ||
| 242 | |||
| 243 | |||
| 244 | void tSampleReducer_setRatio(tSampleReducer* const sr, float ratio) | ||
| 245 | { | ||
| 246 | _tSampleReducer* s = *sr; | ||
| 247 | if ((ratio <= 1.0f) && (ratio >= 0.0f)) | ||
| 248 | s->invRatio = 1.0f / ratio; | ||
| 249 | |||
| 250 | } | ||
| 209 | 251 | ||
| 210 | //============================================================================================================ | 252 | //============================================================================================================ |
| 211 | // Oversampler | 253 | // Oversampler |
| @@ -411,7 +453,7 @@ float tOversampler_downsample(tOversampler *const osr, float* input) · 199 unmodified lines | |||
| 411 | output = acc0; | 453 | output = acc0; |
| 412 | 454 | ||
| 413 | /* Processing is complete. | 455 | /* Processing is complete. |
| 414 | Now copy the last numTaps - 1 samples to the satrt of the state buffer. | 456 | Now copy the last numTaps - 1 samples to the start of the state buffer. |
| 415 | This prepares the state buffer for the next function call. */ | 457 | This prepares the state buffer for the next function call. */ |
| 416 | 458 | ||
| 417 | /* Points to the start of the state buffer */ | 459 | /* Points to the start of the state buffer */ |
| @@ -165,23 +165,6 @@ float LEAF_shaper(float input, float m_drive) · 164 unmodified lines | |||
| 165 | return shaperOut; | 165 | return shaperOut; |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | // reduce sample resolution | ||
| 169 | float hold = 0.f; | ||
| 170 | int reduct_count = 0; | ||
| 171 | |||
| 172 | |||
| 173 | float LEAF_reduct (float input, float ratio) | ||
| 174 | { | ||
| 175 | reduct_count++; | ||
| 176 | if (reduct_count > 1.f / ratio) | ||
| 177 | { | ||
| 178 | hold = input; | ||
| 179 | reduct_count = 0; | ||
| 180 | } | ||
| 181 | |||
| 182 | return hold; | ||
| 183 | } | ||
| 184 | |||
| 185 | // round input to nearest rnd | 168 | // round input to nearest rnd |
| 186 | float LEAF_round (float input, float rnd) | 169 | float LEAF_round (float input, float rnd) |
| 187 | { | 170 | { |
| @@ -270,12 +253,12 @@ oBool LEAF_isPrime(uint64_t number ) · 82 unmodified lines | |||
| 270 | float LEAF_tanh(float x) | 253 | float LEAF_tanh(float x) |
| 271 | { | 254 | { |
| 272 | 255 | ||
| 273 | if( x < -3 ) | 256 | if( x < -3.0f ) |
| 274 | return -1; | 257 | return -1.0f; |
| 275 | else if( x > 3 ) | 258 | else if( x > 3.0f ) |
| 276 | return 1; | 259 | return 1.0f; |
| 277 | else | 260 | else |
| 278 | return x * ( 27 + x * x ) / ( 27 + 9 * x * x ); | 261 | return x * ( 27.0f + x * x ) / ( 27.0f + 9.0f * x * x ); |
| 279 | } | 262 | } |
| 280 | 263 | ||
| 281 | 264 | ||