History

added float tTalkbox

spiricom committed 6 years ago

Commit a3ed8621 parent 77f3ac510 files · +881 −117Browse files

Unified · Split

10 files
  1. leaf/Inc/leaf-effects.h +64 −18
  2. leaf/Inc/leaf-math.h +2 −0
  3. leaf/Inc/leaf-physical.h +48 −0
  4. leaf/Inc/leaf-sampling.h +3 −0
  5. leaf/Src/leaf-analysis.c +11 −4
  6. leaf/Src/leaf-effects.c +464 −80
  7. leaf/Src/leaf-math.c +17 −6
  8. leaf/Src/leaf-physical.c +246 −0
  9. leaf/Src/leaf-sampling.c +25 −8
  10. leaf/Src/leaf-tables.c +1 −1
leaf/Inc/leaf-effects.h+64−18
@@ -1,8 +1,7 @@
1/*==============================================================================1/*==============================================================================
2 2
3 leaf-effects.h3 leaf-effects.h
4 Created: 20 Jan 2017 12:01:54pm4
5 Author: Michael R Mulshine
6 5
7 ==============================================================================*/6 ==============================================================================*/
8 7
@@ -21,14 +20,8 @@ extern "C" { · 12 unmodified lines
21#include "leaf-analysis.h"20#include "leaf-analysis.h"
22#include "leaf-envelopes.h"21#include "leaf-envelopes.h"
23 22
24 /*!23
25 * @internal24
26 * Header.
27 * @include basic-oscillators.h
28 * @example basic-oscillators.c
29 * An example.
30 */
31
32 //==============================================================================25 //==============================================================================
33 26
34 /* tTalkbox */27 /* tTalkbox */
@@ -37,23 +30,23 @@ extern "C" { · 2 unmodified lines
37 typedef struct _tTalkbox30 typedef struct _tTalkbox
38 {31 {
39 float param[NUM_TALKBOX_PARAM];32 float param[NUM_TALKBOX_PARAM];
40 33
41 int bufsize;34 int bufsize;
42 float* car0;35 float* car0;
43 float* car1;36 float* car1;
44 float* window;37 float* window;
45 float* buf0;38 float* buf0;
46 float* buf1;39 float* buf1;
47 40 float* k;
48 float warpFactor;41 float warpFactor;
49 int32_t warpOn;42 int32_t warpOn;
50 43 int freeze;
51 float emphasis;44 float emphasis;
52 int32_t K, N, O, pos;45 int32_t K, N, O, pos;
53 float wet, dry, FX;46 float wet, dry, FX;
54 float d0, d1, d2, d3, d4;47 float d0, d1, d2, d3, d4;
55 float u0, u1, u2, u3, u4;48 float u0, u1, u2, u3, u4;
56 49 float G;
57 double* dl;50 double* dl;
58 double* Rt;51 double* Rt;
59 52
@@ -68,16 +61,69 @@ extern "C" { · 8 unmodified lines
68 void tTalkbox_freeFromPool (tTalkbox* const, tMempool* const);61 void tTalkbox_freeFromPool (tTalkbox* const, tMempool* const);
69 62
70 float tTalkbox_tick (tTalkbox* const, float synth, float voice);63 float tTalkbox_tick (tTalkbox* const, float synth, float voice);
64 float tTalkbox_tickFrozen (tTalkbox* const voc, float synth, float voice);
71 void tTalkbox_update (tTalkbox* const);65 void tTalkbox_update (tTalkbox* const);
72 void tTalkbox_suspend (tTalkbox* const);66 void tTalkbox_suspend (tTalkbox* const);
73 void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);67 void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);
74 void tTalkbox_lpc (float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn);68 void tTalkbox_lpc (float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G);
75 void tTalkbox_setQuality (tTalkbox* const, float quality);69 void tTalkbox_setQuality (tTalkbox* const, float quality);
76 void tTalkbox_setWarpFactor (tTalkbox* const voc, float warp);70 void tTalkbox_setWarpFactor (tTalkbox* const voc, float warp);
77 void tTalkbox_setWarpOn (tTalkbox* const voc, float warpOn);71 void tTalkbox_setWarpOn (tTalkbox* const voc, float warpOn);
72 void tTalkbox_setFreeze (tTalkbox* const voc, float freeze);
78 void tTalkbox_warpedAutocorrelate (float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda);73 void tTalkbox_warpedAutocorrelate (float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda);
79 //==============================================================================74 //==============================================================================
80 75
76
77 ///////
78
79 typedef struct _tTalkboxFloat
80 {
81 float param[NUM_TALKBOX_PARAM];
82
83 int bufsize;
84 float* car0;
85 float* car1;
86 float* window;
87 float* buf0;
88 float* buf1;
89 float* k;
90 float warpFactor;
91 int32_t warpOn;
92 int freeze;
93 float emphasis;
94 int32_t K, N, O, pos;
95 float wet, dry, FX;
96 float d0, d1, d2, d3, d4;
97 float u0, u1, u2, u3, u4;
98 float G;
99 float* dl;
100 float* Rt;
101
102
103 } _tTalkboxFloat;
104
105 typedef _tTalkboxFloat* tTalkboxFloat;
106
107 void tTalkboxFloat_init (tTalkboxFloat* const, int bufsize);
108 void tTalkboxFloat_free (tTalkboxFloat* const);
109 void tTalkboxFloat_initToPool (tTalkboxFloat* const, int bufsize, tMempool* const);
110 void tTalkboxFloat_freeFromPool (tTalkboxFloat* const, tMempool* const);
111
112 float tTalkboxFloat_tick (tTalkboxFloat* const, float synth, float voice);
113 float tTalkboxFloat_tickFrozen (tTalkboxFloat* const voc, float synth, float voice);
114 void tTalkboxFloat_update (tTalkboxFloat* const);
115 void tTalkboxFloat_suspend (tTalkboxFloat* const);
116 void tTalkboxFloat_lpcDurbin (float *r, int p, float *k, float *g);
117 void tTalkboxFloat_lpc (float *buf, float *car, float* dl, float* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G);
118 void tTalkboxFloat_setQuality (tTalkboxFloat* const, float quality);
119 void tTalkboxFloat_setWarpFactor (tTalkboxFloat* const voc, float warp);
120 void tTalkboxFloat_setWarpOn (tTalkboxFloat* const voc, float warpOn);
121 void tTalkboxFloat_setFreeze (tTalkboxFloat* const voc, float freeze);
122 void tTalkboxFloat_warpedAutocorrelate (float * x, float* dl, float* Rt, unsigned int L, float * R, unsigned int P, float lambda);
123 //==============================================================================
124
125
126
81 /* tVocoder */127 /* tVocoder */
82#define NUM_VOCODER_PARAM 8128#define NUM_VOCODER_PARAM 8
83#define NBANDS 16129#define NBANDS 16
@@ -132,7 +178,7 @@ extern "C" { · 48 unmodified lines
132 void tRosenbergGlottalPulse_freeFromPool (tRosenbergGlottalPulse* const, tMempool* const);178 void tRosenbergGlottalPulse_freeFromPool (tRosenbergGlottalPulse* const, tMempool* const);
133 179
134 float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const);180 float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const);
135 181 float tRosenbergGlottalPulse_tickHQ (tRosenbergGlottalPulse* const gp);
136 void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const, float freq);182 void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const, float freq);
137 183
138 void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const, float openLength);184 void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const, float openLength);
@@ -284,7 +330,7 @@ extern "C" { · 145 unmodified lines
284 float radius;330 float radius;
285 331
286 float inputPeriod;332 float inputPeriod;
287 333 int shiftOn;
288 int numVoices;334 int numVoices;
289 } _tAutotune;335 } _tAutotune;
290 336
leaf/Inc/leaf-math.h+2−0
@@ -204,6 +204,8 @@ extern "C" { · 203 unmodified lines
204 204
205 float fastdbtoa(float db);205 float fastdbtoa(float db);
206 206
207 float fasterdbtoa(float db);
208
207 float maximum (float num1, float num2);209 float maximum (float num1, float num2);
208 210
209 float minimum (float num1, float num2);211 float minimum (float num1, float num2);
leaf/Inc/leaf-physical.h+48−0
@@ -228,7 +228,55 @@ extern "C" { · 227 unmodified lines
228 void tLivingString_setLevStrength (tLivingString* const, float levStrength);228 void tLivingString_setLevStrength (tLivingString* const, float levStrength);
229 void tLivingString_setLevMode (tLivingString* const, int levMode);229 void tLivingString_setLevMode (tLivingString* const, int levMode);
230 230
231
232
233 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
234
235 /* Complex Living String */
236 typedef struct _tComplexLivingString {
237 float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length
238 float pickPos; // the pick position, dividing the string, in ratio
239 float prepPos; // preparation position, in ratio
240 int prepLower;
241 float prepIndex; // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj)
242 float dampFreq; // frequency for the bridge LP filter, in Hz
243 float decay; // amplitude damping factor for the string (only active in mode 0)
244 float levMode;
245 float curr;
246 tLinearDelay delLF,delUF, delMF, delMB, delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model
247 tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL;
248 tHighpass DCblockerL, DCblockerU;
249 tFeedbackLeveler fbLevU, fbLevL;
250 tExpSmooth wlSmooth, pickPosSmooth, prepPosSmooth;
251 } _tComplexLivingString;
252
253 typedef _tComplexLivingString* tComplexLivingString;
254
255 void tComplexLivingString_init (tComplexLivingString* const, float freq, float pickPos, float prepPos, float prepIndex,
256 float dampFreq, float decay, float targetLev, float levSmoothFactor,
257 float levStrength, int levMode);
258 void tComplexLivingString_free (tComplexLivingString* const);
259 void tComplexLivingString_initToPool (tComplexLivingString* const, float freq, float pickPos, float prepPos, float prepIndex,
260 float dampFreq, float decay, float targetLev, float levSmoothFactor,
261 float levStrength, int levMode, tMempool* const);
262 void tComplexLivingString_freeFromPool (tComplexLivingString* const, tMempool* const);
263
264 float tComplexLivingString_tick (tComplexLivingString* const, float input);
265 float tComplexLivingString_sample (tComplexLivingString* const);
266 void tComplexLivingString_setFreq (tComplexLivingString* const, float freq);
267 void tComplexLivingString_setWaveLength (tComplexLivingString* const, float waveLength); // in samples
268 void tComplexLivingString_setPickPos (tComplexLivingString* const, float pickPos);
269 void tComplexLivingString_setPrepPos (tComplexLivingString* const, float prepPos);
270 void tComplexLivingString_setPrepIndex (tComplexLivingString* const, float prepIndex);
271 void tComplexLivingString_setDampFreq (tComplexLivingString* const, float dampFreq);
272 void tComplexLivingString_setDecay (tComplexLivingString* const, float decay); // should be near 1.0
273 void tComplexLivingString_setTargetLev (tComplexLivingString* const, float targetLev);
274 void tComplexLivingString_setLevSmoothFactor (tComplexLivingString* const, float levSmoothFactor);
275 void tComplexLivingString_setLevStrength (tComplexLivingString* const, float levStrength);
276 void tComplexLivingString_setLevMode (tComplexLivingString* const, int levMode);
231 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~277 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
278
279
232 280
233 //Reed Table - borrowed from STK281 //Reed Table - borrowed from STK
234 typedef struct _tReedTable {282 typedef struct _tReedTable {
leaf/Inc/leaf-sampling.h+3−0
@@ -69,6 +69,7 @@ extern "C" { · 68 unmodified lines
69 void tBuffer_record (tBuffer* const);69 void tBuffer_record (tBuffer* const);
70 void tBuffer_stop (tBuffer* const);70 void tBuffer_stop (tBuffer* const);
71 int tBuffer_getRecordPosition (tBuffer* const);71 int tBuffer_getRecordPosition (tBuffer* const);
72 void tBuffer_setRecordPosition (tBuffer* const, int pos);
72 73
73 void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);74 void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
74 75
@@ -76,6 +77,8 @@ extern "C" { · 1 unmodified line
76 77
77 uint32_t tBuffer_getBufferLength (tBuffer* const);78 uint32_t tBuffer_getBufferLength (tBuffer* const);
78 uint32_t tBuffer_getRecordedLength (tBuffer* const sb);79 uint32_t tBuffer_getRecordedLength (tBuffer* const sb);
80 void tBuffer_setRecordedLength (tBuffer* const sb, int length);
81 int tBuffer_isActive (tBuffer* const sb);
79 82
80 //==============================================================================83 //==============================================================================
81 84
leaf/Src/leaf-analysis.c+11−4
@@ -62,8 +62,10 @@ float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x) · 61 unmodified lines
62 //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?62 //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?
63 //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff; // too expensive63 //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff; // too expensive
64 64
65#ifdef NO_DENORMAL_CHECK
66#else
65 if( e->y < VSF) e->y = 0.0f;67 if( e->y < VSF) e->y = 0.0f;
66 68#endif
67 return e->y;69 return e->y;
68}70}
69 71
@@ -887,7 +889,10 @@ void tPeriodDetection_initToPool (tPeriodDetection* const pd, float* in, flo · 817 unmodified lines
887 tEnvPD_initToPool(&p->env, p->windowSize, p->hopSize, p->frameSize, mp);889 tEnvPD_initToPool(&p->env, p->windowSize, p->hopSize, p->frameSize, mp);
888 890
889 tSNAC_initToPool(&p->snac, DEFOVERLAP, mp);891 tSNAC_initToPool(&p->snac, DEFOVERLAP, mp);
890 892
893 p->history = 0.0f;
894 p->alpha = 1.0f;
895 p->tolerance = 1.0f;
891 p->timeConstant = DEFTIMECONSTANT;896 p->timeConstant = DEFTIMECONSTANT;
892 p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);897 p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
893 p->fidelityThreshold = 0.95;898 p->fidelityThreshold = 0.95;
@@ -928,14 +933,16 @@ float tPeriodDetection_tick (tPeriodDetection* pd, float sample) · 34 unmodified lines
928 tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);933 tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
929 float fidelity = tSNAC_getFidelity(&p->snac);934 float fidelity = tSNAC_getFidelity(&p->snac);
930 // Fidelity threshold recommended by Katja Vetters is 0.95 for most instruments/voices http://www.katjaas.nl/helmholtz/helmholtz.html935 // Fidelity threshold recommended by Katja Vetters is 0.95 for most instruments/voices http://www.katjaas.nl/helmholtz/helmholtz.html
931 if (fidelity > p->fidelityThreshold) p->period = tSNAC_getPeriod(&p->snac);936 if (fidelity > p->fidelityThreshold)
937 {
938 p->period = tSNAC_getPeriod(&p->snac);
939 }
932 940
933 p->curBlock++;941 p->curBlock++;
934 if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;942 if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
935 p->lastBlock++;943 p->lastBlock++;
936 if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;944 if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
937 }945 }
938
939 return p->period;946 return p->period;
940}947}
941 948
leaf/Src/leaf-effects.c+464−80
@@ -25,6 +25,13 @@ · 24 unmodified lines
25//============================================================================================================25//============================================================================================================
26 26
27//LPC vocoder adapted from MDA's excellent open source talkbox plugin code27//LPC vocoder adapted from MDA's excellent open source talkbox plugin code
28
29#define ORD_MAX 34 // Was 100.
30// order is defined by the set_quality function.
31// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24.
32// -JS
33
34
28void tTalkbox_init(tTalkbox* const voc, int bufsize)35void tTalkbox_init(tTalkbox* const voc, int bufsize)
29{36{
30 tTalkbox_initToPool(voc, bufsize, &leaf.mempool);37 tTalkbox_initToPool(voc, bufsize, &leaf.mempool);
@@ -47,7 +54,8 @@ void tTalkbox_initToPool (tTalkbox* const voc, int bufsize, tMempool* con · 16 unmodified lines
47 v->warpFactor = 0.0f;54 v->warpFactor = 0.0f;
48 v->warpOn = 0;55 v->warpOn = 0;
49 v->bufsize = bufsize;56 v->bufsize = bufsize;
50 57 v->freeze = 0;
58 v->G = 0.0f;
51 v->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);59 v->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
52 v->car1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);60 v->car1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
53 v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);61 v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
@@ -56,7 +64,9 @@ void tTalkbox_initToPool (tTalkbox* const voc, int bufsize, tMempool* con · 2 unmodified lines
56 64
57 v->dl = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);65 v->dl = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);
58 v->Rt = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);66 v->Rt = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);
59 67
68 v->k = (float*) mpool_alloc(sizeof(float) * ORD_MAX, m);
69
60 tTalkbox_update(voc);70 tTalkbox_update(voc);
61 tTalkbox_suspend(voc);71 tTalkbox_suspend(voc);
62}72}
@@ -74,7 +84,7 @@ void tTalkbox_freeFromPool (tTalkbox* const voc, tMempool* const mp) · 11 unmodified lines
74 84
75 mpool_free((char*)v->dl, m);85 mpool_free((char*)v->dl, m);
76 mpool_free((char*)v->Rt, m);86 mpool_free((char*)v->Rt, m);
77 87 mpool_free((char*)v->k, m);
78 mpool_free((char*)v, m);88 mpool_free((char*)v, m);
79}89}
80 90
@@ -132,89 +142,173 @@ void tTalkbox_suspend(tTalkbox* const voc) ///clear any buffers... · 51 unmodified lines
132//wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0);142//wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0);
133void tTalkbox_warpedAutocorrelate(float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda)143void tTalkbox_warpedAutocorrelate(float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda)
134{144{
135// double dl[L];
136// double Rt[L];
137 double r1,r2,r1t;145 double r1,r2,r1t;
138 R[0]=0;146 R[0]=0;
139 Rt[0]=0;147 Rt[0]=0;
140 r1=0;148 r1=0;
141 r2=0;149 r2=0;
142 r1t=0;150 r1t=0;
143 for(int32_t k=0; k<L;k++)151 for(uint32_t m=0; m<L;m++)
144 {152 {
145 Rt[0] += (double)(x[k]) * (double)(x[k]);153 Rt[0] += (double)(x[m]) * (double)(x[m]);
146 154
147 dl[k]= r1 - (double)(lambda) * (double)(x[k]-r2);155 dl[m]= r1 - (double)(lambda) * (double)(x[m]-r2);
148 r1 = x[k];156 r1 = x[m];
149 r2 = dl[k];157 r2 = dl[m];
150 }158 }
151 for(int32_t i=1; i<=P; i++)159 for(uint32_t i=1; i<=P; i++)
152 {160 {
153 Rt[i]=0;161 Rt[i]=0;
154 r1=0;162 r1=0;
155 r2=0;163 r2=0;
156 for(unsigned int k=0; k<L;k++)164 for(unsigned int m=0; m<L;m++)
157 {165 {
158 Rt[i] += (double) (dl[k]) * (double)(x[k]);166 Rt[i] += (double) (dl[m]) * (double)(x[m]);
159 167
160 r1t = dl[k];168 r1t = dl[m];
161 dl[k]= r1 - (double)(lambda) * (double)(r1t-r2);169 dl[m]= r1 - (double)(lambda) * (double)(r1t-r2);
162 r1 = r1t;170 r1 = r1t;
163 r2 = dl[k];171 r2 = dl[m];
164 }172 }
165 }173 }
166 for(int32_t i=0; i<=P; i++)174 for(uint32_t i=0; i<=P; i++)
167 {175 {
168 R[i]=(float)(Rt[i]);176 R[i]=(float)(Rt[i]);
169 }177 }
170 178
171}179}
172 180
173 181void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
174
175#define ORD_MAX 35 // Was 100.
176// order is defined by the set_quality function.
177// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24.
178// -JS
179void tTalkbox_lpc(float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn)
180{182{
181 float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;183 int i, j;
182 int32_t i, j, nn=n;184 float a[ORD_MAX], at[ORD_MAX], e=r[0];
183 185
184 if (warpOn == 0)186 for(i=0; i<=p; i++)
185 {187 {
186 for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed188 a[i] = 0.0f; //probably don't need to clear at[] or k[]
187 {
188 z[j] = r[j] = 0.0f;
189 for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
190 }
191 }189 }
192 else190 k[0] = 0.0f;
191 at[0] = 0.0f;
192 for(i=1; i<=p; i++)
193 {193 {
194 for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed194 k[i] = -r[i];
195
196 for(j=1; j<i; j++)
195 {197 {
196 z[j] = r[j] = 0.0f;198 at[j] = a[j];
199 k[i] -= a[j] * r[i-j];
197 }200 }
198 tTalkbox_warpedAutocorrelate(buf, dl, Rt, n, r, o, warp);201 if(fabs(e) < 1.0e-20f) { e = 0.0f; break; }
202 k[i] /= e;
203
204 a[i] = k[i];
205 for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
206
207 e *= 1.0f - k[i] * k[i];
199 }208 }
200 209
201 r[0] *= 1.001f; //stability fix210 if(e < 1.0e-20f) e = 0.0f;
211 *g = sqrtf(e);
212}
213
214float tTalkbox_tick(tTalkbox* const voc, float synth, float voice)
215{
216 _tTalkbox* v = *voc;
202 217
203 float min = 0.00001f;218 int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
204 if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; }219 float e=v->emphasis, w, o, x, fx=v->FX;
220 float p, q, h0=0.3f, h1=0.77f;
205 221
206 tTalkbox_lpcDurbin(r, o, k, &G); //calc reflection coeffs222 o = voice;
223 x = synth;
224
225
226
227 p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p;
228 q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q;
229 v->d4 = x;
230 x = p + q;
207 231
208 //this is for stability to keep reflection coefficients inside the unit circle232 if(v->K++)
209 //but in Harma's papers I've seen 0.998. just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS
210 for(i=0; i<=o; i++)
211 {233 {
212 if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;234 v->K = 0;
235
236 v->car0[p0] = v->car1[p1] = x; //carrier input
237
238 x = o - e; e = o; //6dB/oct pre-emphasis
239
240 w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows
241 if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G); p0 = 0; }
242
243 w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w;
244 if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G); p1 = 0; }
213 }245 }
214 246
247 p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p;
248 q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q;
249 v->u4 = fx;
250 x = p + q;
251
252 o = x;
253
254 v->emphasis = e;
255 v->pos = p0;
256 v->FX = fx;
257
258
259 return o;
260}
261
262
263void tTalkbox_lpc(float *buf, float *car, double* dl, double* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G)
264{
265 float z[ORD_MAX], r[ORD_MAX], x;
266 int32_t i, j, nn=n;
267
268
269 if (warpOn == 0)
270 {
271 for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
272 {
273 z[j] = r[j] = 0.0f;
274 for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
275 }
276 }
277 else
278 {
279 for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
280 {
281 z[j] = r[j] = 0.0f;
282 }
283 tTalkbox_warpedAutocorrelate(buf, dl, Rt, n, r, o, warp);
284 }
285
286 r[0] *= 1.001f; //stability fix
287
288 float min = 0.000001f;
289 if (!freeze)
290 {
291 if(r[0] < min)
292 {
293 for(i=0; i<n; i++)
294 {
295 buf[i] = 0.0f;
296 return;
297 }
298 }
299
300 tTalkbox_lpcDurbin(r, o, k, G); //calc reflection coeffs
301
302 //this is for stability to keep reflection coefficients inside the unit circle
303 //in mda's code it's .995 but in Harma's papers I've seen 0.998. just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS
304 for(i=0; i<=o; i++)
305 {
306 if(k[i] > 0.998f) k[i] = 0.998f; else if(k[i] < -0.998f) k[i] = -.998f;
307 }
308 }
215 for(i=0; i<n; i++)309 for(i=0; i<n; i++)
216 {310 {
217 x = G * car[i];311 x = G[0] * car[i];
218 for(j=o; j>0; j--) //lattice filter312 for(j=o; j>0; j--) //lattice filter
219 {313 {
220 x -= k[j] * z[j-1];314 x -= k[j] * z[j-1];
@@ -224,18 +318,213 @@ void tTalkbox_lpc(float *buf, float *car, double* dl, double* Rt, int32_t n, int · 3 unmodified lines
224 }318 }
225}319}
226 320
321void tTalkbox_setQuality(tTalkbox* const voc, float quality)
322{
323 _tTalkbox* v = *voc;
324 v->param[3] = quality;
325 v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
326 if (v->O >= ORD_MAX)
327 {
328 v->O = ORD_MAX-1;
329 }
330}
227 331
228void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)332void tTalkbox_setWarpFactor(tTalkbox* const voc, float warpFactor)
333{
334 _tTalkbox* v = *voc;
335
336 v->warpFactor = warpFactor;
337}
338
339void tTalkbox_setWarpOn(tTalkbox* const voc, float warpOn)
340{
341 _tTalkbox* v = *voc;
342
343 v->warpOn = warpOn;
344}
345
346void tTalkbox_setFreeze(tTalkbox* const voc, float freeze)
347{
348 _tTalkbox* v = *voc;
349
350 v->freeze = freeze;
351}
352
353
354
355////
356
357// LPC vocoder adapted from MDA's excellent open source talkbox plugin code
358// order is defined by the set_quality function.
359// it's set to max out at 0.0005 of sample rate (if you don't go above 1.0f in the quality setting) == at 48000 that's 24.
360
361//the "float" version has no double calculations for faster computation on single-precision FPUs
362
363// -JS
364
365
366void tTalkboxFloat_init(tTalkboxFloat* const voc, int bufsize)
367{
368 tTalkboxFloat_initToPool(voc, bufsize, &leaf.mempool);
369}
370
371void tTalkboFloat_free(tTalkboxFloat* const voc)
372{
373 tTalkboxFloat_freeFromPool(voc, &leaf.mempool);
374}
375
376void tTalkboxFloat_initToPool (tTalkboxFloat* const voc, int bufsize, tMempool* const mp)
377{
378 _tMempool* m = *mp;
379 _tTalkboxFloat* v = *voc = (_tTalkboxFloat*) mpool_alloc(sizeof(_tTalkboxFloat), m);
380
381 v->param[0] = 0.5f; //wet
382 v->param[1] = 0.0f; //dry
383 v->param[2] = 0; // Swap
384 v->param[3] = 1.0f; //quality
385 v->warpFactor = 0.0f;
386 v->warpOn = 0;
387 v->bufsize = bufsize;
388 v->freeze = 0;
389 v->G = 0.0f;
390 v->car0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
391 v->car1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
392 v->window = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
393 v->buf0 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
394 v->buf1 = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
395
396 v->dl = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
397 v->Rt = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
398
399 v->k = (float*) mpool_alloc(sizeof(float) * ORD_MAX, m);
400
401 tTalkboxFloat_update(voc);
402 tTalkboxFloat_suspend(voc);
403}
404
405void tTalkboxFloat_freeFromPool (tTalkboxFloat* const voc, tMempool* const mp)
406{
407 _tMempool* m = *mp;
408 _tTalkboxFloat* v = *voc;
409
410 mpool_free((char*)v->buf1, m);
411 mpool_free((char*)v->buf0, m);
412 mpool_free((char*)v->window, m);
413 mpool_free((char*)v->car1, m);
414 mpool_free((char*)v->car0, m);
415
416 mpool_free((char*)v->dl, m);
417 mpool_free((char*)v->Rt, m);
418 mpool_free((char*)v->k, m);
419 mpool_free((char*)v, m);
420}
421
422void tTalkboxFloat_update(tTalkboxFloat* const voc) ///update internal parameters...
423{
424 _tTalkboxFloat* v = *voc;
425
426 float fs = leaf.sampleRate;
427 if(fs < 8000.0f) fs = 8000.0f;
428 if(fs > 96000.0f) fs = 96000.0f;
429
430 int32_t n = (int32_t)(0.01633f * fs); //this sets the window time to 16ms if the buffer is large enough. Buffer needs to be at least 784 samples at 48000
431 if(n > v->bufsize) n = v->bufsize;
432
433 //O = (VstInt32)(0.0005f * fs);
434 v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs);
435
436 if(n != v->N) //recalc hanning window
437 {
438 v->N = n;
439 float dp = TWO_PI / v->N;
440 float p = 0.0f;
441 for(n=0; n<v->N; n++)
442 {
443 v->window[n] = 0.5f - 0.5f * cosf(p);
444 p += dp;
445 }
446 }
447 v->wet = 0.5f * v->param[0] * v->param[0];
448 v->dry = 2.0f * v->param[1] * v->param[1];
449}
450
451void tTalkboxFloat_suspend(tTalkboxFloat* const voc) ///clear any buffers...
452{
453 _tTalkboxFloat* v = *voc;
454
455 v->pos = v->K = 0;
456 v->emphasis = 0.0f;
457 v->FX = 0;
458
459 v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f;
460 v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f;
461
462 for (int32_t i = 0; i < v->bufsize; i++)
463 {
464 v->buf0[i] = 0;
465 v->buf1[i] = 0;
466 v->car0[i] = 0;
467 v->car1[i] = 0;
468 }
469}
470
471// warped autocorrelation adapted from ten.enegatum@liam's post on music-dsp 2004-04-07 09:37:51
472//find the order-P autocorrelation array, R, for the sequence x of length L and warping of lambda
473//wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0);
474void tTalkboxFloat_warpedAutocorrelate(float * x, float* dl, float* Rt, unsigned int L, float * R, unsigned int P, float lambda)
475{
476 float r1,r2,r1t;
477 R[0]=0;
478 Rt[0]=0;
479 r1=0;
480 r2=0;
481 r1t=0;
482 for(uint32_t m=0; m<L;m++)
483 {
484 Rt[0] += (x[m]) * (x[m]);
485
486 dl[m]= r1 - lambda * (x[m]-r2);
487 r1 = x[m];
488 r2 = dl[m];
489 }
490 for(uint32_t i=1; i<=P; i++)
491 {
492 Rt[i]=0;
493 r1=0;
494 r2=0;
495 for(unsigned int m=0; m<L;m++)
496 {
497 Rt[i] += (dl[m]) * (x[m]);
498
499 r1t = dl[m];
500 dl[m]= r1 - lambda * (r1t-r2);
501 r1 = r1t;
502 r2 = dl[m];
503 }
504 }
505 for(uint32_t i=0; i<=P; i++)
506 {
507 R[i]=Rt[i];
508 }
509
510}
511
512void tTalkboxFloat_lpcDurbin(float *r, int p, float *k, float *g)
229{513{
230 int i, j;514 int i, j;
231 float a[ORD_MAX], at[ORD_MAX], e=r[0];515 float a[ORD_MAX], at[ORD_MAX], e=r[0];
232 516
233 for(i=0; i<=p; i++) a[i] = 0.0f; //probably don't need to clear at[] or k[]517 for(i=0; i<=p; i++)
518 {
519 a[i] = 0.0f; //probably don't need to clear at[]
520
521 }
522 k[0] = 0.0f;
234 at[0] = 0.0f;523 at[0] = 0.0f;
235 for(i=1; i<=p; i++)524 for(i=1; i<=p; i++)
236 {525 {
237 k[i] = -r[i];526 k[i] = -r[i];
238 527
239 for(j=1; j<i; j++)528 for(j=1; j<i; j++)
240 {529 {
241 at[j] = a[j];530 at[j] = a[j];
@@ -243,69 +532,127 @@ void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g) · 1 unmodified line
243 }532 }
244 if(fabs(e) < 1.0e-20f) { e = 0.0f; break; }533 if(fabs(e) < 1.0e-20f) { e = 0.0f; break; }
245 k[i] /= e;534 k[i] /= e;
246 535
247 a[i] = k[i];536 a[i] = k[i];
248 for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];537 for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
249 538
250 e *= 1.0f - k[i] * k[i];539 e *= 1.0f - k[i] * k[i];
251 }540 }
252 541
253 if(e < 1.0e-20f) e = 0.0f;542 if(e < 1.0e-20f) e = 0.0f;
254 *g = sqrtf(e);543 *g = sqrtf(e);
255}544}
256 545
257float tTalkbox_tick(tTalkbox* const voc, float synth, float voice)546float tTalkboxFloat_tick(tTalkboxFloat* const voc, float synth, float voice)
258{547{
259 _tTalkbox* v = *voc;548 _tTalkboxFloat* v = *voc;
260 549
261 int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N;550 int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
262 float e=v->emphasis, w, o, x, fx=v->FX;551 float e=v->emphasis, w, o, x, fx=v->FX;
263 float p, q, h0=0.3f, h1=0.77f;552 float p, q, h0=0.3f, h1=0.77f;
264 553
265 o = voice;554 o = voice;
266 x = synth;555 x = synth;
267 556
268 557
269 558
270 p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p;559 p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p;
271 q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q;560 q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q;
272 v->d4 = x;561 v->d4 = x;
273 x = p + q;562 x = p + q;
274 563
275 if(v->K++)564 if(v->K++)
276 {565 {
277 v->K = 0;566 v->K = 0;
278 567
279 v->car0[p0] = v->car1[p1] = x; //carrier input568 v->car0[p0] = v->car1[p1] = x; //carrier input
280 569
281 x = o - e; e = o; //6dB/oct pre-emphasis570 x = o - e; e = o; //6dB/oct pre-emphasis
282 571
283 w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows572 w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows
284 if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn); p0 = 0; }573 if(++p0 >= v->N) { tTalkboxFloat_lpc(v->buf0, v->car0, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G); p0 = 0; }
285 574
286 w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w;575 w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w;
287 if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn); p1 = 0; }576 if(++p1 >= v->N) { tTalkboxFloat_lpc(v->buf1, v->car1, v->dl, v->Rt, v->N, v->O, v->warpFactor, v->warpOn, v->k, v->freeze, &v->G); p1 = 0; }
288 }577 }
289 578
290 p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p;579 p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p;
291 q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q;580 q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q;
292 v->u4 = fx;581 v->u4 = fx;
293 x = p + q;582 x = p + q;
294 583
295 o = x;584 o = x;
296 585
297 v->emphasis = e;586 v->emphasis = e;
298 v->pos = p0;587 v->pos = p0;
299 v->FX = fx;588 v->FX = fx;
300 589
301 590
302 return o;591 return o;
303}592}
304 593
305void tTalkbox_setQuality(tTalkbox* const voc, float quality)594
595void tTalkboxFloat_lpc(float *buf, float *car, float* dl, float* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G)
306{596{
307 _tTalkbox* v = *voc;597 float z[ORD_MAX], r[ORD_MAX], x;
308 598 int32_t i, j, nn=n;
599
600
601 if (warpOn == 0)
602 {
603 for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
604 {
605 z[j] = r[j] = 0.0f;
606 for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
607 }
608 }
609 else
610 {
611 for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
612 {
613 z[j] = r[j] = 0.0f;
614 }
615 tTalkboxFloat_warpedAutocorrelate(buf, dl, Rt, n, r, o, warp);
616 }
617
618 r[0] *= 1.001f; //stability fix
619
620 float min = 0.000001f;
621 if (!freeze)
622 {
623 if(r[0] < min)
624 {
625 for(i=0; i<n; i++)
626 {
627 buf[i] = 0.0f;
628 return;
629 }
630 }
631
632 tTalkbox_lpcDurbin(r, o, k, G); //calc reflection coeffs
633
634 //this is for stability to keep reflection coefficients inside the unit circle
635 //but in Harma's papers I've seen 0.998. just needs to be less than 1 it seems but maybe some wiggle room to avoid instability from floating point precision -JS
636 for(i=0; i<=o; i++)
637 {
638 if(k[i] > 0.998f) k[i] = 0.998f; else if(k[i] < -0.998f) k[i] = -.998f;
639 }
640 }
641 for(i=0; i<n; i++)
642 {
643 x = G[0] * car[i];
644 for(j=o; j>0; j--) //lattice filter
645 {
646 x -= k[j] * z[j-1];
647 z[j] = z[j-1] + k[j] * x;
648 }
649 buf[i] = z[0] = x; //output buf[] will be windowed elsewhere
650 }
651}
652
653void tTalkboxFloat_setQuality(tTalkboxFloat* const voc, float quality)
654{
655 _tTalkboxFloat* v = *voc;
309 v->param[3] = quality;656 v->param[3] = quality;
310 v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);657 v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
311 if (v->O >= ORD_MAX)658 if (v->O >= ORD_MAX)
@@ -314,20 +661,27 @@ void tTalkbox_setQuality(tTalkbox* const voc, float quality) · 2 unmodified lines
314 }661 }
315}662}
316 663
317void tTalkbox_setWarpFactor(tTalkbox* const voc, float warpFactor)664void tTalkboxFloat_setWarpFactor(tTalkboxFloat* const voc, float warpFactor)
318{665{
319 _tTalkbox* v = *voc;666 _tTalkboxFloat* v = *voc;
320 667
321 v->warpFactor = warpFactor;668 v->warpFactor = warpFactor;
322}669}
323 670
324void tTalkbox_setWarpOn(tTalkbox* const voc, float warpOn)671void tTalkboxFloat_setWarpOn(tTalkboxFloat* const voc, float warpOn)
325{672{
326 _tTalkbox* v = *voc;673 _tTalkboxFloat* v = *voc;
327 674
328 v->warpOn = warpOn;675 v->warpOn = warpOn;
329}676}
330 677
678void tTalkboxFloat_setFreeze(tTalkboxFloat* const voc, float freeze)
679{
680 _tTalkboxFloat* v = *voc;
681
682 v->freeze = freeze;
683}
684
331 685
332//============================================================================================================686//============================================================================================================
333// VOCODER687// VOCODER
@@ -374,7 +728,7 @@ void tVocoder_update (tVocoder* const voc) · 40 unmodified lines
374 728
375 float tpofs = 6.2831853f * leaf.invSampleRate;729 float tpofs = 6.2831853f * leaf.invSampleRate;
376 730
377 float rr, th, re;731 float rr, th;
378 732
379 float sh;733 float sh;
380 734
@@ -389,7 +743,7 @@ void tVocoder_update (tVocoder* const voc) · 8 unmodified lines
389 if(v->param[7]<0.5f)743 if(v->param[7]<0.5f)
390 {744 {
391 v->nbnd=8;745 v->nbnd=8;
392 re=0.003f;746
393 v->f[1][2] = 3000.0f;747 v->f[1][2] = 3000.0f;
394 v->f[2][2] = 2200.0f;748 v->f[2][2] = 2200.0f;
395 v->f[3][2] = 1500.0f;749 v->f[3][2] = 1500.0f;
@@ -401,7 +755,7 @@ void tVocoder_update (tVocoder* const voc) · 5 unmodified lines
401 else755 else
402 {756 {
403 v->nbnd=16;757 v->nbnd=16;
404 re=0.0015f;758
405 v->f[ 1][2] = 5000.0f; //+1000759 v->f[ 1][2] = 5000.0f; //+1000
406 v->f[ 2][2] = 4000.0f; //+750760 v->f[ 2][2] = 4000.0f; //+750
407 v->f[ 3][2] = 3250.0f; //+500761 v->f[ 3][2] = 3250.0f; //+500
@@ -588,6 +942,35 @@ float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const gp) · 180 unmodified lines
588 return output;942 return output;
589}943}
590 944
945
946float tRosenbergGlottalPulse_tickHQ (tRosenbergGlottalPulse* const gp)
947{
948 _tRosenbergGlottalPulse* g = *gp;
949
950 float output = 0.0f;
951
952 // Phasor increment
953 g->phase += g->inc;
954 while (g->phase >= 1.0f) g->phase -= 1.0f;
955 while (g->phase < 0.0f) g->phase += 1.0f;
956
957 if (g->phase < g->openLength)
958 {
959 output = 0.5f*(1.0f-cosf(PI * g->phase));
960 }
961
962 else if (g->phase < g->pulseLength)
963 {
964 output = cosf(HALF_PI * (g->phase-g->openLength)* g->invPulseLengthMinusOpenLength);
965 }
966
967 else
968 {
969 output = 0.0f;
970 }
971 return output;
972}
973
591void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const gp, float freq)974void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const gp, float freq)
592{975{
593 _tRosenbergGlottalPulse* g = *gp;976 _tRosenbergGlottalPulse* g = *gp;
@@ -999,7 +1382,7 @@ static int pitchshift_attackdetect(_tPitchShift* ps) · 405 unmodified lines
999 1382
1000void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize)1383void tPitchShift_init (tPitchShift* const psr, tPeriodDetection* pd, float* out, int bufSize)
1001{1384{
1002 tPitchShift_freeFromPool(psr, &leaf.mempool);1385 tPitchShift_initToPool(psr, pd, out, bufSize, &leaf.mempool);
1003}1386}
1004 1387
1005void tPitchShift_free(tPitchShift* const psr)1388void tPitchShift_free(tPitchShift* const psr)
@@ -1386,6 +1769,7 @@ void tAutotune_initToPool (tAutotune* const rt, int numVoices, int buf · 380 unmodified lines
1386 }1769 }
1387 1770
1388 r->inputPeriod = 0.0f;1771 r->inputPeriod = 0.0f;
1772 r->shiftOn = 0;
1389}1773}
1390 1774
1391void tAutotune_freeFromPool (tAutotune* const rt, tMempool* const mp)1775void tAutotune_freeFromPool (tAutotune* const rt, tMempool* const mp)
leaf/Src/leaf-math.c+17−6
@@ -109,7 +109,7 @@ int fastabs_int(int in){ · 108 unmodified lines
109 109
110// alternative implementation for abs()110// alternative implementation for abs()
111// REQUIRES: 32 bit floats111// REQUIRES: 32 bit floats
112float fastabsf(float f)112inline float fastabsf(float f)
113{113{
114 union114 union
115 {115 {
@@ -130,7 +130,7 @@ double fastexp(double x) { · 14 unmodified lines
130 return x;130 return x;
131}131}
132 132
133float fastexpf(float x) {133inline float fastexpf(float x) {
134 x = 1.0f + (x * 0.0009765625f);134 x = 1.0f + (x * 0.0009765625f);
135 x *= x; x *= x; x *= x; x *= x;135 x *= x; x *= x; x *= x; x *= x;
136 x *= x; x *= x; x *= x; x *= x;136 x *= x; x *= x; x *= x; x *= x;
@@ -145,7 +145,7 @@ double fasterexp(double x) { · 8 unmodified lines
145 return x;145 return x;
146}146}
147 147
148float fasterexpf(float x) {148inline float fasterexpf(float x) {
149 x = 1.0f + (x * 0.00390625f);149 x = 1.0f + (x * 0.00390625f);
150 x *= x; x *= x; x *= x; x *= x;150 x *= x; x *= x; x *= x; x *= x;
151 x *= x; x *= x; x *= x; x *= x;151 x *= x; x *= x; x *= x; x *= x;
@@ -329,11 +329,16 @@ float LEAF_clip(float min, float val, float max) · 177 unmodified lines
329 tempmin = max;329 tempmin = max;
330 tempmax = min;330 tempmax = min;
331 }331 }
332 if (val < tempmin) {332 if (val < tempmin)
333 {
333 return tempmin;334 return tempmin;
334 } else if (val > tempmax) {335 }
336 else if (val > tempmax)
337 {
335 return tempmax;338 return tempmax;
336 } else {339 }
340 else
341 {
337 return val;342 return val;
338 }343 }
339}344}
@@ -698,6 +703,12 @@ float fastdbtoa(float db) · 358 unmodified lines
698 return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html703 return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
699}704}
700 705
706float fasterdbtoa(float db)
707{
708 //return powf(10.0f, db * 0.05f);
709 return fasterexpf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
710}
711
701 712
702float maximum (float num1, float num2)713float maximum (float num1, float num2)
703{714{
leaf/Src/leaf-physical.c+246−0
@@ -668,6 +668,252 @@ float tLivingString_sample(tLivingString* const pl) · 667 unmodified lines
668 return p->curr;668 return p->curr;
669}669}
670 670
671
672//////////---------------------------
673
674/* Complex Living String (has pick position and preparation position separated) */
675
676void tComplexLivingString_init(tComplexLivingString* const pl, float freq, float pickPos, float prepPos, float prepIndex,
677 float dampFreq, float decay, float targetLev, float levSmoothFactor,
678 float levStrength, int levMode)
679{
680 tComplexLivingString_initToPool(pl, freq, pickPos, prepPos, prepIndex, dampFreq, decay, targetLev, levSmoothFactor, levStrength, levMode, &leaf.mempool);
681}
682
683void tComplexLivingString_free(tComplexLivingString* const pl)
684{
685 tComplexLivingString_freeFromPool(pl, &leaf.mempool);
686}
687
688void tComplexLivingString_initToPool (tComplexLivingString* const pl, float freq, float pickPos, float prepPos, float prepIndex,
689 float dampFreq, float decay, float targetLev, float levSmoothFactor,
690 float levStrength, int levMode, tMempool* const mp)
691{
692 _tMempool* m = *mp;
693 _tComplexLivingString* p = *pl = (_tComplexLivingString*) mpool_alloc(sizeof(_tComplexLivingString), m);
694
695 p->curr=0.0f;
696 tExpSmooth_initToPool(&p->wlSmooth, leaf.sampleRate/freq, 0.01, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
697 tComplexLivingString_setFreq(pl, freq);
698 p->freq = freq;
699 tExpSmooth_initToPool(&p->pickPosSmooth, pickPos, 0.01f, mp); // smoother for pick position
700 tExpSmooth_initToPool(&p->prepPosSmooth, prepPos, 0.01f, mp); // smoother for pick position
701
702 tComplexLivingString_setPickPos(pl, pickPos);
703 tComplexLivingString_setPrepPos(pl, prepPos);
704
705 p->prepPos=prepPos;
706 p->pickPos=pickPos;
707 tLinearDelay_initToPool(&p->delLF,p->waveLengthInSamples, 2400, mp);
708 tLinearDelay_initToPool(&p->delMF,p->waveLengthInSamples, 2400, mp);
709 tLinearDelay_initToPool(&p->delUF,p->waveLengthInSamples, 2400, mp);
710 tLinearDelay_initToPool(&p->delUB,p->waveLengthInSamples, 2400, mp);
711 tLinearDelay_initToPool(&p->delMB,p->waveLengthInSamples, 2400, mp);
712 tLinearDelay_initToPool(&p->delLB,p->waveLengthInSamples, 2400, mp);
713 tLinearDelay_clear(&p->delLF);
714 tLinearDelay_clear(&p->delMF);
715 tLinearDelay_clear(&p->delUF);
716 tLinearDelay_clear(&p->delUB);
717 tLinearDelay_clear(&p->delMB);
718 tLinearDelay_clear(&p->delLB);
719 p->dampFreq = dampFreq;
720 tOnePole_initToPool(&p->bridgeFilter, dampFreq, mp);
721 tOnePole_initToPool(&p->nutFilter, dampFreq, mp);
722 tOnePole_initToPool(&p->prepFilterU, dampFreq, mp);
723 tOnePole_initToPool(&p->prepFilterL, dampFreq, mp);
724 tHighpass_initToPool(&p->DCblockerU,13, mp);
725 tHighpass_initToPool(&p->DCblockerL,13, mp);
726 p->decay=decay;
727 p->prepIndex = prepIndex;
728 tFeedbackLeveler_initToPool(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode, mp);
729 tFeedbackLeveler_initToPool(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode, mp);
730 p->levMode=levMode;
731}
732
733void tComplexLivingString_freeFromPool (tComplexLivingString* const pl, tMempool* const mp)
734{
735 _tMempool* m = *mp;
736 _tComplexLivingString* p = *pl;
737
738 tExpSmooth_freeFromPool(&p->wlSmooth, mp);
739 tExpSmooth_freeFromPool(&p->pickPosSmooth, mp);
740 tExpSmooth_freeFromPool(&p->prepPosSmooth, mp);
741 tLinearDelay_freeFromPool(&p->delLF, mp);
742 tLinearDelay_freeFromPool(&p->delMF, mp);
743 tLinearDelay_freeFromPool(&p->delUF, mp);
744 tLinearDelay_freeFromPool(&p->delUB, mp);
745 tLinearDelay_freeFromPool(&p->delMB, mp);
746 tLinearDelay_freeFromPool(&p->delLB, mp);
747 tOnePole_freeFromPool(&p->bridgeFilter, mp);
748 tOnePole_freeFromPool(&p->nutFilter, mp);
749 tOnePole_freeFromPool(&p->prepFilterU, mp);
750 tOnePole_freeFromPool(&p->prepFilterL, mp);
751 tHighpass_freeFromPool(&p->DCblockerU, mp);
752 tHighpass_freeFromPool(&p->DCblockerL, mp);
753 tFeedbackLeveler_freeFromPool(&p->fbLevU, mp);
754 tFeedbackLeveler_freeFromPool(&p->fbLevL, mp);
755
756 mpool_free((char*)p, m);
757}
758
759void tComplexLivingString_setFreq(tComplexLivingString* const pl, float freq)
760{ // NOTE: It is faster to set wavelength in samples directly
761 _tComplexLivingString* p = *pl;
762 if (freq<20.0f) freq=20.0f;
763 else if (freq>10000.0f) freq=10000.0f;
764 p->waveLengthInSamples = leaf.sampleRate/freq;
765 tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
766}
767
768void tComplexLivingString_setWaveLength(tComplexLivingString* const pl, float waveLength)
769{
770 _tComplexLivingString* p = *pl;
771 if (waveLength<4.8f) waveLength=4.8f;
772 else if (waveLength>2400.0f) waveLength=2400.0f;
773 p->waveLengthInSamples = waveLength;
774 tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
775}
776
777void tComplexLivingString_setPickPos(tComplexLivingString* const pl, float pickPos)
778{ // between 0 and 1
779 _tComplexLivingString* p = *pl;
780 if (pickPos<0.5f) pickPos=0.5f;
781 else if (pickPos>1.f) pickPos=1.f;
782 p->pickPos = pickPos;
783 tExpSmooth_setDest(&p->pickPosSmooth, p->pickPos);
784}
785
786void tComplexLivingString_setPrepPos(tComplexLivingString* const pl, float prepPos)
787{ // between 0 and 1
788 _tComplexLivingString* p = *pl;
789 if (prepPos<0.f) prepPos=0.f;
790 else if (prepPos>0.5f) prepPos=0.5f;
791 p->prepPos = prepPos;
792 tExpSmooth_setDest(&p->prepPosSmooth, p->prepPos);
793}
794
795void tComplexLivingString_setPrepIndex(tComplexLivingString* const pl, float prepIndex)
796{ // between 0 and 1
797 _tComplexLivingString* p = *pl;
798 if (prepIndex<0.f) prepIndex=0.f;
799 else if (prepIndex>1.f) prepIndex=1.f;
800 p->prepIndex = prepIndex;
801}
802
803void tComplexLivingString_setDampFreq(tComplexLivingString* const pl, float dampFreq)
804{
805 _tComplexLivingString* p = *pl;
806 tOnePole_setFreq(&p->bridgeFilter, dampFreq);
807 tOnePole_setFreq(&p->nutFilter, dampFreq);
808 tOnePole_setFreq(&p->prepFilterU, dampFreq);
809 tOnePole_setFreq(&p->prepFilterL, dampFreq);
810}
811
812void tComplexLivingString_setDecay(tComplexLivingString* const pl, float decay)
813{
814 _tComplexLivingString* p = *pl;
815 p->decay=decay;
816}
817
818void tComplexLivingString_setTargetLev(tComplexLivingString* const pl, float targetLev)
819{
820 _tComplexLivingString* p = *pl;
821 tFeedbackLeveler_setTargetLevel(&p->fbLevU, targetLev);
822 tFeedbackLeveler_setTargetLevel(&p->fbLevL, targetLev);
823}
824
825void tComplexLivingString_setLevSmoothFactor(tComplexLivingString* const pl, float levSmoothFactor)
826{
827 _tComplexLivingString* p = *pl;
828 tFeedbackLeveler_setFactor(&p->fbLevU, levSmoothFactor);
829 tFeedbackLeveler_setFactor(&p->fbLevL, levSmoothFactor);
830}
831
832void tComplexLivingString_setLevStrength(tComplexLivingString* const pl, float levStrength)
833{
834 _tComplexLivingString* p = *pl;
835 tFeedbackLeveler_setStrength(&p->fbLevU, levStrength);
836 tFeedbackLeveler_setStrength(&p->fbLevL, levStrength);
837}
838
839void tComplexLivingString_setLevMode(tComplexLivingString* const pl, int levMode)
840{
841 _tComplexLivingString* p = *pl;
842 tFeedbackLeveler_setMode(&p->fbLevU, levMode);
843 tFeedbackLeveler_setMode(&p->fbLevL, levMode);
844 p->levMode=levMode;
845}
846
847float tComplexLivingString_tick(tComplexLivingString* const pl, float input)
848{
849 _tComplexLivingString* p = *pl;
850
851 // from pickPos upwards=forwards
852 float fromLF=tLinearDelay_tickOut(&p->delLF);
853 float fromMF=tLinearDelay_tickOut(&p->delMF);
854 float fromUF=tLinearDelay_tickOut(&p->delUF);
855 float fromUB=tLinearDelay_tickOut(&p->delUB);
856 float fromMB=tLinearDelay_tickOut(&p->delMB);
857 float fromLB=tLinearDelay_tickOut(&p->delLB);
858
859 // into upper part of string, from bridge, going backwards
860 float fromBridge=-tFeedbackLeveler_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->bridgeFilter, fromUF)));
861 tLinearDelay_tickIn(&p->delUB, fromBridge);
862
863 // into pick position, take input and add it into the waveguide, going to come out of middle segment
864 tLinearDelay_tickIn(&p->delMB, fromUB+input);
865
866 // into lower part of string, from prepPos, going backwards
867 float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
868 float intoLower=p->prepIndex*fromLowerPrep+(1.0f - p->prepIndex)*fromMB;
869 tLinearDelay_tickIn(&p->delLB, intoLower);
870
871 // into lower part of string, from nut, going forwards toward prep position
872 float fromNut=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1.0f)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->nutFilter, fromLB)));
873 tLinearDelay_tickIn(&p->delLF, fromNut);
874
875 // into middle part of string, from prep going toward pick position
876 float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
877 float intoMiddle=p->prepIndex*fromUpperPrep+(1.0f - p->prepIndex)*fromLF;
878
879 //pick position, take input and add it into the waveguide, going to come out of middle segment
880 tLinearDelay_tickIn(&p->delMF, intoMiddle + input);
881
882 //take output of middle segment and put it into upper segment connecting to the bridge
883 tLinearDelay_tickIn(&p->delUF, fromMF);
884
885 // update all delay lengths
886 float pickP=tExpSmooth_tick(&p->pickPosSmooth);
887 float prepP=tExpSmooth_tick(&p->prepPosSmooth);
888 float wLen=tExpSmooth_tick(&p->wlSmooth);
889
890 float midLen = (pickP-prepP) * wLen; // the length between the pick and the prep;
891 float lowLen = prepP*wLen; // the length from prep to nut
892 float upLen = (1.0f-pickP)*wLen; // the length from pick to bridge
893
894
895 tLinearDelay_setDelay(&p->delLF, lowLen);
896 tLinearDelay_setDelay(&p->delLB, lowLen);
897
898 tLinearDelay_setDelay(&p->delMF, midLen);
899 tLinearDelay_setDelay(&p->delMB, midLen);
900
901 tLinearDelay_setDelay(&p->delUF, upLen);
902 tLinearDelay_setDelay(&p->delUB, upLen);
903
904 //update this to allow pickup position variation
905 p->curr = fromBridge;
906 return p->curr;
907}
908
909float tComplexLivingString_sample(tComplexLivingString* const pl)
910{
911 _tComplexLivingString* p = *pl;
912 return p->curr;
913}
914
915
916
671///Reed Table model917///Reed Table model
672//default values from STK are 0.6 offset and -0.8 slope918//default values from STK are 0.6 offset and -0.8 slope
673 919
leaf/Src/leaf-sampling.c+25−8
@@ -78,6 +78,7 @@ void tBuffer_tick (tBuffer* const sb, float sample) · 77 unmodified lines
78 s->idx = 0;78 s->idx = 0;
79 }79 }
80 }80 }
81 s->recordedLength = s->idx;
81 }82 }
82}83}
83 84
@@ -110,7 +111,6 @@ void tBuffer_stop(tBuffer* const sb) · 26 unmodified lines
110{111{
111 _tBuffer* s = *sb;112 _tBuffer* s = *sb;
112 s->active = 0;113 s->active = 0;
113 s->recordedLength = s->idx;
114}114}
115 115
116int tBuffer_getRecordPosition(tBuffer* const sb)116int tBuffer_getRecordPosition(tBuffer* const sb)
@@ -119,6 +119,12 @@ int tBuffer_getRecordPosition(tBuffer* const sb) · 2 unmodified lines
119 return s->idx;119 return s->idx;
120}120}
121 121
122void tBuffer_setRecordPosition(tBuffer* const sb, int pos)
123{
124 _tBuffer* s = *sb;
125 s->idx = pos;
126}
127
122void tBuffer_setRecordMode (tBuffer* const sb, RecordMode mode)128void tBuffer_setRecordMode (tBuffer* const sb, RecordMode mode)
123{129{
124 _tBuffer* s = *sb;130 _tBuffer* s = *sb;
@@ -132,6 +138,7 @@ void tBuffer_clear (tBuffer* const sb) · 7 unmodified lines
132 {138 {
133 s->buff[i] = 0.f;139 s->buff[i] = 0.f;
134 }140 }
141
135}142}
136 143
137uint32_t tBuffer_getBufferLength(tBuffer* const sb)144uint32_t tBuffer_getBufferLength(tBuffer* const sb)
@@ -146,6 +153,18 @@ uint32_t tBuffer_getRecordedLength(tBuffer* const sb) · 8 unmodified lines
146 return s->recordedLength;153 return s->recordedLength;
147}154}
148 155
156void tBuffer_setRecordedLength(tBuffer* const sb, int length)
157{
158 _tBuffer* s = *sb;
159 s->recordedLength = length;
160}
161
162int tBuffer_isActive(tBuffer* const sb)
163{
164 _tBuffer* s = *sb;
165 return s->active;
166}
167
149//================================tSampler=====================================168//================================tSampler=====================================
150 169
151static void handleStartEndChange(tSampler* const sp);170static void handleStartEndChange(tSampler* const sp);
@@ -224,7 +243,7 @@ void tSampler_setSample (tSampler* const sp, tBuffer* const b) · 72 unmodified lines
224 p->idx = 0.f;243 p->idx = 0.f;
225}244}
226 245
227volatile uint32_t errorState = 0;246
228 247
229float tSampler_tick (tSampler* const sp)248float tSampler_tick (tSampler* const sp)
230{249{
@@ -429,10 +448,11 @@ float tSampler_tick (tSampler* const sp) · 198 unmodified lines
429 }448 }
430 }449 }
431 450
432 float ticksToEnd = rev ? ((idx - start) * p->iinc) : ((end - idx) * p->iinc);451
433 if (p->mode == PlayNormal)452 if (p->mode == PlayNormal)
434 {453 {
435 if (ticksToEnd < (0.007f * leaf.sampleRate))454 float ticksToEnd = rev ? ((idx - start) * p->iinc) : ((end - idx) * p->iinc);
455 if (ticksToEnd < (0.007f * leaf.sampleRate))
436 {456 {
437 tRamp_setDest(&p->gain, 0.f);457 tRamp_setDest(&p->gain, 0.f);
438 p->active = -1;458 p->active = -1;
@@ -472,10 +492,7 @@ float tSampler_tick (tSampler* const sp) · 33 unmodified lines
472 }492 }
473 }493 }
474 494
475 if (fabsf(sample-p->last) > 0.1f)495
476 {
477 errorState = 1;
478 }
479 496
480 p->last = sample;497 p->last = sample;
481 498
leaf/Src/leaf-tables.c+1−1
@@ -3489,7 +3489,7 @@ const float __leaf_table_squarewave[11][SQR_TABLE_SIZE] = · 3488 unmodified lines
3489 3489
3490 3490
3491 3491
3492#if DECAY_TABLES_USED3492#ifdef DECAY_TABLES_USED
3493const float __leaf_table_exp_decay[EXP_DECAY_TABLE_SIZE] = { 3493const float __leaf_table_exp_decay[EXP_DECAY_TABLE_SIZE] = {
3494 1.0f, 0.999969f, 0.999939f, 0.999908f, 0.999878f, 0.999847f, 0.999817f, 0.999786f, 0.999756f, 0.999725f, 0.999695f, 0.999664f, 0.999634f, 0.999603f, 0.999573f, 0.999542f, 0.999512f, 0.999481f, 0.999451f, 0.99942f,3494 1.0f, 0.999969f, 0.999939f, 0.999908f, 0.999878f, 0.999847f, 0.999817f, 0.999786f, 0.999756f, 0.999725f, 0.999695f, 0.999664f, 0.999634f, 0.999603f, 0.999573f, 0.999542f, 0.999512f, 0.999481f, 0.999451f, 0.99942f,
34950.99939f, 0.999359f, 0.999329f, 0.999298f, 0.999268f, 0.999237f, 0.999207f, 0.999176f, 0.999146f, 0.999115f, 0.999085f, 0.999054f, 0.999024f, 0.998993f, 0.998963f, 0.998932f, 0.998902f, 0.998871f, 0.998841f, 0.99881f,34950.99939f, 0.999359f, 0.999329f, 0.999298f, 0.999268f, 0.999237f, 0.999207f, 0.999176f, 0.999146f, 0.999115f, 0.999085f, 0.999054f, 0.999024f, 0.998993f, 0.998963f, 0.998932f, 0.998902f, 0.998871f, 0.998841f, 0.99881f,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t