History

recategorization of objects, some objects renamed

Matthew Wang committed 7 years ago

Commit 7803edf1 parent 3b564d450 files · +5701 −5731Browse files

Unified · Split

50 files
  1. LEAF/Inc/.DS_Store +0 −0
  2. LEAF/Inc/leaf-analysis.h +226 −0
  3. LEAF/Inc/leaf-crusher.h +0 −64
  4. LEAF/Inc/leaf-delay.h +26 −26
  5. LEAF/Inc/leaf-distortion.h +99 −0
  6. LEAF/Inc/leaf-dynamics.h +79 −0
  7. LEAF/Inc/leaf-effects.h +251 −0
  8. LEAF/Inc/leaf-electrical.h +4 −4
  9. LEAF/Inc/leaf-envelopes.h +136 −0
  10. LEAF/Inc/leaf-filters.h +12 −12
  11. LEAF/Inc/leaf-formant.h +0 −68
  12. LEAF/Inc/leaf-instruments.h +7 −7
  13. LEAF/Inc/leaf-midi.h +29 −1
  14. LEAF/Inc/leaf-oscillators.h +83 −84
  15. LEAF/Inc/leaf-oversampler.h +0 −51
  16. LEAF/Inc/leaf-physical.h +221 −0
  17. LEAF/Inc/leaf-pitch.h +0 −161
  18. LEAF/Inc/leaf-reverb.h +29 −30
  19. LEAF/Inc/leaf-sample.h +0 −125
  20. LEAF/Inc/leaf-sampling.h +124 −0
  21. LEAF/Inc/leaf-string.h +0 −143
  22. LEAF/Inc/leaf-tables.h +3 −3
  23. LEAF/Inc/leaf-utilities.h +0 −483
  24. LEAF/Inc/leaf-vocoder.h +0 −89
  25. LEAF/Inc/leaf-wavefolder.h +0 −48
  26. LEAF/Src/leaf-analysis.c +733 −0
  27. LEAF/Src/leaf-crusher.c +0 −84
  28. LEAF/Src/leaf-delay.c +30 −30
  29. LEAF/Src/leaf-distortion.c +173 −2
  30. LEAF/Src/leaf-dynamics.c +172 −0
  31. LEAF/Src/leaf-effects.c +1393 −0
  32. LEAF/Src/leaf-electrical.c +13 −2
  33. LEAF/Src/leaf-envelopes.c +629 −0
  34. LEAF/Src/leaf-filters.c +11 −11
  35. LEAF/Src/leaf-formant.c +0 −206
  36. LEAF/Src/leaf-instruments.c +3 −3
  37. LEAF/Src/leaf-math.c +2 −0
  38. LEAF/Src/leaf-midi.c +213 −0
  39. LEAF/Src/leaf-oscillators.c +305 −299
  40. LEAF/Src/leaf-physical.c +596 −0
  41. LEAF/Src/leaf-pitch.c +0 −563
  42. LEAF/Src/leaf-reverb.c +32 −32
  43. LEAF/Src/leaf-sampling.c +3 −3
  44. LEAF/Src/leaf-string.c +0 −289
  45. LEAF/Src/leaf-utilities.c +0 −2227
  46. LEAF/Src/leaf-vocoder.c +0 −400
  47. LEAF/Src/leaf-wavefolder.c +0 −114
  48. LEAF/leaf.h +24 −27
  49. LEAF_JUCEPlugin/LEAF.jucer +38 −40
  50. LEAF_JUCEPlugin/Source/MyTest.cpp +3 −1
LEAF/Inc/.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-analysis.h+226−0
@@ -0,0 +1,226 @@
1+/*==============================================================================
2+
3+ leaf-analysis.h
4+ Created: 25 Oct 2019 10:30:52am
5+ Author: Matthew Wang
6+
7+ ==============================================================================*/
8+
9+#ifndef LEAF_ANALYSIS_H_INCLUDED
10+#define LEAF_ANALYSIS_H_INCLUDED
11+
12+#ifdef __cplusplus
13+extern "C" {
14+#endif
15+
16+//==============================================================================
17+
18+#include "leaf-global.h"
19+#include "leaf-mempool.h"
20+#include "leaf-math.h"
21+#include "leaf-filters.h"
22+
23+//==============================================================================
24+
25+/* Envelope Follower */
26+typedef struct _tEnvelopeFollower
27+{
28+ float y;
29+ float a_thresh;
30+ float d_coeff;
31+
32+} tEnvelopeFollower;
33+
34+void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff);
35+void tEnvelopeFollower_free (tEnvelopeFollower* const);
36+
37+float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x);
38+int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff);
39+int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh);
40+
41+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
42+
43+/* PowerEnvelopeFollower */
44+typedef struct _tPowerFollower {
45+ float factor, oneminusfactor;
46+ float curr;
47+
48+} tPowerFollower;
49+
50+void tPowerFollower_init (tPowerFollower* const, float factor);
51+void tPowerFollower_free (tPowerFollower* const);
52+float tPowerFollower_tick (tPowerFollower* const, float input);
53+float tPowerFollower_sample (tPowerFollower* const);
54+int tPowerFollower_setFactor (tPowerFollower* const, float factor);
55+
56+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
57+
58+// ENV~ from PD, modified for LEAF
59+#define MAXOVERLAP 32
60+#define INITVSTAKEN 64
61+#define ENV_WINDOW_SIZE 1024
62+#define ENV_HOP_SIZE 256
63+
64+typedef struct _tEnvPD
65+{
66+ float buf[ENV_WINDOW_SIZE + INITVSTAKEN];
67+ uint16_t x_phase; /* number of points since last output */
68+ uint16_t x_period; /* requested period of output */
69+ uint16_t x_realperiod; /* period rounded up to vecsize multiple */
70+ uint16_t x_npoints; /* analysis window size in samples */
71+ float x_result; /* result to output */
72+ float x_sumbuf[MAXOVERLAP]; /* summing buffer */
73+ float x_f;
74+ uint16_t windowSize, hopSize, blockSize;
75+ uint16_t x_allocforvs; /* extra buffer for DSP vector size */
76+} tEnvPD;
77+
78+void tEnvPD_init (tEnvPD* const, int windowSize, int hopSize, int blockSize);
79+void tEnvPD_free (tEnvPD* const);
80+float tEnvPD_tick (tEnvPD* const);
81+void tEnvPD_processBlock (tEnvPD* const, float* in);
82+
83+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
84+
85+/* tAttackDetection */
86+#define DEFBLOCKSIZE 1024
87+#define DEFTHRESHOLD 6
88+#define DEFATTACK 10
89+#define DEFRELEASE 10
90+
91+typedef struct _tAttackDetection
92+{
93+ float env;
94+
95+ //Attack & Release times in msec
96+ int atk;
97+ int rel;
98+
99+ //Attack & Release coefficients based on times
100+ float atk_coeff;
101+ float rel_coeff;
102+
103+ int blocksize;
104+ int samplerate;
105+
106+ //RMS amplitude of previous block - used to decide if attack is present
107+ float prevAmp;
108+
109+ float threshold;
110+} tAttackDetection;
111+
112+void tAttackDetection_init (tAttackDetection* const, int blocksize);
113+void tAttackDetection_init_expanded (tAttackDetection* const, int blocksize, int atk, int rel);
114+void tAttackDetection_free (tAttackDetection* const);
115+
116+// set expected input blocksize
117+void tAttackDetection_setBlocksize (tAttackDetection* const, int size);
118+
119+// change atkDetector sample rate
120+void tAttackDetection_setSamplerate (tAttackDetection* const, int inRate);
121+
122+// set attack time and coeff
123+void tAttackDetection_setAtk (tAttackDetection* const, int inAtk);
124+
125+// set release time and coeff
126+void tAttackDetection_setRel (tAttackDetection* const, int inRel);
127+
128+// set level above which values are identified as attacks
129+void tAttackDetection_setThreshold (tAttackDetection* const, float thres);
130+
131+// find largest transient in input block, return index of attack
132+int tAttackDetection_detect (tAttackDetection* const, float *in);
133+
134+//==============================================================================
135+
136+// tSNAC: period detector
137+#define SNAC_FRAME_SIZE 1024 // default analysis framesize // should be the same as (or smaller than?) PS_FRAME_SIZE
138+#define DEFOVERLAP 1 // default overlap
139+#define DEFBIAS 0.2f // default bias
140+#define DEFMINRMS 0.003f // default minimum RMS
141+#define SEEK 0.85f // seek-length as ratio of framesize
142+
143+typedef struct _tSNAC
144+{
145+ float* inputbuf;
146+ float* processbuf;
147+ float* spectrumbuf;
148+ float* biasbuf;
149+ uint16_t timeindex;
150+ uint16_t framesize;
151+ uint16_t overlap;
152+ uint16_t periodindex;
153+
154+ float periodlength;
155+ float fidelity;
156+ float biasfactor;
157+ float minrms;
158+
159+} tSNAC;
160+
161+void tSNAC_init (tSNAC* const, int overlaparg); // constructor
162+void tSNAC_free (tSNAC* const); // destructor
163+
164+void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size);
165+void tSNAC_setOverlap (tSNAC *s, int lap);
166+void tSNAC_setBias (tSNAC *s, float bias);
167+void tSNAC_setMinRMS (tSNAC *s, float rms);
168+
169+/*To get freq, perform SAMPLE_RATE/snac_getperiod() */
170+float tSNAC_getPeriod (tSNAC *s);
171+float tSNAC_getfidelity (tSNAC *s);
172+
173+#define DEFPITCHRATIO 2.0f
174+#define DEFTIMECONSTANT 100.0f
175+#define DEFHOPSIZE 64
176+#define DEFWINDOWSIZE 64
177+#define FBA 20
178+#define HPFREQ 40.0f
179+
180+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
181+// Period detection
182+typedef struct _tPeriodDetection
183+{
184+ tEnvPD env;
185+ tSNAC snac;
186+ float* inBuffer;
187+ float* outBuffer;
188+ int frameSize;
189+ int bufSize;
190+ int framesPerBuffer;
191+ int curBlock;
192+ int lastBlock;
193+ int i;
194+ int indexstore;
195+ int iLast;
196+ int index;
197+ float period;
198+
199+ uint16_t hopSize;
200+ uint16_t windowSize;
201+ uint8_t fba;
202+
203+ float timeConstant;
204+ float radius;
205+ float max;
206+ float lastmax;
207+ float deltamax;
208+
209+}tPeriodDetection;
210+
211+void tPeriodDetection_init (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize);
212+void tPeriodDetection_free (tPeriodDetection* const);
213+
214+float tPeriodDetection_findPeriod (tPeriodDetection* const, float sample);
215+void tPeriodDetection_setHopSize (tPeriodDetection* p, int hs);
216+void tPeriodDetection_setWindowSize (tPeriodDetection* p, int ws);
217+
218+//==============================================================================
219+
220+#ifdef __cplusplus
221+}
222+#endif
223+
224+#endif // LEAF_ANALYSIS_H_INCLUDED
225+
226+//==============================================================================
LEAF/Inc/leaf-crusher.h+0−64
@@ -1,64 +0,0 @@
1−/*
2− ==============================================================================
3−
4− leaf-crusher.h
5− Created: 7 Feb 2019 10:58:22am
6− Author: airship
7−
8− ==============================================================================
9−*/
10−
11−#ifndef LEAF_CRUSHER_H_INCLUDED
12−#define LEAF_CRUSHER_H_INCLUDED
13−
14−
15−#ifdef __cplusplus
16−extern "C" {
17−#endif
18−
19−//==============================================================================
20−
21−#include "leaf-global.h"
22−#include "leaf-math.h"
23−
24−//==============================================================================
25−
26−typedef struct _tCrusher
27−{
28− float srr;
29− float mult, div;
30− float rnd;
31−
32− uint32_t op; //which bitwise operation (0-7)
33−
34− float gain;
35−
36−} tCrusher;
37−
38−
39−void tCrusher_init (tCrusher* const);
40−void tCrusher_free (tCrusher* const);
41−
42−float tCrusher_tick (tCrusher* const, float input);
43−
44−// 0.0 - 1.0
45−void tCrusher_setOperation (tCrusher* const, float op);
46−
47−// 0.0 - 1.0
48−void tCrusher_setQuality (tCrusher* const, float val);
49−
50−// what division to round to
51−void tCrusher_setRound (tCrusher* const, float rnd);
52−
53−// sampling ratio
54−void tCrusher_setSamplingRatio (tCrusher* const, float ratio);
55−
56−//==============================================================================
57−
58−#ifdef __cplusplus
59−}
60−#endif
61−
62−#endif // LEAF_WAVEFOLDER_H_INCLUDED
63−
64−//==============================================================================
LEAF/Inc/leaf-delay.h+26−26
@@ -48,7 +48,7 @@ float tDelay_getLastIn (tDelay* const); · 47 unmodified lines
4848 //==============================================================================
4949
5050 /* Linearly-interpolating delay, reimplemented from STK (Cook and Scavone). */
51−typedef struct _tDelayL
51+typedef struct _tLinearDelay
5252 {
5353 float gain;
5454 float* buff;
@@ -63,26 +63,26 @@ typedef struct _tDelayL · 8 unmodified lines
6363
6464 float alpha, omAlpha;
6565
66−} tDelayL;
66+} tLinearDelay;
6767
68−void tDelayL_init (tDelayL* const, float delay, uint32_t maxDelay);
69−void tDelayL_free (tDelayL* const);
68+void tLinearDelay_init (tLinearDelay* const, float delay, uint32_t maxDelay);
69+void tLinearDelay_free (tLinearDelay* const);
7070
71−int tDelayL_setDelay (tDelayL* const, float delay);
72−float tDelayL_getDelay (tDelayL* const);
73−void tDelayL_tapIn (tDelayL* const, float in, uint32_t tapDelay);
74−float tDelayL_tapOut (tDelayL* const, float tapDelay);
75−float tDelayL_addTo (tDelayL* const, float value, uint32_t tapDelay);
76−float tDelayL_tick (tDelayL* const, float sample);
77−void tDelayL_tickIn (tDelayL* const d, float input);
78−float tDelayL_tickOut (tDelayL* const d);
79−float tDelayL_getLastOut (tDelayL* const);
80−float tDelayL_getLastIn (tDelayL* const);
71+int tLinearDelay_setDelay (tLinearDelay* const, float delay);
72+float tLinearDelay_getDelay (tLinearDelay* const);
73+void tLinearDelay_tapIn (tLinearDelay* const, float in, uint32_t tapDelay);
74+float tLinearDelay_tapOut (tLinearDelay* const, float tapDelay);
75+float tLinearDelay_addTo (tLinearDelay* const, float value, uint32_t tapDelay);
76+float tLinearDelay_tick (tLinearDelay* const, float sample);
77+void tLinearDelay_tickIn (tLinearDelay* const d, float input);
78+float tLinearDelay_tickOut (tLinearDelay* const d);
79+float tLinearDelay_getLastOut (tLinearDelay* const);
80+float tLinearDelay_getLastIn (tLinearDelay* const);
8181
8282 //==============================================================================
8383
8484 /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */
85−typedef struct _tDelayA
85+typedef struct _tAllpassDelay
8686 {
8787 float gain;
8888 float* buff;
@@ -99,19 +99,19 @@ typedef struct _tDelayA · 10 unmodified lines
9999
100100 float apInput;
101101
102−} tDelayA;
102+} tAllpassDelay;
103103
104−void tDelayA_init (tDelayA* const, float delay, uint32_t maxDelay);
105−void tDelayA_free (tDelayA* const);
104+void tAllpassDelay_init (tAllpassDelay* const, float delay, uint32_t maxDelay);
105+void tAllpassDelay_free (tAllpassDelay* const);
106106
107−int tDelayA_setDelay (tDelayA* const, float delay);
108−float tDelayA_getDelay (tDelayA* const);
109−void tDelayA_tapIn (tDelayA* const, float in, uint32_t tapDelay);
110−float tDelayA_tapOut (tDelayA* const, uint32_t tapDelay);
111−float tDelayA_addTo (tDelayA* const, float value, uint32_t tapDelay);
112−float tDelayA_tick (tDelayA* const, float sample);
113−float tDelayA_getLastOut (tDelayA* const);
114−float tDelayA_getLastIn (tDelayA* const);
107+int tAllpassDelay_setDelay (tAllpassDelay* const, float delay);
108+float tAllpassDelay_getDelay (tAllpassDelay* const);
109+void tAllpassDelay_tapIn (tAllpassDelay* const, float in, uint32_t tapDelay);
110+float tAllpassDelay_tapOut (tAllpassDelay* const, uint32_t tapDelay);
111+float tAllpassDelay_addTo (tAllpassDelay* const, float value, uint32_t tapDelay);
112+float tAllpassDelay_tick (tAllpassDelay* const, float sample);
113+float tAllpassDelay_getLastOut (tAllpassDelay* const);
114+float tAllpassDelay_getLastIn (tAllpassDelay* const);
115115
116116 //==============================================================================
117117
LEAF/Inc/leaf-distortion.h+99−0
@@ -0,0 +1,99 @@
1+/*==============================================================================
2+
3+ leaf-distortion.h
4+ Created: 25 Oct 2019 10:23:28am
5+ Author: Matthew Wang
6+
7+==============================================================================*/
8+
9+#ifndef LEAF_DISTORTION_H_INCLUDED
10+#define LEAF_DISTORTION_H_INCLUDED
11+
12+#ifdef __cplusplus
13+extern "C" {
14+#endif
15+
16+//==============================================================================
17+
18+#include "leaf-global.h"
19+#include "leaf-mempool.h"
20+#include "leaf-math.h"
21+
22+//==============================================================================
23+
24+/* tLockhartWavefolder */
25+
26+typedef struct _tLockhartWavefolder
27+{
28+ double Ln1;
29+ double Fn1;
30+ float xn1;
31+
32+} tLockhartWavefolder;
33+
34+void tLockhartWavefolder_init (tLockhartWavefolder* const);
35+void tLockhartWavefolder_free (tLockhartWavefolder* const);
36+
37+float tLockhartWavefolder_tick (tLockhartWavefolder* const, float samp);
38+
39+//==============================================================================
40+
41+typedef struct _tCrusher
42+{
43+ float srr;
44+ float mult, div;
45+ float rnd;
46+
47+ uint32_t op; //which bitwise operation (0-7)
48+
49+ float gain;
50+
51+} tCrusher;
52+
53+
54+void tCrusher_init (tCrusher* const);
55+void tCrusher_free (tCrusher* const);
56+
57+float tCrusher_tick (tCrusher* const, float input);
58+
59+// 0.0 - 1.0
60+void tCrusher_setOperation (tCrusher* const, float op);
61+
62+// 0.0 - 1.0
63+void tCrusher_setQuality (tCrusher* const, float val);
64+
65+// what division to round to
66+void tCrusher_setRound (tCrusher* const, float rnd);
67+
68+// sampling ratio
69+void tCrusher_setSamplingRatio (tCrusher* const, float ratio);
70+
71+//==============================================================================
72+
73+typedef struct _tOversampler
74+{
75+ int ratio;
76+ float* pCoeffs;
77+ float* upState;
78+ float* downState;
79+ int numTaps;
80+ int phaseLength;
81+} tOversampler;
82+
83+void tOversampler_init(tOversampler* const, int order, oBool extraQuality);
84+void tOversampler_free(tOversampler* const);
85+void tOversampler_upsample(tOversampler* const, float input, float* output);
86+float tOversampler_downsample(tOversampler *const os, float* input);
87+float tOversampler_tick(tOversampler* const, float input, float (*effectTick)(float));
88+int tOversampler_getLatency(tOversampler* const os);
89+
90+//==============================================================================
91+
92+#ifdef __cplusplus
93+}
94+#endif
95+
96+#endif // LEAF_DISTORTION_H_INCLUDED
97+
98+//==============================================================================
99+
LEAF/Inc/leaf-dynamics.h+79−0
@@ -0,0 +1,79 @@
1+/*==============================================================================
2+
3+ leaf-dynamics.h
4+ Created: 30 Nov 2018 11:57:05am
5+ Author: airship
6+
7+==============================================================================*/
8+
9+#ifndef LEAF_DYNAMICS_H_INCLUDED
10+#define LEAF_DYNAMICS_H_INCLUDED
11+
12+
13+#ifdef __cplusplus
14+extern "C" {
15+#endif
16+
17+//==============================================================================
18+
19+#include "leaf-global.h"
20+#include "leaf-math.h"
21+#include "leaf-analysis.h"
22+
23+//==============================================================================
24+
25+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
26+
27+/* Compressor */
28+typedef struct _tCompressor
29+{
30+ float tauAttack, tauRelease;
31+ float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain
32+
33+ float x_G[2], y_G[2], x_T[2], y_T[2];
34+
35+ oBool isActive;
36+
37+}tCompressor;
38+
39+void tCompressor_init (tCompressor* const);
40+void tCompressor_free (tCompressor* const);
41+float tCompressor_tick (tCompressor* const, float input);
42+
43+///
44+/* Feedback leveller */
45+// An auto VCA that you put into a feedback circuit to make it stay at the same level.
46+// It can enforce level bidirectionally (amplifying and attenuating as needed) or
47+// just attenutating. The former option allows for infinite sustain strings, for example, while
48+// The latter option allows for decaying strings, which can never exceed
49+// a specific level.
50+
51+typedef struct _tFeedbackLeveler {
52+ float targetLevel; // target power level
53+ float strength; // how strongly level difference affects the VCA
54+ int mode; // 0 for upwards limiting only, 1 for biderctional limiting
55+ float curr;
56+ tPowerFollower pwrFlw; // internal power follower needed for level tracking
57+
58+} tFeedbackLeveler;
59+
60+void tFeedbackLeveler_init (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode);
61+void tFeedbackLeveler_free (tFeedbackLeveler* const);
62+
63+float tFeedbackLeveler_tick (tFeedbackLeveler* const, float input);
64+float tFeedbackLeveler_sample (tFeedbackLeveler* const);
65+void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const, float TargetLevel);
66+void tFeedbackLeveler_setFactor (tFeedbackLeveler* const, float factor);
67+void tFeedbackLeveler_setMode (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
68+void tFeedbackLeveler_setStrength (tFeedbackLeveler* const, float strength);
69+
70+
71+//==============================================================================
72+
73+#ifdef __cplusplus
74+}
75+#endif
76+
77+#endif // LEAF_DYNAMICS_H_INCLUDED
78+
79+//==============================================================================
LEAF/Inc/leaf-effects.h+251−0
@@ -0,0 +1,251 @@
1+/*==============================================================================
2+
3+ leaf-effects.h
4+ Created: 20 Jan 2017 12:01:54pm
5+ Author: Michael R Mulshine
6+
7+==============================================================================*/
8+
9+#ifndef LEAF_EFFECTS_H_INCLUDED
10+#define LEAF_EFFECTS_H_INCLUDED
11+
12+#ifdef __cplusplus
13+extern "C" {
14+#endif
15+
16+//==============================================================================
17+
18+#include "leaf-global.h"
19+#include "leaf-math.h"
20+#include "leaf-analysis.h"
21+
22+//==============================================================================
23+
24+/* tTalkbox */
25+#define NUM_TALKBOX_PARAM 4
26+
27+typedef struct _tTalkbox
28+{
29+ float param[NUM_TALKBOX_PARAM];
30+
31+ int bufsize;
32+ float* car0;
33+ float* car1;
34+ float* window;
35+ float* buf0;
36+ float* buf1;
37+
38+ float emphasis;
39+ int32_t K, N, O, pos;
40+ float wet, dry, FX;
41+ float d0, d1, d2, d3, d4;
42+ float u0, u1, u2, u3, u4;
43+
44+} tTalkbox;
45+
46+void tTalkbox_init (tTalkbox* const, int bufsize);
47+void tTalkbox_free (tTalkbox* const);
48+float tTalkbox_tick (tTalkbox* const, float synth, float voice);
49+void tTalkbox_update (tTalkbox* const);
50+void tTalkbox_suspend (tTalkbox* const);
51+void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);
52+void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o);
53+void tTalkbox_setQuality (tTalkbox* const, float quality);
54+
55+//==============================================================================
56+
57+/* tVocoder */
58+#define NUM_VOCODER_PARAM 8
59+#define NBANDS 16
60+
61+typedef struct _tVocoder
62+{
63+ float param[NUM_VOCODER_PARAM];
64+
65+ float gain; //output level
66+ float thru, high; //hf thru
67+ float kout; //downsampled output
68+ int32_t kval; //downsample counter
69+ int32_t nbnd; //number of bands
70+
71+ //filter coeffs and buffers - seems it's faster to leave this global than make local copy
72+ float f[NBANDS][13]; //[0-8][0 1 2 | 0 1 2 3 | 0 1 2 3 | val rate]
73+
74+} tVocoder;
75+
76+void tVocoder_init (tVocoder* const);
77+void tVocoder_free (tVocoder* const);
78+float tVocoder_tick (tVocoder* const, float synth, float voice);
79+void tVocoder_update (tVocoder* const);
80+void tVocoder_suspend (tVocoder* const);
81+
82+//==============================================================================
83+
84+
85+//==============================================================================
86+
87+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
88+
89+/* tSOLAD : pitch shifting algorithm that underlies tPitchShifter etc */
90+#define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two
91+#define LOOPMASK (LOOPSIZE - 1)
92+#define PITCHFACTORDEFAULT 1.0f
93+#define INITPERIOD 64.0f
94+#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f)
95+#define MINPERIOD 8.0f
96+
97+typedef struct _tSOLAD
98+{
99+ uint16_t timeindex; // current reference time, write index
100+ uint16_t blocksize; // signal input / output block size
101+ float pitchfactor; // pitch factor between 0.25 and 4
102+ float readlag; // read pointer's lag behind write pointer
103+ float period; // period length in input signal
104+ float jump; // read pointer jump length and direction
105+ float xfadelength; // crossfade length expressed at input sample rate
106+ float xfadevalue; // crossfade phase and value
107+
108+ float* delaybuf;
109+
110+} tSOLAD;
111+
112+void tSOLAD_init (tSOLAD* const);
113+void tSOLAD_free (tSOLAD* const);
114+
115+// send one block of input samples, receive one block of output samples
116+void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize);
117+
118+// set periodicity analysis data
119+void tSOLAD_setPeriod (tSOLAD *w, float period);
120+
121+// set pitch factor between 0.25 and 4
122+void tSOLAD_setPitchFactor (tSOLAD *w, float pitchfactor);
123+
124+// force readpointer lag
125+void tSOLAD_setReadLag (tSOLAD *w, float readlag);
126+
127+// reset state variables
128+void tSOLAD_resetState (tSOLAD *w);
129+
130+// Pitch shifter
131+typedef struct _tPitchShifter
132+{
133+ tEnvPD env;
134+ tSNAC snac;
135+ tSOLAD sola;
136+ tHighpass hp;
137+
138+ float* inBuffer;
139+ float* outBuffer;
140+ int frameSize;
141+ int bufSize;
142+ int framesPerBuffer;
143+ int curBlock;
144+ int lastBlock;
145+ int index;
146+
147+ uint16_t hopSize;
148+ uint16_t windowSize;
149+ uint8_t fba;
150+
151+ float pitchFactor;
152+ float timeConstant;
153+ float radius;
154+ float max;
155+ float lastmax;
156+ float deltamax;
157+
158+} tPitchShifter;
159+
160+void tPitchShifter_init (tPitchShifter* const, float* in, float* out, int bufSize, int frameSize);
161+void tPitchShifter_free (tPitchShifter* const);
162+
163+float tPitchShifter_tick (tPitchShifter* const, float sample);
164+float tPitchShifterToFreq_tick (tPitchShifter* const, float sample, float freq);
165+float tPitchShifterToFunc_tick (tPitchShifter* const, float sample, float (*fun)(float));
166+void tPitchShifter_ioSamples_toFreq (tPitchShifter* const, float* in, float* out, int size, float toFreq);
167+void tPitchShifter_ioSamples_toPeriod(tPitchShifter* const, float* in, float* out, int size, float toPeriod);
168+void tPitchShifter_ioSamples_toFunc (tPitchShifter* const, float* in, float* out, int size, float (*fun)(float));
169+void tPitchShifter_setPitchFactor (tPitchShifter* const, float pf);
170+void tPitchShifter_setTimeConstant (tPitchShifter* const, float tc);
171+void tPitchShifter_setHopSize (tPitchShifter* const, int hs);
172+void tPitchShifter_setWindowSize (tPitchShifter* const, int ws);
173+float tPitchShifter_getPeriod (tPitchShifter* const);
174+
175+//==============================================================================
176+
177+// Pitch shift
178+typedef struct _tPitchShift
179+{
180+ tSOLAD sola;
181+ tHighpass hp;
182+ tPeriodDetection* p;
183+
184+ float* outBuffer;
185+ int frameSize;
186+ int bufSize;
187+
188+ int framesPerBuffer;
189+ int curBlock;
190+ int lastBlock;
191+ int index;
192+
193+ float pitchFactor;
194+ float timeConstant;
195+ float radius;
196+} tPitchShift;
197+
198+void tPitchShift_init (tPitchShift* const,tPeriodDetection* const, float* out, int bufSize);
199+void tPitchShift_free (tPitchShift* const);
200+
201+float tPitchShift_shift (tPitchShift* const);
202+float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float));
203+float tPitchShift_shiftToFreq (tPitchShift* const, float freq);
204+void tPitchShift_setPitchFactor (tPitchShift* const, float pf);
205+
206+//==============================================================================
207+
208+#define FORD 7
209+#define FORMANT_BUFFER_SIZE 2048
210+
211+typedef struct _tFormantShifter
212+{
213+ int ford;
214+ int bufsize;
215+ float falph;
216+ float flamb;
217+ float* fk;
218+ float* fb;
219+ float* fc;
220+ float* frb;
221+ float* frc;
222+ float* fsig;
223+ float* fsmooth;
224+ float fhp;
225+ float flp;
226+ float flpa;
227+ float** fbuff;
228+ float* ftvec;
229+ float fmute;
230+ float fmutealph;
231+ unsigned int cbi;
232+
233+} tFormantShifter;
234+
235+void tFormantShifter_init (tFormantShifter* const, int bufsize, int order);
236+void tFormantShifter_free (tFormantShifter* const);
237+
238+float tFormantShifter_tick (tFormantShifter* const, float input, float fwarp);
239+float tFormantShifter_remove (tFormantShifter* const, float input);
240+float tFormantShifter_add (tFormantShifter* const, float input, float fwarp);
241+void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp);
242+
243+//==============================================================================
244+
245+#ifdef __cplusplus
246+}
247+#endif
248+
249+#endif // LEAF_EFFECTS_H_INCLUDED
250+
251+//==============================================================================
LEAF/Inc/leaf-electrical.hrenamed from LEAF/Inc/leaf-WDF.h+4−4
@@ -1,12 +1,12 @@
11 /*
2− * leaf-WDF.h
2+ * leaf-electrical.h
33 *
44 * Created on: Sep 25, 2019
55 * Author: jeffsnyder
66 */
77
8−#ifndef LEAF_INC_LEAF_WDF_H_
9−#define LEAF_INC_LEAF_WDF_H_
8+#ifndef LEAF_INC_LEAF_ELECTRICAL_H_
9+#define LEAF_INC_LEAF_ELECTRICAL_H_
1010
1111 #ifdef __cplusplus
1212 extern "C" {
@@ -86,4 +86,4 @@ float tWDF_getCurrent(tWDF* const r); · 73 unmodified lines
8686 }
8787 #endif
8888
89−#endif /* LEAF_INC_LEAF_WDF_H_ */
89+#endif /* LEAF_INC_LEAF_ELECTRICAL_H_ */
LEAF/Inc/leaf-envelopes.h+136−0
@@ -0,0 +1,136 @@
1+/*
2+ ==============================================================================
3+
4+ leaf-envelopes.h
5+ Created: 20 Jan 2017 12:02:17pm
6+ Author: Michael R Mulshine
7+
8+ ==============================================================================
9+*/
10+
11+#ifndef LEAF_ENVELOPES_H_INCLUDED
12+#define LEAF_ENVELOPES_H_INCLUDED
13+
14+#ifdef __cplusplus
15+extern "C" {
16+#endif
17+
18+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
19+
20+#include "leaf-math.h"
21+#include "leaf-filters.h"
22+#include "leaf-delay.h"
23+
24+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
25+
26+/* Attack-Decay envelope */
27+typedef struct _tEnvelope {
28+
29+ const float *exp_buff;
30+ const float *inc_buff;
31+ uint32_t buff_size;
32+
33+ float next;
34+
35+ float attackInc, decayInc, rampInc;
36+
37+ oBool inAttack, inDecay, inRamp;
38+
39+ oBool loop;
40+
41+ float gain, rampPeak;
42+
43+ float attackPhase, decayPhase, rampPhase;
44+
45+} tEnvelope;
46+
47+void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop);
48+void tEnvelope_free (tEnvelope* const);
49+
50+float tEnvelope_tick (tEnvelope* const);
51+int tEnvelope_setAttack (tEnvelope* const, float attack);
52+int tEnvelope_setDecay (tEnvelope* const, float decay);
53+int tEnvelope_loop (tEnvelope* const, oBool loop);
54+int tEnvelope_on (tEnvelope* const, float velocity);
55+
56+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
57+
58+/* ADSR */
59+typedef struct _tADSR
60+{
61+ const float *exp_buff;
62+ const float *inc_buff;
63+ uint32_t buff_size;
64+
65+ float next;
66+
67+ float attackInc, decayInc, releaseInc, rampInc;
68+
69+ oBool inAttack, inDecay, inSustain, inRelease, inRamp;
70+
71+ float sustain, gain, rampPeak, releasePeak;
72+
73+ float attackPhase, decayPhase, releasePhase, rampPhase;
74+
75+} tADSR;
76+
77+void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
78+void tADSR_free (tADSR* const);
79+
80+float tADSR_tick (tADSR* const);
81+int tADSR_setAttack (tADSR* const, float attack);
82+int tADSR_setDecay (tADSR* const, float decay);
83+int tADSR_setSustain(tADSR* const, float sustain);
84+int tADSR_setRelease(tADSR* const, float release);
85+int tADSR_on (tADSR* const, float velocity);
86+int tADSR_off (tADSR* const);
87+
88+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
89+
90+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
91+
92+/* Ramp */
93+typedef struct _tRamp {
94+ float inc;
95+ float inv_sr_ms;
96+ float minimum_time;
97+ float curr,dest;
98+ float time;
99+ int samples_per_tick;
100+
101+} tRamp;
102+
103+void tRamp_init (tRamp* const, float time, int samplesPerTick);
104+void tRamp_free (tRamp* const);
105+
106+float tRamp_tick (tRamp* const);
107+float tRamp_sample (tRamp* const);
108+int tRamp_setTime (tRamp* const, float time);
109+int tRamp_setDest (tRamp* const, float dest);
110+int tRamp_setVal (tRamp* const, float val);
111+
112+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
113+
114+/* Exponential Smoother */
115+typedef struct _tExpSmooth {
116+ float factor, oneminusfactor;
117+ float curr,dest;
118+
119+} tExpSmooth;
120+
121+void tExpSmooth_init (tExpSmooth* const, float val, float factor);
122+void tExpSmooth_free (tExpSmooth* const);
123+
124+float tExpSmooth_tick (tExpSmooth* const);
125+float tExpSmooth_sample (tExpSmooth* const);
126+int tExpSmooth_setFactor (tExpSmooth* const, float factor);
127+int tExpSmooth_setDest (tExpSmooth* const, float dest);
128+int tExpSmooth_setVal (tExpSmooth* const, float val);
129+
130+#ifdef __cplusplus
131+}
132+#endif
133+
134+#endif // LEAF_ENVELOPES_H_INCLUDED
135+
136+
LEAF/Inc/leaf-filters.hrenamed from LEAF/Inc/leaf-filter.h+12−12
@@ -1,13 +1,13 @@
11 /*==============================================================================
22
3− leaf-filter.h
3+ leaf-filters.h
44 Created: 20 Jan 2017 12:01:10pm
55 Author: Michael R Mulshine
66
77 ==============================================================================*/
88
9−#ifndef LEAF_FILTER_H_INCLUDED
10−#define LEAF_FILTER_H_INCLUDED
9+#ifndef LEAF_FILTERS_H_INCLUDED
10+#define LEAF_FILTERS_H_INCLUDED
1111
1212 #ifdef __cplusplus
1313 extern "C" {
@@ -26,7 +26,7 @@ typedef struct _tAllpass · 12 unmodified lines
2626 {
2727 float gain;
2828
29− tDelayL delay;
29+ tLinearDelay delay;
3030
3131 float lastOut;
3232
@@ -227,21 +227,21 @@ int tSVF_setQ (tSVF* const, float Q); · 194 unmodified lines
227227 //==============================================================================
228228
229229 /* Efficient State Variable Filter for 14-bit control input, [0, 4096). */
230−typedef struct _tSVFE
230+typedef struct _tEfficientSVF
231231 {
232232 SVFType type;
233233 float cutoff, Q;
234234 float ic1eq,ic2eq;
235235 float g,k,a1,a2,a3;
236236
237−} tSVFE;
237+} tEfficientSVF;
238238
239−void tSVFE_init (tSVFE* const, SVFType type, uint16_t controlFreq, float Q);
240−void tSVFE_free (tSVFE* const);
239+void tEfficientSVF_init (tEfficientSVF* const, SVFType type, uint16_t controlFreq, float Q);
240+void tEfficientSVF_free (tEfficientSVF* const);
241241
242−float tSVFE_tick (tSVFE* const, float v0);
243−int tSVFE_setFreq (tSVFE* const, uint16_t controlFreq);
244−int tSVFE_setQ (tSVFE* const, float Q);
242+float tEfficientSVF_tick (tEfficientSVF* const, float v0);
243+int tEfficientSVF_setFreq (tEfficientSVF* const, uint16_t controlFreq);
244+int tEfficientSVF_setQ (tEfficientSVF* const, float Q);
245245
246246 //==============================================================================
247247
@@ -307,6 +307,6 @@ void tFIR_coeffs (tFIR* const, float in); · 59 unmodified lines
307307 }
308308 #endif
309309
310−#endif // LEAF_FILTER_H_INCLUDED
310+#endif // LEAF_FILTERS_H_INCLUDED
311311
312312 //==============================================================================
LEAF/Inc/leaf-formant.h+0−68
@@ -1,68 +0,0 @@
1−/*==============================================================================
2−
3− leaf-formant.h
4− Created: 30 Nov 2018 11:03:37am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#ifndef LEAF_FORMANT_H_INCLUDED
10−#define LEAF_FORMANT_H_INCLUDED
11−
12−#ifdef __cplusplus
13−extern "C" {
14−#endif
15−
16−//==============================================================================
17−
18−#include "leaf-global.h"
19−#include "leaf-mempool.h"
20−#include "leaf-math.h"
21−
22−//==============================================================================
23−
24−#define FORD 7
25−#define FORMANT_BUFFER_SIZE 2048
26−
27−typedef struct _tFormantShifter
28−{
29− int ford;
30− int bufsize;
31− float falph;
32− float flamb;
33− float* fk;
34− float* fb;
35− float* fc;
36− float* frb;
37− float* frc;
38− float* fsig;
39− float* fsmooth;
40− float fhp;
41− float flp;
42− float flpa;
43− float** fbuff;
44− float* ftvec;
45− float fmute;
46− float fmutealph;
47− unsigned int cbi;
48−
49−} tFormantShifter;
50−
51−void tFormantShifter_init (tFormantShifter* const, int bufsize, int order);
52−void tFormantShifter_free (tFormantShifter* const);
53−
54−float tFormantShifter_tick (tFormantShifter* const, float input, float fwarp);
55−float tFormantShifter_remove (tFormantShifter* const, float input);
56−float tFormantShifter_add (tFormantShifter* const, float input, float fwarp);
57−void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp);
58−
59−//==============================================================================
60−
61−#ifdef __cplusplus
62−}
63−#endif
64−
65−#endif // LEAF_FORMANT_H_INCLUDED
66−
67−//==============================================================================
68−
LEAF/Inc/leaf-instruments.hrenamed from LEAF/Inc/leaf-808.h+7−7
@@ -1,13 +1,13 @@
11 /*==============================================================================
22
3− leaf-808.h
3+ leaf-instruments.h
44 Created: 30 Nov 2018 10:24:44am
55 Author: airship
66
77 ==============================================================================*/
88
9−#ifndef LEAF_808_H_INCLUDED
10−#define LEAF_808_H_INCLUDED
9+#ifndef LEAF_INSTRUMENTS_H_INCLUDED
10+#define LEAF_INSTRUMENTS_H_INCLUDED
1111
1212 #ifdef __cplusplus
1313 extern "C" {
@@ -16,9 +16,9 @@ extern "C" { · 2 unmodified lines
1616 //==============================================================================
1717
1818 #include "leaf-math.h"
19−#include "leaf-oscillator.h"
20−#include "leaf-utilities.h"
21−#include "leaf-filter.h"
19+#include "leaf-oscillators.h"
20+#include "leaf-filters.h"
21+#include "leaf-envelopes.h"
2222
2323 //==============================================================================
2424
@@ -177,7 +177,7 @@ void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ) · 152 unmodified lines
177177 }
178178 #endif
179179
180−#endif // LEAF_808_H_INCLUDED
180+#endif // LEAF_INSTRUMENTS_H_INCLUDED
181181
182182 //==============================================================================
183183
LEAF/Inc/leaf-midi.h+29−1
@@ -18,10 +18,38 @@ extern "C" { · 17 unmodified lines
1818 #include "leaf-global.h"
1919 #include "leaf-mempool.h"
2020 #include "leaf-math.h"
21−#include "leaf-utilities.h"
21+#include "leaf-envelopes.h"
2222
2323 //==============================================================================
2424
25+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
26+
27+// STACK implementation (fixed size)
28+#define STACK_SIZE 128
29+typedef struct _tStack
30+{
31+ int data[STACK_SIZE];
32+ uint16_t pos;
33+ uint16_t size;
34+ uint16_t capacity;
35+ oBool ordered;
36+
37+} tStack;
38+
39+void tStack_init (tStack* const);
40+void tStack_free (tStack* const);
41+
42+void tStack_setCapacity (tStack* const, uint16_t cap);
43+int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);
44+void tStack_add (tStack* const, uint16_t item);
45+int tStack_remove (tStack* const, uint16_t item);
46+void tStack_clear (tStack* const);
47+int tStack_first (tStack* const);
48+int tStack_getSize (tStack* const);
49+int tStack_contains (tStack* const, uint16_t item);
50+int tStack_next (tStack* const);
51+int tStack_get (tStack* const, int which);
52+
2553 /* tPoly */
2654 typedef struct _tPoly
2755 {
LEAF/Inc/leaf-oscillators.hrenamed from LEAF/Inc/leaf-oscillator.h+83−84
@@ -1,13 +1,13 @@
11 /*==============================================================================
22
3− leaf-oscillator.h
3+ leaf-oscillators.h
44 Created: 20 Jan 2017 12:00:58pm
55 Author: Michael R Mulshine
66
77 ==============================================================================*/
88
9−#ifndef LEAF_OSCILLATOR_H_INCLUDED
10−#define LEAF_OSCILLATOR_H_INCLUDED
9+#ifndef LEAF_OSCILLATORS_H_INCLUDED
10+#define LEAF_OSCILLATORS_H_INCLUDED
1111
1212 #ifdef __cplusplus
1313 extern "C" {
@@ -16,68 +16,7 @@ extern "C" { · 2 unmodified lines
1616 //==============================================================================
1717
1818 #include "leaf-math.h"
19−
20−#include "leaf-filter.h"
21−
22−//==============================================================================
23−
24−/* tNeuron */
25−typedef enum NeuronMode
26−{
27− NeuronNormal = 0,
28− NeuronTanh,
29− NeuronAaltoShaper,
30− NeuronModeNil
31−} NeuronMode;
32−
33−typedef struct _tNeuron
34−{
35− tPoleZero f;
36−
37− NeuronMode mode;
38−
39− float voltage, current;
40− float timeStep;
41−
42− float alpha[3];
43− float beta[3];
44− float rate[3];
45− float V[3];
46− float P[3];
47− float gK, gN, gL, C;
48−} tNeuron;
49−
50−void tNeuron_init (tNeuron* const);
51−void tNeuron_free (tNeuron* const);
52−
53−void tNeuron_reset (tNeuron* const);
54−float tNeuron_Tick (tNeuron* const);
55−void tNeuron_setMode (tNeuron* const, NeuronMode mode);
56−void tNeuron_setCurrent (tNeuron* const, float current);
57−void tNeuron_setK (tNeuron* const, float K);
58−void tNeuron_setL (tNeuron* const, float L);
59−void tNeuron_setN (tNeuron* const, float N);
60−void tNeuron_setC (tNeuron* const, float C);
61−void tNeuron_setV1 (tNeuron* const, float V1);
62−void tNeuron_setV2 (tNeuron* const, float V2);
63−void tNeuron_setV3 (tNeuron* const, float V3);
64−void tNeuron_setTimeStep (tNeuron* const, float timestep);
65−
66−//==============================================================================
67−
68−/* tPhasor: Aliasing phasor [0.0, 1.0) */
69−typedef struct _tPhasor
70−{
71− float phase;
72− float inc,freq;
73−
74−} tPhasor;
75−
76−void tPhasor_init (tPhasor* const);
77−void tPhasor_free (tPhasor* const);
78−
79−float tPhasor_tick (tPhasor* const);
80−int tPhasor_setFreq (tPhasor* const, float freq);
19+#include "leaf-filters.h"
8120
8221 //==============================================================================
8322
@@ -98,23 +37,6 @@ int tCycle_setFreq (tCycle* const, float freq); · 14 unmodified lines
9837
9938 //==============================================================================
10039
101−/* tSawtooth: Anti-aliased Sawtooth waveform using wavetable interpolation. Wavetables constructed from sine components. */
102−typedef struct _tSawtooth
103−{
104− // Underlying phasor
105− float phase;
106− float inc,freq;
107−
108−} tSawtooth;
109−
110−void tSawtooth_init (tSawtooth* const);
111−void tSawtooth_free (tSawtooth* const);
112−
113−float tSawtooth_tick (tSawtooth* const);
114−int tSawtooth_setFreq (tSawtooth* const, float freq);
115−
116−//==============================================================================
117−
11840 /* tTriangle: Anti-aliased Triangle waveform using wavetable interpolation. Wavetables constructed from sine components. */
11941 typedef struct _tTriangle
12042 {
@@ -146,6 +68,39 @@ void tSquare_free (tSquare* const); · 25 unmodified lines
14668
14769 float tSquare_tick (tSquare* const);
14870 int tSquare_setFreq (tSquare* const, float freq);
71+
72+//==============================================================================
73+
74+/* tSawtooth: Anti-aliased Sawtooth waveform using wavetable interpolation. Wavetables constructed from sine components. */
75+typedef struct _tSawtooth
76+{
77+ // Underlying phasor
78+ float phase;
79+ float inc,freq;
80+
81+} tSawtooth;
82+
83+void tSawtooth_init (tSawtooth* const);
84+void tSawtooth_free (tSawtooth* const);
85+
86+float tSawtooth_tick (tSawtooth* const);
87+int tSawtooth_setFreq (tSawtooth* const, float freq);
88+
89+//==============================================================================
90+
91+/* tPhasor: Aliasing phasor [0.0, 1.0) */
92+typedef struct _tPhasor
93+{
94+ float phase;
95+ float inc,freq;
96+
97+} tPhasor;
98+
99+void tPhasor_init (tPhasor* const);
100+void tPhasor_free (tPhasor* const);
101+
102+float tPhasor_tick (tPhasor* const);
103+int tPhasor_setFreq (tPhasor* const, float freq);
149104
150105 //==============================================================================
151106
@@ -161,7 +116,7 @@ typedef struct _tNoise · 9 unmodified lines
161116 {
162117 NoiseType type;
163118 float pinkb0, pinkb1, pinkb2;
164− float(*rand)();
119+ float(*rand)(void);
165120
166121 } tNoise;
167122
@@ -169,6 +124,50 @@ void tNoise_init (tNoise* const, NoiseType type); · 1 unmodified line
169124 void tNoise_free (tNoise* const);
170125
171126 float tNoise_tick (tNoise* const);
127+
128+//==============================================================================
129+
130+/* tNeuron */
131+typedef enum NeuronMode
132+{
133+ NeuronNormal = 0,
134+ NeuronTanh,
135+ NeuronAaltoShaper,
136+ NeuronModeNil
137+} NeuronMode;
138+
139+typedef struct _tNeuron
140+{
141+ tPoleZero f;
142+
143+ NeuronMode mode;
144+
145+ float voltage, current;
146+ float timeStep;
147+
148+ float alpha[3];
149+ float beta[3];
150+ float rate[3];
151+ float V[3];
152+ float P[3];
153+ float gK, gN, gL, C;
154+} tNeuron;
155+
156+void tNeuron_init (tNeuron* const);
157+void tNeuron_free (tNeuron* const);
158+
159+void tNeuron_reset (tNeuron* const);
160+float tNeuron_Tick (tNeuron* const);
161+void tNeuron_setMode (tNeuron* const, NeuronMode mode);
162+void tNeuron_setCurrent (tNeuron* const, float current);
163+void tNeuron_setK (tNeuron* const, float K);
164+void tNeuron_setL (tNeuron* const, float L);
165+void tNeuron_setN (tNeuron* const, float N);
166+void tNeuron_setC (tNeuron* const, float C);
167+void tNeuron_setV1 (tNeuron* const, float V1);
168+void tNeuron_setV2 (tNeuron* const, float V2);
169+void tNeuron_setV3 (tNeuron* const, float V3);
170+void tNeuron_setTimeStep (tNeuron* const, float timestep);
172171
173172 //==============================================================================
174173
@@ -176,6 +175,6 @@ float tNoise_tick (tNoise* const); · 1 unmodified line
176175 }
177176 #endif
178177
179−#endif // LEAF_OSCILLATOR_H_INCLUDED
178+#endif // LEAF_OSCILLATORS_H_INCLUDED
180179
181180 //==============================================================================
LEAF/Inc/leaf-oversampler.h+0−51
@@ -1,51 +0,0 @@
1−//
2−// leaf-oversampler.h
3−// LEAF
4−//
5−// Created by Matthew Wang and Joshua Becker on 2/28/19.
6−// Copyright © 2019 Princeton University. All rights reserved.
7−//
8−//==============================================================================
9−
10−#ifndef LEAF_OVERSAMPLER_H_INCLUDED
11−#define LEAF_OVERSAMPLER_H_INCLUDED
12−
13−#ifdef __cplusplus
14−extern "C" {
15−#endif
16−
17−//==============================================================================
18−
19−#include "leaf-global.h"
20−#include "leaf-mempool.h"
21−#include "leaf-math.h"
22−#include "leaf-filter.h"
23−
24−//==============================================================================
25−
26−typedef struct _tOversampler
27−{
28− int ratio;
29− float* pCoeffs;
30− float* upState;
31− float* downState;
32− int numTaps;
33− int phaseLength;
34−} tOversampler;
35−
36−void tOversampler_init(tOversampler* const, int order, oBool extraQuality);
37−void tOversampler_free(tOversampler* const);
38−void tOversampler_upsample(tOversampler* const, float input, float* output);
39−float tOversampler_downsample(tOversampler *const os, float* input);
40−float tOversampler_tick(tOversampler* const, float input, float (*effectTick)(float));
41−int tOversampler_getLatency(tOversampler* const os);
42−
43−//==============================================================================
44−
45−#ifdef __cplusplus
46−}
47−#endif
48−
49−#endif // LEAF_OVERSAMPLER_H_INCLUDED
50−
51−//==============================================================================
LEAF/Inc/leaf-physical.h+221−0
@@ -0,0 +1,221 @@
1+/*
2+ ==============================================================================
3+
4+ leaf-physical.h
5+ Created: 30 Nov 2018 10:41:55am
6+ Author: airship
7+
8+ ==============================================================================
9+*/
10+
11+#ifndef LEAF_PHYSICAL_H_INCLUDED
12+#define LEAF_PHYSICAL_H_INCLUDED
13+
14+#ifdef __cplusplus
15+extern "C" {
16+#endif
17+
18+//==============================================================================
19+
20+#include "leaf-global.h"
21+#include "leaf-math.h"
22+#include "leaf-delay.h"
23+#include "leaf-filters.h"
24+#include "leaf-oscillators.h"
25+#include "leaf-envelopes.h"
26+#include "leaf-dynamics.h"
27+
28+//==============================================================================
29+
30+/* Karplus Strong model */
31+typedef struct _tPluck
32+{
33+ tAllpassDelay delayLine; // Allpass or Linear?? big difference...
34+ tOneZero loopFilter;
35+ tOnePole pickFilter;
36+ tNoise noise;
37+
38+ float lastOut;
39+ float loopGain;
40+ float lastFreq;
41+
42+ float sr;
43+
44+} tPluck;
45+
46+void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
47+void tPluck_free (tPluck* const);
48+
49+float tPluck_tick (tPluck* const);
50+
51+// Pluck the string.
52+void tPluck_pluck (tPluck* const, float amplitude);
53+
54+// Start a note with the given frequency and amplitude.;
55+void tPluck_noteOn (tPluck* const, float frequency, float amplitude );
56+
57+// Stop a note with the given amplitude (speed of decay).
58+void tPluck_noteOff (tPluck* const, float amplitude );
59+
60+// Set instrument parameters for a particular frequency.
61+void tPluck_setFrequency (tPluck* const, float frequency );
62+
63+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
64+void tPluck_controlChange (tPluck* const, int number, float value);
65+
66+// tPluck Utilities.
67+float tPluck_getLastOut (tPluck* const);
68+
69+//==============================================================================
70+
71+/* Stif Karplus Strong model */
72+typedef struct _tKarplusStrong
73+{
74+ tAllpassDelay delayLine;
75+ tLinearDelay combDelay;
76+ tOneZero filter;
77+ tNoise noise;
78+ tBiQuad biquad[4];
79+
80+
81+
82+ uint32_t length;
83+ float loopGain;
84+ float baseLoopGain;
85+ float lastFrequency;
86+ float lastLength;
87+ float stretching;
88+ float pluckAmplitude;
89+ float pickupPosition;
90+
91+ float lastOut;
92+
93+} tKarplusStrong;
94+
95+typedef enum SKControlType
96+{
97+ SKPickPosition = 0,
98+ SKStringDamping,
99+ SKDetune,
100+ SKControlTypeNil
101+} SKControlType;
102+
103+void tKarplusStrong_init (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
104+void tKarplusStrong_free (tKarplusStrong* const);
105+
106+float tKarplusStrong_tick (tKarplusStrong* const);
107+
108+// Pluck the string.
109+void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude);
110+
111+// Start a note with the given frequency and amplitude.;
112+void tKarplusStrong_noteOn (tKarplusStrong* const, float frequency, float amplitude );
113+
114+// Stop a note with the given amplitude (speed of decay).
115+void tKarplusStrong_noteOff (tKarplusStrong* const, float amplitude );
116+
117+// Set instrument parameters for a particular frequency.
118+void tKarplusStrong_setFrequency (tKarplusStrong* const, float frequency );
119+
120+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
121+// Use SKPickPosition, SKStringDamping, or SKDetune for type.
122+void tKarplusStrong_controlChange (tKarplusStrong* const, SKControlType type, float value);
123+
124+// Set the stretch "factor" of the string (0.0 - 1.0).
125+void tKarplusStrong_setStretch (tKarplusStrong* const, float stretch );
126+
127+// Set the pluck or "excitation" position along the string (0.0 - 1.0).
128+void tKarplusStrong_setPickupPosition (tKarplusStrong* const, float position );
129+
130+// Set the base loop gain.
131+void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const, float aGain );
132+
133+// tKarplusStrong utilities.
134+float tKarplusStrong_getLastOut (tKarplusStrong* const);
135+
136+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
137+
138+/* Simple Living String */
139+typedef struct _tSimpleLivingString {
140+ float freq, waveLengthInSamples; // the frequency of the string, determining delay length
141+ float dampFreq; // frequency for the bridge LP filter, in Hz
142+ float decay; // amplitude damping factor for the string (only active in mode 0)
143+ float levMode;
144+ float curr;
145+ tLinearDelay delayLine;
146+ tOnePole bridgeFilter;
147+ tHighpass DCblocker;
148+ tFeedbackLeveler fbLev;
149+ tExpSmooth wlSmooth;
150+} tSimpleLivingString;
151+
152+void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode);
153+void tSimpleLivingString_free (tSimpleLivingString* const);
154+float tSimpleLivingString_tick (tSimpleLivingString* const, float input);
155+float tSimpleLivingString_sample (tSimpleLivingString* const);
156+int tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq);
157+int tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples
158+int tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq);
159+int tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0
160+int tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev);
161+int tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor);
162+int tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);
163+int tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);
164+
165+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
166+
167+/* Living String */
168+typedef struct _tLivingString {
169+ float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length
170+ float pickPos; // the pick position, dividing the string in two, in ratio
171+ float prepIndex; // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj)
172+ float dampFreq; // frequency for the bridge LP filter, in Hz
173+ float decay; // amplitude damping factor for the string (only active in mode 0)
174+ float levMode;
175+ float curr;
176+ tLinearDelay delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model
177+ tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL;
178+ tHighpass DCblockerL, DCblockerU;
179+ tFeedbackLeveler fbLevU, fbLevL;
180+ tExpSmooth wlSmooth, ppSmooth;
181+} tLivingString;
182+
183+void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay,
184+ float targetLev, float levSmoothFactor, float levStrength, int levMode);
185+void tLivingString_free (tLivingString* const);
186+float tLivingString_tick (tLivingString* const, float input);
187+float tLivingString_sample (tLivingString* const);
188+int tLivingString_setFreq (tLivingString* const, float freq);
189+int tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples
190+int tLivingString_setPickPos (tLivingString* const, float pickPos);
191+int tLivingString_setPrepIndex (tLivingString* const, float prepIndex);
192+int tLivingString_setDampFreq (tLivingString* const, float dampFreq);
193+int tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0
194+int tLivingString_setTargetLev (tLivingString* const, float targetLev);
195+int tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);
196+int tLivingString_setLevStrength (tLivingString* const, float levStrength);
197+int tLivingString_setLevMode (tLivingString* const, int levMode);
198+
199+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
200+
201+//Reed Table - borrowed from STK
202+typedef struct _tReedTable {
203+ float offset, slope;
204+} tReedTable;
205+
206+void tReedTable_init (tReedTable* const, float offset, float slope);
207+void tReedTable_free (tReedTable* const);
208+float tReedTable_tick (tReedTable* const, float input);
209+float tReedTable_tanh_tick (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code
210+void tReedTable_setOffset (tReedTable* const, float offset);
211+void tReedTable_setSlope (tReedTable* const, float slope);
212+
213+//==============================================================================
214+
215+#ifdef __cplusplus
216+}
217+#endif
218+
219+#endif // LEAF_PHYSICAL_H_INCLUDED
220+
221+//==============================================================================
LEAF/Inc/leaf-pitch.h+0−161
@@ -1,161 +0,0 @@
1−/*
2− ==============================================================================
3−
4− leaf-pitch.h
5− Created: 30 Nov 2018 11:03:13am
6− Author: airship
7−
8− ==============================================================================
9−*/
10−
11−#ifndef LEAF_PITCH_H_INCLUDED
12−#define LEAF_PITCH_H_INCLUDED
13−
14−#ifdef __cplusplus
15−extern "C" {
16−#endif
17−
18−//==============================================================================
19−
20−#include "leaf-global.h"
21−#include "leaf-math.h"
22−
23−#include "leaf-filter.h"
24−#include "leaf-utilities.h"
25−
26−//==============================================================================
27−
28−#define DEFPITCHRATIO 2.0f
29−#define DEFTIMECONSTANT 100.0f
30−#define DEFHOPSIZE 64
31−#define DEFWINDOWSIZE 64
32−#define FBA 20
33−#define HPFREQ 40.0f
34−
35−
36−//==============================================================================
37−
38−// Pitch shifter
39−typedef struct _tPitchShifter
40−{
41− tEnv env;
42− tSNAC snac;
43− tSOLAD sola;
44− tHighpass hp;
45−
46− float* inBuffer;
47− float* outBuffer;
48− int frameSize;
49− int bufSize;
50− int framesPerBuffer;
51− int curBlock;
52− int lastBlock;
53− int index;
54−
55− uint16_t hopSize;
56− uint16_t windowSize;
57− uint8_t fba;
58−
59− float pitchFactor;
60− float timeConstant;
61− float radius;
62− float max;
63− float lastmax;
64− float deltamax;
65−
66−} tPitchShifter;
67−
68−void tPitchShifter_init (tPitchShifter* const, float* in, float* out, int bufSize, int frameSize);
69−void tPitchShifter_free (tPitchShifter* const);
70−
71−float tPitchShifter_tick (tPitchShifter* const, float sample);
72−float tPitchShifterToFreq_tick (tPitchShifter* const, float sample, float freq);
73−float tPitchShifterToFunc_tick (tPitchShifter* const, float sample, float (*fun)(float));
74−void tPitchShifter_ioSamples_toFreq (tPitchShifter* const, float* in, float* out, int size, float toFreq);
75−void tPitchShifter_ioSamples_toPeriod(tPitchShifter* const, float* in, float* out, int size, float toPeriod);
76−void tPitchShifter_ioSamples_toFunc (tPitchShifter* const, float* in, float* out, int size, float (*fun)(float));
77−void tPitchShifter_setPitchFactor (tPitchShifter* const, float pf);
78−void tPitchShifter_setTimeConstant (tPitchShifter* const, float tc);
79−void tPitchShifter_setHopSize (tPitchShifter* const, int hs);
80−void tPitchShifter_setWindowSize (tPitchShifter* const, int ws);
81−float tPitchShifter_getPeriod (tPitchShifter* const);
82−
83−//==============================================================================
84−
85−// Period detection
86−typedef struct _tPeriod
87−{
88− tEnv env;
89− tSNAC snac;
90− float* inBuffer;
91− float* outBuffer;
92− int frameSize;
93− int bufSize;
94− int framesPerBuffer;
95− int curBlock;
96− int lastBlock;
97− int i;
98− int indexstore;
99− int iLast;
100− int index;
101− float period;
102−
103− uint16_t hopSize;
104− uint16_t windowSize;
105− uint8_t fba;
106−
107− float timeConstant;
108− float radius;
109− float max;
110− float lastmax;
111− float deltamax;
112−
113−}tPeriod;
114−
115−void tPeriod_init (tPeriod* const, float* in, float* out, int bufSize, int frameSize);
116−void tPeriod_free (tPeriod* const);
117−
118−float tPeriod_findPeriod (tPeriod* const, float sample);
119−void tPeriod_setHopSize (tPeriod* p, int hs);
120−void tPeriod_setWindowSize (tPeriod* p, int ws);
121−
122−//==============================================================================
123−
124−// Pitch shift
125−typedef struct _tPitchShift
126−{
127− tSOLAD sola;
128− tHighpass hp;
129− tPeriod* p;
130−
131− float* outBuffer;
132− int frameSize;
133− int bufSize;
134−
135− int framesPerBuffer;
136− int curBlock;
137− int lastBlock;
138− int index;
139−
140− float pitchFactor;
141− float timeConstant;
142− float radius;
143−} tPitchShift;
144−
145−void tPitchShift_init (tPitchShift* const, tPeriod* const, float* out, int bufSize);
146−void tPitchShift_free (tPitchShift* const);
147−
148−float tPitchShift_shift (tPitchShift* const);
149−float tPitchShift_shiftToFunc (tPitchShift* const, float (*fun)(float));
150−float tPitchShift_shiftToFreq (tPitchShift* const, float freq);
151−void tPitchShift_setPitchFactor (tPitchShift* const, float pf);
152−
153−//==============================================================================
154−
155−#ifdef __cplusplus
156−}
157−#endif
158−
159−#endif // LEAF_PITCH_H_INCLUDED
160−
161−//==============================================================================
LEAF/Inc/leaf-reverb.h+29−30
@@ -17,15 +17,14 @@ extern "C" { · 16 unmodified lines
1717
1818 #include "leaf-global.h"
1919 #include "leaf-math.h"
20−
2120 #include "leaf-delay.h"
22−#include "leaf-filter.h"
23−#include "leaf-oscillator.h"
21+#include "leaf-filters.h"
22+#include "leaf-oscillators.h"
2423
2524 //==============================================================================
2625
27−/* PRCRev: Reverb, reimplemented from STK (Cook and Scavone). */
28−typedef struct _tPRCRev
26+/* PRCReverb: Reverb, reimplemented from STK (Cook and Scavone). */
27+typedef struct _tPRCReverb
2928 {
3029 float mix, t60;
3130
@@ -38,23 +37,23 @@ typedef struct _tPRCRev · 6 unmodified lines
3837
3938 float lastIn, lastOut;
4039
41−} tPRCRev;
40+} tPRCReverb;
4241
43−void tPRCRev_init (tPRCRev* const, float t60);
44−void tPRCRev_free (tPRCRev* const);
42+void tPRCReverb_init (tPRCReverb* const, float t60);
43+void tPRCReverb_free (tPRCReverb* const);
4544
46−float tPRCRev_tick (tPRCRev* const, float input);
45+float tPRCReverb_tick (tPRCReverb* const, float input);
4746
4847 // Set reverb time in seconds.
49−void tPRCRev_setT60 (tPRCRev* const, float t60);
48+void tPRCReverb_setT60 (tPRCReverb* const, float t60);
5049
5150 // Set mix between dry input and wet output signal.
52−void tPRCRev_setMix (tPRCRev* const, float mix);
51+void tPRCReverb_setMix (tPRCReverb* const, float mix);
5352
5453 //==============================================================================
5554
56−/* NRev: Reverb, reimplemented from STK (Cook and Scavone). */
57−typedef struct _tNRev
55+/* NReverb: Reverb, reimplemented from STK (Cook and Scavone). */
56+typedef struct _tNReverb
5857 {
5958 float mix, t60;
6059
@@ -68,22 +67,22 @@ typedef struct _tNRev · 7 unmodified lines
6867
6968 float lastIn, lastOut;
7069
71−} tNRev;
70+} tNReverb;
7271
73−void tNRev_init (tNRev* const, float t60);
74−void tNRev_free (tNRev* const);
72+void tNReverb_init (tNReverb* const, float t60);
73+void tNReverb_free (tNReverb* const);
7574
76−float tNRev_tick (tNRev* const, float input);
75+float tNReverb_tick (tNReverb* const, float input);
7776
7877 // Set reverb time in seconds.
79−void tNRev_setT60 (tNRev* const, float t60);
78+void tNReverb_setT60 (tNReverb* const, float t60);
8079
8180 // Set mix between dry input and wet output signal.
82−void tNRev_setMix (tNRev* const, float mix);
81+void tNReverb_setMix (tNReverb* const, float mix);
8382
8483 //==============================================================================
8584
86−typedef struct _tDattorro
85+typedef struct _tDattorroReverb
8786 {
8887 float predelay;
8988 float input_filter;
@@ -125,19 +124,19 @@ typedef struct _tDattorro · 35 unmodified lines
125124
126125 tCycle f2_lfo;
127126
128−} tDattorro;
127+} tDattorroReverb;
129128
130−void tDattorro_init (tDattorro* const);
131−void tDattorro_free (tDattorro* const);
129+void tDattorroReverb_init (tDattorroReverb* const);
130+void tDattorroReverb_free (tDattorroReverb* const);
132131
133−float tDattorro_tick (tDattorro* const, float input);
132+float tDattorroReverb_tick (tDattorroReverb* const, float input);
134133
135−void tDattorro_setMix (tDattorro* const, float mix);
136−void tDattorro_setSize (tDattorro* const, float size);
137−void tDattorro_setInputDelay (tDattorro* const, float preDelay);
138−void tDattorro_setInputFilter (tDattorro* const, float freq);
139−void tDattorro_setFeedbackFilter (tDattorro* const, float freq);
140−void tDattorro_setFeedbackGain (tDattorro* const, float gain);
134+void tDattorroReverb_setMix (tDattorroReverb* const, float mix);
135+void tDattorroReverb_setSize (tDattorroReverb* const, float size);
136+void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay);
137+void tDattorroReverb_setInputFilter (tDattorroReverb* const, float freq);
138+void tDattorroReverb_setFeedbackFilter (tDattorroReverb* const, float freq);
139+void tDattorroReverb_setFeedbackGain (tDattorroReverb* const, float gain);
141140
142141 #ifdef __cplusplus
143142 }
LEAF/Inc/leaf-sample.h+0−125
@@ -1,125 +0,0 @@
1−/*==============================================================================
2−
3− leaf-sample.h
4− Created: 23 Jan 2019 11:22:09am
5− Author: Mike Mulshine
6−
7−==============================================================================*/
8−
9−
10−#ifndef LEAF_SAMPLE_H_INCLUDED
11−#define LEAF_SAMPLE_H_INCLUDED
12−
13−#ifdef __cplusplus
14−extern "C" {
15−#endif
16−
17−//==============================================================================
18−
19−#include "leaf-global.h"
20−#include "leaf-math.h"
21−
22−#include "leaf-utilities.h"
23−
24−//==============================================================================
25−
26− typedef enum RecordMode
27− {
28− RecordOneShot = 0,
29− RecordLoop,
30− RecordModeNil
31− } RecordMode;
32−
33− typedef struct _tBuffer
34− {
35− float* buff;
36−
37− uint32_t idx;
38− uint32_t length;
39−
40− RecordMode mode;
41−
42− int active;
43−
44− } tBuffer;
45−
46− void tBuffer_init (tBuffer* const, uint32_t length);
47− void tBuffer_free (tBuffer* const);
48−
49− void tBuffer_tick (tBuffer* const, float sample);
50−
51− void tBuffer_read(tBuffer* const, float* buff, uint32_t len);
52−
53− float tBuffer_get (tBuffer* const, int idx);
54−
55− void tBuffer_record (tBuffer* const);
56− void tBuffer_stop (tBuffer* const);
57−
58− void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
59−
60− void tBuffer_clear (tBuffer* const);
61−
62−//==============================================================================
63−
64− typedef enum PlayMode
65− {
66− PlayNormal,
67− PlayLoop,
68− PlayBackAndForth,
69− PlayModeNil
70− } PlayMode;
71−
72− typedef struct _tSampler
73− {
74− tBuffer* samp;
75−
76− tRamp gain;
77−
78− float idx;
79− float inc;
80− float last;
81− float iinc;
82− int8_t dir;
83− int8_t flip;
84− int8_t bnf;
85−
86− int32_t start;
87− int32_t end;
88− uint32_t len;
89− uint32_t cfxlen;
90−
91− PlayMode mode;
92− int retrigger;
93−
94− int active;
95−
96− } tSampler;
97−
98− void tSampler_init (tSampler* const, tBuffer* const);
99− void tSampler_free (tSampler* const);
100−
101− float tSampler_tick (tSampler* const);
102−
103− void tSampler_setSample (tSampler* const, tBuffer* s);
104−
105− void tSampler_setMode (tSampler* const, PlayMode mode);
106−
107− void tSampler_play (tSampler* const);
108− void tSampler_stop (tSampler* const);
109−
110− void tSampler_setStart (tSampler* const, int32_t start);
111− void tSampler_setEnd (tSampler* const, int32_t end);
112−
113− void tSampler_setCrossfadeLength (tSampler* const p, uint32_t length);
114−
115− void tSampler_setRate (tSampler* const, float rate);
116−
117−//==============================================================================
118−
119−#ifdef __cplusplus
120−}
121−#endif
122−
123−#endif // LEAF_SAMPLE_H_INCLUDED
124−
125−//==============================================================================
LEAF/Inc/leaf-sampling.h+124−0
@@ -0,0 +1,124 @@
1+/*==============================================================================
2+
3+leaf-sampling.h
4+Created: 23 Jan 2019 11:22:09am
5+Author: Mike Mulshine
6+
7+==============================================================================*/
8+
9+
10+#ifndef LEAF_SAMPLING_H_INCLUDED
11+#define LEAF_SAMPLING_H_INCLUDED
12+
13+#ifdef __cplusplus
14+extern "C" {
15+#endif
16+
17+//==============================================================================
18+
19+#include "leaf-global.h"
20+#include "leaf-math.h"
21+#include "leaf-envelopes.h"
22+
23+//==============================================================================
24+
25+typedef enum RecordMode
26+{
27+ RecordOneShot = 0,
28+ RecordLoop,
29+ RecordModeNil
30+} RecordMode;
31+
32+typedef struct _tBuffer
33+{
34+ float* buff;
35+
36+ uint32_t idx;
37+ uint32_t length;
38+
39+ RecordMode mode;
40+
41+ int active;
42+
43+} tBuffer;
44+
45+void tBuffer_init (tBuffer* const, uint32_t length);
46+void tBuffer_free (tBuffer* const);
47+
48+void tBuffer_tick (tBuffer* const, float sample);
49+
50+void tBuffer_read(tBuffer* const, float* buff, uint32_t len);
51+
52+float tBuffer_get (tBuffer* const, int idx);
53+
54+void tBuffer_record (tBuffer* const);
55+void tBuffer_stop (tBuffer* const);
56+
57+void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
58+
59+void tBuffer_clear (tBuffer* const);
60+
61+//==============================================================================
62+
63+typedef enum PlayMode
64+{
65+ PlayNormal,
66+ PlayLoop,
67+ PlayBackAndForth,
68+ PlayModeNil
69+} PlayMode;
70+
71+typedef struct _tSampler
72+{
73+ tBuffer* samp;
74+
75+ tRamp gain;
76+
77+ float idx;
78+ float inc;
79+ float last;
80+ float iinc;
81+ int8_t dir;
82+ int8_t flip;
83+ int8_t bnf;
84+
85+ int32_t start;
86+ int32_t end;
87+ uint32_t len;
88+ uint32_t cfxlen;
89+
90+ PlayMode mode;
91+ int retrigger;
92+
93+ int active;
94+
95+} tSampler;
96+
97+void tSampler_init (tSampler* const, tBuffer* const);
98+void tSampler_free (tSampler* const);
99+
100+float tSampler_tick (tSampler* const);
101+
102+void tSampler_setSample (tSampler* const, tBuffer* s);
103+
104+void tSampler_setMode (tSampler* const, PlayMode mode);
105+
106+void tSampler_play (tSampler* const);
107+void tSampler_stop (tSampler* const);
108+
109+void tSampler_setStart (tSampler* const, int32_t start);
110+void tSampler_setEnd (tSampler* const, int32_t end);
111+
112+void tSampler_setCrossfadeLength (tSampler* const p, uint32_t length);
113+
114+void tSampler_setRate (tSampler* const, float rate);
115+
116+//==============================================================================
117+
118+#ifdef __cplusplus
119+}
120+#endif
121+
122+#endif // LEAF_SAMPLING_H_INCLUDED
123+
124+//==============================================================================
LEAF/Inc/leaf-string.h+0−143
@@ -1,143 +0,0 @@
1−/*
2− ==============================================================================
3−
4− leaf-string.h
5− Created: 30 Nov 2018 10:41:55am
6− Author: airship
7−
8− ==============================================================================
9−*/
10−
11−#ifndef LEAF_STRING_H_INCLUDED
12−#define LEAF_STRING_H_INCLUDED
13−
14−#ifdef __cplusplus
15−extern "C" {
16−#endif
17−
18−//==============================================================================
19−
20−#include "leaf-global.h"
21−#include "leaf-math.h"
22−
23−#include "leaf-delay.h"
24−#include "leaf-filter.h"
25−#include "leaf-oscillator.h"
26−
27−//==============================================================================
28−
29−/* Karplus Strong model */
30−typedef struct _tPluck
31−{
32− tDelayA delayLine; // Allpass or Linear?? big difference...
33− tOneZero loopFilter;
34− tOnePole pickFilter;
35− tNoise noise;
36−
37− float lastOut;
38− float loopGain;
39− float lastFreq;
40−
41− float sr;
42−
43−} tPluck;
44−
45−void tPluck_init (tPluck* const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
46−void tPluck_free (tPluck* const);
47−
48−float tPluck_tick (tPluck* const);
49−
50−// Pluck the string.
51−void tPluck_pluck (tPluck* const, float amplitude);
52−
53−// Start a note with the given frequency and amplitude.;
54−void tPluck_noteOn (tPluck* const, float frequency, float amplitude );
55−
56−// Stop a note with the given amplitude (speed of decay).
57−void tPluck_noteOff (tPluck* const, float amplitude );
58−
59−// Set instrument parameters for a particular frequency.
60−void tPluck_setFrequency (tPluck* const, float frequency );
61−
62−// Perform the control change specified by \e number and \e value (0.0 - 128.0).
63−void tPluck_controlChange (tPluck* const, int number, float value);
64−
65−// tPluck Utilities.
66−float tPluck_getLastOut (tPluck* const);
67−
68−//==============================================================================
69−
70−/* Stif Karplus Strong model */
71−typedef struct _tStifKarp
72−{
73− tDelayA delayLine;
74− tDelayL combDelay;
75− tOneZero filter;
76− tNoise noise;
77− tBiQuad biquad[4];
78−
79−
80−
81− uint32_t length;
82− float loopGain;
83− float baseLoopGain;
84− float lastFrequency;
85− float lastLength;
86− float stretching;
87− float pluckAmplitude;
88− float pickupPosition;
89−
90− float lastOut;
91−
92−} tStifKarp;
93−
94−typedef enum SKControlType
95−{
96− SKPickPosition = 0,
97− SKStringDamping,
98− SKDetune,
99− SKControlTypeNil
100−} SKControlType;
101−
102−void tStifKarp_init (tStifKarp* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
103−void tStifKarp_free (tStifKarp* const);
104−
105−float tStifKarp_tick (tStifKarp* const);
106−
107−// Pluck the string.
108−void tStifKarp_pluck (tStifKarp* const, float amplitude);
109−
110−// Start a note with the given frequency and amplitude.;
111−void tStifKarp_noteOn (tStifKarp* const, float frequency, float amplitude );
112−
113−// Stop a note with the given amplitude (speed of decay).
114−void tStifKarp_noteOff (tStifKarp* const, float amplitude );
115−
116−// Set instrument parameters for a particular frequency.
117−void tStifKarp_setFrequency (tStifKarp* const, float frequency );
118−
119−// Perform the control change specified by \e number and \e value (0.0 - 128.0).
120−// Use SKPickPosition, SKStringDamping, or SKDetune for type.
121−void tStifKarp_controlChange (tStifKarp* const, SKControlType type, float value);
122−
123−// Set the stretch "factor" of the string (0.0 - 1.0).
124−void tStifKarp_setStretch (tStifKarp* const, float stretch );
125−
126−// Set the pluck or "excitation" position along the string (0.0 - 1.0).
127−void tStifKarp_setPickupPosition (tStifKarp* const, float position );
128−
129−// Set the base loop gain.
130−void tStifKarp_setBaseLoopGain (tStifKarp* const, float aGain );
131−
132−// tStifKarp utilities.
133−float tStifKarp_getLastOut (tStifKarp* const);
134−
135−//==============================================================================
136−
137−#ifdef __cplusplus
138−}
139−#endif
140−
141−#endif // LEAF_STRING_H_INCLUDED
142−
143−//==============================================================================
LEAF/Inc/leaf-tables.h+3−3
@@ -6,8 +6,8 @@ · 5 unmodified lines
66
77 ==============================================================================*/
88
9−#ifndef LEAF_WAVETABLES_H_INCLUDED
10−#define LEAF_WAVETABLES_H_INCLUDED
9+#ifndef LEAF_TABLES_H_INCLUDED
10+#define LEAF_TABLES_H_INCLUDED
1111
1212 #ifdef __cplusplus
1313 extern "C" {
@@ -95,6 +95,6 @@ extern const float squarewave[11][SQR_TABLE_SIZE]; · 81 unmodified lines
9595 }
9696 #endif
9797
98−#endif // LEAF_WAVETABLES_H_INCLUDED
98+#endif // LEAF_TABLES_H_INCLUDED
9999
100100 //==============================================================================
LEAF/Inc/leaf-utilities.h+0−483
@@ -1,483 +0,0 @@
1−/*
2− ==============================================================================
3−
4− LEAFUtilities.h
5− Created: 20 Jan 2017 12:02:17pm
6− Author: Michael R Mulshine
7−
8− ==============================================================================
9−*/
10−
11−#ifndef LEAFUTILITIES_H_INCLUDED
12−#define LEAFUTILITIES_H_INCLUDED
13−
14−#ifdef __cplusplus
15−extern "C" {
16−#endif
17−
18−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
19−
20−#include "leaf-math.h"
21−#include "leaf-filter.h"
22−#include "leaf-delay.h"
23−
24−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
25−
26−// STACK implementation (fixed size)
27−#define STACK_SIZE 128
28−typedef struct _tStack
29−{
30− int data[STACK_SIZE];
31− uint16_t pos;
32− uint16_t size;
33− uint16_t capacity;
34− oBool ordered;
35−
36−} tStack;
37−
38−void tStack_init (tStack* const);
39−void tStack_free (tStack* const);
40−
41−void tStack_setCapacity (tStack* const, uint16_t cap);
42−int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);
43−void tStack_add (tStack* const, uint16_t item);
44−int tStack_remove (tStack* const, uint16_t item);
45−void tStack_clear (tStack* const);
46−int tStack_first (tStack* const);
47−int tStack_getSize (tStack* const);
48−int tStack_contains (tStack* const, uint16_t item);
49−int tStack_next (tStack* const);
50−int tStack_get (tStack* const, int which);
51−
52−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
53−
54−/* Ramp */
55−typedef struct _tRamp {
56− float inc;
57− float inv_sr_ms;
58− float minimum_time;
59− float curr,dest;
60− float time;
61− int samples_per_tick;
62−
63−} tRamp;
64−
65−void tRamp_init (tRamp* const, float time, int samplesPerTick);
66−void tRamp_free (tRamp* const);
67−
68−float tRamp_tick (tRamp* const);
69−float tRamp_sample (tRamp* const);
70−int tRamp_setTime (tRamp* const, float time);
71−int tRamp_setDest (tRamp* const, float dest);
72−int tRamp_setVal (tRamp* const, float val);
73−
74−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
75−
76−/* Exponential Smoother */
77−typedef struct _tExpSmooth {
78− float factor, oneminusfactor;
79− float curr,dest;
80−
81−} tExpSmooth;
82−
83−void tExpSmooth_init (tExpSmooth* const, float val, float factor);
84−void tExpSmooth_free (tExpSmooth* const);
85−
86−float tExpSmooth_tick (tExpSmooth* const);
87−float tExpSmooth_sample (tExpSmooth* const);
88−int tExpSmooth_setFactor (tExpSmooth* const, float factor);
89−int tExpSmooth_setDest (tExpSmooth* const, float dest);
90−int tExpSmooth_setVal (tExpSmooth* const, float val);
91−
92−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
93−
94−/* PowerEnvelopeFollower */
95−typedef struct _tPwrFollow {
96− float factor, oneminusfactor;
97− float curr;
98−
99−} tPwrFollow;
100−
101−void tPwrFollow_init (tPwrFollow* const, float factor);
102−void tPwrFollow_free (tPwrFollow* const);
103−float tPwrFollow_tick (tPwrFollow* const, float input);
104−float tPwrFollow_sample (tPwrFollow* const);
105−int tPwrFollow_setFactor (tPwrFollow* const, float factor);
106−
107−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
108−
109−//Reed Table - borrowed from STK
110−typedef struct _tReedTable {
111− float offset, slope;
112−} tReedTable;
113−
114−void tReedTable_init (tReedTable* const, float offset, float slope);
115−void tReedTable_free (tReedTable* const);
116−float tReedTable_tick (tReedTable* const, float input);
117−float tReedTable_tanh_tick (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code
118−void tReedTable_setOffset (tReedTable* const, float offset);
119−void tReedTable_setSlope (tReedTable* const, float slope);
120−
121−
122−
123−///
124−/* Feedback leveller */
125−// An auto VCA that you put into a feedback circuit to make it stay at the same level.
126−// It can enforce level bidirectionally (amplifying and attenuating as needed) or
127−// just attenutating. The former option allows for infinite sustain strings, for example, while
128−// The latter option allows for decaying strings, which can never exceed
129−// a specific level.
130−
131−typedef struct _tFBleveller {
132− float targetLevel; // target power level
133− float strength; // how strongly level difference affects the VCA
134− int mode; // 0 for upwards limiting only, 1 for biderctional limiting
135− float curr;
136− tPwrFollow pwrFlw; // internal power follower needed for level tracking
137−
138−} tFBleveller;
139−
140−void tFBleveller_init (tFBleveller* const, float targetLevel, float factor, float strength, int mode);
141−void tFBleveller_free (tFBleveller* const);
142−
143−float tFBleveller_tick (tFBleveller* const, float input);
144−float tFBleveller_sample (tFBleveller* const);
145−int tFBleveller_setTargetLevel (tFBleveller* const, float TargetLevel);
146−int tFBleveller_setFactor (tFBleveller* const, float factor);
147−int tFBleveller_setMode (tFBleveller* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
148−int tFBleveller_setStrength (tFBleveller* const, float strength);
149−
150−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
151−
152−/* Simple Living String */
153−typedef struct _tSimpleLivingString {
154− float freq, waveLengthInSamples; // the frequency of the string, determining delay length
155− float dampFreq; // frequency for the bridge LP filter, in Hz
156− float decay; // amplitude damping factor for the string (only active in mode 0)
157− float levMode;
158− float curr;
159− tDelayL delayLine;
160− tOnePole bridgeFilter;
161− tHighpass DCblocker;
162− tFBleveller fbLev;
163− tExpSmooth wlSmooth;
164−} tSimpleLivingString;
165−
166−void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode);
167−void tSimpleLivingString_free (tSimpleLivingString* const);
168−float tSimpleLivingString_tick (tSimpleLivingString* const, float input);
169−float tSimpleLivingString_sample (tSimpleLivingString* const);
170−int tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq);
171−int tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples
172−int tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq);
173−int tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0
174−int tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev);
175−int tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor);
176−int tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);
177−int tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);
178−
179−
180−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
181−
182−/* Living String */
183−typedef struct _tLivingString {
184− float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length
185− float pickPos; // the pick position, dividing the string in two, in ratio
186− float prepIndex; // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj)
187− float dampFreq; // frequency for the bridge LP filter, in Hz
188− float decay; // amplitude damping factor for the string (only active in mode 0)
189− float levMode;
190− float curr;
191− tDelayL delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model
192− tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL;
193− tHighpass DCblockerL, DCblockerU;
194− tFBleveller fbLevU, fbLevL;
195− tExpSmooth wlSmooth, ppSmooth;
196−} tLivingString;
197−
198−void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay,
199− float targetLev, float levSmoothFactor, float levStrength, int levMode);
200−void tLivingString_free (tLivingString* const);
201−float tLivingString_tick (tLivingString* const, float input);
202−float tLivingString_sample (tLivingString* const);
203−int tLivingString_setFreq (tLivingString* const, float freq);
204−int tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples
205−int tLivingString_setPickPos (tLivingString* const, float pickPos);
206−int tLivingString_setPrepIndex (tLivingString* const, float prepIndex);
207−int tLivingString_setDampFreq (tLivingString* const, float dampFreq);
208−int tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0
209−int tLivingString_setTargetLev (tLivingString* const, float targetLev);
210−int tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);
211−int tLivingString_setLevStrength (tLivingString* const, float levStrength);
212−int tLivingString_setLevMode (tLivingString* const, int levMode);
213−
214−
215−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
216−
217−/* Compressor */
218−typedef struct _tCompressor
219−{
220− float tauAttack, tauRelease;
221− float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain
222−
223− float x_G[2], y_G[2], x_T[2], y_T[2];
224−
225− oBool isActive;
226−
227−}tCompressor;
228−
229−void tCompressor_init (tCompressor* const);
230−void tCompressor_free (tCompressor* const);
231−float tCompressor_tick (tCompressor* const, float input);
232−
233−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
234−
235−/* Attack-Decay envelope */
236−typedef struct _tEnvelope {
237−
238− const float *exp_buff;
239− const float *inc_buff;
240− uint32_t buff_size;
241−
242− float next;
243−
244− float attackInc, decayInc, rampInc;
245−
246− oBool inAttack, inDecay, inRamp;
247−
248− oBool loop;
249−
250− float gain, rampPeak;
251−
252− float attackPhase, decayPhase, rampPhase;
253−
254−} tEnvelope;
255−
256−void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop);
257−void tEnvelope_free (tEnvelope* const);
258−
259−float tEnvelope_tick (tEnvelope* const);
260−int tEnvelope_setAttack (tEnvelope* const, float attack);
261−int tEnvelope_setDecay (tEnvelope* const, float decay);
262−int tEnvelope_loop (tEnvelope* const, oBool loop);
263−int tEnvelope_on (tEnvelope* const, float velocity);
264−
265−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
266−
267−/* ADSR */
268−typedef struct _tADSR
269−{
270− const float *exp_buff;
271− const float *inc_buff;
272− uint32_t buff_size;
273−
274− float next;
275−
276− float attackInc, decayInc, releaseInc, rampInc;
277−
278− oBool inAttack, inDecay, inSustain, inRelease, inRamp;
279−
280− float sustain, gain, rampPeak, releasePeak;
281−
282− float attackPhase, decayPhase, releasePhase, rampPhase;
283−
284−} tADSR;
285−
286−void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
287−void tADSR_free (tADSR* const);
288−
289−float tADSR_tick (tADSR* const);
290−int tADSR_setAttack (tADSR* const, float attack);
291−int tADSR_setDecay (tADSR* const, float decay);
292−int tADSR_setSustain(tADSR* const, float sustain);
293−int tADSR_setRelease(tADSR* const, float release);
294−int tADSR_on (tADSR* const, float velocity);
295−int tADSR_off (tADSR* const);
296−
297−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
298−
299−/* Envelope Follower */
300−typedef struct _tEnvelopeFollower
301−{
302− float y;
303− float a_thresh;
304− float d_coeff;
305−
306−} tEnvelopeFollower;
307−
308−void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff);
309−void tEnvelopeFollower_free (tEnvelopeFollower* const);
310−
311−float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x);
312−int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff);
313−int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh);
314−
315−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
316−
317−/* tAtkDtk */
318−#define DEFBLOCKSIZE 1024
319−#define DEFTHRESHOLD 6
320−#define DEFATTACK 10
321−#define DEFRELEASE 10
322−
323−typedef struct _tAtkDtk
324−{
325− float env;
326−
327− //Attack & Release times in msec
328− int atk;
329− int rel;
330−
331− //Attack & Release coefficients based on times
332− float atk_coeff;
333− float rel_coeff;
334−
335− int blocksize;
336− int samplerate;
337−
338− //RMS amplitude of previous block - used to decide if attack is present
339− float prevAmp;
340−
341− float threshold;
342−} tAtkDtk;
343−
344−void tAtkDtk_init (tAtkDtk* const, int blocksize);
345−void tAtkDtk_init_expanded (tAtkDtk* const, int blocksize, int atk, int rel);
346−void tAtkDtk_free (tAtkDtk* const);
347−
348−// set expected input blocksize
349−void tAtkDtk_setBlocksize (tAtkDtk* const, int size);
350−
351−// change atkDetector sample rate
352−void tAtkDtk_setSamplerate (tAtkDtk* const, int inRate);
353−
354−// set attack time and coeff
355−void tAtkDtk_setAtk (tAtkDtk* const, int inAtk);
356−
357−// set release time and coeff
358−void tAtkDtk_setRel (tAtkDtk* const, int inRel);
359−
360−// set level above which values are identified as attacks
361−void tAtkDtk_setThreshold (tAtkDtk* const, float thres);
362−
363−// find largest transient in input block, return index of attack
364−int tAtkDtk_detect (tAtkDtk* const, float *in);
365−
366−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
367−
368−// ENV~ from PD, modified for LEAF
369−#define MAXOVERLAP 32
370−#define INITVSTAKEN 64
371−#define ENV_WINDOW_SIZE 1024
372−#define ENV_HOP_SIZE 256
373−
374−typedef struct _tEnv
375−{
376− float buf[ENV_WINDOW_SIZE + INITVSTAKEN];
377− uint16_t x_phase; /* number of points since last output */
378− uint16_t x_period; /* requested period of output */
379− uint16_t x_realperiod; /* period rounded up to vecsize multiple */
380− uint16_t x_npoints; /* analysis window size in samples */
381− float x_result; /* result to output */
382− float x_sumbuf[MAXOVERLAP]; /* summing buffer */
383− float x_f;
384− uint16_t windowSize, hopSize, blockSize;
385− uint16_t x_allocforvs; /* extra buffer for DSP vector size */
386−} tEnv;
387−
388−void tEnv_init (tEnv* const, int windowSize, int hopSize, int blockSize);
389−void tEnv_free (tEnv* const);
390−float tEnv_tick (tEnv* const);
391−void tEnv_processBlock (tEnv* const, float* in);
392−
393−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
394−
395−/* tSOLAD : pitch shifting algorithm that underlies tPitchShifter etc */
396−#define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two
397−#define LOOPMASK (LOOPSIZE - 1)
398−#define PITCHFACTORDEFAULT 1.0f
399−#define INITPERIOD 64.0f
400−#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f)
401−#define MINPERIOD 8.0f
402−
403−typedef struct _tSOLAD
404−{
405− uint16_t timeindex; // current reference time, write index
406− uint16_t blocksize; // signal input / output block size
407− float pitchfactor; // pitch factor between 0.25 and 4
408− float readlag; // read pointer's lag behind write pointer
409− float period; // period length in input signal
410− float jump; // read pointer jump length and direction
411− float xfadelength; // crossfade length expressed at input sample rate
412− float xfadevalue; // crossfade phase and value
413−
414− float* delaybuf;
415−
416−} tSOLAD;
417−
418−void tSOLAD_init (tSOLAD* const);
419−void tSOLAD_free (tSOLAD* const);
420−
421−// send one block of input samples, receive one block of output samples
422−void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize);
423−
424−// set periodicity analysis data
425−void tSOLAD_setPeriod (tSOLAD *w, float period);
426−
427−// set pitch factor between 0.25 and 4
428−void tSOLAD_setPitchFactor (tSOLAD *w, float pitchfactor);
429−
430−// force readpointer lag
431−void tSOLAD_setReadLag (tSOLAD *w, float readlag);
432−
433−// reset state variables
434−void tSOLAD_resetState (tSOLAD *w);
435−
436−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
437−
438−// tSNAC: period detector
439−#define SNAC_FRAME_SIZE 1024 // default analysis framesize // should be the same as (or smaller than?) PS_FRAME_SIZE
440−#define DEFOVERLAP 1 // default overlap
441−#define DEFBIAS 0.2f // default bias
442−#define DEFMINRMS 0.003f // default minimum RMS
443−#define SEEK 0.85f // seek-length as ratio of framesize
444−
445−typedef struct _tSNAC
446−{
447− float* inputbuf;
448− float* processbuf;
449− float* spectrumbuf;
450− float* biasbuf;
451− uint16_t timeindex;
452− uint16_t framesize;
453− uint16_t overlap;
454− uint16_t periodindex;
455−
456− float periodlength;
457− float fidelity;
458− float biasfactor;
459− float minrms;
460−
461−} tSNAC;
462−
463−void tSNAC_init (tSNAC* const, int overlaparg); // constructor
464−void tSNAC_free (tSNAC* const); // destructor
465−
466−void tSNAC_ioSamples (tSNAC *s, float *in, float *out, int size);
467−void tSNAC_setOverlap (tSNAC *s, int lap);
468−void tSNAC_setBias (tSNAC *s, float bias);
469−void tSNAC_setMinRMS (tSNAC *s, float rms);
470−
471−/*To get freq, perform SAMPLE_RATE/snac_getperiod() */
472−float tSNAC_getPeriod (tSNAC *s);
473−float tSNAC_getfidelity (tSNAC *s);
474−
475−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
476−
477−#ifdef __cplusplus
478−}
479−#endif
480−
481−#endif // LEAFUTILITIES_H_INCLUDED
482−
483−
LEAF/Inc/leaf-vocoder.h+0−89
@@ -1,89 +0,0 @@
1−/*==============================================================================
2−
3− leaf-vocoder.h
4− Created: 20 Jan 2017 12:01:54pm
5− Author: Michael R Mulshine
6−
7−==============================================================================*/
8−
9−#ifndef LEAF_VOCODER_H_INCLUDED
10−#define LEAF_VOCODER_H_INCLUDED
11−
12−#ifdef __cplusplus
13−extern "C" {
14−#endif
15−
16−//==============================================================================
17−
18−#include "leaf-global.h"
19−#include "leaf-math.h"
20−
21−//==============================================================================
22−
23−/* tTalkbox */
24−#define NUM_TALKBOX_PARAM 4
25−
26−typedef struct _tTalkbox
27−{
28− float param[NUM_TALKBOX_PARAM];
29−
30− int bufsize;
31− float* car0;
32− float* car1;
33− float* window;
34− float* buf0;
35− float* buf1;
36−
37− float emphasis;
38− int32_t K, N, O, pos;
39− float wet, dry, FX;
40− float d0, d1, d2, d3, d4;
41− float u0, u1, u2, u3, u4;
42−
43−} tTalkbox;
44−
45−void tTalkbox_init (tTalkbox* const, int bufsize);
46−void tTalkbox_free (tTalkbox* const);
47−float tTalkbox_tick (tTalkbox* const, float synth, float voice);
48−void tTalkbox_update (tTalkbox* const);
49−void tTalkbox_suspend (tTalkbox* const);
50−void tTalkbox_lpcDurbin (float *r, int p, float *k, float *g);
51−void tTalkbox_lpc (float *buf, float *car, int32_t n, int32_t o);
52−void tTalkbox_setQuality (tTalkbox* const, float quality);
53−
54−//==============================================================================
55−
56−/* tVocoder */
57−#define NUM_VOCODER_PARAM 8
58−#define NBANDS 16
59−
60−typedef struct _tVocoder
61−{
62− float param[NUM_VOCODER_PARAM];
63−
64− float gain; //output level
65− float thru, high; //hf thru
66− float kout; //downsampled output
67− int32_t kval; //downsample counter
68− int32_t nbnd; //number of bands
69−
70− //filter coeffs and buffers - seems it's faster to leave this global than make local copy
71− float f[NBANDS][13]; //[0-8][0 1 2 | 0 1 2 3 | 0 1 2 3 | val rate]
72−
73−} tVocoder;
74−
75−void tVocoder_init (tVocoder* const);
76−void tVocoder_free (tVocoder* const);
77−float tVocoder_tick (tVocoder* const, float synth, float voice);
78−void tVocoder_update (tVocoder* const);
79−void tVocoder_suspend (tVocoder* const);
80−
81−//==============================================================================
82−
83−#ifdef __cplusplus
84−}
85−#endif
86−
87−#endif // LEAF_VOCODER_H_INCLUDED
88−
89−//==============================================================================
LEAF/Inc/leaf-wavefolder.h+0−48
@@ -1,48 +0,0 @@
1−/*==============================================================================
2−
3− leaf-wavefolder.h
4− Created: 30 Nov 2018 11:57:05am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#ifndef LEAF_WAVEFOLDER_H_INCLUDED
10−#define LEAF_WAVEFOLDER_H_INCLUDED
11−
12−
13−#ifdef __cplusplus
14−extern "C" {
15−#endif
16−
17−//==============================================================================
18−
19−#include "leaf-global.h"
20−#include "leaf-math.h"
21−
22−//==============================================================================
23−
24−/* tLockhartWavefolder */
25−
26−typedef struct _tLockhartWavefolder
27−{
28− double Ln1;
29− double Fn1;
30− float xn1;
31−
32−} tLockhartWavefolder;
33−
34−void tLockhartWavefolder_init (tLockhartWavefolder* const);
35−void tLockhartWavefolder_free (tLockhartWavefolder* const);
36−
37−float tLockhartWavefolder_tick (tLockhartWavefolder* const, float samp);
38−
39−
40−//==============================================================================
41−
42−#ifdef __cplusplus
43−}
44−#endif
45−
46−#endif // LEAF_WAVEFOLDER_H_INCLUDED
47−
48−//==============================================================================
LEAF/Src/leaf-analysis.c+733−0
@@ -0,0 +1,733 @@
1+/*==============================================================================
2+
3+ leaf-analysis.c
4+ Created: 30 Nov 2018 11:56:49am
5+ Author: airship
6+
7+==============================================================================*/
8+
9+#if _WIN32 || _WIN64
10+
11+#include "..\Inc\leaf-analysis.h"
12+#include "..\Externals\d_fft_mayer.h"
13+
14+#else
15+
16+#include "../Inc/leaf-analysis.h"
17+#include "../Externals/d_fft_mayer.h"
18+
19+#endif
20+
21+//===========================================================================
22+/* Envelope Follower */
23+//===========================================================================
24+
25+void tEnvelopeFollower_init(tEnvelopeFollower* const e, float attackThreshold, float decayCoeff)
26+{
27+ e->y = 0.0f;
28+ e->a_thresh = attackThreshold;
29+ e->d_coeff = decayCoeff;
30+}
31+
32+void tEnvelopeFollower_free(tEnvelopeFollower* const e)
33+{
34+
35+}
36+
37+float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)
38+{
39+ if (x < 0.0f ) x = -x; /* Absolute value. */
40+
41+ if ((x >= ef->y) && (x > ef->a_thresh)) ef->y = x; /* If we hit a peak, ride the peak to the top. */
42+ else ef->y = ef->y * ef->d_coeff; /* Else, exponential decay of output. */
43+
44+ //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?
45+ //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff; // too expensive
46+
47+ if( ef->y < VSF) ef->y = 0.0f;
48+
49+ return ef->y;
50+}
51+
52+int tEnvelopeFollower_decayCoeff(tEnvelopeFollower* const ef, float decayCoeff)
53+{
54+ return ef->d_coeff = decayCoeff;
55+}
56+
57+int tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attackThresh)
58+{
59+ return ef->a_thresh = attackThresh;
60+}
61+
62+
63+
64+
65+
66+//===========================================================================
67+/* Power Follower */
68+//===========================================================================
69+void tPowerFollower_init(tPowerFollower* const p, float factor)
70+{
71+ p->curr=0.0f;
72+ p->factor=factor;
73+ p->oneminusfactor=1.0f-factor;
74+}
75+
76+void tPowerFollower_free(tPowerFollower* const p)
77+{
78+
79+}
80+
81+int tPowerFollower_setFactor(tPowerFollower* const p, float factor)
82+{
83+ if (factor<0) factor=0;
84+ if (factor>1) factor=1;
85+ p->factor=factor;
86+ p->oneminusfactor=1.0f-factor;
87+ return 0;
88+}
89+
90+float tPowerFollower_tick(tPowerFollower* const p, float input)
91+{
92+ p->curr = p->factor*input*input+p->oneminusfactor*p->curr;
93+ return p->curr;
94+}
95+
96+float tPowerFollower_sample(tPowerFollower* const p)
97+{
98+ return p->curr;
99+}
100+
101+
102+
103+
104+//===========================================================================
105+/* ---------------- env~ - simple envelope follower. ----------------- */
106+//===========================================================================
107+
108+void tEnvPD_init(tEnvPD* const x, int ws, int hs, int bs)
109+{
110+ int period = hs, npoints = ws;
111+
112+ int i;
113+
114+ if (npoints < 1) npoints = 1024;
115+ if (period < 1) period = npoints/2;
116+ if (period < npoints / MAXOVERLAP + 1)
117+ period = npoints / MAXOVERLAP + 1;
118+
119+ x->x_npoints = npoints;
120+ x->x_phase = 0;
121+ x->x_period = period;
122+
123+ x->windowSize = npoints;
124+ x->hopSize = period;
125+ x->blockSize = bs;
126+
127+ for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
128+ for (i = 0; i < npoints; i++)
129+ x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints;
130+ for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0;
131+
132+ x->x_f = 0;
133+
134+ x->x_allocforvs = INITVSTAKEN;
135+
136+ // ~ ~ ~ dsp ~ ~ ~
137+ if (x->x_period % x->blockSize)
138+ {
139+ x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize);
140+ }
141+ else
142+ {
143+ x->x_realperiod = x->x_period;
144+ }
145+ // ~ ~ ~ ~ ~ ~ ~ ~
146+}
147+
148+void tEnvPD_free (tEnvPD* const x)
149+{
150+
151+}
152+
153+float tEnvPD_tick (tEnvPD* const x)
154+{
155+ return powtodb(x->x_result);
156+}
157+
158+void tEnvPD_processBlock(tEnvPD* const x, float* in)
159+{
160+ int n = x->blockSize;
161+
162+ int count;
163+ t_sample *sump;
164+ in += n;
165+ for (count = x->x_phase, sump = x->x_sumbuf;
166+ count < x->x_npoints; count += x->x_realperiod, sump++)
167+ {
168+ t_sample *hp = x->buf + count;
169+ t_sample *fp = in;
170+ t_sample sum = *sump;
171+ int i;
172+
173+ for (i = 0; i < n; i++)
174+ {
175+ fp--;
176+ sum += *hp++ * (*fp * *fp);
177+ }
178+ *sump = sum;
179+ }
180+ sump[0] = 0;
181+ x->x_phase -= n;
182+ if (x->x_phase < 0)
183+ {
184+ x->x_result = x->x_sumbuf[0];
185+ for (count = x->x_realperiod, sump = x->x_sumbuf;
186+ count < x->x_npoints; count += x->x_realperiod, sump++)
187+ sump[0] = sump[1];
188+ sump[0] = 0;
189+ x->x_phase = x->x_realperiod - n;
190+ }
191+}
192+
193+//===========================================================================
194+// ATTACKDETECTION
195+//===========================================================================
196+/********Private function prototypes**********/
197+static void atkdtk_init(tAttackDetection* const a, int blocksize, int atk, int rel);
198+static void atkdtk_envelope(tAttackDetection* const a, float *in);
199+
200+/********Constructor/Destructor***************/
201+
202+void tAttackDetection_init(tAttackDetection* const a, int blocksize)
203+{
204+ atkdtk_init(a, blocksize, DEFATTACK, DEFRELEASE);
205+}
206+
207+void tAttackDetection_init_expanded(tAttackDetection* const a, int blocksize, int atk, int rel)
208+{
209+ atkdtk_init(a, blocksize, atk, rel);
210+}
211+
212+void tAttackDetection_free(tAttackDetection *a)
213+{
214+
215+}
216+
217+/*******Public Functions***********/
218+
219+
220+void tAttackDetection_setBlocksize(tAttackDetection* const a, int size)
221+{
222+
223+ if(!((size==64)|(size==128)|(size==256)|(size==512)|(size==1024)|(size==2048)))
224+ size = DEFBLOCKSIZE;
225+ a->blocksize = size;
226+
227+ return;
228+
229+}
230+
231+void tAttackDetection_setSamplerate(tAttackDetection* const a, int inRate)
232+{
233+ a->samplerate = inRate;
234+
235+ //Reset atk and rel to recalculate coeff
236+ tAttackDetection_setAtk(a, a->atk);
237+ tAttackDetection_setRel(a, a->rel);
238+
239+ return;
240+}
241+
242+void tAttackDetection_setThreshold(tAttackDetection* const a, float thres)
243+{
244+ a->threshold = thres;
245+ return;
246+}
247+
248+void tAttackDetection_setAtk(tAttackDetection* const a, int inAtk)
249+{
250+ a->atk = inAtk;
251+ a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));
252+
253+ return;
254+}
255+
256+void tAttackDetection_setRel(tAttackDetection* const a, int inRel)
257+{
258+ a->rel = inRel;
259+ a->rel_coeff = pow(0.01, 1.0/(a->rel * a->samplerate * 0.001));
260+
261+ return;
262+}
263+
264+
265+int tAttackDetection_detect(tAttackDetection* const a, float *in)
266+{
267+ int result;
268+
269+ atkdtk_envelope(a, in);
270+
271+ if(a->env >= a->prevAmp*2) //2 times greater = 6dB increase
272+ result = 1;
273+ else
274+ result = 0;
275+
276+ a->prevAmp = a->env;
277+
278+ return result;
279+
280+}
281+
282+/*******Private Functions**********/
283+
284+static void atkdtk_init(tAttackDetection* const a, int blocksize, int atk, int rel)
285+{
286+ a->env = 0;
287+ a->blocksize = blocksize;
288+ a->threshold = DEFTHRESHOLD;
289+ a->samplerate = leaf.sampleRate;
290+ a->prevAmp = 0;
291+
292+ a->env = 0;
293+
294+ tAttackDetection_setAtk(a, atk);
295+ tAttackDetection_setRel(a, rel);
296+}
297+
298+static void atkdtk_envelope(tAttackDetection* const a, float *in)
299+{
300+ int i = 0;
301+ float tmp;
302+ for(i = 0; i < a->blocksize; ++i){
303+ tmp = fastabs(in[i]);
304+
305+ if(tmp > a->env)
306+ a->env = a->atk_coeff * (a->env - tmp) + tmp;
307+ else
308+ a->env = a->rel_coeff * (a->env - tmp) + tmp;
309+ }
310+
311+}
312+
313+//===========================================================================
314+// PERIODDETECTION
315+//===========================================================================
316+void tPeriodDetection_init (tPeriodDetection* const p, float* in, float* out, int bufSize, int frameSize)
317+{
318+ p->inBuffer = in;
319+ p->outBuffer = out;
320+ p->bufSize = bufSize;
321+ p->frameSize = frameSize;
322+ p->framesPerBuffer = p->bufSize / p->frameSize;
323+ p->curBlock = 1;
324+ p->lastBlock = 0;
325+ p->index = 0;
326+
327+ p->hopSize = DEFHOPSIZE;
328+ p->windowSize = DEFWINDOWSIZE;
329+ p->fba = FBA;
330+
331+ tEnvPD_init(&p->env, p->windowSize, p->hopSize, p->frameSize);
332+
333+ tSNAC_init(&p->snac, DEFOVERLAP);
334+
335+ p->timeConstant = DEFTIMECONSTANT;
336+ p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
337+}
338+
339+void tPeriodDetection_free (tPeriodDetection* const p)
340+{
341+ tEnvPD_free(&p->env);
342+ tSNAC_free(&p->snac);
343+}
344+
345+float tPeriodDetection_findPeriod (tPeriodDetection* p, float sample)
346+{
347+ int i, iLast;
348+
349+ i = (p->curBlock*p->frameSize);
350+ iLast = (p->lastBlock*p->frameSize)+p->index;
351+
352+ p->i = i;
353+ p->iLast = iLast;
354+
355+ p->inBuffer[i+p->index] = sample;
356+
357+ p->index++;
358+ p->indexstore = p->index;
359+ if (p->index >= p->frameSize)
360+ {
361+ p->index = 0;
362+
363+ tEnvPD_processBlock(&p->env, &(p->inBuffer[i]));
364+
365+ tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
366+ p->period = tSNAC_getPeriod(&p->snac);
367+
368+ p->curBlock++;
369+ if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
370+ p->lastBlock++;
371+ if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
372+ }
373+
374+ // changed from period to p->period
375+ return p->period;
376+}
377+
378+void tPeriodDetection_setHopSize(tPeriodDetection* p, int hs)
379+{
380+ p->hopSize = hs;
381+}
382+
383+void tPeriodDetection_setWindowSize(tPeriodDetection* p, int ws)
384+{
385+ p->windowSize = ws;
386+}
387+
388+
389+
390+
391+
392+
393+
394+
395+
396+//===========================================================================
397+// SNAC
398+//===========================================================================
399+/******************************************************************************/
400+/***************************** private procedures *****************************/
401+/******************************************************************************/
402+
403+#define REALFFT mayer_realfft
404+#define REALIFFT mayer_realifft
405+
406+static void snac_analyzeframe(tSNAC* const s);
407+static void snac_autocorrelation(tSNAC* const s);
408+static void snac_normalize(tSNAC* const s);
409+static void snac_pickpeak(tSNAC* const s);
410+static void snac_periodandfidelity(tSNAC* const s);
411+static void snac_biasbuf(tSNAC* const s);
412+static float snac_spectralpeak(tSNAC* const s, float periodlength);
413+
414+
415+/******************************************************************************/
416+/******************************** constructor, destructor *********************/
417+/******************************************************************************/
418+
419+
420+void tSNAC_init(tSNAC* const s, int overlaparg)
421+{
422+ s->biasfactor = DEFBIAS;
423+ s->timeindex = 0;
424+ s->periodindex = 0;
425+ s->periodlength = 0.;
426+ s->fidelity = 0.;
427+ s->minrms = DEFMINRMS;
428+ s->framesize = SNAC_FRAME_SIZE;
429+
430+ s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
431+ s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2));
432+ s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2));
433+ s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
434+
435+ snac_biasbuf(s);
436+ tSNAC_setOverlap(s, overlaparg);
437+}
438+
439+void tSNAC_free(tSNAC* const s)
440+{
441+ leaf_free(s->inputbuf);
442+ leaf_free(s->processbuf);
443+ leaf_free(s->spectrumbuf);
444+ leaf_free(s->biasbuf);
445+}
446+/******************************************************************************/
447+/************************** public access functions****************************/
448+/******************************************************************************/
449+
450+
451+void tSNAC_ioSamples(tSNAC* const s, float *in, float *out, int size)
452+{
453+ int timeindex = s->timeindex;
454+ int mask = s->framesize - 1;
455+ int outindex = 0;
456+ float *inputbuf = s->inputbuf;
457+ float *processbuf = s->processbuf;
458+
459+ // call analysis function when it is time
460+ if(!(timeindex & (s->framesize / s->overlap - 1))) snac_analyzeframe(s);
461+
462+ while(size--)
463+ {
464+ inputbuf[timeindex] = *in++;
465+ out[outindex++] = processbuf[timeindex++];
466+ timeindex &= mask;
467+ }
468+ s->timeindex = timeindex;
469+}
470+
471+void tSNAC_setOverlap(tSNAC* const s, int lap)
472+{
473+ if(!((lap==1)|(lap==2)|(lap==4)|(lap==8))) lap = DEFOVERLAP;
474+ s->overlap = lap;
475+}
476+
477+
478+void tSNAC_setBias(tSNAC* const s, float bias)
479+{
480+ if(bias > 1.) bias = 1.;
481+ if(bias < 0.) bias = 0.;
482+ s->biasfactor = bias;
483+ snac_biasbuf(s);
484+ return;
485+}
486+
487+
488+void tSNAC_setMinRMS(tSNAC* const s, float rms)
489+{
490+ if(rms > 1.) rms = 1.;
491+ if(rms < 0.) rms = 0.;
492+ s->minrms = rms;
493+ return;
494+}
495+
496+
497+float tSNAC_getPeriod(tSNAC* const s)
498+{
499+ return(s->periodlength);
500+}
501+
502+
503+float tSNAC_getFidelity(tSNAC* const s)
504+{
505+ return(s->fidelity);
506+}
507+
508+
509+/******************************************************************************/
510+/***************************** private procedures *****************************/
511+/******************************************************************************/
512+
513+
514+// main analysis function
515+static void snac_analyzeframe(tSNAC* const s)
516+{
517+ int n, tindex = s->timeindex;
518+ int framesize = s->framesize;
519+ int mask = framesize - 1;
520+ float norm = 1. / sqrt((float)(framesize * 2));
521+
522+ float *inputbuf = s->inputbuf;
523+ float *processbuf = s->processbuf;
524+
525+ // copy input to processing buffers
526+ for(n=0; n<framesize; n++)
527+ {
528+ processbuf[n] = inputbuf[tindex] * norm;
529+ tindex++;
530+ tindex &= mask;
531+ }
532+
533+ // zeropadding
534+ for(n=framesize; n<(framesize<<1); n++) processbuf[n] = 0.;
535+
536+ // call analysis procedures
537+ snac_autocorrelation(s);
538+ snac_normalize(s);
539+ snac_pickpeak(s);
540+ snac_periodandfidelity(s);
541+}
542+
543+
544+static void snac_autocorrelation(tSNAC* const s)
545+{
546+ int n, m;
547+ int framesize = s->framesize;
548+ int fftsize = framesize * 2;
549+ float *processbuf = s->processbuf;
550+ float *spectrumbuf = s->spectrumbuf;
551+
552+ REALFFT(fftsize, processbuf);
553+
554+ // compute power spectrum
555+ processbuf[0] *= processbuf[0]; // DC
556+ processbuf[framesize] *= processbuf[framesize]; // Nyquist
557+
558+ for(n=1; n<framesize; n++)
559+ {
560+ processbuf[n] = processbuf[n] * processbuf[n]
561+ + processbuf[fftsize-n] * processbuf[fftsize-n]; // imag coefficients appear reversed
562+ processbuf[fftsize-n] = 0.;
563+ }
564+
565+ // store power spectrum up to SR/4 for possible later use
566+ for(m=0; m<(framesize>>1); m++)
567+ {
568+ spectrumbuf[m] = processbuf[m];
569+ }
570+
571+ // transform power spectrum to autocorrelation function
572+ REALIFFT(fftsize, processbuf);
573+ return;
574+}
575+
576+
577+static void snac_normalize(tSNAC* const s)
578+{
579+ int framesize = s->framesize;
580+ int framesizeplustimeindex = s->framesize + s->timeindex;
581+ int timeindexminusone = s->timeindex - 1;
582+ int n, m;
583+ int mask = framesize - 1;
584+ int seek = framesize * SEEK;
585+ float *inputbuf = s->inputbuf;
586+ float *processbuf= s->processbuf;
587+ float signal1, signal2;
588+
589+ // minimum RMS implemented as minimum autocorrelation at index 0
590+ // functionally equivalent to white noise floor
591+ float rms = s->minrms / sqrt(1.0f / (float)framesize);
592+ float minrzero = rms * rms;
593+ float rzero = processbuf[0];
594+ if(rzero < minrzero) rzero = minrzero;
595+ double normintegral = (double)rzero * 2.;
596+
597+ // normalize biased autocorrelation function
598+ // inputbuf is circular buffer: timeindex may be non-zero when overlap > 1
599+ processbuf[0] = 1;
600+ for(n=1, m=s->timeindex+1; n<seek; n++, m++)
601+ {
602+ signal1 = inputbuf[(n + timeindexminusone)&mask];
603+ signal2 = inputbuf[(framesizeplustimeindex - n)&mask];
604+ normintegral -= (double)(signal1 * signal1 + signal2 * signal2);
605+ processbuf[n] /= (float)normintegral * 0.5f;
606+ }
607+
608+ // flush instable function tail
609+ for(n = seek; n<framesize; n++) processbuf[n] = 0.;
610+ return;
611+}
612+
613+
614+static void snac_periodandfidelity(tSNAC* const s)
615+{
616+ float periodlength;
617+
618+ if(s->periodindex)
619+ {
620+ periodlength = (float)s->periodindex +
621+ interpolate3phase(s->processbuf, s->periodindex);
622+ if(periodlength < 8) periodlength = snac_spectralpeak(s, periodlength);
623+ s->periodlength = periodlength;
624+ s->fidelity = interpolate3max(s->processbuf, s->periodindex);
625+ }
626+ return;
627+}
628+
629+// select the peak which most probably represents period length
630+static void snac_pickpeak(tSNAC* const s)
631+{
632+ int n, peakindex=0;
633+ int seek = s->framesize * SEEK;
634+ float *processbuf= s->processbuf;
635+ float maxvalue = 0.;
636+ float biasedpeak;
637+ float *biasbuf = s->biasbuf;
638+
639+ // skip main lobe
640+ for(n=1; n<seek; n++)
641+ {
642+ if(processbuf[n] < 0.) break;
643+ }
644+
645+ // find interpolated / biased maximum in SNAC function
646+ // interpolation finds the 'real maximum'
647+ // biasing favours the first candidate
648+ for(; n<seek-1; n++)
649+ {
650+ if(processbuf[n] >= processbuf[n-1])
651+ {
652+ if(processbuf[n] > processbuf[n+1]) // we have a local peak
653+ {
654+ biasedpeak = interpolate3max(processbuf, n) * biasbuf[n];
655+
656+ if(biasedpeak > maxvalue)
657+ {
658+ maxvalue = biasedpeak;
659+ peakindex = n;
660+ }
661+ }
662+ }
663+ }
664+ s->periodindex = peakindex;
665+ return;
666+}
667+
668+
669+// verify period length via frequency domain (up till SR/4)
670+// frequency domain is more precise than lag domain for period lengths < 8
671+// argument 'periodlength' is initial estimation from autocorrelation
672+static float snac_spectralpeak(tSNAC* const s, float periodlength)
673+{
674+ if(periodlength < 4.) return periodlength;
675+
676+ float max = 0.;
677+ int n, startbin, stopbin, peakbin = 0;
678+ int spectrumsize = s->framesize>>1;
679+ float *spectrumbuf = s->spectrumbuf;
680+ float peaklocation = (float)(s->framesize * 2.) / periodlength;
681+
682+ startbin = (int)(peaklocation * 0.8 + 0.5);
683+ if(startbin < 1) startbin = 1;
684+ stopbin = (int)(peaklocation * 1.25 + 0.5);
685+ if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;
686+
687+ for(n=startbin; n<stopbin; n++)
688+ {
689+ if(spectrumbuf[n] >= spectrumbuf[n-1])
690+ {
691+ if(spectrumbuf[n] > spectrumbuf[n+1])
692+ {
693+ if(spectrumbuf[n] > max)
694+ {
695+ max = spectrumbuf[n];
696+ peakbin = n;
697+ }
698+ }
699+ }
700+ }
701+
702+ // calculate amplitudes in peak region
703+ for(n=(peakbin-1); n<(peakbin+2); n++)
704+ {
705+ spectrumbuf[n] = sqrt(spectrumbuf[n]);
706+ }
707+
708+ peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);
709+ periodlength = (float)(s->framesize * 2.0f) / peaklocation;
710+
711+ return periodlength;
712+}
713+
714+
715+// modified logarithmic bias function
716+static void snac_biasbuf(tSNAC* const s)
717+{
718+ int n;
719+ int maxperiod = (int)(s->framesize * (float)SEEK);
720+ float bias = s->biasfactor / log((float)(maxperiod - 4));
721+ float *biasbuf = s->biasbuf;
722+
723+ for(n=0; n<5; n++) // periods < 5 samples can't be tracked
724+ {
725+ biasbuf[n] = 0.;
726+ }
727+
728+ for(n=5; n<maxperiod; n++)
729+ {
730+ biasbuf[n] = 1.0f - (float)log(n - 4) * bias;
731+ }
732+}
733+
LEAF/Src/leaf-crusher.c+0−84
@@ -1,84 +0,0 @@
1−/*==============================================================================
2−
3− leaf-crusher.c
4− Created: 30 Nov 2018 11:56:49am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#if _WIN32 || _WIN64
10−
11−#include "..\Inc\leaf-crusher.h"
12−
13−#else
14−
15−#include "../Inc/leaf-crusher.h"
16−
17−#endif
18−
19−//==============================================================================
20−
21−#define SCALAR 5000.f
22−
23−void tCrusher_init (tCrusher* const c)
24−{
25− c->op = 4;
26− c->div = SCALAR;
27− c->rnd = 0.25f;
28− c->srr = 0.25f;
29−
30− c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
31−}
32−
33−void tCrusher_free (tCrusher* const c)
34−{
35−
36−}
37−
38−float tCrusher_tick (tCrusher* const c, float input)
39−{
40− float sample = input;
41−
42− sample *= SCALAR; // SCALAR is 5000 by default
43−
44− sample = (int32_t) sample;
45−
46− sample /= c->div;
47−
48− sample = LEAF_bitwise_xor(sample, c->op << 23);
49−
50− sample = LEAF_clip(-1.f, sample, 1.f);
51−
52− sample = LEAF_round(sample, c->rnd);
53−
54− sample = LEAF_reduct(sample, c->srr);
55−
56− return sample * c->gain;
57−
58−}
59−
60−void tCrusher_setOperation (tCrusher* const c, float op)
61−{
62− c->op = (uint32_t) (op * 8.0f);
63−}
64−
65−// 0.0 - 1.0
66−void tCrusher_setQuality (tCrusher* const c, float val)
67−{
68− val = LEAF_clip(0.0f, val, 1.0f);
69−
70− c->div = 0.01f + val * SCALAR;
71−
72− c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
73−}
74−
75−// what decimal to round to
76−void tCrusher_setRound (tCrusher* const c, float rnd)
77−{
78− c->rnd = fabsf(rnd);
79−}
80−
81−void tCrusher_setSamplingRatio (tCrusher* const c, float ratio)
82−{
83− c->srr = ratio;
84−}
LEAF/Src/leaf-delay.c+30−30
@@ -127,8 +127,8 @@ float tDelay_getGain (tDelay* const d) · 126 unmodified lines
127127 return d->gain;
128128 }
129129
130−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ DelayL ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
131−void tDelayL_init (tDelayL* const d, float delay, uint32_t maxDelay)
130+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
131+void tLinearDelay_init (tLinearDelay* const d, float delay, uint32_t maxDelay)
132132 {
133133 d->maxDelay = maxDelay;
134134
@@ -146,15 +146,15 @@ void tDelayL_init (tDelayL* const d, float delay, uint32_t maxDelay) · 11 unmodified lines
146146 d->inPoint = 0;
147147 d->outPoint = 0;
148148
149− tDelayL_setDelay(d, d->delay);
149+ tLinearDelay_setDelay(d, d->delay);
150150 }
151151
152−void tDelayL_free(tDelayL* const d)
152+void tLinearDelay_free(tLinearDelay* const d)
153153 {
154154 leaf_free(d->buff);
155155 }
156156
157−float tDelayL_tick (tDelayL* const d, float input)
157+float tLinearDelay_tick (tLinearDelay* const d, float input)
158158 {
159159 d->buff[d->inPoint] = input * d->gain;
160160
@@ -176,7 +176,7 @@ float tDelayL_tick (tDelayL* const d, float input) · 15 unmodified lines
176176 return d->lastOut;
177177 }
178178
179−void tDelayL_tickIn (tDelayL* const d, float input)
179+void tLinearDelay_tickIn (tLinearDelay* const d, float input)
180180 {
181181 d->buff[d->inPoint] = input * d->gain;
182182
@@ -184,7 +184,7 @@ void tDelayL_tickIn (tDelayL* const d, float input) · 1 unmodified line
184184 if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
185185 }
186186
187−float tDelayL_tickOut (tDelayL* const d)
187+float tLinearDelay_tickOut (tLinearDelay* const d)
188188 {
189189 uint32_t idx = (uint32_t) d->outPoint;
190190
@@ -200,7 +200,7 @@ float tDelayL_tickOut (tDelayL* const d) · 9 unmodified lines
200200 return d->lastOut;
201201 }
202202
203−int tDelayL_setDelay (tDelayL* const d, float delay)
203+int tLinearDelay_setDelay (tLinearDelay* const d, float delay)
204204 {
205205 d->delay = LEAF_clip(0.0f, delay, d->maxDelay);
206206
@@ -219,7 +219,7 @@ int tDelayL_setDelay (tDelayL* const d, float delay) · 12 unmodified lines
219219 return 0;
220220 }
221221
222−float tDelayL_tapOut (tDelayL* const d, float tapDelay)
222+float tLinearDelay_tapOut (tLinearDelay* const d, float tapDelay)
223223 {
224224 float tap = (float) d->inPoint - tapDelay - 1.f;
225225
@@ -244,7 +244,7 @@ float tDelayL_tapOut (tDelayL* const d, float tapDelay) · 18 unmodified lines
244244
245245 }
246246
247−void tDelayL_tapIn (tDelayL* const d, float value, uint32_t tapDelay)
247+void tLinearDelay_tapIn (tLinearDelay* const d, float value, uint32_t tapDelay)
248248 {
249249 int32_t tap = d->inPoint - tapDelay - 1;
250250
@@ -254,7 +254,7 @@ void tDelayL_tapIn (tDelayL* const d, float value, uint32_t tapDelay) · 3 unmodified lines
254254 d->buff[tap] = value;
255255 }
256256
257−float tDelayL_addTo (tDelayL* const d, float value, uint32_t tapDelay)
257+float tLinearDelay_addTo (tLinearDelay* const d, float value, uint32_t tapDelay)
258258 {
259259 int32_t tap = d->inPoint - tapDelay - 1;
260260
@@ -264,34 +264,34 @@ float tDelayL_addTo (tDelayL* const d, float value, uint32_t tapDelay) · 3 unmodified lines
264264 return (d->buff[tap] += value);
265265 }
266266
267−float tDelayL_getDelay (tDelayL *d)
267+float tLinearDelay_getDelay (tLinearDelay *d)
268268 {
269269 return d->delay;
270270 }
271271
272−float tDelayL_getLastOut (tDelayL* const d)
272+float tLinearDelay_getLastOut (tLinearDelay* const d)
273273 {
274274 return d->lastOut;
275275 }
276276
277−float tDelayL_getLastIn (tDelayL* const d)
277+float tLinearDelay_getLastIn (tLinearDelay* const d)
278278 {
279279 return d->lastIn;
280280 }
281281
282−void tDelayL_setGain (tDelayL* const d, float gain)
282+void tLinearDelay_setGain (tLinearDelay* const d, float gain)
283283 {
284284 if (gain < 0.0f) d->gain = 0.0f;
285285 else d->gain = gain;
286286 }
287287
288−float tDelayL_getGain (tDelayL* const d)
288+float tLinearDelay_getGain (tLinearDelay* const d)
289289 {
290290 return d->gain;
291291 }
292292
293−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ DelayA ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
294−void tDelayA_init (tDelayA* const d, float delay, uint32_t maxDelay)
293+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
294+void tAllpassDelay_init (tAllpassDelay* const d, float delay, uint32_t maxDelay)
295295 {
296296 d->maxDelay = maxDelay;
297297
@@ -309,17 +309,17 @@ void tDelayA_init (tDelayA* const d, float delay, uint32_t maxDelay) · 11 unmodified lines
309309 d->inPoint = 0;
310310 d->outPoint = 0;
311311
312− tDelayA_setDelay(d, d->delay);
312+ tAllpassDelay_setDelay(d, d->delay);
313313
314314 d->apInput = 0.0f;
315315 }
316316
317−void tDelayA_free(tDelayA* const d)
317+void tAllpassDelay_free(tAllpassDelay* const d)
318318 {
319319 leaf_free(d->buff);
320320 }
321321
322−float tDelayA_tick (tDelayA* const d, float input)
322+float tAllpassDelay_tick (tAllpassDelay* const d, float input)
323323 {
324324 d->buff[d->inPoint] = input * d->gain;
325325
@@ -340,7 +340,7 @@ float tDelayA_tick (tDelayA* const d, float input) · 14 unmodified lines
340340 return d->lastOut;
341341 }
342342
343−int tDelayA_setDelay (tDelayA* const d, float delay)
343+int tAllpassDelay_setDelay (tAllpassDelay* const d, float delay)
344344 {
345345 d->delay = LEAF_clip(0.5f, delay, d->maxDelay);
346346
@@ -373,7 +373,7 @@ int tDelayA_setDelay (tDelayA* const d, float delay) · 26 unmodified lines
373373 return 0;
374374 }
375375
376−float tDelayA_tapOut (tDelayA* const d, uint32_t tapDelay)
376+float tAllpassDelay_tapOut (tAllpassDelay* const d, uint32_t tapDelay)
377377 {
378378 int32_t tap = d->inPoint - tapDelay - 1;
379379
@@ -384,7 +384,7 @@ float tDelayA_tapOut (tDelayA* const d, uint32_t tapDelay) · 4 unmodified lines
384384
385385 }
386386
387−void tDelayA_tapIn (tDelayA* const d, float value, uint32_t tapDelay)
387+void tAllpassDelay_tapIn (tAllpassDelay* const d, float value, uint32_t tapDelay)
388388 {
389389 int32_t tap = d->inPoint - tapDelay - 1;
390390
@@ -394,7 +394,7 @@ void tDelayA_tapIn (tDelayA* const d, float value, uint32_t tapDelay) · 3 unmodified lines
394394 d->buff[tap] = value;
395395 }
396396
397−float tDelayA_addTo (tDelayA* const d, float value, uint32_t tapDelay)
397+float tAllpassDelay_addTo (tAllpassDelay* const d, float value, uint32_t tapDelay)
398398 {
399399 int32_t tap = d->inPoint - tapDelay - 1;
400400
@@ -404,28 +404,28 @@ float tDelayA_addTo (tDelayA* const d, float value, uint32_t tapDelay) · 3 unmodified lines
404404 return (d->buff[tap] += value);
405405 }
406406
407−float tDelayA_getDelay (tDelayA* const d)
407+float tAllpassDelay_getDelay (tAllpassDelay* const d)
408408 {
409409 return d->delay;
410410 }
411411
412−float tDelayA_getLastOut (tDelayA* const d)
412+float tAllpassDelay_getLastOut (tAllpassDelay* const d)
413413 {
414414 return d->lastOut;
415415 }
416416
417−float tDelayA_getLastIn (tDelayA* const d)
417+float tAllpassDelay_getLastIn (tAllpassDelay* const d)
418418 {
419419 return d->lastIn;
420420 }
421421
422−void tDelayA_setGain (tDelayA* const d, float gain)
422+void tAllpassDelay_setGain (tAllpassDelay* const d, float gain)
423423 {
424424 if (gain < 0.0f) d->gain = 0.0f;
425425 else d->gain = gain;
426426 }
427427
428−float tDelayA_getGain (tDelayA* const d)
428+float tAllpassDelay_getGain (tAllpassDelay* const d)
429429 {
430430 return d->gain;
431431 }
LEAF/Src/leaf-distortion.crenamed from LEAF/Src/leaf-oversampler.c+173−2
@@ -8,17 +8,188 @@ · 7 unmodified lines
88
99 #if _WIN32 || _WIN64
1010
11−#include "..\Inc\leaf-oversampler.h"
11+#include "..\Inc\leaf-distortion.h"
1212 #include "..\Inc\leaf-tables.h"
1313 #else
1414
1515
16−#include "../Inc/leaf-oversampler.h"
16+#include "../Inc/leaf-distortion.h"
1717 #include "../Inc/leaf-tables.h"
1818
1919 #endif
2020
21+//============================================================================================================
22+// WAVEFOLDER
23+//============================================================================================================
24+void tLockhartWavefolder_init(tLockhartWavefolder* const w)
25+{
26+ w->Ln1 = 0.0;
27+ w->Fn1 = 0.0;
28+ w->xn1 = 0.0f;
29+}
30+
31+void tLockhardWavefolder_free(tLockhartWavefolder* const w)
32+{
33+
34+}
35+
36+double tLockhartWavefolderLambert(double x, double ln)
37+{
38+ double thresh, w, expw, p, r, s, err;
39+ // Error threshold
40+ thresh = 10e-6;
41+ // Initial guess (use previous value)
42+ w = ln;
43+
44+ // Haley's method (Sec. 4.2 of the paper)
45+ for(int i=0; i<100; i+=1) {
46+
47+ expw = exp(w);
48+
49+ p = w*expw - x;
50+ r = (w+1.0)*expw;
51+ s = (w+2.0)/(2.0*(w+1.0)); err = (p/(r-(p*s)));
52+
53+ if (fabs(err)<thresh) {
54+ break;
55+ }
56+ if (isnan(err))
57+ {
58+ break;
59+ }
60+
61+ w = w - err;
62+ }
63+ return w;
64+}
65+
66+float tLockhartWavefolder_tick(tLockhartWavefolder* const w, float samp)
67+{
68+
69+ float out = 0.0f;
70+ // Constants
71+ double RL = 7.5e3;
72+ double R = 15e3;
73+ double VT = 26e-3;
74+ double Is = 10e-16;
75+
76+ double a = 2.0*RL/R;
77+ double b = (R+2.0*RL)/(VT*R);
78+ double d = (RL*Is)/VT;
79+
80+ // Antialiasing error threshold
81+ double thresh = 10e-10;
82+
83+ // Compute Antiderivative
84+ int l = (samp > 0) - (samp < 0);
85+ double u = d*exp(l*b*samp);
86+ double Ln = tLockhartWavefolderLambert(u,w->Ln1);
87+ double Fn = (0.5*VT/b)*(Ln*(Ln + 2.0)) - 0.5*a*samp*samp;
88+
89+ // Check for ill-conditioning
90+ if (fabs(samp-w->xn1)<thresh) {
91+
92+ // Compute Averaged Wavefolder Output
93+ double xn = 0.5*(samp+w->xn1);
94+ u = d*exp(l*b*xn);
95+ Ln = tLockhartWavefolderLambert(u,w->Ln1);
96+ out = (float) (l*VT*Ln - a*xn);
97+ if (isnan(out))
98+ {
99+ ;
100+ }
101+
102+ }
103+ else {
104+
105+ // Apply AA Form
106+ out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
107+ if (isnan(out))
108+ {
109+ ;
110+ }
111+ }
112+
113+ // Update States
114+ w->Ln1 = Ln;
115+ w->Fn1 = Fn;
116+ w->xn1 = samp;
117+
118+ return out;
119+}
120+
121+//============================================================================================================
122+// CRUSHER
123+//============================================================================================================
124+#define SCALAR 5000.f
125+
126+void tCrusher_init (tCrusher* const c)
127+{
128+ c->op = 4;
129+ c->div = SCALAR;
130+ c->rnd = 0.25f;
131+ c->srr = 0.25f;
132+
133+ c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
134+}
135+
136+void tCrusher_free (tCrusher* const c)
137+{
138+
139+}
140+
141+float tCrusher_tick (tCrusher* const c, float input)
142+{
143+ float sample = input;
144+
145+ sample *= SCALAR; // SCALAR is 5000 by default
146+
147+ sample = (int32_t) sample;
148+
149+ sample /= c->div;
150+
151+ sample = LEAF_bitwise_xor(sample, c->op << 23);
152+
153+ sample = LEAF_clip(-1.f, sample, 1.f);
154+
155+ sample = LEAF_round(sample, c->rnd);
156+
157+ sample = LEAF_reduct(sample, c->srr);
158+
159+ return sample * c->gain;
160+
161+}
162+
163+void tCrusher_setOperation (tCrusher* const c, float op)
164+{
165+ c->op = (uint32_t) (op * 8.0f);
166+}
167+
168+// 0.0 - 1.0
169+void tCrusher_setQuality (tCrusher* const c, float val)
170+{
171+ val = LEAF_clip(0.0f, val, 1.0f);
172+
173+ c->div = 0.01f + val * SCALAR;
174+
175+ c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
176+}
177+
178+// what decimal to round to
179+void tCrusher_setRound (tCrusher* const c, float rnd)
180+{
181+ c->rnd = fabsf(rnd);
182+}
183+
184+void tCrusher_setSamplingRatio (tCrusher* const c, float ratio)
185+{
186+ c->srr = ratio;
187+}
188+
189+
190+//============================================================================================================
21191 // Oversampler
192+//============================================================================================================
22193 // Latency is equal to the phase length (numTaps / ratio)
23194 void tOversampler_init(tOversampler* const os, int ratio, oBool extraQuality)
24195 {
LEAF/Src/leaf-dynamics.c+172−0
@@ -0,0 +1,172 @@
1+/*==============================================================================
2+
3+ leaf-dynamics.c
4+ Created: 30 Nov 2018 11:56:49am
5+ Author: airship
6+
7+==============================================================================*/
8+
9+#if _WIN32 || _WIN64
10+
11+#include "..\Inc\leaf-dynamics.h"
12+
13+#else
14+
15+#include "../Inc/leaf-dynamics.h"
16+
17+#endif
18+
19+//==============================================================================
20+
21+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Compressor ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22+
23+/*
24+ tCompressor* tCompressorInit(int tauAttack, int tauRelease)
25+ {
26+ tCompressor* c = &leaf.tCompressorRegistry[leaf.registryIndex[T_COMPRESSOR]++];
27+
28+ c->tauAttack = tauAttack;
29+ c->tauRelease = tauRelease;
30+
31+ c->x_G[0] = 0.0f, c->x_G[1] = 0.0f,
32+ c->y_G[0] = 0.0f, c->y_G[1] = 0.0f,
33+ c->x_T[0] = 0.0f, c->x_T[1] = 0.0f,
34+ c->y_T[0] = 0.0f, c->y_T[1] = 0.0f;
35+
36+ c->T = 0.0f; // Threshold
37+ c->R = 1.0f; // compression Ratio
38+ c->M = 0.0f; // decibel Make-up gain
39+ c->W = 0.0f; // decibel Width of knee transition
40+
41+ return c;
42+ }
43+ */
44+void tCompressor_init(tCompressor* const c)
45+{
46+ c->tauAttack = 100;
47+ c->tauRelease = 100;
48+
49+ c->isActive = OFALSE;
50+
51+ c->T = 0.0f; // Threshold
52+ c->R = 0.5f; // compression Ratio
53+ c->M = 3.0f; // decibel Width of knee transition
54+ c->W = 1.0f; // decibel Make-up gain
55+}
56+
57+void tCompressor_free(tCompressor* const c)
58+{
59+
60+}
61+
62+int ccount = 0;
63+float tCompressor_tick(tCompressor* const c, float in)
64+{
65+ float slope, overshoot;
66+ float alphaAtt, alphaRel;
67+
68+ float in_db = 20.0f * log10f( fmaxf( fabsf( in), 0.000001f)), out_db = 0.0f;
69+
70+ c->y_T[1] = c->y_T[0];
71+
72+ slope = c->R - 1.0f; // feed-forward topology; was 1/C->R - 1
73+
74+ overshoot = in_db - c->T;
75+
76+
77+ if (overshoot <= -(c->W * 0.5f))
78+ {
79+ out_db = in_db;
80+ c->isActive = OFALSE;
81+ }
82+ else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f)))
83+ {
84+ out_db = in_db + slope * (powf((overshoot + c->W*0.5f),2) / (2.0f * c->W)); // .^ 2 ???
85+ c->isActive = OTRUE;
86+ }
87+ else if (overshoot >= (c->W * 0.5f))
88+ {
89+ out_db = in_db + slope * overshoot;
90+ c->isActive = OTRUE;
91+ }
92+
93+
94+
95+ c->x_T[0] = out_db - in_db;
96+
97+ alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * leaf.sampleRate));
98+ alphaRel = expf(-1.0f/(0.001f * c->tauRelease * leaf.sampleRate));
99+
100+ if (c->x_T[0] > c->y_T[1])
101+ c->y_T[0] = alphaAtt * c->y_T[1] + (1-alphaAtt) * c->x_T[0];
102+ else
103+ c->y_T[0] = alphaRel * c->y_T[1] + (1-alphaRel) * c->x_T[0];
104+
105+ float attenuation = powf(10.0f, ((c->M - c->y_T[0])/20.0f));
106+
107+ /*
108+ if (++ccount > 5000)
109+ {
110+
111+ ccount = 0;
112+ DBG(".5width: " + String(c->W * 0.5f));
113+ DBG("slope: " + String(slope) + " overshoot: " + String(overshoot));
114+ DBG("attenuation: " + String(attenuation));
115+ }
116+ */
117+ return attenuation * in;
118+
119+
120+}
121+
122+/* Feedback Leveler */
123+
124+void tFeedbackLeveler_init(tFeedbackLeveler* const p, float targetLevel, float factor, float strength, int mode)
125+{
126+ p->curr=0.0f;
127+ p->targetLevel=targetLevel;
128+ tPowerFollower_init(&p->pwrFlw,factor);
129+ p->mode=mode;
130+ p->strength=strength;
131+}
132+
133+void tFeedbackLeveler_free(tFeedbackLeveler* const p)
134+{
135+ tPowerFollower_free(&p->pwrFlw);
136+}
137+
138+void tFeedbackLeveler_setStrength(tFeedbackLeveler* const p, float strength)
139+{ // strength is how strongly level diff is affecting the amp ratio
140+ // try 0.125 for a start
141+ p->strength=strength;
142+}
143+
144+void tFeedbackLeveler_setFactor(tFeedbackLeveler* const p, float factor)
145+{
146+ tPowerFollower_setFactor(&p->pwrFlw,factor);
147+}
148+
149+void tFeedbackLeveler_setMode(tFeedbackLeveler* const p, int mode)
150+{ // 0 for decaying with upwards lev limiting, 1 for constrained absolute level (also downwards limiting)
151+ p->mode=mode;
152+}
153+
154+float tFeedbackLeveler_tick(tFeedbackLeveler* const p, float input)
155+{
156+ float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel);
157+ if (p->mode==0 && levdiff<0) levdiff=0;
158+ p->curr=input*(1-p->strength*levdiff);
159+ return p->curr;
160+}
161+
162+float tFeedbackLeveler_sample(tFeedbackLeveler* const p)
163+{
164+ return p->curr;
165+}
166+
167+
168+void tFeedbackLeveler_setTargetLevel (tFeedbackLeveler* const p, float TargetLevel)
169+{
170+ p->targetLevel=TargetLevel;
171+}
172+
LEAF/Src/leaf-effects.c+1393−0
@@ -0,0 +1,1393 @@
1+/*==============================================================================
2+
3+ leaf-vocoder.c
4+ Created: 20 Jan 2017 12:01:54pm
5+ Author: Michael R Mulshine
6+
7+==============================================================================*/
8+
9+#if _WIN32 || _WIN64
10+
11+#include "..\Inc\leaf-effects.c"
12+#include "..\leaf.h"
13+
14+#else
15+
16+#include "../Inc/leaf-effects.h"
17+#include "../leaf.h"
18+
19+#endif
20+
21+
22+
23+//============================================================================================================
24+// TALKBOX
25+//============================================================================================================
26+
27+void tTalkbox_init(tTalkbox* const v, int bufsize)
28+{
29+ v->param[0] = 0.5f; //wet
30+ v->param[1] = 0.0f; //dry
31+ v->param[2] = 0; // Swap
32+ v->param[3] = 1.0f; //quality
33+
34+ v->bufsize = bufsize;
35+
36+ v->car0 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
37+ v->car1 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
38+ v->window = (float*) leaf_alloc(sizeof(float) * v->bufsize);
39+ v->buf0 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
40+ v->buf1 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
41+
42+ tTalkbox_update(v);
43+}
44+
45+void tTalkbox_free(tTalkbox* const v)
46+{
47+ leaf_free(v->car0);
48+ leaf_free(v->car1);
49+ leaf_free(v->window);
50+ leaf_free(v->buf0);
51+ leaf_free(v->buf1);
52+}
53+
54+void tTalkbox_update(tTalkbox* const v) ///update internal parameters...
55+{
56+ float fs = leaf.sampleRate;
57+ if(fs < 8000.0f) fs = 8000.0f;
58+ if(fs > 96000.0f) fs = 96000.0f;
59+
60+ int32_t n = (int32_t)(0.01633f * fs);
61+ if(n > v->bufsize) n = v->bufsize;
62+
63+ //O = (VstInt32)(0.0005f * fs);
64+ v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs);
65+
66+ if(n != v->N) //recalc hanning window
67+ {
68+ v->N = n;
69+ float dp = TWO_PI / v->N;
70+ float p = 0.0f;
71+ for(n=0; n<v->N; n++)
72+ {
73+ v->window[n] = 0.5f - 0.5f * cosf(p);
74+ p += dp;
75+ }
76+ }
77+ v->wet = 0.5f * v->param[0] * v->param[0];
78+ v->dry = 2.0f * v->param[1] * v->param[1];
79+}
80+
81+void tTalkbox_suspend(tTalkbox* const v) ///clear any buffers...
82+{
83+ v->pos = v->K = 0;
84+ v->emphasis = 0.0f;
85+ v->FX = 0;
86+
87+ v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f;
88+ v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f;
89+
90+ for (int32_t i = 0; i < v->bufsize; i++)
91+ {
92+ v->buf0[i] = 0;
93+ v->buf1[i] = 0;
94+ v->car0[i] = 0;
95+ v->car1[i] = 0;
96+ }
97+}
98+
99+
100+#define ORD_MAX 100 // Was 50. Increasing this gets rid of glitchiness, lowering it breaks it; not sure how it affects performance
101+void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o)
102+{
103+ float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;
104+ int32_t i, j, nn=n;
105+
106+ for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
107+ {
108+ z[j] = r[j] = 0.0f;
109+ for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
110+ }
111+ r[0] *= 1.001f; //stability fix
112+
113+ float min = 0.00001f;
114+ if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; }
115+
116+ tTalkbox_lpcDurbin(r, o, k, &G); //calc reflection coeffs
117+
118+ for(i=0; i<=o; i++)
119+ {
120+ if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;
121+ }
122+
123+ for(i=0; i<n; i++)
124+ {
125+ x = G * car[i];
126+ for(j=o; j>0; j--) //lattice filter
127+ {
128+ x -= k[j] * z[j-1];
129+ z[j] = z[j-1] + k[j] * x;
130+ }
131+ buf[i] = z[0] = x; //output buf[] will be windowed elsewhere
132+ }
133+}
134+
135+
136+void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
137+{
138+ int i, j;
139+ float a[ORD_MAX], at[ORD_MAX], e=r[0];
140+
141+ for(i=0; i<=p; i++) a[i] = at[i] = 0.0f; //probably don't need to clear at[] or k[]
142+
143+ for(i=1; i<=p; i++)
144+ {
145+ k[i] = -r[i];
146+
147+ for(j=1; j<i; j++)
148+ {
149+ at[j] = a[j];
150+ k[i] -= a[j] * r[i-j];
151+ }
152+ if(fabs(e) < 1.0e-20f) { e = 0.0f; break; }
153+ k[i] /= e; // This might be costing us
154+
155+ a[i] = k[i];
156+ for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
157+
158+ e *= 1.0f - k[i] * k[i];
159+ }
160+
161+ if(e < 1.0e-20f) e = 0.0f;
162+ *g = sqrtf(e);
163+}
164+
165+float tTalkbox_tick(tTalkbox* const v, float synth, float voice)
166+{
167+
168+ int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
169+ float e=v->emphasis, w, o, x, dr, fx=v->FX;
170+ float p, q, h0=0.3f, h1=0.77f;
171+
172+ o = voice;
173+ x = synth;
174+
175+ dr = o;
176+
177+ p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p;
178+ q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q;
179+ v->d4 = x;
180+ x = p + q;
181+
182+ if(v->K++)
183+ {
184+ v->K = 0;
185+
186+ v->car0[p0] = v->car1[p1] = x; //carrier input
187+
188+ x = o - e; e = o; //6dB/oct pre-emphasis
189+
190+ w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows
191+ if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O); p0 = 0; }
192+
193+ w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w;
194+ if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O); p1 = 0; }
195+ }
196+
197+ p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p;
198+ q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q;
199+ v->u4 = fx;
200+ x = p + q;
201+
202+ o = x;
203+
204+ v->emphasis = e;
205+ v->pos = p0;
206+ v->FX = fx;
207+
208+ float den = 1.0e-10f; //(float)pow(10.0f, -10.0f * param[4]);
209+ if(fabs(v->d0) < den) v->d0 = 0.0f; //anti-denormal (doesn't seem necessary but P4?)
210+ if(fabs(v->d1) < den) v->d1 = 0.0f;
211+ if(fabs(v->d2) < den) v->d2 = 0.0f;
212+ if(fabs(v->d3) < den) v->d3 = 0.0f;
213+ if(fabs(v->u0) < den) v->u0 = 0.0f;
214+ if(fabs(v->u1) < den) v->u1 = 0.0f;
215+ if(fabs(v->u2) < den) v->u2 = 0.0f;
216+ if(fabs(v->u3) < den) v->u3 = 0.0f;
217+ return o;
218+}
219+
220+void tTalkbox_setQuality(tTalkbox* const v, float quality)
221+{
222+ v->param[3] = quality;
223+ v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
224+}
225+
226+
227+//============================================================================================================
228+// VOCODER
229+//============================================================================================================
230+
231+void tVocoder_init (tVocoder* const v)
232+{
233+ v->param[0] = 0.33f; //input select
234+ v->param[1] = 0.50f; //output dB
235+ v->param[2] = 0.40f; //hi thru
236+ v->param[3] = 0.40f; //hi band
237+ v->param[4] = 0.16f; //envelope
238+ v->param[5] = 0.55f; //filter q
239+ v->param[6] = 0.6667f;//freq range
240+ v->param[7] = 0.33f; //num bands
241+
242+ tVocoder_update(v);
243+}
244+
245+void tVocoder_free (tVocoder* const v)
246+{
247+
248+}
249+
250+void tVocoder_update (tVocoder* const v)
251+{
252+ float tpofs = 6.2831853f * leaf.invSampleRate;
253+
254+ float rr, th, re;
255+
256+ float sh;
257+
258+ int32_t i;
259+
260+ v->gain = (float)pow(10.0f, 2.0f * v->param[1] - 3.0f * v->param[5] - 2.0f);
261+
262+ v->thru = (float)pow(10.0f, 0.5f + 2.0f * v->param[1]);
263+ v->high = v->param[3] * v->param[3] * v->param[3] * v->thru;
264+ v->thru *= v->param[2] * v->param[2] * v->param[2];
265+
266+ if(v->param[7]<0.5f)
267+ {
268+ v->nbnd=8;
269+ re=0.003f;
270+ v->f[1][2] = 3000.0f;
271+ v->f[2][2] = 2200.0f;
272+ v->f[3][2] = 1500.0f;
273+ v->f[4][2] = 1080.0f;
274+ v->f[5][2] = 700.0f;
275+ v->f[6][2] = 390.0f;
276+ v->f[7][2] = 190.0f;
277+ }
278+ else
279+ {
280+ v->nbnd=16;
281+ re=0.0015f;
282+ v->f[ 1][2] = 5000.0f; //+1000
283+ v->f[ 2][2] = 4000.0f; //+750
284+ v->f[ 3][2] = 3250.0f; //+500
285+ v->f[ 4][2] = 2750.0f; //+450
286+ v->f[ 5][2] = 2300.0f; //+300
287+ v->f[ 6][2] = 2000.0f; //+250
288+ v->f[ 7][2] = 1750.0f; //+250
289+ v->f[ 8][2] = 1500.0f; //+250
290+ v->f[ 9][2] = 1250.0f; //+250
291+ v->f[10][2] = 1000.0f; //+250
292+ v->f[11][2] = 750.0f; //+210
293+ v->f[12][2] = 540.0f; //+190
294+ v->f[13][2] = 350.0f; //+155
295+ v->f[14][2] = 195.0f; //+100
296+ v->f[15][2] = 95.0f;
297+ }
298+
299+ if(v->param[4]<0.05f) //freeze
300+ {
301+ for(i=0;i<v->nbnd;i++) v->f[i][12]=0.0f;
302+ }
303+ else
304+ {
305+ v->f[0][12] = (float)pow(10.0, -1.7 - 2.7f * v->param[4]); //envelope speed
306+
307+ rr = 0.022f / (float)v->nbnd; //minimum proportional to frequency to stop distortion
308+ for(i=1;i<v->nbnd;i++)
309+ {
310+ v->f[i][12] = (float)(0.025 - rr * (double)i);
311+ if(v->f[0][12] < v->f[i][12]) v->f[i][12] = v->f[0][12];
312+ }
313+ v->f[0][12] = 0.5f * v->f[0][12]; //only top band is at full rate
314+ }
315+
316+ rr = 1.0 - pow(10.0f, -1.0f - 1.2f * v->param[5]);
317+ sh = (float)pow(2.0f, 3.0f * v->param[6] - 1.0f); //filter bank range shift
318+
319+ for(i=1;i<v->nbnd;i++)
320+ {
321+ v->f[i][2] *= sh;
322+ th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
323+ v->f[i][0] = (float)(2.0 * rr * cos(th)); //a0
324+ v->f[i][1] = (float)(-rr * rr); //a1
325+ //was .98
326+ v->f[i][2] *= 0.96f; //shift 2nd stage slightly to stop high resonance peaks
327+ th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
328+ v->f[i][2] = (float)(2.0 * rr * cos(th));
329+ }
330+}
331+
332+float tVocoder_tick (tVocoder* const v, float synth, float voice)
333+{
334+ float a, b, o=0.0f, aa, bb, oo = v->kout, g = v->gain, ht = v->thru, hh = v->high, tmp;
335+ uint32_t i, k = v->kval, nb = v->nbnd;
336+
337+ a = voice; //speech
338+ b = synth; //synth
339+
340+ tmp = a - v->f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis
341+ v->f[0][7] = a;
342+ a = tmp;
343+
344+ if(tmp<0.0f) tmp = -tmp;
345+ v->f[0][11] -= v->f[0][12] * (v->f[0][11] - tmp); //high band envelope
346+ o = v->f[0][11] * (ht * a + hh * (b - v->f[0][3])); //high band + high thru
347+
348+ v->f[0][3] = b; //integrate carrier for HF band
349+
350+ if(++k & 0x1) //this block runs at half sample rate
351+ {
352+ oo = 0.0f;
353+ aa = a + v->f[0][9] - v->f[0][8] - v->f[0][8]; //apply zeros here instead of in each reson
354+ v->f[0][9] = v->f[0][8]; v->f[0][8] = a;
355+ bb = b + v->f[0][5] - v->f[0][4] - v->f[0][4];
356+ v->f[0][5] = v->f[0][4]; v->f[0][4] = b;
357+
358+ for(i=1; i<nb; i++) //filter bank: 4th-order band pass
359+ {
360+ tmp = v->f[i][0] * v->f[i][3] + v->f[i][1] * v->f[i][4] + bb;
361+ v->f[i][4] = v->f[i][3];
362+ v->f[i][3] = tmp;
363+ tmp += v->f[i][2] * v->f[i][5] + v->f[i][1] * v->f[i][6];
364+ v->f[i][6] = v->f[i][5];
365+ v->f[i][5] = tmp;
366+
367+ tmp = v->f[i][0] * v->f[i][7] + v->f[i][1] * v->f[i][8] + aa;
368+ v->f[i][8] = v->f[i][7];
369+ v->f[i][7] = tmp;
370+ tmp += v->f[i][2] * v->f[i][9] + v->f[i][1] * v->f[i][10];
371+ v->f[i][10] = v->f[i][9];
372+ v->f[i][9] = tmp;
373+
374+ if(tmp<0.0f) tmp = -tmp;
375+ v->f[i][11] -= v->f[i][12] * (v->f[i][11] - tmp);
376+ oo += v->f[i][5] * v->f[i][11];
377+ }
378+ }
379+ o += oo * g; //effect of interpolating back up to Fs would be minimal (aliasing >16kHz)
380+
381+ v->kout = oo;
382+ v->kval = k & 0x1;
383+ if(fabs(v->f[0][11])<1.0e-10) v->f[0][11] = 0.0f; //catch HF envelope denormal
384+
385+ for(i=1;i<nb;i++)
386+ if(fabs(v->f[i][3])<1.0e-10 || fabs(v->f[i][7])<1.0e-10)
387+ for(k=3; k<12; k++) v->f[i][k] = 0.0f; //catch reson & envelope denormals
388+
389+ if(fabs(o)>10.0f) tVocoder_suspend(v); //catch instability
390+
391+ return o;
392+
393+}
394+
395+void tVocoder_suspend (tVocoder* const v)
396+{
397+ int32_t i, j;
398+
399+ for(i=0; i<v->nbnd; i++) for(j=3; j<12; j++) v->f[i][j] = 0.0f; //zero band filters and envelopes
400+ v->kout = 0.0f;
401+ v->kval = 0;
402+}
403+
404+//============================================================================================================
405+// PITCHSHIFTER
406+//============================================================================================================
407+static int pitchshifter_attackdetect(tPitchShifter* ps);
408+
409+void tPitchShifter_init(tPitchShifter* const ps, float* in, float* out, int bufSize, int frameSize)
410+{
411+ ps->inBuffer = in;
412+ ps->outBuffer = out;
413+ ps->bufSize = bufSize;
414+ ps->frameSize = frameSize;
415+ ps->framesPerBuffer = ps->bufSize / ps->frameSize;
416+ ps->curBlock = 1;
417+ ps->lastBlock = 0;
418+ ps->index = 0;
419+
420+ ps->hopSize = DEFHOPSIZE;
421+ ps->windowSize = DEFWINDOWSIZE;
422+ ps->fba = FBA;
423+
424+ tEnvPD_init(&ps->env, ps->windowSize, ps->hopSize, ps->frameSize);
425+
426+ tSNAC_init(&ps->snac, DEFOVERLAP);
427+
428+ tSOLAD_init(&ps->sola);
429+
430+ tHighpass_init(&ps->hp, HPFREQ);
431+
432+ tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
433+
434+ tPitchShifter_setTimeConstant(ps, DEFTIMECONSTANT);
435+}
436+
437+void tPitchShifter_free(tPitchShifter* const ps)
438+{
439+ tEnvPD_free(&ps->env);
440+ tSNAC_free(&ps->snac);
441+ tSOLAD_free(&ps->sola);
442+ tHighpass_free(&ps->hp);
443+}
444+
445+float tPitchShifter_tick(tPitchShifter* ps, float sample)
446+{
447+ float period, out;
448+ int i, iLast;
449+
450+ i = (ps->curBlock*ps->frameSize);
451+ iLast = (ps->lastBlock*ps->frameSize)+ps->index;
452+
453+ out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
454+ ps->inBuffer[i+ps->index] = sample;
455+
456+ ps->index++;
457+ if (ps->index >= ps->frameSize)
458+ {
459+ ps->index = 0;
460+
461+ tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i]));
462+
463+ if(pitchshifter_attackdetect(ps) == 1)
464+ {
465+ ps->fba = 5;
466+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
467+ }
468+
469+ tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
470+ period = tSNAC_getPeriod(&ps->snac);
471+
472+ ps->curBlock++;
473+ if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
474+ ps->lastBlock++;
475+ if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
476+
477+ //separate here
478+
479+ tSOLAD_setPeriod(&ps->sola, period);
480+
481+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
482+ tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
483+
484+ }
485+
486+ return out;
487+}
488+
489+float tPitchShifterToFreq_tick(tPitchShifter* ps, float sample, float freq)
490+{
491+ float period, out;
492+ int i, iLast;
493+
494+ i = (ps->curBlock*ps->frameSize);
495+ iLast = (ps->lastBlock*ps->frameSize)+ps->index;
496+
497+ out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
498+ ps->inBuffer[i+ps->index] = sample;
499+
500+ ps->index++;
501+ if (ps->index >= ps->frameSize)
502+ {
503+ ps->index = 0;
504+
505+ tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i]));
506+
507+ if(pitchshifter_attackdetect(ps) == 1)
508+ {
509+ ps->fba = 5;
510+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
511+ }
512+
513+ tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
514+ period = tSNAC_getPeriod(&ps->snac);
515+
516+ tSOLAD_setPeriod(&ps->sola, period);
517+
518+ ps->pitchFactor = period*freq*leaf.invSampleRate;
519+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
520+ tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
521+
522+ ps->curBlock++;
523+ if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
524+ ps->lastBlock++;
525+ if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
526+ }
527+
528+ return out;
529+}
530+
531+float tPitchShifterToFunc_tick(tPitchShifter* ps, float sample, float (*fun)(float))
532+{
533+ float period, out;
534+ int i, iLast;
535+
536+ i = (ps->curBlock*ps->frameSize);
537+ iLast = (ps->lastBlock*ps->frameSize)+ps->index;
538+
539+ out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
540+ ps->inBuffer[i+ps->index] = sample;
541+
542+ ps->index++;
543+ if (ps->index >= ps->frameSize)
544+ {
545+ ps->index = 0;
546+
547+ tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i]));
548+
549+ if(pitchshifter_attackdetect(ps) == 1)
550+ {
551+ ps->fba = 5;
552+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
553+ }
554+
555+ tSNAC_ioSamples(&ps->snac, (&ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
556+ period = tSNAC_getPeriod(&ps->snac);
557+
558+ tSOLAD_setPeriod(&ps->sola, period);
559+
560+ ps->pitchFactor = period/fun(period);
561+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
562+ tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
563+
564+ ps->curBlock++;
565+ if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
566+ ps->lastBlock++;
567+ if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
568+ }
569+
570+ return out;
571+}
572+
573+void tPitchShifter_ioSamples(tPitchShifter* ps, float* in, float* out, int size)
574+{
575+ float period;
576+
577+ tEnvPD_processBlock(&ps->env, in);
578+
579+ if(pitchshifter_attackdetect(ps) == 1)
580+ {
581+ ps->fba = 5;
582+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
583+ }
584+
585+ tSNAC_ioSamples(&ps->snac, in, out, size);
586+ period = tSNAC_getPeriod(&ps->snac);
587+
588+ tSOLAD_setPeriod(&ps->sola, period);
589+
590+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
591+ tSOLAD_ioSamples(&ps->sola, in, out, size);
592+
593+ for (int cc = 0; cc < size; ++cc)
594+ {
595+ out[cc] = tHighpass_tick(&ps->hp, out[cc]);
596+ }
597+}
598+
599+void tPitchShifter_ioSamples_toFreq(tPitchShifter* ps, float* in, float* out, int size, float toFreq)
600+{
601+ float period;
602+
603+ tEnvPD_processBlock(&ps->env, in);
604+
605+ if(pitchshifter_attackdetect(ps) == 1)
606+ {
607+ ps->fba = 5;
608+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
609+ }
610+
611+ tSNAC_ioSamples(&ps->snac, in, out, size);
612+ period = tSNAC_getPeriod(&ps->snac);
613+
614+ tSOLAD_setPeriod(&ps->sola, period);
615+ ps->pitchFactor = period*toFreq;
616+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
617+ tSOLAD_ioSamples(&ps->sola, in, out, size);
618+
619+ for (int cc = 0; cc < size; ++cc)
620+ {
621+ out[cc] = tHighpass_tick(&ps->hp, out[cc]);
622+ }
623+}
624+
625+void tPitchShifter_ioSamples_toPeriod(tPitchShifter* ps, float* in, float* out, int size, float toPeriod)
626+{
627+ float period;
628+
629+ tEnvPD_processBlock(&ps->env, in);
630+
631+ if(pitchshifter_attackdetect(ps) == 1)
632+ {
633+ ps->fba = 5;
634+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
635+ }
636+
637+ tSNAC_ioSamples(&ps->snac, in, out, size);
638+ period = tSNAC_getPeriod(&ps->snac);
639+
640+ tSOLAD_setPeriod(&ps->sola, period);
641+ ps->pitchFactor = period/toPeriod;
642+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
643+ tSOLAD_ioSamples(&ps->sola, in, out, size);
644+
645+ for (int cc = 0; cc < size; ++cc)
646+ {
647+ out[cc] = tHighpass_tick(&ps->hp, out[cc]);
648+ }
649+}
650+
651+void tPitchShifter_ioSamples_toFunc(tPitchShifter* ps, float* in, float* out, int size, float (*fun)(float))
652+{
653+ float period;
654+
655+ tEnvPD_processBlock(&ps->env, in);
656+
657+ if(pitchshifter_attackdetect(ps) == 1)
658+ {
659+ ps->fba = 5;
660+ tSOLAD_setReadLag(&ps->sola, ps->windowSize);
661+ }
662+
663+ tSNAC_ioSamples(&ps->snac, in, out, size);
664+ period = tSNAC_getPeriod(&ps->snac);
665+
666+ tSOLAD_setPeriod(&ps->sola, period);
667+ ps->pitchFactor = period/fun(period);
668+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
669+ tSOLAD_ioSamples(&ps->sola, in, out, size);
670+
671+ for (int cc = 0; cc < size; ++cc)
672+ {
673+ out[cc] = tHighpass_tick(&ps->hp, out[cc]);
674+ }
675+}
676+
677+void tPitchShifter_setPitchFactor(tPitchShifter* ps, float pf)
678+{
679+ ps->pitchFactor = pf;
680+}
681+
682+void tPitchShifter_setTimeConstant(tPitchShifter* ps, float tc)
683+{
684+ ps->timeConstant = tc;
685+ ps->radius = expf(-1000.0f * ps->hopSize * leaf.invSampleRate / ps->timeConstant);
686+}
687+
688+void tPitchShifter_setHopSize(tPitchShifter* ps, int hs)
689+{
690+ ps->hopSize = hs;
691+}
692+
693+void tPitchShifter_setWindowSize(tPitchShifter* ps, int ws)
694+{
695+ ps->windowSize = ws;
696+}
697+
698+float tPitchShifter_getPeriod(tPitchShifter* ps)
699+{
700+ return tSNAC_getPeriod(&ps->snac);
701+}
702+
703+static int pitchshifter_attackdetect(tPitchShifter* ps)
704+{
705+ float envout;
706+
707+ envout = tEnvPD_tick(&ps->env);
708+
709+ if (envout >= 1.0f)
710+ {
711+ ps->lastmax = ps->max;
712+ if (envout > ps->max)
713+ {
714+ ps->max = envout;
715+ }
716+ else
717+ {
718+ ps->deltamax = envout - ps->max;
719+ ps->max = ps->max * ps->radius;
720+ }
721+ ps->deltamax = ps->max - ps->lastmax;
722+ }
723+
724+ ps->fba = ps->fba ? (ps->fba - 1) : 0;
725+
726+ return (ps->fba == 0 && (ps->max > 60 && ps->deltamax > 6)) ? 1 : 0;
727+}
728+
729+
730+//============================================================================================================
731+// PITCHSHIFT
732+//============================================================================================================
733+
734+static int pitchshift_attackdetect(tPitchShift* ps)
735+{
736+ float envout;
737+
738+ envout = tEnvPD_tick(&ps->p->env);
739+
740+ if (envout >= 1.0f)
741+ {
742+ ps->p->lastmax = ps->p->max;
743+ if (envout > ps->p->max)
744+ {
745+ ps->p->max = envout;
746+ }
747+ else
748+ {
749+ ps->p->deltamax = envout - ps->p->max;
750+ ps->p->max = ps->p->max * ps->radius;
751+ }
752+ ps->p->deltamax = ps->p->max - ps->p->lastmax;
753+ }
754+
755+ ps->p->fba = ps->p->fba ? (ps->p->fba - 1) : 0;
756+
757+ return (ps->p->fba == 0 && (ps->p->max > 60 && ps->p->deltamax > 6)) ? 1 : 0;
758+}
759+
760+void tPitchShift_init (tPitchShift* const ps,tPeriodDetection* p, float* out, int bufSize)
761+{
762+ ps->p = p;
763+
764+ ps->outBuffer = out;
765+ ps->bufSize = bufSize;
766+ ps->frameSize = p->frameSize;
767+ ps->framesPerBuffer = ps->bufSize / ps->frameSize;
768+ ps->curBlock = 1;
769+ ps->lastBlock = 0;
770+ ps->index = 0;
771+ ps->pitchFactor = 1.0f;
772+
773+ tSOLAD_init(&ps->sola);
774+
775+ tHighpass_init(&ps->hp, HPFREQ);
776+
777+ tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
778+}
779+
780+void tPitchShift_free(tPitchShift* const ps)
781+{
782+ tSOLAD_free(&ps->sola);
783+ tHighpass_free(&ps->hp);
784+}
785+
786+void tPitchShift_setPitchFactor(tPitchShift* ps, float pf)
787+{
788+ ps->pitchFactor = pf;
789+}
790+
791+float tPitchShift_shift (tPitchShift* ps)
792+{
793+ float period, out;
794+ int i, iLast;
795+
796+ i = ps->p->i;
797+ iLast = ps->p->iLast;
798+
799+ out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
800+
801+ if (ps->p->indexstore >= ps->frameSize)
802+ {
803+ period = ps->p->period;
804+
805+ if(pitchshift_attackdetect(ps) == 1)
806+ {
807+ ps->p->fba = 5;
808+ tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
809+ }
810+
811+ tSOLAD_setPeriod(&ps->sola, period);
812+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
813+
814+ tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
815+ }
816+
817+ return out;
818+}
819+
820+float tPitchShift_shiftToFreq (tPitchShift* ps, float freq)
821+{
822+ float period, out;
823+ int i, iLast;
824+
825+ i = ps->p->i;
826+ iLast = ps->p->iLast;
827+
828+ out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
829+
830+ if (ps->p->indexstore >= ps->frameSize)
831+ {
832+ period = ps->p->period;
833+
834+ if(pitchshift_attackdetect(ps) == 1)
835+ {
836+ ps->p->fba = 5;
837+ tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
838+ }
839+
840+ tSOLAD_setPeriod(&ps->sola, period);
841+
842+ ps->pitchFactor = period*freq*leaf.invSampleRate;
843+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
844+
845+ tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
846+ }
847+ return out;
848+}
849+
850+float tPitchShift_shiftToFunc (tPitchShift* ps, float (*fun)(float))
851+{
852+ float period, out;
853+ int i, iLast;
854+
855+ i = ps->p->i;
856+ iLast = ps->p->iLast;
857+
858+ out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
859+
860+ if (ps->p->indexstore >= ps->frameSize)
861+ {
862+ period = ps->p->period;
863+
864+ if(pitchshift_attackdetect(ps) == 1)
865+ {
866+ ps->p->fba = 5;
867+ tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
868+ }
869+
870+ tSOLAD_setPeriod(&ps->sola, period);
871+
872+ ps->pitchFactor = period/fun(period);
873+ tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
874+
875+ tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
876+
877+ ps->curBlock++;
878+ if (ps->curBlock >= ps->p->framesPerBuffer) ps->curBlock = 0;
879+ ps->lastBlock++;
880+ if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
881+ }
882+
883+ return out;
884+}
885+
886+//============================================================================================================
887+// SOLAD
888+//============================================================================================================
889+/******************************************************************************/
890+/***************** static function declarations *******************************/
891+/******************************************************************************/
892+
893+static void solad_init(tSOLAD *w);
894+static inline float read_sample(tSOLAD *w, float floatindex);
895+static void pitchdown(tSOLAD *w, float *out);
896+static void pitchup(tSOLAD *w, float *out);
897+
898+/******************************************************************************/
899+/***************** public access functions ************************************/
900+/******************************************************************************/
901+
902+// init
903+void tSOLAD_init(tSOLAD* const w)
904+{
905+ w->pitchfactor = 1.;
906+ w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16));
907+ solad_init(w);
908+}
909+
910+void tSOLAD_free(tSOLAD* const w)
911+{
912+}
913+
914+// send one block of input samples, receive one block of output samples
915+void tSOLAD_ioSamples(tSOLAD* const w, float* in, float* out, int blocksize)
916+{
917+ int i = w->timeindex;
918+ int n = w->blocksize = blocksize;
919+
920+ if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation
921+ while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer
922+
923+ if(w->pitchfactor > 1) pitchup(w, out);
924+ else pitchdown(w, out);
925+
926+ w->timeindex += blocksize;
927+ w->timeindex &= LOOPMASK;
928+}
929+
930+// set periodicity analysis data
931+void tSOLAD_setPeriod(tSOLAD* const w, float period)
932+{
933+ if(period > MAXPERIOD) period = MAXPERIOD;
934+ if(period > MINPERIOD) w->period = period; // ignore period when too small
935+}
936+
937+// set pitch factor between 0.25 and 4
938+void tSOLAD_setPitchFactor(tSOLAD* const w, float pitchfactor)
939+{
940+ if(pitchfactor < 0.25) pitchfactor = 0.25;
941+ else if(pitchfactor > 4.) pitchfactor = 4.;
942+ w->pitchfactor = pitchfactor;
943+}
944+
945+// force readpointer lag
946+void tSOLAD_setReadLag(tSOLAD* const w, float readlag)
947+{
948+ if(readlag < 0) readlag = 0;
949+ if(readlag < w->readlag) // do not jump backward, only forward
950+ {
951+ w->jump = w->readlag - readlag;
952+ w->readlag = readlag;
953+ w->xfadelength = readlag;
954+ w->xfadevalue = 1;
955+ }
956+}
957+
958+// reset state variables
959+void tSOLAD_resetState(tSOLAD* const w)
960+{
961+ int n = LOOPSIZE + 1;
962+ float *buf = w->delaybuf;
963+
964+ while(n--) *buf++ = 0;
965+ solad_init(w);
966+}
967+
968+/******************************************************************************/
969+/******************** private procedures **************************************/
970+/******************************************************************************/
971+
972+/*
973+ Function pitchdown() is called to read samples from the delay buffer when pitch
974+ factor is between 0.25 and 1. The read pointer lags behind because of the slowed
975+ down speed, and it must jump forward towards the write pointer soon as there is
976+ sufficient space to jump. That is, if there is at least one period of the input
977+ signal between read pointer and write pointer. When short periods follow up on
978+ long periods, the read pointer may have space to jump over more than one period
979+ lenghts. Jump length must be [periodlength ^ 2] in any case.
980+
981+ A linear crossfade function joins the jump-from point with the jump-to point.
982+ The crossfade must be completed before another read pointer jump is allowed.
983+ Length of the crossfade function is stored as a number of samples in terms of
984+ the input sample rate. This length is dynamically translated
985+ to a crossfade length expressed in output reading rate, according to pitch
986+ factor which can change before the crossfade is completed. Crossfade length does
987+ not cover an invariable length in periods for all pitch transposition factors.
988+ For pitch factors from 0.5 till 1, crossfade length is stretched in the
989+ output just as much as the signal itself, as crossfade speed is set to equal
990+ pitch factor. For pitch factors below 0.5, the read pointer wants to jump
991+ forward before one period is read, therefore the crossfade length as expressed
992+ in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
993+ for those cases. Pitch factor 0.5 is the natural switch point between crossfade
994+ speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
995+ speed modification for pitch factors below 0.5 also means that much of the
996+ original signal content will be skipped.
997+ */
998+
999+
1000+static void pitchdown(tSOLAD* const w, float *out)
1001+{
1002+ int n = w->blocksize;
1003+ float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
1004+ float pitchfactor = w->pitchfactor;
1005+ float period = w->period;
1006+ float readlag = w->readlag;
1007+ float readlagstep = 1 - pitchfactor;
1008+ float jump = w->jump;
1009+ float xfadevalue = w->xfadevalue;
1010+ float xfadelength = w->xfadelength;
1011+ float xfadespeed, xfadestep, readindex, outputsample;
1012+
1013+ if(pitchfactor > 0.5) xfadespeed = pitchfactor;
1014+ else xfadespeed = 1 - pitchfactor;
1015+ xfadestep = xfadespeed / xfadelength;
1016+
1017+ while(n--)
1018+ {
1019+ if(readlag > period) // check if read pointer may jump forward...
1020+ {
1021+ if(xfadevalue <= 0) // ...but do not interrupt crossfade
1022+ {
1023+ jump = period; // jump forward
1024+ while((jump * 2) < readlag) jump *= 2; // use available space
1025+ readlag -= jump; // reduce read pointer lag
1026+ xfadevalue = 1; // start crossfade
1027+ xfadelength = period - 1;
1028+ xfadestep = xfadespeed / xfadelength;
1029+ }
1030+ }
1031+
1032+ readindex = refindex - readlag;
1033+ outputsample = read_sample(w, readindex);
1034+
1035+ if(xfadevalue > 0)
1036+ {
1037+ outputsample *= (1 - xfadevalue); // fadein
1038+ outputsample += read_sample(w, readindex - jump) * xfadevalue; // fadeout
1039+ xfadevalue -= xfadestep;
1040+ }
1041+
1042+ *out++ = outputsample;
1043+ refindex += 1;
1044+ readlag += readlagstep;
1045+ }
1046+
1047+ w->jump = jump; // state variables
1048+ w->readlag = readlag;
1049+ w->xfadevalue = xfadevalue;
1050+ w->xfadelength = xfadelength;
1051+}
1052+
1053+
1054+/*
1055+ Function pitchup() for pitch factors above 1 is more complicated than
1056+ pitchdown(). The read pointer increments faster than the write pointer and a
1057+ backward jump must happen in time, reckoning with the crossfade region. The read
1058+ pointer backward jump length is always one period. In order to minimize the area
1059+ of signal duplicates, crossfade length is aimed at [period / pitchfactor].
1060+ This leads to a crossfade speed of [pitchfactor * pitchfactor].
1061+
1062+ Some samples for the fade out (but not all of them) must already be in the
1063+ buffer, otherwise we will run out of input samples before the crossfade is
1064+ completed. The ratio of past samples and future samples for a crossfade of any
1065+ length is as follows:
1066+
1067+ past samples: xfadelength * (1 - 1 / pitchfactor)
1068+ future samples: xfadelength * (1 / pitchfactor)
1069+
1070+ For example in the case of pitch factor 1.5 this would be:
1071+
1072+ past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3
1073+ future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3
1074+
1075+ In the case of pitch factor 4 this would be:
1076+
1077+ past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4
1078+ future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4
1079+
1080+ The read pointer lag must therefore preserve a minimum dependent on pitch
1081+ factor. The minimum is called 'limit' here:
1082+
1083+ limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor
1084+
1085+ Components of this expression are combined to reuse them in operations, while
1086+ (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical
1087+ resolution issues for pitch factors slightly above 1:
1088+
1089+ xfadespeed = pitchfactor * pitchfactor
1090+ limitfactor = (pitchfactor - 0.99) / xfadespeed
1091+ limit = period * limitfactor
1092+
1093+ When read lag is smaller than this limit, the read pointer must preferably
1094+ jump backward, unless a previous crossfade is not yet completed. Crossfades must
1095+ preferably be completed, unless the read pointer lag becomes smaller than zero.
1096+ With fluctuating period lengths and pitch factors, the readpointer lag limit may
1097+ change from one input block to the next in such a way that the actual lag is
1098+ suddenly much smaller than the limit, and the intended crossfade length can not
1099+ be applied. Therefore the crossfade length is simply calculated from the
1100+ available amount of samples for all cases, like so:
1101+
1102+ xfadelength = readlag / limitfactor
1103+
1104+ For most occurrences, this will amount to a crossfade length reduced to
1105+ [period / pitchfactor] in the output for pitch factors above 1, while in some
1106+ cases it will be considerably shorter. Fortunately, an incidental aberration of
1107+ the intended crossfade length hardly ever creates an audible artifact. The
1108+ reason to specify preferred crossfade length according to pitch factor is to
1109+ minimize the impression of echoes without sacrificing too much of the signal
1110+ content. The readpointer jump length remains one period in any case.
1111+
1112+ Sometimes, the input signal periodicity may decrease substantially between one
1113+ signal block and the next. In such cases it may be possible for the read pointer
1114+ to jump forward and reduce latency. For every signal block, a check on this
1115+ possibility is done. A previous crossfade must be completed before a forward
1116+ jump is allowed.
1117+ */
1118+static void pitchup(tSOLAD* const w, float *out)
1119+{
1120+ int n = w->blocksize;
1121+ float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
1122+ float pitchfactor = w->pitchfactor;
1123+ float period = w->period;
1124+ float readlag = w->readlag;
1125+ float jump = w->jump;
1126+ float xfadevalue = w->xfadevalue;
1127+ float xfadelength = w->xfadelength;
1128+
1129+ float readlagstep = pitchfactor - 1;
1130+ float xfadespeed = pitchfactor * pitchfactor;
1131+ float xfadestep = xfadespeed / xfadelength;
1132+ float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;
1133+ float limit = period * limitfactor;
1134+ float readindex, outputsample;
1135+
1136+ if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
1137+ {
1138+ jump = period; // jump forward
1139+ while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space
1140+ readlag -= jump; // reduce read pointer lag
1141+ xfadevalue = 1; // start crossfade
1142+ xfadelength = period - 1;
1143+ xfadestep = xfadespeed / xfadelength;
1144+ }
1145+
1146+ while(n--)
1147+ {
1148+ if(readlag < limit) // check if read pointer should jump backward...
1149+ {
1150+ if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade
1151+ {
1152+ xfadelength = readlag / limitfactor;
1153+ if(xfadelength < 1) xfadelength = 1;
1154+ xfadestep = xfadespeed / xfadelength;
1155+
1156+ jump = -period; // jump backward
1157+ readlag += period; // increase read pointer lag
1158+ xfadevalue = 1; // start crossfade
1159+ }
1160+ }
1161+
1162+ readindex = refindex - readlag;
1163+ outputsample = read_sample(w, readindex);
1164+
1165+ if(xfadevalue > 0)
1166+ {
1167+ outputsample *= (1 - xfadevalue);
1168+ outputsample += read_sample(w, readindex - jump) * xfadevalue;
1169+ xfadevalue -= xfadestep;
1170+ }
1171+
1172+ *out++ = outputsample;
1173+ refindex += 1;
1174+ readlag -= readlagstep;
1175+ }
1176+
1177+ w->readlag = readlag; // state variables
1178+ w->jump = jump;
1179+ w->xfadelength = xfadelength;
1180+ w->xfadevalue = xfadevalue;
1181+}
1182+
1183+// read one sample from delay buffer, with linear interpolation
1184+static inline float read_sample(tSOLAD* const w, float floatindex)
1185+{
1186+ int index = (int)floatindex;
1187+ float fraction = floatindex - (float)index;
1188+ float *buf = w->delaybuf;
1189+ index &= LOOPMASK;
1190+
1191+ return (buf[index] + (fraction * (buf[index+1] - buf[index])));
1192+}
1193+
1194+static void solad_init(tSOLAD* const w)
1195+{
1196+ w->timeindex = 0;
1197+ w->xfadevalue = -1;
1198+ w->period = INITPERIOD;
1199+ w->readlag = INITPERIOD;
1200+ w->blocksize = INITPERIOD;
1201+}
1202+//============================================================================================================
1203+// FORMANTSHIFTER
1204+//============================================================================================================
1205+
1206+void tFormantShifter_init(tFormantShifter* const fs, int bufsize, int order)
1207+{
1208+ fs->ford = order;
1209+ fs->bufsize = bufsize;
1210+ fs->fk = (float*) leaf_alloc(sizeof(float) * fs->ford);
1211+ fs->fb = (float*) leaf_alloc(sizeof(float) * fs->ford);
1212+ fs->fc = (float*) leaf_alloc(sizeof(float) * fs->ford);
1213+ fs->frb = (float*) leaf_alloc(sizeof(float) * fs->ford);
1214+ fs->frc = (float*) leaf_alloc(sizeof(float) * fs->ford);
1215+ fs->fsig = (float*) leaf_alloc(sizeof(float) * fs->ford);
1216+ fs->fsmooth = (float*) leaf_alloc(sizeof(float) * fs->ford);
1217+ fs->ftvec = (float*) leaf_alloc(sizeof(float) * fs->ford);
1218+
1219+ fs->fbuff = (float**) leaf_alloc(sizeof(float*) * fs->ford);
1220+ for (int i = 0; i < fs->ford; i++)
1221+ {
1222+ fs->fbuff[i] = (float*) leaf_alloc(sizeof(float) * fs->bufsize);
1223+ }
1224+
1225+
1226+ fs->falph = powf(0.001f, 80.0f / (leaf.sampleRate));
1227+ fs->flamb = -(0.8517f*sqrt(atanf(0.06583f*leaf.sampleRate))-0.1916f);
1228+ fs->fhp = 0.0f;
1229+ fs->flp = 0.0f;
1230+ fs->flpa = powf(0.001f, 10.0f / (leaf.sampleRate));
1231+ fs->fmute = 1.0f;
1232+ fs->fmutealph = powf(0.001f, 1.0f / (leaf.sampleRate));
1233+ fs->cbi = 0;
1234+}
1235+
1236+void tFormantShifter_free(tFormantShifter* const fs)
1237+{
1238+ leaf_free(fs->fk);
1239+ leaf_free(fs->fb);
1240+ leaf_free(fs->fc);
1241+ leaf_free(fs->frb);
1242+ leaf_free(fs->frc);
1243+ leaf_free(fs->fsig);
1244+ leaf_free(fs->fsmooth);
1245+ leaf_free(fs->ftvec);
1246+ for (int i = 0; i < fs->ford; i++)
1247+ {
1248+ leaf_free(fs->fbuff[i]);
1249+ }
1250+ leaf_free(fs->fbuff);
1251+}
1252+
1253+
1254+float tFormantShifter_tick(tFormantShifter* fs, float in, float fwarp)
1255+{
1256+ return tFormantShifter_add(fs, tFormantShifter_remove(fs, in), fwarp);
1257+}
1258+
1259+float tFormantShifter_remove(tFormantShifter* fs, float in)
1260+{
1261+ float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, fk;
1262+ int ti4;
1263+ ford = fs->ford;
1264+ falph = fs->falph;
1265+ foma = (1.0f - falph);
1266+ flpa = fs->flpa;
1267+ flamb = fs->flamb;
1268+
1269+ tf = in;
1270+ ti4 = fs->cbi;
1271+
1272+ fa = tf - fs->fhp;
1273+ fs->fhp = tf;
1274+ fb = fa;
1275+ for(int i = 0; i < ford; i++)
1276+ {
1277+ fs->fsig[i] = fa*fa*foma + fs->fsig[i]*falph;
1278+ fc = (fb - fs->fc[i])*flamb + fs->fb[i];
1279+ fs->fc[i] = fc;
1280+ fs->fb[i] = fb;
1281+ fk = fa*fc*foma + fs->fk[i]*falph;
1282+ fs->fk[i] = fk;
1283+ tf = fk/(fs->fsig[i] + 0.000001f);
1284+ tf = tf*foma + fs->fsmooth[i]*falph;
1285+ fs->fsmooth[i] = tf;
1286+ fs->fbuff[i][ti4] = tf;
1287+ fb = fc - tf*fa;
1288+ fa = fa - tf*fc;
1289+ }
1290+ fs->cbi++;
1291+ if(fs->cbi >= fs->bufsize)
1292+ {
1293+ fs->cbi = 0;
1294+ }
1295+
1296+ return fa;
1297+}
1298+
1299+float tFormantShifter_add(tFormantShifter* fs, float in, float fwarp)
1300+{
1301+ float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
1302+ int ti4;
1303+ ford = fs->ford;
1304+ falph = fs->falph;
1305+ foma = (1.0f - falph);
1306+ flpa = fs->flpa;
1307+ flamb = fs->flamb;
1308+ tf = exp2(fwarp/2.0f) * (1+flamb)/(1-flamb);
1309+ frlamb = (tf-1)/(tf+1);
1310+ ti4 = fs->cbi;
1311+
1312+ tf2 = in;
1313+ fa = 0;
1314+ fb = fa;
1315+ for (int i=0; i<ford; i++)
1316+ {
1317+ fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
1318+ tf = fs->fbuff[i][ti4];
1319+ fb = fc - tf*fa;
1320+ fs->ftvec[i] = tf*fc;
1321+ fa = fa - fs->ftvec[i];
1322+ }
1323+ tf = -fa;
1324+ for (int i=ford-1; i>=0; i--)
1325+ {
1326+ tf = tf + fs->ftvec[i];
1327+ }
1328+ f0resp = tf;
1329+
1330+ // second time: compute 1-response
1331+ fa = 1;
1332+ fb = fa;
1333+ for (int i=0; i<ford; i++)
1334+ {
1335+ fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
1336+ tf = fs->fbuff[i][ti4];
1337+ fb = fc - tf*fa;
1338+ fs->ftvec[i] = tf*fc;
1339+ fa = fa - fs->ftvec[i];
1340+ }
1341+ tf = -fa;
1342+ for (int i=ford-1; i>=0; i--)
1343+ {
1344+ tf = tf + fs->ftvec[i];
1345+ }
1346+ f1resp = tf;
1347+
1348+ // now solve equations for output, based on 0-response and 1-response
1349+ tf = (float)2*tf2;
1350+ tf2 = tf;
1351+ tf = ((float)1 - f1resp + f0resp);
1352+ if (tf!=0)
1353+ {
1354+ tf2 = (tf2 + f0resp) / tf;
1355+ }
1356+ else
1357+ {
1358+ tf2 = 0;
1359+ }
1360+
1361+ // third time: update delay registers
1362+ fa = tf2;
1363+ fb = fa;
1364+ for (int i=0; i<ford; i++)
1365+ {
1366+ fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
1367+ fs->frc[i] = fc;
1368+ fs->frb[i] = fb;
1369+ tf = fs->fbuff[i][ti4];
1370+ fb = fc - tf*fa;
1371+ fa = fa - tf*fc;
1372+ }
1373+ tf = tf2;
1374+ tf = tf + flpa * fs->flp; // lowpass post-emphasis filter
1375+ fs->flp = tf;
1376+
1377+ // Bring up the gain slowly when formant correction goes from disabled
1378+ // to enabled, while things stabilize.
1379+ if (fs->fmute>0.5)
1380+ {
1381+ tf = tf*(fs->fmute - 0.5)*2;
1382+ }
1383+ else
1384+ {
1385+ tf = 0;
1386+ }
1387+ tf2 = fs->fmutealph;
1388+ fs->fmute = (1-tf2) + tf2*fs->fmute;
1389+ // now tf is signal output
1390+ // ...and we're done messing with formants
1391+
1392+ return tf;
1393+}
LEAF/Src/leaf-electrical.crenamed from LEAF/Src/leaf-WDF.c+13−2
@@ -1,12 +1,23 @@
11 /*
2− * leaf-WDF.c
2+ * leaf-electrical.c
33 *
44 * Created on: Sep 25, 2019
55 * Author: jeffsnyder
66 */
77
8+#if _WIN32 || _WIN64
89
9−#include "../Inc/leaf-WDF.h"
10+#include "..\Inc\leaf-electrical.h"
11+#include "..\leaf.h"
12+
13+#else
14+
15+#include "../Inc/leaf-electrical.h"
16+#include "../leaf.h"
17+
18+#endif
19+
20+//==============================================================================
1021
1122 static float get_port_resistance_for_resistor(tWDF* const r);
1223 static float get_port_resistance_for_capacitor(tWDF* const r);
LEAF/Src/leaf-envelopes.c+629−0
@@ -0,0 +1,629 @@
1+/*
2+ ==============================================================================
3+
4+ leaf-envelopes.c
5+ Created: 20 Jan 2017 12:02:17pm
6+ Author: Michael R Mulshine
7+
8+ ==============================================================================
9+*/
10+
11+
12+#if _WIN32 || _WIN64
13+
14+#include "..\Inc\leaf-envelopes.h"
15+#include "..\Inc\leaf-tables.h"
16+#include "..\leaf.h"
17+
18+#else
19+
20+#include "../Inc/leaf-envelopes.h"
21+#include "../Inc/leaf-tables.h"
22+#include "../leaf.h"
23+
24+#endif
25+
26+#define LOGTEN 2.302585092994
27+
28+float mtof(float f)
29+{
30+ if (f <= -1500.0f) return(0);
31+ else if (f > 1499.0f) return(mtof(1499.0f));
32+ else return (8.17579891564f * expf(0.0577622650f * f));
33+}
34+
35+float ftom(float f)
36+{
37+ return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
38+}
39+
40+float powtodb(float f)
41+{
42+ if (f <= 0) return (0);
43+ else
44+ {
45+ float val = 100 + 10.f/LOGTEN * logf(f);
46+ return (val < 0 ? 0 : val);
47+ }
48+}
49+
50+float rmstodb(float f)
51+{
52+ if (f <= 0) return (0);
53+ else
54+ {
55+ float val = 100 + 20.f/LOGTEN * log(f);
56+ return (val < 0 ? 0 : val);
57+ }
58+}
59+
60+float dbtopow(float f)
61+{
62+ if (f <= 0)
63+ return(0);
64+ else
65+ {
66+ if (f > 870.0f)
67+ f = 870.0f;
68+ return (expf((LOGTEN * 0.1f) * (f-100.0f)));
69+ }
70+}
71+
72+float dbtorms(float f)
73+{
74+ if (f <= 0)
75+ return(0);
76+ else
77+ {
78+ if (f > 485.0f)
79+ f = 485.0f;
80+ }
81+ return (expf((LOGTEN * 0.05f) * (f-100.0f)));
82+}
83+
84+
85+
86+
87+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
88+void tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
89+{
90+ env->exp_buff = exp_decay;
91+ env->inc_buff = attack_decay_inc;
92+ env->buff_size = sizeof(exp_decay);
93+
94+ env->loop = loop;
95+
96+ if (attack > 8192.0f)
97+ attack = 8192.0f;
98+ if (attack < 0.0f)
99+ attack = 0.0f;
100+
101+ if (decay > 8192.0f)
102+ decay = 8192.0f;
103+ if (decay < 0.0f)
104+ decay = 0.0f;
105+
106+ int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
107+ int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
108+ int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
109+
110+ if (attackIndex < 0)
111+ attackIndex = 0;
112+ if (decayIndex < 0)
113+ decayIndex = 0;
114+ if (rampIndex < 0)
115+ rampIndex = 0;
116+
117+ env->inRamp = OFALSE;
118+ env->inAttack = OFALSE;
119+ env->inDecay = OFALSE;
120+
121+ env->attackInc = env->inc_buff[attackIndex];
122+ env->decayInc = env->inc_buff[decayIndex];
123+ env->rampInc = env->inc_buff[rampIndex];
124+
125+}
126+
127+void tEnvelope_free(tEnvelope* const env)
128+{
129+
130+}
131+
132+int tEnvelope_setAttack(tEnvelope* const env, float attack)
133+{
134+ int32_t attackIndex;
135+
136+ if (attack < 0.0f) {
137+ attackIndex = 0.0f;
138+ } else if (attack < 8192.0f) {
139+ attackIndex = ((int32_t)(attack * 8.0f))-1;
140+ } else {
141+ attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
142+ }
143+
144+ env->attackInc = env->inc_buff[attackIndex];
145+
146+ return 0;
147+}
148+
149+int tEnvelope_setDecay(tEnvelope* const env, float decay)
150+{
151+ int32_t decayIndex;
152+
153+ if (decay < 0.0f) {
154+ decayIndex = 0.0f;
155+ } else if (decay < 8192.0f) {
156+ decayIndex = ((int32_t)(decay * 8.0f)) - 1;
157+ } else {
158+ decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
159+ }
160+
161+ env->decayInc = env->inc_buff[decayIndex];
162+
163+ return 0;
164+}
165+
166+int tEnvelope_loop(tEnvelope* const env, oBool loop)
167+{
168+ env->loop = loop;
169+
170+ return 0;
171+}
172+
173+
174+int tEnvelope_on(tEnvelope* const env, float velocity)
175+{
176+ if (env->inAttack || env->inDecay) // In case envelope retriggered while it is still happening.
177+ {
178+ env->rampPhase = 0;
179+ env->inRamp = OTRUE;
180+ env->rampPeak = env->next;
181+ }
182+ else // Normal start.
183+ {
184+ env->inAttack = OTRUE;
185+ }
186+
187+
188+ env->attackPhase = 0;
189+ env->decayPhase = 0;
190+ env->inDecay = OFALSE;
191+ env->gain = velocity;
192+
193+ return 0;
194+}
195+
196+float tEnvelope_tick(tEnvelope* const env)
197+{
198+ if (env->inRamp)
199+ {
200+ if (env->rampPhase > UINT16_MAX)
201+ {
202+ env->inRamp = OFALSE;
203+ env->inAttack = OTRUE;
204+ env->next = 0.0f;
205+ }
206+ else
207+ {
208+ env->next = env->rampPeak * env->exp_buff[(uint32_t)env->rampPhase];
209+ }
210+
211+ env->rampPhase += env->rampInc;
212+ }
213+
214+ if (env->inAttack)
215+ {
216+
217+ // If attack done, time to turn around.
218+ if (env->attackPhase > UINT16_MAX)
219+ {
220+ env->inDecay = OTRUE;
221+ env->inAttack = OFALSE;
222+ env->next = env->gain * 1.0f;
223+ }
224+ else
225+ {
226+ // do interpolation !
227+ env->next = env->gain * env->exp_buff[UINT16_MAX - (uint32_t)env->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
228+ }
229+
230+ // Increment envelope attack.
231+ env->attackPhase += env->attackInc;
232+
233+ }
234+
235+ if (env->inDecay)
236+ {
237+
238+ // If decay done, finish.
239+ if (env->decayPhase >= UINT16_MAX)
240+ {
241+ env->inDecay = OFALSE;
242+
243+ if (env->loop)
244+ {
245+ env->attackPhase = 0;
246+ env->decayPhase = 0;
247+ env->inAttack = OTRUE;
248+ }
249+ else
250+ {
251+ env->next = 0.0f;
252+ }
253+
254+ } else {
255+
256+ env->next = env->gain * (env->exp_buff[(uint32_t)env->decayPhase]); // do interpolation !
257+ }
258+
259+ // Increment envelope decay;
260+ env->decayPhase += env->decayInc;
261+ }
262+
263+ return env->next;
264+}
265+
266+/* ADSR */
267+void tADSR_init(tADSR* const adsr, float attack, float decay, float sustain, float release)
268+{
269+ adsr->exp_buff = exp_decay;
270+ adsr->inc_buff = attack_decay_inc;
271+ adsr->buff_size = sizeof(exp_decay);
272+
273+ if (attack > 8192.0f)
274+ attack = 8192.0f;
275+ if (attack < 0.0f)
276+ attack = 0.0f;
277+
278+ if (decay > 8192.0f)
279+ decay = 8192.0f;
280+ if (decay < 0.0f)
281+ decay = 0.0f;
282+
283+ if (sustain > 1.0f)
284+ sustain = 1.0f;
285+ if (sustain < 0.0f)
286+ sustain = 0.0f;
287+
288+ if (release > 8192.0f)
289+ release = 8192.0f;
290+ if (release < 0.0f)
291+ release = 0.0f;
292+
293+ int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
294+ int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
295+ int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
296+ int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
297+
298+ if (attackIndex < 0)
299+ attackIndex = 0;
300+ if (decayIndex < 0)
301+ decayIndex = 0;
302+ if (releaseIndex < 0)
303+ releaseIndex = 0;
304+ if (rampIndex < 0)
305+ rampIndex = 0;
306+
307+ adsr->inRamp = OFALSE;
308+ adsr->inAttack = OFALSE;
309+ adsr->inDecay = OFALSE;
310+ adsr->inSustain = OFALSE;
311+ adsr->inRelease = OFALSE;
312+
313+ adsr->sustain = sustain;
314+
315+ adsr->attackInc = adsr->inc_buff[attackIndex];
316+ adsr->decayInc = adsr->inc_buff[decayIndex];
317+ adsr->releaseInc = adsr->inc_buff[releaseIndex];
318+ adsr->rampInc = adsr->inc_buff[rampIndex];
319+}
320+
321+void tADSR_free(tADSR* const adsr)
322+{
323+
324+}
325+
326+int tADSR_setAttack(tADSR* const adsr, float attack)
327+{
328+ int32_t attackIndex;
329+
330+ if (attack < 0.0f) {
331+ attackIndex = 0.0f;
332+ } else if (attack < 8192.0f) {
333+ attackIndex = ((int32_t)(attack * 8.0f))-1;
334+ } else {
335+ attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
336+ }
337+
338+ adsr->attackInc = adsr->inc_buff[attackIndex];
339+
340+ return 0;
341+}
342+
343+int tADSR_detDecay(tADSR* const adsr, float decay)
344+{
345+ int32_t decayIndex;
346+
347+ if (decay < 0.0f) {
348+ decayIndex = 0.0f;
349+ } else if (decay < 8192.0f) {
350+ decayIndex = ((int32_t)(decay * 8.0f)) - 1;
351+ } else {
352+ decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
353+ }
354+
355+ adsr->decayInc = adsr->inc_buff[decayIndex];
356+
357+ return 0;
358+}
359+
360+int tADSR_setSustain(tADSR *const adsr, float sustain)
361+{
362+ if (sustain > 1.0f) adsr->sustain = 1.0f;
363+ else if (sustain < 0.0f) adsr->sustain = 0.0f;
364+ else adsr->sustain = sustain;
365+
366+ return 0;
367+}
368+
369+int tADSR_setRelease(tADSR* const adsr, float release)
370+{
371+ int32_t releaseIndex;
372+
373+ if (release < 0.0f) {
374+ releaseIndex = 0.0f;
375+ } else if (release < 8192.0f) {
376+ releaseIndex = ((int32_t)(release * 8.0f)) - 1;
377+ } else {
378+ releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
379+ }
380+
381+ adsr->releaseInc = adsr->inc_buff[releaseIndex];
382+
383+ return 0;
384+}
385+
386+int tADSR_on(tADSR* const adsr, float velocity)
387+{
388+ if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.
389+ {
390+ adsr->rampPhase = 0;
391+ adsr->inRamp = OTRUE;
392+ adsr->rampPeak = adsr->next;
393+ }
394+ else // Normal start.
395+ {
396+ adsr->inAttack = OTRUE;
397+ }
398+
399+ adsr->attackPhase = 0;
400+ adsr->decayPhase = 0;
401+ adsr->releasePhase = 0;
402+ adsr->inDecay = OFALSE;
403+ adsr->inSustain = OFALSE;
404+ adsr->inRelease = OFALSE;
405+ adsr->gain = velocity;
406+
407+ return 0;
408+}
409+
410+int tADSR_off(tADSR* const adsr)
411+{
412+ if (adsr->inRelease) return 0;
413+
414+ adsr->inAttack = OFALSE;
415+ adsr->inDecay = OFALSE;
416+ adsr->inSustain = OFALSE;
417+ adsr->inRelease = OTRUE;
418+
419+ adsr->releasePeak = adsr->next;
420+
421+ return 0;
422+}
423+
424+float tADSR_tick(tADSR* const adsr)
425+{
426+ if (adsr->inRamp)
427+ {
428+ if (adsr->rampPhase > UINT16_MAX)
429+ {
430+ adsr->inRamp = OFALSE;
431+ adsr->inAttack = OTRUE;
432+ adsr->next = 0.0f;
433+ }
434+ else
435+ {
436+ adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
437+ }
438+
439+ adsr->rampPhase += adsr->rampInc;
440+ }
441+
442+ if (adsr->inAttack)
443+ {
444+
445+ // If attack done, time to turn around.
446+ if (adsr->attackPhase > UINT16_MAX)
447+ {
448+ adsr->inDecay = OTRUE;
449+ adsr->inAttack = OFALSE;
450+ adsr->next = adsr->gain * 1.0f;
451+ }
452+ else
453+ {
454+ // do interpolation !
455+ adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
456+ }
457+
458+ // Increment ADSR attack.
459+ adsr->attackPhase += adsr->attackInc;
460+
461+ }
462+
463+ if (adsr->inDecay)
464+ {
465+
466+ // If decay done, sustain.
467+ if (adsr->decayPhase >= UINT16_MAX)
468+ {
469+ adsr->inDecay = OFALSE;
470+ adsr->inSustain = OTRUE;
471+ adsr->next = adsr->gain * adsr->sustain;
472+ }
473+
474+ else
475+ {
476+ adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation !
477+ }
478+
479+ // Increment ADSR decay.
480+ adsr->decayPhase += adsr->decayInc;
481+ }
482+
483+ if (adsr->inRelease)
484+ {
485+ // If release done, finish.
486+ if (adsr->releasePhase >= UINT16_MAX)
487+ {
488+ adsr->inRelease = OFALSE;
489+ adsr->next = 0.0f;
490+ }
491+ else {
492+
493+ adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation !
494+ }
495+
496+ // Increment envelope release;
497+ adsr->releasePhase += adsr->releaseInc;
498+ }
499+
500+ return adsr->next;
501+}
502+
503+/* Ramp */
504+void tRamp_init(tRamp* const ramp, float time, int samples_per_tick)
505+{
506+ ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f);
507+ ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
508+ ramp->curr = 0.0f;
509+ ramp->dest = 0.0f;
510+
511+ if (time < ramp->minimum_time)
512+ {
513+ ramp->time = ramp->minimum_time;
514+ }
515+ else
516+ {
517+ ramp->time = time;
518+ }
519+
520+ ramp->samples_per_tick = samples_per_tick;
521+ ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick;
522+}
523+
524+void tRamp_free(tRamp* const ramp)
525+{
526+
527+}
528+
529+int tRamp_setTime(tRamp* const r, float time)
530+{
531+ if (time < r->minimum_time)
532+ {
533+ r->time = r->minimum_time;
534+ }
535+ else
536+ {
537+ r->time = time;
538+ }
539+ r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
540+ return 0;
541+}
542+
543+int tRamp_setDest(tRamp* const r, float dest)
544+{
545+ r->dest = dest;
546+ r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
547+ return 0;
548+}
549+
550+int tRamp_setVal(tRamp* const r, float val)
551+{
552+ r->curr = val;
553+ r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
554+ return 0;
555+}
556+
557+float tRamp_tick(tRamp* const r) {
558+
559+ r->curr += r->inc;
560+
561+ if (((r->curr >= r->dest) && (r->inc > 0.0f)) || ((r->curr <= r->dest) && (r->inc < 0.0f))) r->inc = 0.0f;
562+ // Palle: There is a slight risk that you overshoot here and stay on dest+inc, which with a large inc value could be a real problem
563+ // I suggest you add: r->curr=r->dest in the true if case
564+
565+ return r->curr;
566+}
567+
568+float tRamp_sample(tRamp* const r) {
569+
570+ return r->curr;
571+}
572+
573+void tRampSampleRateChanged(tRamp* const r)
574+{
575+ r->inv_sr_ms = 1.0f / (leaf.sampleRate * 0.001f);
576+ r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms)*((float)r->samples_per_tick);
577+}
578+
579+
580+/* Exponential Smoother */
581+void tExpSmooth_init(tExpSmooth* const smooth, float val, float factor)
582+{ // factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
583+ smooth->curr=val;
584+ smooth->dest=val;
585+ if (factor<0) factor=0;
586+ if (factor>1) factor=1;
587+ smooth->factor=factor;
588+ smooth->oneminusfactor=1.0f-factor;
589+}
590+
591+void tExpSmooth_free(tExpSmooth* const smooth)
592+{
593+
594+}
595+
596+int tExpSmooth_setFactor(tExpSmooth* const smooth, float factor)
597+{ // factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
598+ if (factor<0)
599+ factor=0;
600+ else
601+ if (factor>1) factor=1;
602+ smooth->factor=factor;
603+ smooth->oneminusfactor=1.0f-factor;
604+ return 0;
605+}
606+
607+int tExpSmooth_setDest(tExpSmooth* const smooth, float dest)
608+{
609+ smooth->dest=dest;
610+ return 0;
611+}
612+
613+int tExpSmooth_setVal(tExpSmooth* const smooth, float val)
614+{
615+ smooth->curr=val;
616+ return 0;
617+}
618+
619+float tExpSmooth_tick(tExpSmooth* const smooth)
620+{
621+ smooth->curr = smooth->factor*smooth->dest+smooth->oneminusfactor*smooth->curr;
622+ return smooth->curr;
623+}
624+
625+float tExpSmooth_sample(tExpSmooth* const smooth)
626+{
627+ return smooth->curr;
628+}
629+
LEAF/Src/leaf-filters.crenamed from LEAF/Src/leaf-filter.c+11−11
@@ -8,13 +8,13 @@ · 7 unmodified lines
88
99 #if _WIN32 || _WIN64
1010
11−#include "..\Inc\leaf-filter.h"
11+#include "..\Inc\leaf-filters.h"
1212 #include "..\Inc\leaf-tables.h"
1313 #include "..\leaf.h"
1414
1515 #else
1616
17−#include "../Inc/leaf-filter.h"
17+#include "../Inc/leaf-filters.h"
1818 #include "../Inc/leaf-tables.h"
1919 #include "../leaf.h"
2020
@@ -27,17 +27,17 @@ void tAllpass_init(tAllpass* const f, float initDelay, uint32_t maxDelay) · 6 unmodified lines
2727
2828 f->lastOut = 0.0f;
2929
30− tDelayL_init(&f->delay, initDelay, maxDelay);
30+ tLinearDelay_init(&f->delay, initDelay, maxDelay);
3131 }
3232
3333 void tAllpass_free(tAllpass* const f)
3434 {
35− tDelayL_free(&f->delay);
35+ tLinearDelay_free(&f->delay);
3636 }
3737
3838 void tAllpass_setDelay(tAllpass* const f, float delay)
3939 {
40− tDelayL_setDelay(&f->delay, delay);
40+ tLinearDelay_setDelay(&f->delay, delay);
4141 }
4242
4343 void tAllpass_setGain(tAllpass* const f, float gain)
@@ -49,7 +49,7 @@ float tAllpass_tick(tAllpass* const f, float input) · 5 unmodified lines
4949 {
5050 float s1 = (-f->gain) * f->lastOut + input;
5151
52− float s2 = tDelayL_tick(&f->delay, s1) + (f->gain) * input;
52+ float s2 = tLinearDelay_tick(&f->delay, s1) + (f->gain) * input;
5353
5454 f->lastOut = s2;
5555
@@ -758,7 +758,7 @@ int tSVF_setQ(tSVF* const svf, float Q) · 702 unmodified lines
758758 }
759759
760760 // Efficient version of tSVF where frequency is set based on 12-bit integer input for lookup in tanh wavetable.
761−void tSVFE_init(tSVFE* const svf, SVFType type, uint16_t input, float Q)
761+void tEfficientSVF_init(tEfficientSVF* const svf, SVFType type, uint16_t input, float Q)
762762 {
763763 svf->type = type;
764764
@@ -779,12 +779,12 @@ void tSVFE_init(tSVFE* const svf, SVFType type, uint16_t input, float Q) · 14 unmodified lines
779779 svf->a3 = a3;
780780 }
781781
782−void tSVFE_free(tSVFE* const svf)
782+void tEfficientSVF_free(tEfficientSVF* const svf)
783783 {
784784
785785 }
786786
787−float tSVFE_tick(tSVFE* const svf, float v0)
787+float tEfficientSVF_tick(tEfficientSVF* const svf, float v0)
788788 {
789789 float v1,v2,v3;
790790 v3 = v0 - svf->ic2eq;
@@ -802,7 +802,7 @@ float tSVFE_tick(tSVFE* const svf, float v0) · 11 unmodified lines
802802
803803 }
804804
805−int tSVFE_setFreq(tSVFE* const svf, uint16_t input)
805+int tEfficientSVF_setFreq(tEfficientSVF* const svf, uint16_t input)
806806 {
807807 svf->g = filtertan[input];
808808 svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
@@ -812,7 +812,7 @@ int tSVFE_setFreq(tSVFE* const svf, uint16_t input) · 3 unmodified lines
812812 return 0;
813813 }
814814
815−int tSVFE_setQ(tSVFE* const svf, float Q)
815+int tEfficientSVF_setQ(tEfficientSVF* const svf, float Q)
816816 {
817817 svf->k = 1.0f/Q;
818818 svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
LEAF/Src/leaf-formant.c+0−206
@@ -1,206 +0,0 @@
1−/*==============================================================================
2−
3− leaf-formant.c
4− Created: 30 Nov 2018 11:03:30am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#if _WIN32 || _WIN64
10−
11−#include "..\Inc\leaf-formant.h"
12−#else
13−
14−#include "../Inc/leaf-formant.h"
15−
16−#endif
17−
18−
19−void tFormantShifter_init(tFormantShifter* const fs, int bufsize, int order)
20−{
21− fs->ford = order;
22− fs->bufsize = bufsize;
23− fs->fk = (float*) leaf_alloc(sizeof(float) * fs->ford);
24− fs->fb = (float*) leaf_alloc(sizeof(float) * fs->ford);
25− fs->fc = (float*) leaf_alloc(sizeof(float) * fs->ford);
26− fs->frb = (float*) leaf_alloc(sizeof(float) * fs->ford);
27− fs->frc = (float*) leaf_alloc(sizeof(float) * fs->ford);
28− fs->fsig = (float*) leaf_alloc(sizeof(float) * fs->ford);
29− fs->fsmooth = (float*) leaf_alloc(sizeof(float) * fs->ford);
30− fs->ftvec = (float*) leaf_alloc(sizeof(float) * fs->ford);
31−
32− fs->fbuff = (float**) leaf_alloc(sizeof(float*) * fs->ford);
33− for (int i = 0; i < fs->ford; i++)
34− {
35− fs->fbuff[i] = (float*) leaf_alloc(sizeof(float) * fs->bufsize);
36− }
37−
38−
39− fs->falph = powf(0.001f, 80.0f / (leaf.sampleRate));
40− fs->flamb = -(0.8517f*sqrt(atanf(0.06583f*leaf.sampleRate))-0.1916f);
41− fs->fhp = 0.0f;
42− fs->flp = 0.0f;
43− fs->flpa = powf(0.001f, 10.0f / (leaf.sampleRate));
44− fs->fmute = 1.0f;
45− fs->fmutealph = powf(0.001f, 1.0f / (leaf.sampleRate));
46− fs->cbi = 0;
47−}
48−
49−void tFormantShifter_free(tFormantShifter* const fs)
50−{
51− leaf_free(fs->fk);
52− leaf_free(fs->fb);
53− leaf_free(fs->fc);
54− leaf_free(fs->frb);
55− leaf_free(fs->frc);
56− leaf_free(fs->fsig);
57− leaf_free(fs->fsmooth);
58− leaf_free(fs->ftvec);
59− for (int i = 0; i < fs->ford; i++)
60− {
61− leaf_free(fs->fbuff[i]);
62− }
63− leaf_free(fs->fbuff);
64−}
65−
66−
67−float tFormantShifter_tick(tFormantShifter* fs, float in, float fwarp)
68−{
69− return tFormantShifter_add(fs, tFormantShifter_remove(fs, in), fwarp);
70−}
71−
72−float tFormantShifter_remove(tFormantShifter* fs, float in)
73−{
74− float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, fk;
75− int ti4;
76− ford = fs->ford;
77− falph = fs->falph;
78− foma = (1.0f - falph);
79− flpa = fs->flpa;
80− flamb = fs->flamb;
81−
82− tf = in;
83− ti4 = fs->cbi;
84−
85− fa = tf - fs->fhp;
86− fs->fhp = tf;
87− fb = fa;
88− for(int i = 0; i < ford; i++)
89− {
90− fs->fsig[i] = fa*fa*foma + fs->fsig[i]*falph;
91− fc = (fb - fs->fc[i])*flamb + fs->fb[i];
92− fs->fc[i] = fc;
93− fs->fb[i] = fb;
94− fk = fa*fc*foma + fs->fk[i]*falph;
95− fs->fk[i] = fk;
96− tf = fk/(fs->fsig[i] + 0.000001f);
97− tf = tf*foma + fs->fsmooth[i]*falph;
98− fs->fsmooth[i] = tf;
99− fs->fbuff[i][ti4] = tf;
100− fb = fc - tf*fa;
101− fa = fa - tf*fc;
102− }
103− fs->cbi++;
104− if(fs->cbi >= fs->bufsize)
105− {
106− fs->cbi = 0;
107− }
108−
109− return fa;
110−}
111−
112−float tFormantShifter_add(tFormantShifter* fs, float in, float fwarp)
113−{
114− float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
115− int ti4;
116− ford = fs->ford;
117− falph = fs->falph;
118− foma = (1.0f - falph);
119− flpa = fs->flpa;
120− flamb = fs->flamb;
121− tf = exp2(fwarp/2.0f) * (1+flamb)/(1-flamb);
122− frlamb = (tf-1)/(tf+1);
123− ti4 = fs->cbi;
124−
125− tf2 = in;
126− fa = 0;
127− fb = fa;
128− for (int i=0; i<ford; i++)
129− {
130− fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
131− tf = fs->fbuff[i][ti4];
132− fb = fc - tf*fa;
133− fs->ftvec[i] = tf*fc;
134− fa = fa - fs->ftvec[i];
135− }
136− tf = -fa;
137− for (int i=ford-1; i>=0; i--)
138− {
139− tf = tf + fs->ftvec[i];
140− }
141− f0resp = tf;
142−
143− // second time: compute 1-response
144− fa = 1;
145− fb = fa;
146− for (int i=0; i<ford; i++)
147− {
148− fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
149− tf = fs->fbuff[i][ti4];
150− fb = fc - tf*fa;
151− fs->ftvec[i] = tf*fc;
152− fa = fa - fs->ftvec[i];
153− }
154− tf = -fa;
155− for (int i=ford-1; i>=0; i--)
156− {
157− tf = tf + fs->ftvec[i];
158− }
159− f1resp = tf;
160−
161− // now solve equations for output, based on 0-response and 1-response
162− tf = (float)2*tf2;
163− tf2 = tf;
164− tf = ((float)1 - f1resp + f0resp);
165− if (tf!=0)
166− {
167− tf2 = (tf2 + f0resp) / tf;
168− }
169− else
170− {
171− tf2 = 0;
172− }
173−
174− // third time: update delay registers
175− fa = tf2;
176− fb = fa;
177− for (int i=0; i<ford; i++)
178− {
179− fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
180− fs->frc[i] = fc;
181− fs->frb[i] = fb;
182− tf = fs->fbuff[i][ti4];
183− fb = fc - tf*fa;
184− fa = fa - tf*fc;
185− }
186− tf = tf2;
187− tf = tf + flpa * fs->flp; // lowpass post-emphasis filter
188− fs->flp = tf;
189−
190− // Bring up the gain slowly when formant correction goes from disabled
191− // to enabled, while things stabilize.
192− if (fs->fmute>0.5)
193− {
194− tf = tf*(fs->fmute - 0.5)*2;
195− }
196− else
197− {
198− tf = 0;
199− }
200− tf2 = fs->fmutealph;
201− fs->fmute = (1-tf2) + tf2*fs->fmute;
202− // now tf is signal output
203− // ...and we're done messing with formants
204−
205− return tf;
206−}
LEAF/Src/leaf-instruments.crenamed from LEAF/Src/leaf-808.c+3−3
@@ -1,6 +1,6 @@
11 /*==============================================================================
22
3− leaf-808.c
3+ leaf-instruments.c
44 Created: 30 Nov 2018 10:24:21am
55 Author: airship
66
@@ -8,11 +8,11 @@ · 1 unmodified line
88
99 #if _WIN32 || _WIN64
1010
11−#include "..\Inc\leaf-808.h"
11+#include "..\Inc\leaf-instruments.h"
1212
1313 #else
1414
15−#include "../Inc/leaf-808.h"
15+#include "../Inc/leaf-instruments.h"
1616
1717 #endif
1818
LEAF/Src/leaf-math.c+2−0
@@ -355,3 +355,5 @@ float LEAF_interpolation_linear (float A, float B, float alpha) · 354 unmodified lines
355355
356356 return out;
357357 }
358+
359+
LEAF/Src/leaf-midi.c+213−0
@@ -305,3 +305,216 @@ int tPoly_isOn(tPoly* const poly, uint8_t voice) · 304 unmodified lines
305305 return (poly->voices[voice][0] > 0) ? 1 : 0;
306306 }
307307
308+
309+//====================================================================================
310+/* Stack */
311+//====================================================================================
312+
313+void tStack_init(tStack* const ns)
314+{
315+ ns->ordered = OFALSE;
316+ ns->size = 0;
317+ ns->pos = 0;
318+ ns->capacity = STACK_SIZE;
319+
320+ for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
321+}
322+
323+void tStack_free(tStack* const ns)
324+{
325+
326+}
327+
328+// If stack contains note, returns index. Else returns -1;
329+int tStack_contains(tStack* const ns, uint16_t noteVal)
330+{
331+ for (int i = 0; i < ns->size; i++)
332+ {
333+ if (ns->data[i] == noteVal) return i;
334+ }
335+ return -1;
336+}
337+
338+void tStack_add(tStack* const ns, uint16_t noteVal)
339+{
340+ uint8_t j;
341+
342+ int whereToInsert = 0;
343+ if (ns->ordered)
344+ {
345+ for (j = 0; j < ns->size; j++)
346+ {
347+ if (noteVal > ns->data[j])
348+ {
349+ if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
350+ {
351+ whereToInsert = j+1;
352+ break;
353+ }
354+ }
355+ }
356+ }
357+
358+ //first move notes that are already in the stack one position to the right
359+ for (j = ns->size; j > whereToInsert; j--)
360+ {
361+ ns->data[j] = ns->data[(j - 1)];
362+ }
363+
364+ //then, insert the new note into the front of the stack
365+ ns->data[whereToInsert] = noteVal;
366+
367+ ns->size++;
368+}
369+
370+int tStack_addIfNotAlreadyThere(tStack* const ns, uint16_t noteVal)
371+{
372+ uint8_t j;
373+
374+ int added = 0;
375+
376+ if (tStack_contains(ns, noteVal) == -1)
377+ {
378+ int whereToInsert = 0;
379+ if (ns->ordered)
380+ {
381+ for (j = 0; j < ns->size; j++)
382+ {
383+ if (noteVal > ns->data[j])
384+ {
385+ if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
386+ {
387+ whereToInsert = j+1;
388+ break;
389+ }
390+ }
391+ }
392+ }
393+
394+ //first move notes that are already in the stack one position to the right
395+ for (j = ns->size; j > whereToInsert; j--)
396+ {
397+ ns->data[j] = ns->data[(j - 1)];
398+ }
399+
400+ //then, insert the new note into the front of the stack
401+ ns->data[whereToInsert] = noteVal;
402+
403+ ns->size++;
404+
405+ added = 1;
406+ }
407+
408+ return added;
409+}
410+
411+
412+// Remove noteVal. return 1 if removed, 0 if not
413+int tStack_remove(tStack* const ns, uint16_t noteVal)
414+{
415+ uint8_t k;
416+ int foundIndex = tStack_contains(ns, noteVal);
417+ int removed = 0;
418+
419+ if (foundIndex >= 0)
420+ {
421+ for (k = 0; k < (ns->size - foundIndex); k++)
422+ {
423+ if ((k+foundIndex) >= (ns->capacity - 1))
424+ {
425+ ns->data[k + foundIndex] = -1;
426+ }
427+ else
428+ {
429+ ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
430+ if ((k + foundIndex) == (ns->size - 1))
431+ {
432+ ns->data[k + foundIndex + 1] = -1;
433+ }
434+ }
435+
436+ }
437+ // in case it got put on the stack multiple times
438+ foundIndex--;
439+ ns->size--;
440+ removed = 1;
441+ }
442+
443+
444+
445+ return removed;
446+}
447+
448+// Doesn't change size of data types
449+void tStack_setCapacity(tStack* const ns, uint16_t cap)
450+{
451+ if (cap <= 0)
452+ ns->capacity = 1;
453+ else if (cap <= STACK_SIZE)
454+ ns->capacity = cap;
455+ else
456+ ns->capacity = STACK_SIZE;
457+
458+ for (int i = cap; i < STACK_SIZE; i++)
459+ {
460+ if ((int)ns->data[i] != -1)
461+ {
462+ ns->data[i] = -1;
463+ ns->size -= 1;
464+ }
465+ }
466+
467+ if (ns->pos >= cap)
468+ {
469+ ns->pos = 0;
470+ }
471+}
472+
473+int tStack_getSize(tStack* const ns)
474+{
475+ return ns->size;
476+}
477+
478+void tStack_clear(tStack* const ns)
479+{
480+ for (int i = 0; i < STACK_SIZE; i++)
481+ {
482+ ns->data[i] = -1;
483+ }
484+ ns->pos = 0;
485+ ns->size = 0;
486+}
487+
488+// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
489+int tStack_next(tStack* const ns)
490+{
491+ int step = 0;
492+ if (ns->size != 0) // if there is at least one note in the stack
493+ {
494+ if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest)
495+ {
496+ ns->pos--;
497+ }
498+ else
499+ {
500+ ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
501+ }
502+
503+ step = ns->data[ns->pos];
504+ return step;
505+ }
506+ else
507+ {
508+ return -1;
509+ }
510+}
511+
512+int tStack_get(tStack* const ns, int which)
513+{
514+ return ns->data[which];
515+}
516+
517+int tStack_first(tStack* const ns)
518+{
519+ return ns->data[0];
520+}
LEAF/Src/leaf-oscillators.crenamed from LEAF/Src/leaf-oscillator.c+305−299
@@ -1,6 +1,6 @@
11 /*==============================================================================
22
3− leaf-oscillator.c
3+ leaf-oscillators.c
44 Created: 20 Jan 2017 12:00:58pm
55 Author: Michael R Mulshine
66
@@ -9,212 +9,17 @@ · 2 unmodified lines
99 #if _WIN32 || _WIN64
1010
1111 #include "..\Inc\leaf-tables.h"
12−#include "..\Inc\leaf-oscillator.h"
12+#include "..\Inc\leaf-oscillators.h"
1313 #include "..\leaf.h"
1414
1515 #else
1616
1717 #include "../Inc/leaf-tables.h"
18−#include "../Inc/leaf-oscillator.h"
18+#include "../Inc/leaf-oscillators.h"
1919 #include "../leaf.h"
2020
2121 #endif
2222
23−void tNeuronSampleRateChanged(tNeuron* n)
24−{
25−
26−}
27−
28−void tNeuron_init(tNeuron* const n)
29−{
30− tPoleZero_init(&n->f);
31−
32− tPoleZero_setBlockZero(&n->f, 0.99f);
33−
34− n->timeStep = 1.0f / 50.0f;
35−
36− n->current = 0.0f; // 100.0f for sound
37− n->voltage = 0.0f;
38−
39− n->mode = NeuronNormal;
40−
41− n->P[0] = 0.0f;
42− n->P[1] = 0.0f;
43− n->P[2] = 1.0f;
44−
45− n->V[0] = -12.0f;
46− n->V[1] = 115.0f;
47− n->V[2] = 10.613f;
48−
49− n->gK = 36.0f;
50− n->gN = 120.0f;
51− n->gL = 0.3f;
52− n->C = 1.0f;
53−
54− n->rate[2] = n->gL/n->C;
55−}
56−
57−void tNeuron_free(tNeuron* const n)
58−{
59− tPoleZero_free(&n->f);
60−}
61−
62−void tNeuron_reset(tNeuron* const n)
63−{
64−
65− tPoleZero_setBlockZero(&n->f, 0.99f);
66−
67− n->timeStep = 1.0f / 50.0f;
68−
69− n->current = 0.0f; // 100.0f for sound
70− n->voltage = 0.0f;
71−
72− n->mode = NeuronNormal;
73−
74− n->P[0] = 0.0f;
75− n->P[1] = 0.0f;
76− n->P[2] = 1.0f;
77−
78− n->V[0] = -12.0f;
79− n->V[1] = 115.0f;
80− n->V[2] = 10.613f;
81−
82− n->gK = 36.0f;
83− n->gN = 120.0f;
84− n->gL = 0.3f;
85− n->C = 1.0f;
86−
87− n->rate[2] = n->gL/n->C;
88−}
89−
90−
91−void tNeuron_setV1(tNeuron* const n, float V1)
92−{
93− n->V[0] = V1;
94−}
95−
96−
97−void tNeuron_setV2(tNeuron* const n, float V2)
98−{
99− n->V[1] = V2;
100−}
101−
102−void tNeuron_setV3(tNeuron* const n, float V3)
103−{
104− n->V[2] = V3;
105−}
106−
107−void tNeuron_setTimeStep(tNeuron* const n, float timeStep)
108−{
109− n->timeStep = timeStep;
110−}
111−
112−void tNeuron_setK(tNeuron* const n, float K)
113−{
114− n->gK = K;
115−}
116−
117−void tNeuron_setL(tNeuron* const n, float L)
118−{
119− n->gL = L;
120− n->rate[2] = n->gL/n->C;
121−}
122−
123−void tNeuron_setN(tNeuron* const n, float N)
124−{
125− n->gN = N;
126−}
127−
128−void tNeuron_setC(tNeuron* const n, float C)
129−{
130− n->C = C;
131− n->rate[2] = n->gL/n->C;
132−}
133−
134−float tNeuron_tick(tNeuron* const n)
135−{
136− float output = 0.0f;
137− float voltage = n->voltage;
138−
139− n->alpha[0] = (0.01f * (10.0f - voltage)) / (expf((10.0f - voltage)/10.0f) - 1.0f);
140− n->alpha[1] = (0.1f * (25.0f-voltage)) / (expf((25.0f-voltage)/10.0f) - 1.0f);
141− n->alpha[2] = (0.07f * expf((-1.0f * voltage)/20.0f));
142−
143− n->beta[0] = (0.125f * expf((-1.0f* voltage)/80.0f));
144− n->beta[1] = (4.0f * expf((-1.0f * voltage)/18.0f));
145− n->beta[2] = (1.0f / (expf((30.0f-voltage)/10.0f) + 1.0f));
146−
147− for (int i = 0; i < 3; i++)
148− {
149− n->P[i] = (n->alpha[i] * n->timeStep) + ((1.0f - ((n->alpha[i] + n->beta[i]) * n->timeStep)) * n->P[i]);
150−
151− if (n->P[i] > 1.0f) n->P[i] = 0.0f;
152− else if (n->P[i] < -1.0f) n->P[i] = 0.0f;
153− }
154− // rate[0]= k ; rate[1] = Na ; rate[2] = l
155− n->rate[0] = ((n->gK * powf(n->P[0], 4.0f)) / n->C);
156− n->rate[1] = ((n->gN * powf(n->P[1], 3.0f) * n->P[2]) / n->C);
157−
158− //calculate the final membrane voltage based on the computed variables
159− n->voltage = voltage +
160− (n->timeStep * n->current / n->C) -
161− (n->timeStep * ( n->rate[0] * (voltage - n->V[0]) + n->rate[1] * (voltage - n->V[1]) + n->rate[2] * (voltage - n->V[2])));
162−
163− if (n->mode == NeuronTanh)
164− {
165− n->voltage = 100.0f * tanhf(0.01f * n->voltage);
166− }
167− else if (n->mode == NeuronAaltoShaper)
168− {
169− float shapeVoltage = 0.01f * n->voltage;
170−
171− float w, c, xc, xc2, xc4;
172−
173− float sqrt8 = 2.82842712475f;
174−
175− float wscale = 1.30612244898f;
176− float m_drive = 1.0f;
177−
178− xc = LEAF_clip(-sqrt8, shapeVoltage, sqrt8);
179−
180− xc2 = xc*xc;
181−
182− c = 0.5f * shapeVoltage * (3.0f - (xc2));
183−
184− xc4 = xc2 * xc2;
185−
186− w = (1.0f - xc2 * 0.25f + xc4 * 0.015625f) * wscale;
187−
188− shapeVoltage = w * (c + 0.05f * xc2) * (m_drive + 0.75f);
189−
190− n->voltage = 100.0f * shapeVoltage;
191− }
192−
193−
194− if (n->voltage > 100.0f) n->voltage = 100.0f;
195− else if (n->voltage < -100.) n->voltage = -100.0f;
196−
197− //(inputCurrent + (voltage - ((voltage * timeStep) / timeConstant)) + P[0] + P[1] + P[2]) => voltage;
198− // now we should have a result
199− //set the output voltage to the "step" ugen, which controls the DAC.
200− output = n->voltage * 0.01f; // volts
201−
202− output = tPoleZero_tick(&n->f, output);
203−
204− return output;
205−
206−}
207−
208−void tNeuron_setMode (tNeuron* const n, NeuronMode mode)
209−{
210− n->mode = mode;
211−}
212−
213−void tNeuron_setCurrent (tNeuron* const n, float current)
214−{
215− n->current = current;
216−}
217−
21823 // Cycle
21924 void tCycle_init(tCycle* const c)
22025 {
@@ -258,56 +63,25 @@ void tCycleSampleRateChanged (tCycle* const c) · 37 unmodified lines
25863 c->inc = c->freq * leaf.invSampleRate;
25964 }
26065
261−/* Phasor */
262−void tPhasorSampleRateChanged (tPhasor* const p)
263−{
264− p->inc = p->freq * leaf.invSampleRate;
265−};
266−
267−void tPhasor_init(tPhasor* const p)
268−{
269− p->phase = 0.0f;
270− p->inc = 0.0f;
271−}
272−
273−void tPhasor_free(tPhasor* const p)
66+//========================================================================
67+/* Triangle */
68+void tTriangle_start(tTriangle* const c)
27469 {
27570
27671 }
27772
278−int tPhasor_setFreq(tPhasor* const p, float freq)
73+void tTriangle_init(tTriangle* const c)
27974 {
280− if (freq < 0.0f) freq = 0.0f;
281−
282− p->freq = freq;
283− p->inc = freq * leaf.invSampleRate;
284−
285− return 0;
75+ c->inc = 0.0f;
76+ c->phase = 0.0f;
28677 }
28778
288−float tPhasor_tick(tPhasor* const p)
79+void tTriangle_free(tTriangle* const c)
28980 {
290− p->phase += p->inc;
291−
292− if (p->phase >= 1.0f) p->phase -= 1.0f;
29381
294− return p->phase;
29582 }
29683
297−
298−
299−void tSawtooth_init(tSawtooth* const c)
300−{
301− c->inc = 0.0f;
302− c->phase = 0.0f;
303−}
304−
305−void tSawtooth_free(tSawtooth* const c)
306−{
307−
308−}
309−
310−int tSawtooth_setFreq(tSawtooth* const c, float freq)
84+int tTriangle_setFreq(tTriangle* const c, float freq)
31185 {
31286 if (freq < 0.0f) freq = 0.0f;
31387
@@ -317,7 +91,8 @@ int tSawtooth_setFreq(tSawtooth* const c, float freq) · 3 unmodified lines
31791 return 0;
31892 }
31993
320−float tSawtooth_tick(tSawtooth* const c)
94+
95+float tTriangle_tick(tTriangle* const c)
32196 {
32297 // Phasor increment
32398 c->phase += c->inc;
@@ -332,89 +107,85 @@ float tSawtooth_tick(tSawtooth* const c) · 8 unmodified lines
332107
333108 if (c->freq <= 20.0f)
334109 {
335− out = sawtooth[T20][idx];
110+ out = triangle[T20][idx];
336111 }
337112 else if (c->freq <= 40.0f)
338113 {
339114 w = ((40.0f - c->freq) * INV_20);
340− out = (sawtooth[T20][idx] * w) + (sawtooth[T40][idx] * (1.0f - w));
115+ out = (triangle[T20][idx] * w) + (triangle[T40][idx] * (1.0f - w));
341116 }
342117 else if (c->freq <= 80.0f)
343118 {
344119 w = ((80.0f - c->freq) * INV_40);
345− out = (sawtooth[T40][idx] * w) + (sawtooth[T80][idx] * (1.0f - w));
120+ out = (triangle[T40][idx] * w) + (triangle[T80][idx] * (1.0f - w));
346121 }
347122 else if (c->freq <= 160.0f)
348123 {
349124 w = ((160.0f - c->freq) * INV_80);
350− out = (sawtooth[T80][idx] * w) + (sawtooth[T160][idx] * (1.0f - w));
125+ out = (triangle[T80][idx] * w) + (triangle[T160][idx] * (1.0f - w));
351126 }
352127 else if (c->freq <= 320.0f)
353128 {
354129 w = ((320.0f - c->freq) * INV_160);
355− out = (sawtooth[T160][idx] * w) + (sawtooth[T320][idx] * (1.0f - w));
130+ out = (triangle[T160][idx] * w) + (triangle[T320][idx] * (1.0f - w));
356131 }
357132 else if (c->freq <= 640.0f)
358133 {
359134 w = ((640.0f - c->freq) * INV_320);
360− out = (sawtooth[T320][idx] * w) + (sawtooth[T640][idx] * (1.0f - w));
135+ out = (triangle[T320][idx] * w) + (triangle[T640][idx] * (1.0f - w));
361136 }
362137 else if (c->freq <= 1280.0f)
363138 {
364139 w = ((1280.0f - c->freq) * INV_640);
365− out = (sawtooth[T640][idx] * w) + (sawtooth[T1280][idx] * (1.0f - w));
140+ out = (triangle[T640][idx] * w) + (triangle[T1280][idx] * (1.0f - w));
366141 }
367142 else if (c->freq <= 2560.0f)
368143 {
369144 w = ((2560.0f - c->freq) * INV_1280);
370− out = (sawtooth[T1280][idx] * w) + (sawtooth[T2560][idx] * (1.0f - w));
145+ out = (triangle[T1280][idx] * w) + (triangle[T2560][idx] * (1.0f - w));
371146 }
372147 else if (c->freq <= 5120.0f)
373148 {
374149 w = ((5120.0f - c->freq) * INV_2560);
375− out = (sawtooth[T2560][idx] * w) + (sawtooth[T5120][idx] * (1.0f - w));
150+ out = (triangle[T2560][idx] * w) + (triangle[T5120][idx] * (1.0f - w));
376151 }
377152 else if (c->freq <= 10240.0f)
378153 {
379154 w = ((10240.0f - c->freq) * INV_5120);
380− out = (sawtooth[T5120][idx] * w) + (sawtooth[T10240][idx] * (1.0f - w));
155+ out = (triangle[T5120][idx] * w) + (triangle[T10240][idx] * (1.0f - w));
381156 }
382157 else if (c->freq <= 20480.0f)
383158 {
384159 w = ((20480.0f - c->freq) * INV_10240);
385− out = (sawtooth[T10240][idx] * w) + (sawtooth[T20480][idx] * (1.0f - w));
160+ out = (triangle[T10240][idx] * w) + (triangle[T20480][idx] * (1.0f - w));
386161 }
387162 else
388163 {
389− out = sawtooth[T20480][idx];
164+ out = triangle[T20480][idx];
390165 }
391166
392167 return out;
393168 }
394169
395−void tSawtoothSampleRateChanged (tSawtooth* const c)
170+void tTriangleSampleRateChanged (tTriangle* const c)
396171 {
397172 c->inc = c->freq * leaf.invSampleRate;
398173 }
399174
400−/* Triangle */
401−void tTriangle_start(tTriangle* const c)
402−{
403−
404−}
405−
406−void tTriangle_init(tTriangle* const c)
175+//========================================================================
176+/* Square */
177+void tSquare_init(tSquare* const c)
407178 {
408179 c->inc = 0.0f;
409180 c->phase = 0.0f;
410181 }
411182
412−void tTriangle_free(tTriangle* const c)
183+void tSquare_free(tSquare* const c)
413184 {
414185
415186 }
416187
417−int tTriangle_setFreq(tTriangle* const c, float freq)
188+int tSquare_setFreq(tSquare* const c, float freq)
418189 {
419190 if (freq < 0.0f) freq = 0.0f;
420191
@@ -424,100 +195,99 @@ int tTriangle_setFreq(tTriangle* const c, float freq) · 3 unmodified lines
424195 return 0;
425196 }
426197
427−
428−float tTriangle_tick(tTriangle* const c)
198+float tSquare_tick(tSquare* const c)
429199 {
430200 // Phasor increment
431201 c->phase += c->inc;
432202 while (c->phase >= 1.0f) c->phase -= 1.0f;
433203
434204 float out = 0.0f;
435− float w;
436−
205+ float w = 0.0f;
437206 int idx = (int)(c->phase * TRI_TABLE_SIZE);
438207
439208 // Wavetable synthesis
440209
441210 if (c->freq <= 20.0f)
442211 {
443− out = triangle[T20][idx];
212+ out = squarewave[T20][idx];
444213 }
445214 else if (c->freq <= 40.0f)
446215 {
447216 w = ((40.0f - c->freq) * INV_20);
448− out = (triangle[T20][idx] * w) + (triangle[T40][idx] * (1.0f - w));
217+ out = (squarewave[T20][idx] * w) + (squarewave[T40][idx] * (1.0f - w));
449218 }
450219 else if (c->freq <= 80.0f)
451220 {
452221 w = ((80.0f - c->freq) * INV_40);
453− out = (triangle[T40][idx] * w) + (triangle[T80][idx] * (1.0f - w));
222+ out = (squarewave[T40][idx] * w) + (squarewave[T80][idx] * (1.0f - w));
454223 }
455224 else if (c->freq <= 160.0f)
456225 {
457226 w = ((160.0f - c->freq) * INV_80);
458− out = (triangle[T80][idx] * w) + (triangle[T160][idx] * (1.0f - w));
227+ out = (squarewave[T80][idx] * w) + (squarewave[T160][idx] * (1.0f - w));
459228 }
460229 else if (c->freq <= 320.0f)
461230 {
462231 w = ((320.0f - c->freq) * INV_160);
463− out = (triangle[T160][idx] * w) + (triangle[T320][idx] * (1.0f - w));
232+ out = (squarewave[T160][idx] * w) + (squarewave[T320][idx] * (1.0f - w));
464233 }
465234 else if (c->freq <= 640.0f)
466235 {
467236 w = ((640.0f - c->freq) * INV_320);
468− out = (triangle[T320][idx] * w) + (triangle[T640][idx] * (1.0f - w));
237+ out = (squarewave[T320][idx] * w) + (squarewave[T640][idx] * (1.0f - w));
469238 }
470239 else if (c->freq <= 1280.0f)
471240 {
472241 w = ((1280.0f - c->freq) * INV_640);
473− out = (triangle[T640][idx] * w) + (triangle[T1280][idx] * (1.0f - w));
242+ out = (squarewave[T640][idx] * w) + (squarewave[T1280][idx] * (1.0f - w));
474243 }
475244 else if (c->freq <= 2560.0f)
476245 {
477246 w = ((2560.0f - c->freq) * INV_1280);
478− out = (triangle[T1280][idx] * w) + (triangle[T2560][idx] * (1.0f - w));
247+ out = (squarewave[T1280][idx] * w) + (squarewave[T2560][idx] * (1.0f - w));
479248 }
480249 else if (c->freq <= 5120.0f)
481250 {
482251 w = ((5120.0f - c->freq) * INV_2560);
483− out = (triangle[T2560][idx] * w) + (triangle[T5120][idx] * (1.0f - w));
252+ out = (squarewave[T2560][idx] * w) + (squarewave[T5120][idx] * (1.0f - w));
484253 }
485254 else if (c->freq <= 10240.0f)
486255 {
487256 w = ((10240.0f - c->freq) * INV_5120);
488− out = (triangle[T5120][idx] * w) + (triangle[T10240][idx] * (1.0f - w));
257+ out = (squarewave[T5120][idx] * w) + (squarewave[T10240][idx] * (1.0f - w));
489258 }
490259 else if (c->freq <= 20480.0f)
491260 {
492261 w = ((20480.0f - c->freq) * INV_10240);
493− out = (triangle[T10240][idx] * w) + (triangle[T20480][idx] * (1.0f - w));
262+ out = (squarewave[T10240][idx] * w) + (squarewave[T20480][idx] * (1.0f - w));
494263 }
495264 else
496265 {
497− out = triangle[T20480][idx];
266+ out = squarewave[T20480][idx];
498267 }
499268
500269 return out;
501270 }
502271
503−void tTriangleSampleRateChanged (tTriangle* const c)
272+void tSquareSampleRateChanged (tSquare* const c)
504273 {
505274 c->inc = c->freq * leaf.invSampleRate;
506275 }
507276
508−/* Square */
509−void tSquare_init(tSquare* const c)
277+//=====================================================================
278+// Sawtooth
279+void tSawtooth_init(tSawtooth* const c)
510280 {
511− c->inc = 0.0f;
512− c->phase = 0.0f;
281+ c->inc = 0.0f;
282+ c->phase = 0.0f;
513283 }
514284
515−void tSquare_free(tSquare* const c)
285+void tSawtooth_free(tSawtooth* const c)
516286 {
517−
287+
518288 }
519289
520−int tSquare_setFreq(tSquare* const c, float freq)
290+int tSawtooth_setFreq(tSawtooth* const c, float freq)
521291 {
522292 if (freq < 0.0f) freq = 0.0f;
523293
@@ -527,85 +297,123 @@ int tSquare_setFreq(tSquare* const c, float freq) · 3 unmodified lines
527297 return 0;
528298 }
529299
530−float tSquare_tick(tSquare* const c)
300+float tSawtooth_tick(tSawtooth* const c)
531301 {
532302 // Phasor increment
533303 c->phase += c->inc;
534304 while (c->phase >= 1.0f) c->phase -= 1.0f;
535305
536306 float out = 0.0f;
537− float w = 0.0f;
307+ float w;
308+
538309 int idx = (int)(c->phase * TRI_TABLE_SIZE);
539310
540311 // Wavetable synthesis
541312
542313 if (c->freq <= 20.0f)
543314 {
544− out = squarewave[T20][idx];
315+ out = sawtooth[T20][idx];
545316 }
546317 else if (c->freq <= 40.0f)
547318 {
548319 w = ((40.0f - c->freq) * INV_20);
549− out = (squarewave[T20][idx] * w) + (squarewave[T40][idx] * (1.0f - w));
320+ out = (sawtooth[T20][idx] * w) + (sawtooth[T40][idx] * (1.0f - w));
550321 }
551322 else if (c->freq <= 80.0f)
552323 {
553324 w = ((80.0f - c->freq) * INV_40);
554− out = (squarewave[T40][idx] * w) + (squarewave[T80][idx] * (1.0f - w));
325+ out = (sawtooth[T40][idx] * w) + (sawtooth[T80][idx] * (1.0f - w));
555326 }
556327 else if (c->freq <= 160.0f)
557328 {
558329 w = ((160.0f - c->freq) * INV_80);
559− out = (squarewave[T80][idx] * w) + (squarewave[T160][idx] * (1.0f - w));
330+ out = (sawtooth[T80][idx] * w) + (sawtooth[T160][idx] * (1.0f - w));
560331 }
561332 else if (c->freq <= 320.0f)
562333 {
563334 w = ((320.0f - c->freq) * INV_160);
564− out = (squarewave[T160][idx] * w) + (squarewave[T320][idx] * (1.0f - w));
335+ out = (sawtooth[T160][idx] * w) + (sawtooth[T320][idx] * (1.0f - w));
565336 }
566337 else if (c->freq <= 640.0f)
567338 {
568339 w = ((640.0f - c->freq) * INV_320);
569− out = (squarewave[T320][idx] * w) + (squarewave[T640][idx] * (1.0f - w));
340+ out = (sawtooth[T320][idx] * w) + (sawtooth[T640][idx] * (1.0f - w));
570341 }
571342 else if (c->freq <= 1280.0f)
572343 {
573344 w = ((1280.0f - c->freq) * INV_640);
574− out = (squarewave[T640][idx] * w) + (squarewave[T1280][idx] * (1.0f - w));
345+ out = (sawtooth[T640][idx] * w) + (sawtooth[T1280][idx] * (1.0f - w));
575346 }
576347 else if (c->freq <= 2560.0f)
577348 {
578349 w = ((2560.0f - c->freq) * INV_1280);
579− out = (squarewave[T1280][idx] * w) + (squarewave[T2560][idx] * (1.0f - w));
350+ out = (sawtooth[T1280][idx] * w) + (sawtooth[T2560][idx] * (1.0f - w));
580351 }
581352 else if (c->freq <= 5120.0f)
582353 {
583354 w = ((5120.0f - c->freq) * INV_2560);
584− out = (squarewave[T2560][idx] * w) + (squarewave[T5120][idx] * (1.0f - w));
355+ out = (sawtooth[T2560][idx] * w) + (sawtooth[T5120][idx] * (1.0f - w));
585356 }
586357 else if (c->freq <= 10240.0f)
587358 {
588359 w = ((10240.0f - c->freq) * INV_5120);
589− out = (squarewave[T5120][idx] * w) + (squarewave[T10240][idx] * (1.0f - w));
360+ out = (sawtooth[T5120][idx] * w) + (sawtooth[T10240][idx] * (1.0f - w));
590361 }
591362 else if (c->freq <= 20480.0f)
592363 {
593364 w = ((20480.0f - c->freq) * INV_10240);
594− out = (squarewave[T10240][idx] * w) + (squarewave[T20480][idx] * (1.0f - w));
365+ out = (sawtooth[T10240][idx] * w) + (sawtooth[T20480][idx] * (1.0f - w));
595366 }
596367 else
597368 {
598− out = squarewave[T20480][idx];
369+ out = sawtooth[T20480][idx];
599370 }
600371
601372 return out;
602373 }
603374
604−void tSquareSampleRateChanged (tSquare* const c)
375+void tSawtoothSampleRateChanged (tSawtooth* const c)
605376 {
606377 c->inc = c->freq * leaf.invSampleRate;
607378 }
608379
380+//========================================================================
381+/* Phasor */
382+void tPhasorSampleRateChanged (tPhasor* const p)
383+{
384+ p->inc = p->freq * leaf.invSampleRate;
385+};
386+
387+void tPhasor_init(tPhasor* const p)
388+{
389+ p->phase = 0.0f;
390+ p->inc = 0.0f;
391+}
392+
393+void tPhasor_free(tPhasor* const p)
394+{
395+
396+}
397+
398+int tPhasor_setFreq(tPhasor* const p, float freq)
399+{
400+ if (freq < 0.0f) freq = 0.0f;
401+
402+ p->freq = freq;
403+ p->inc = freq * leaf.invSampleRate;
404+
405+ return 0;
406+}
407+
408+float tPhasor_tick(tPhasor* const p)
409+{
410+ p->phase += p->inc;
411+
412+ if (p->phase >= 1.0f) p->phase -= 1.0f;
413+
414+ return p->phase;
415+}
416+
609417 /* Noise */
610418 void tNoise_init(tNoise* const n, NoiseType type)
611419 {
@@ -636,3 +444,201 @@ float tNoise_tick(tNoise* const n) · 24 unmodified lines
636444 return rand;
637445 }
638446 }
447+
448+//=================================================================================
449+/* Neuron */
450+
451+void tNeuronSampleRateChanged(tNeuron* n)
452+{
453+
454+}
455+
456+void tNeuron_init(tNeuron* const n)
457+{
458+ tPoleZero_init(&n->f);
459+
460+ tPoleZero_setBlockZero(&n->f, 0.99f);
461+
462+ n->timeStep = 1.0f / 50.0f;
463+
464+ n->current = 0.0f; // 100.0f for sound
465+ n->voltage = 0.0f;
466+
467+ n->mode = NeuronNormal;
468+
469+ n->P[0] = 0.0f;
470+ n->P[1] = 0.0f;
471+ n->P[2] = 1.0f;
472+
473+ n->V[0] = -12.0f;
474+ n->V[1] = 115.0f;
475+ n->V[2] = 10.613f;
476+
477+ n->gK = 36.0f;
478+ n->gN = 120.0f;
479+ n->gL = 0.3f;
480+ n->C = 1.0f;
481+
482+ n->rate[2] = n->gL/n->C;
483+}
484+
485+void tNeuron_free(tNeuron* const n)
486+{
487+ tPoleZero_free(&n->f);
488+}
489+
490+void tNeuron_reset(tNeuron* const n)
491+{
492+
493+ tPoleZero_setBlockZero(&n->f, 0.99f);
494+
495+ n->timeStep = 1.0f / 50.0f;
496+
497+ n->current = 0.0f; // 100.0f for sound
498+ n->voltage = 0.0f;
499+
500+ n->mode = NeuronNormal;
501+
502+ n->P[0] = 0.0f;
503+ n->P[1] = 0.0f;
504+ n->P[2] = 1.0f;
505+
506+ n->V[0] = -12.0f;
507+ n->V[1] = 115.0f;
508+ n->V[2] = 10.613f;
509+
510+ n->gK = 36.0f;
511+ n->gN = 120.0f;
512+ n->gL = 0.3f;
513+ n->C = 1.0f;
514+
515+ n->rate[2] = n->gL/n->C;
516+}
517+
518+
519+void tNeuron_setV1(tNeuron* const n, float V1)
520+{
521+ n->V[0] = V1;
522+}
523+
524+
525+void tNeuron_setV2(tNeuron* const n, float V2)
526+{
527+ n->V[1] = V2;
528+}
529+
530+void tNeuron_setV3(tNeuron* const n, float V3)
531+{
532+ n->V[2] = V3;
533+}
534+
535+void tNeuron_setTimeStep(tNeuron* const n, float timeStep)
536+{
537+ n->timeStep = timeStep;
538+}
539+
540+void tNeuron_setK(tNeuron* const n, float K)
541+{
542+ n->gK = K;
543+}
544+
545+void tNeuron_setL(tNeuron* const n, float L)
546+{
547+ n->gL = L;
548+ n->rate[2] = n->gL/n->C;
549+}
550+
551+void tNeuron_setN(tNeuron* const n, float N)
552+{
553+ n->gN = N;
554+}
555+
556+void tNeuron_setC(tNeuron* const n, float C)
557+{
558+ n->C = C;
559+ n->rate[2] = n->gL/n->C;
560+}
561+
562+float tNeuron_tick(tNeuron* const n)
563+{
564+ float output = 0.0f;
565+ float voltage = n->voltage;
566+
567+ n->alpha[0] = (0.01f * (10.0f - voltage)) / (expf((10.0f - voltage)/10.0f) - 1.0f);
568+ n->alpha[1] = (0.1f * (25.0f-voltage)) / (expf((25.0f-voltage)/10.0f) - 1.0f);
569+ n->alpha[2] = (0.07f * expf((-1.0f * voltage)/20.0f));
570+
571+ n->beta[0] = (0.125f * expf((-1.0f* voltage)/80.0f));
572+ n->beta[1] = (4.0f * expf((-1.0f * voltage)/18.0f));
573+ n->beta[2] = (1.0f / (expf((30.0f-voltage)/10.0f) + 1.0f));
574+
575+ for (int i = 0; i < 3; i++)
576+ {
577+ n->P[i] = (n->alpha[i] * n->timeStep) + ((1.0f - ((n->alpha[i] + n->beta[i]) * n->timeStep)) * n->P[i]);
578+
579+ if (n->P[i] > 1.0f) n->P[i] = 0.0f;
580+ else if (n->P[i] < -1.0f) n->P[i] = 0.0f;
581+ }
582+ // rate[0]= k ; rate[1] = Na ; rate[2] = l
583+ n->rate[0] = ((n->gK * powf(n->P[0], 4.0f)) / n->C);
584+ n->rate[1] = ((n->gN * powf(n->P[1], 3.0f) * n->P[2]) / n->C);
585+
586+ //calculate the final membrane voltage based on the computed variables
587+ n->voltage = voltage +
588+ (n->timeStep * n->current / n->C) -
589+ (n->timeStep * ( n->rate[0] * (voltage - n->V[0]) + n->rate[1] * (voltage - n->V[1]) + n->rate[2] * (voltage - n->V[2])));
590+
591+ if (n->mode == NeuronTanh)
592+ {
593+ n->voltage = 100.0f * tanhf(0.01f * n->voltage);
594+ }
595+ else if (n->mode == NeuronAaltoShaper)
596+ {
597+ float shapeVoltage = 0.01f * n->voltage;
598+
599+ float w, c, xc, xc2, xc4;
600+
601+ float sqrt8 = 2.82842712475f;
602+
603+ float wscale = 1.30612244898f;
604+ float m_drive = 1.0f;
605+
606+ xc = LEAF_clip(-sqrt8, shapeVoltage, sqrt8);
607+
608+ xc2 = xc*xc;
609+
610+ c = 0.5f * shapeVoltage * (3.0f - (xc2));
611+
612+ xc4 = xc2 * xc2;
613+
614+ w = (1.0f - xc2 * 0.25f + xc4 * 0.015625f) * wscale;
615+
616+ shapeVoltage = w * (c + 0.05f * xc2) * (m_drive + 0.75f);
617+
618+ n->voltage = 100.0f * shapeVoltage;
619+ }
620+
621+
622+ if (n->voltage > 100.0f) n->voltage = 100.0f;
623+ else if (n->voltage < -100.) n->voltage = -100.0f;
624+
625+ //(inputCurrent + (voltage - ((voltage * timeStep) / timeConstant)) + P[0] + P[1] + P[2]) => voltage;
626+ // now we should have a result
627+ //set the output voltage to the "step" ugen, which controls the DAC.
628+ output = n->voltage * 0.01f; // volts
629+
630+ output = tPoleZero_tick(&n->f, output);
631+
632+ return output;
633+
634+}
635+
636+void tNeuron_setMode (tNeuron* const n, NeuronMode mode)
637+{
638+ n->mode = mode;
639+}
640+
641+void tNeuron_setCurrent (tNeuron* const n, float current)
642+{
643+ n->current = current;
644+}
LEAF/Src/leaf-physical.c+596−0
@@ -0,0 +1,596 @@
1+/*==============================================================================
2+
3+ leaf-string.c
4+ Created: 30 Nov 2018 10:41:42am
5+ Author: airship
6+
7+==============================================================================*/
8+
9+#if _WIN32 || _WIN64
10+
11+#include "..\Inc\leaf-physical.h"
12+
13+#else
14+
15+#include "../Inc/leaf-physical.h"
16+
17+#endif
18+
19+/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tPluck ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
20+void tPluck_init (tPluck* const p, float lowestFrequency)
21+{
22+ if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f;
23+
24+ tNoise_init(&p->noise, WhiteNoise);
25+
26+ tOnePole_init(&p->pickFilter, 0.0f);
27+
28+ tOneZero_init(&p->loopFilter, 0.0f);
29+
30+ tAllpassDelay_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
31+
32+ tPluck_setFrequency(p, 220.0f);
33+}
34+
35+void tPluck_free (tPluck* const p)
36+{
37+ tNoise_free(&p->noise);
38+ tOnePole_free(&p->pickFilter);
39+ tOneZero_free(&p->loopFilter);
40+ tAllpassDelay_free(&p->delayLine);
41+}
42+
43+float tPluck_getLastOut (tPluck *p)
44+{
45+ return p->lastOut;
46+}
47+
48+float tPluck_tick (tPluck *p)
49+{
50+ return (p->lastOut = 3.0f * tAllpassDelay_tick(&p->delayLine, tOneZero_tick(&p->loopFilter, tAllpassDelay_getLastOut(&p->delayLine) * p->loopGain ) ));
51+}
52+
53+void tPluck_pluck (tPluck* const p, float amplitude)
54+{
55+ if ( amplitude < 0.0f) amplitude = 0.0f;
56+ else if (amplitude > 1.0f) amplitude = 1.0f;
57+
58+ tOnePole_setPole(&p->pickFilter, 0.999f - (amplitude * 0.15f));
59+ tOnePole_setGain(&p->pickFilter, amplitude * 0.5f );
60+
61+ // Fill delay with noise additively with current contents.
62+ for ( uint32_t i = 0; i < (uint32_t)tAllpassDelay_getDelay(&p->delayLine); i++ )
63+ tAllpassDelay_tick(&p->delayLine, 0.6f * tAllpassDelay_getLastOut(&p->delayLine) + tOnePole_tick(&p->pickFilter, tNoise_tick(&p->noise) ) );
64+}
65+
66+// Start a note with the given frequency and amplitude.;
67+void tPluck_noteOn (tPluck* const p, float frequency, float amplitude )
68+{
69+ p->lastFreq = frequency;
70+ tPluck_setFrequency( p, frequency );
71+ tPluck_pluck( p, amplitude );
72+}
73+
74+// Stop a note with the given amplitude (speed of decay).
75+void tPluck_noteOff (tPluck* const p, float amplitude )
76+{
77+ if ( amplitude < 0.0f) amplitude = 0.0f;
78+ else if (amplitude > 1.0f) amplitude = 1.0f;
79+
80+ p->loopGain = 1.0f - amplitude;
81+}
82+
83+// Set instrument parameters for a particular frequency.
84+void tPluck_setFrequency (tPluck* const p, float frequency )
85+{
86+ if ( frequency <= 0.0f ) frequency = 0.001f;
87+
88+ // Delay = length - filter delay.
89+ float delay = ( leaf.sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency );
90+
91+ tAllpassDelay_setDelay(&p->delayLine, delay );
92+
93+ p->loopGain = 0.99f + (frequency * 0.000005f);
94+
95+ if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f;
96+
97+}
98+
99+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
100+void tPluck_controlChange (tPluck* const p, int number, float value)
101+{
102+ return;
103+}
104+
105+void tPluckSampleRateChanged(tPluck* const p)
106+{
107+ //tPluckSetFrequency(p, p->lastFreq);
108+}
109+
110+/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
111+void tKarplusStrong_init (tKarplusStrong* const p, float lowestFrequency)
112+{
113+ if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f;
114+
115+ tAllpassDelay_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
116+
117+ tLinearDelay_init(&p->combDelay, 0.0f, leaf.sampleRate * 2);
118+
119+ tOneZero_init(&p->filter, 0.0f);
120+
121+ tNoise_init(&p->noise, WhiteNoise);
122+
123+ for (int i = 0; i < 4; i++)
124+ {
125+ tBiQuad_init(&p->biquad[i]);
126+ }
127+
128+ p->pluckAmplitude = 0.3f;
129+ p->pickupPosition = 0.4f;
130+
131+ p->stretching = 0.9999f;
132+ p->baseLoopGain = 0.995f;
133+ p->loopGain = 0.999f;
134+
135+ tKarplusStrong_setFrequency( p, 220.0f );
136+
137+}
138+
139+void tKarplusStrong_free (tKarplusStrong* const p)
140+{
141+ tAllpassDelay_free(&p->delayLine);
142+ tLinearDelay_free(&p->combDelay);
143+ tOneZero_free(&p->filter);
144+ tNoise_free(&p->noise);
145+
146+ for (int i = 0; i < 4; i++)
147+ {
148+ tBiQuad_free(&p->biquad[i]);
149+ }
150+}
151+
152+float tKarplusStrong_getLastOut (tKarplusStrong* const p)
153+{
154+ return p->lastOut;
155+}
156+
157+float tKarplusStrong_tick (tKarplusStrong* const p)
158+{
159+ float temp = tAllpassDelay_getLastOut(&p->delayLine) * p->loopGain;
160+
161+ // Calculate allpass stretching.
162+ for (int i=0; i<4; i++) temp = tBiQuad_tick(&p->biquad[i],temp);
163+
164+ // Moving average filter.
165+ temp = tOneZero_tick(&p->filter, temp);
166+
167+ float out = tAllpassDelay_tick(&p->delayLine, temp);
168+ out = out - tLinearDelay_tick(&p->combDelay, out);
169+ p->lastOut = out;
170+
171+ return p->lastOut;
172+}
173+
174+void tKarplusStrong_pluck (tKarplusStrong* const p, float amplitude)
175+{
176+ if ( amplitude < 0.0f) amplitude = 0.0f;
177+ else if (amplitude > 1.0f) amplitude = 1.0f;
178+
179+ p->pluckAmplitude = amplitude;
180+
181+ for ( uint32_t i=0; i < (uint32_t)tAllpassDelay_getDelay(&p->delayLine); i++ )
182+ {
183+ // Fill delay with noise additively with current contents.
184+ tAllpassDelay_tick(&p->delayLine, (tAllpassDelay_getLastOut(&p->delayLine) * 0.6f) + 0.4f * tNoise_tick(&p->noise) * p->pluckAmplitude );
185+ //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
186+ }
187+}
188+
189+// Start a note with the given frequency and amplitude.;
190+void tKarplusStrong_noteOn (tKarplusStrong* const p, float frequency, float amplitude )
191+{
192+ tKarplusStrong_setFrequency( p, frequency );
193+ tKarplusStrong_pluck( p, amplitude );
194+}
195+
196+// Stop a note with the given amplitude (speed of decay).
197+void tKarplusStrong_noteOff (tKarplusStrong* const p, float amplitude )
198+{
199+ if ( amplitude < 0.0f) amplitude = 0.0f;
200+ else if (amplitude > 1.0f) amplitude = 1.0f;
201+
202+ p->loopGain = 1.0f - amplitude;
203+}
204+
205+// Set instrument parameters for a particular frequency.
206+void tKarplusStrong_setFrequency (tKarplusStrong* const p, float frequency )
207+{
208+ if ( frequency <= 0.0f ) frequency = 0.001f;
209+
210+ p->lastFrequency = frequency;
211+ p->lastLength = leaf.sampleRate / p->lastFrequency;
212+ float delay = p->lastLength - 0.5f;
213+ tAllpassDelay_setDelay(&p->delayLine, delay);
214+
215+ // MAYBE MODIFY LOOP GAINS
216+ p->loopGain = p->baseLoopGain + (frequency * 0.000005f);
217+ if (p->loopGain >= 1.0f) p->loopGain = 0.99999f;
218+
219+ tKarplusStrong_setStretch(p, p->stretching);
220+
221+ tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength );
222+
223+}
224+
225+// Set the stretch "factor" of the string (0.0 - 1.0).
226+void tKarplusStrong_setStretch (tKarplusStrong* const p, float stretch )
227+{
228+ p->stretching = stretch;
229+ float coefficient;
230+ float freq = p->lastFrequency * 2.0f;
231+ float dFreq = ( (0.5f * leaf.sampleRate) - freq ) * 0.25f;
232+ float temp = 0.5f + (stretch * 0.5f);
233+ if ( temp > 0.9999f ) temp = 0.9999f;
234+
235+ for ( int i=0; i<4; i++ )
236+ {
237+ coefficient = temp * temp;
238+ tBiQuad_setA2(&p->biquad[i], coefficient);
239+ tBiQuad_setB0(&p->biquad[i], coefficient);
240+ tBiQuad_setB2(&p->biquad[i], 1.0f);
241+
242+ coefficient = -2.0f * temp * cos(TWO_PI * freq / leaf.sampleRate);
243+ tBiQuad_setA1(&p->biquad[i], coefficient);
244+ tBiQuad_setB1(&p->biquad[i], coefficient);
245+
246+ freq += dFreq;
247+ }
248+}
249+
250+// Set the pluck or "excitation" position along the string (0.0 - 1.0).
251+void tKarplusStrong_setPickupPosition (tKarplusStrong* const p, float position )
252+{
253+ if (position < 0.0f) p->pickupPosition = 0.0f;
254+ else if (position <= 1.0f) p->pickupPosition = position;
255+ else p->pickupPosition = 1.0f;
256+
257+ tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength);
258+}
259+
260+// Set the base loop gain.
261+void tKarplusStrong_setBaseLoopGain (tKarplusStrong* const p, float aGain )
262+{
263+ p->baseLoopGain = aGain;
264+ p->loopGain = p->baseLoopGain + (p->lastFrequency * 0.000005f);
265+ if ( p->loopGain > 0.99999f ) p->loopGain = 0.99999f;
266+}
267+
268+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
269+void tKarplusStrong_controlChange (tKarplusStrong* const p, SKControlType type, float value)
270+{
271+ if ( value < 0.0f ) value = 0.0f;
272+ else if (value > 128.0f) value = 128.0f;
273+
274+ float normalizedValue = value * INV_128;
275+
276+ if (type == SKPickPosition) // 4
277+ tKarplusStrong_setPickupPosition( p, normalizedValue );
278+ else if (type == SKStringDamping) // 11
279+ tKarplusStrong_setBaseLoopGain( p, 0.97f + (normalizedValue * 0.03f) );
280+ else if (type == SKDetune) // 1
281+ tKarplusStrong_setStretch( p, 0.91f + (0.09f * (1.0f - normalizedValue)) );
282+
283+}
284+
285+void tKarplusStrongSampleRateChanged (tKarplusStrong* const c)
286+{
287+ tKarplusStrong_setFrequency(c, c->lastFrequency);
288+ tKarplusStrong_setStretch(c, c->stretching);
289+}
290+
291+/* Simple Living String*/
292+
293+void tSimpleLivingString_init(tSimpleLivingString* const p, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
294+{
295+ p->curr=0.0f;
296+ tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
297+ tSimpleLivingString_setFreq(p, freq);
298+ tLinearDelay_init(&p->delayLine,p->waveLengthInSamples, 2400);
299+ tOnePole_init(&p->bridgeFilter, dampFreq);
300+ tHighpass_init(&p->DCblocker,13);
301+ p->decay=decay;
302+ tFeedbackLeveler_init(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode);
303+ p->levMode=levMode;
304+}
305+
306+void tSimpleLivingString_free(tSimpleLivingString* const p)
307+{
308+ tExpSmooth_free(&p->wlSmooth);
309+ tLinearDelay_free(&p->delayLine);
310+ tOnePole_free(&p->bridgeFilter);
311+ tHighpass_free(&p->DCblocker);
312+ tFeedbackLeveler_free(&p->fbLev);
313+}
314+
315+int tSimpleLivingString_setFreq(tSimpleLivingString* const p, float freq)
316+{
317+ if (freq<20) freq=20;
318+ else if (freq>10000) freq=10000;
319+ p->waveLengthInSamples = leaf.sampleRate/freq;
320+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
321+ return 0;
322+}
323+
324+int tSimpleLivingString_setWaveLength(tSimpleLivingString* const p, float waveLength)
325+{
326+ if (waveLength<4.8) waveLength=4.8;
327+ else if (waveLength>2400) waveLength=2400;
328+ p->waveLengthInSamples = waveLength;
329+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
330+ return 0;
331+}
332+
333+int tSimpleLivingString_setDampFreq(tSimpleLivingString* const p, float dampFreq)
334+{
335+ tOnePole_setFreq(&p->bridgeFilter, dampFreq);
336+ return 0;
337+}
338+
339+int tSimpleLivingString_setDecay(tSimpleLivingString* const p, float decay)
340+{
341+ p->decay=decay;
342+ return 0;
343+}
344+
345+int tSimpleLivingString_setTargetLev(tSimpleLivingString* const p, float targetLev)
346+{
347+ tFeedbackLeveler_setTargetLevel(&p->fbLev, targetLev);
348+ return 0;
349+}
350+
351+int tSimpleLivingString_setLevSmoothFactor(tSimpleLivingString* const p, float levSmoothFactor)
352+{
353+ tFeedbackLeveler_setFactor(&p->fbLev, levSmoothFactor);
354+ return 0;
355+}
356+
357+int tSimpleLivingString_setLevStrength(tSimpleLivingString* const p, float levStrength)
358+{
359+ tFeedbackLeveler_setStrength(&p->fbLev, levStrength);
360+ return 0;
361+}
362+
363+int tSimpleLivingString_setLevMode(tSimpleLivingString* const p, int levMode)
364+{
365+ tFeedbackLeveler_setMode(&p->fbLev, levMode);
366+ p->levMode=levMode;
367+ return 0;
368+}
369+
370+float tSimpleLivingString_tick(tSimpleLivingString* const p, float input)
371+{
372+ float stringOut=tOnePole_tick(&p->bridgeFilter,tLinearDelay_tickOut(&p->delayLine));
373+ float stringInput=tHighpass_tick(&p->DCblocker, tFeedbackLeveler_tick(&p->fbLev, (p->levMode==0?p->decay*stringOut:stringOut)+input));
374+ tLinearDelay_tickIn(&p->delayLine, stringInput);
375+ tLinearDelay_setDelay(&p->delayLine, tExpSmooth_tick(&p->wlSmooth));
376+ p->curr = stringOut;
377+ return p->curr;
378+}
379+
380+float tSimpleLivingString_sample(tSimpleLivingString* const p)
381+{
382+ return p->curr;
383+}
384+
385+/* Living String*/
386+
387+void tLivingString_init(tLivingString* const p, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
388+{
389+ p->curr=0.0f;
390+ tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
391+ tLivingString_setFreq(p, freq);
392+ tExpSmooth_init(&p->ppSmooth, pickPos, 0.01); // smoother for pick position
393+ tLivingString_setPickPos(p, pickPos);
394+ p->prepIndex=prepIndex;
395+ tLinearDelay_init(&p->delLF,p->waveLengthInSamples, 2400);
396+ tLinearDelay_init(&p->delUF,p->waveLengthInSamples, 2400);
397+ tLinearDelay_init(&p->delUB,p->waveLengthInSamples, 2400);
398+ tLinearDelay_init(&p->delLB,p->waveLengthInSamples, 2400);
399+ tOnePole_init(&p->bridgeFilter, dampFreq);
400+ tOnePole_init(&p->nutFilter, dampFreq);
401+ tOnePole_init(&p->prepFilterU, dampFreq);
402+ tOnePole_init(&p->prepFilterL, dampFreq);
403+ tHighpass_init(&p->DCblockerU,13);
404+ tHighpass_init(&p->DCblockerL,13);
405+ p->decay=decay;
406+ tFeedbackLeveler_init(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode);
407+ tFeedbackLeveler_init(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode);
408+ p->levMode=levMode;
409+}
410+
411+void tLivingString_free(tLivingString* const p)
412+{
413+ tExpSmooth_free(&p->wlSmooth);
414+ tExpSmooth_free(&p->ppSmooth);
415+ tLinearDelay_free(&p->delLF);
416+ tLinearDelay_free(&p->delUF);
417+ tLinearDelay_free(&p->delUB);
418+ tLinearDelay_free(&p->delLB);
419+ tOnePole_free(&p->bridgeFilter);
420+ tOnePole_free(&p->nutFilter);
421+ tOnePole_free(&p->prepFilterU);
422+ tOnePole_free(&p->prepFilterL);
423+ tHighpass_free(&p->DCblockerU);
424+ tHighpass_free(&p->DCblockerL);
425+ tFeedbackLeveler_free(&p->fbLevU);
426+ tFeedbackLeveler_free(&p->fbLevL);
427+}
428+
429+int tLivingString_setFreq(tLivingString* const p, float freq)
430+{ // NOTE: It is faster to set wavelength in samples directly
431+ if (freq<20) freq=20;
432+ else if (freq>10000) freq=10000;
433+ p->waveLengthInSamples = leaf.sampleRate/freq;
434+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
435+ return 0;
436+}
437+
438+int tLivingString_setWaveLength(tLivingString* const p, float waveLength)
439+{
440+ if (waveLength<4.8) waveLength=4.8;
441+ else if (waveLength>2400) waveLength=2400;
442+ p->waveLengthInSamples = waveLength;
443+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
444+ return 0;
445+}
446+
447+int tLivingString_setPickPos(tLivingString* const p, float pickPos)
448+{ // between 0 and 1
449+ if (pickPos<0.f) pickPos=0.f;
450+ else if (pickPos>1.f) pickPos=1.f;
451+ p->pickPos = pickPos;
452+ tExpSmooth_setDest(&p->ppSmooth, p->pickPos);
453+ return 0;
454+}
455+
456+int tLivingString_setPrepIndex(tLivingString* const p, float prepIndex)
457+{ // between 0 and 1
458+ if (prepIndex<0.f) prepIndex=0.f;
459+ else if (prepIndex>1.f) prepIndex=1.f;
460+ p->prepIndex = prepIndex;
461+ return 0;
462+}
463+
464+int tLivingString_setDampFreq(tLivingString* const p, float dampFreq)
465+{
466+ tOnePole_setFreq(&p->bridgeFilter, dampFreq);
467+ tOnePole_setFreq(&p->nutFilter, dampFreq);
468+ tOnePole_setFreq(&p->prepFilterU, dampFreq);
469+ tOnePole_setFreq(&p->prepFilterL, dampFreq);
470+ return 0;
471+}
472+
473+int tLivingString_setDecay(tLivingString* const p, float decay)
474+{
475+ p->decay=decay;
476+ return 0;
477+}
478+
479+int tLivingString_setTargetLev(tLivingString* const p, float targetLev)
480+{
481+ tFeedbackLeveler_setTargetLevel(&p->fbLevU, targetLev);
482+ tFeedbackLeveler_setTargetLevel(&p->fbLevL, targetLev);
483+ return 0;
484+}
485+
486+int tLivingString_setLevSmoothFactor(tLivingString* const p, float levSmoothFactor)
487+{
488+ tFeedbackLeveler_setFactor(&p->fbLevU, levSmoothFactor);
489+ tFeedbackLeveler_setFactor(&p->fbLevL, levSmoothFactor);
490+ return 0;
491+}
492+
493+int tLivingString_setLevStrength(tLivingString* const p, float levStrength)
494+{
495+ tFeedbackLeveler_setStrength(&p->fbLevU, levStrength);
496+ tFeedbackLeveler_setStrength(&p->fbLevL, levStrength);
497+ return 0;
498+}
499+
500+int tLivingString_setLevMode(tLivingString* const p, int levMode)
501+{
502+ tFeedbackLeveler_setMode(&p->fbLevU, levMode);
503+ tFeedbackLeveler_setMode(&p->fbLevL, levMode);
504+ p->levMode=levMode;
505+ return 0;
506+}
507+
508+float tLivingString_tick(tLivingString* const p, float input)
509+{
510+ // from pickPos upwards=forwards
511+ float fromLF=tLinearDelay_tickOut(&p->delLF);
512+ float fromUF=tLinearDelay_tickOut(&p->delUF);
513+ float fromUB=tLinearDelay_tickOut(&p->delUB);
514+ float fromLB=tLinearDelay_tickOut(&p->delLB);
515+ // into upper half of string, from nut, going backwards
516+ float fromNut=-tFeedbackLeveler_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->nutFilter, fromUF)));
517+ tLinearDelay_tickIn(&p->delUB, fromNut);
518+ // into lower half of string, from pickpoint, going backwards
519+ float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
520+ float intoLower=p->prepIndex*fromLowerPrep+(1-p->prepIndex)*fromUB+input;
521+ tLinearDelay_tickIn(&p->delLB, intoLower);
522+ // into lower half of string, from bridge
523+ float fromBridge=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB)));
524+ tLinearDelay_tickIn(&p->delLF, fromBridge);
525+ // into upper half of string, from pickpoint, going forwards/upwards
526+ float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
527+ float intoUpper=p->prepIndex*fromUpperPrep+(1-p->prepIndex)*fromLF+input;
528+ tLinearDelay_tickIn(&p->delUF, intoUpper);
529+ // update all delay lengths
530+ float pickP=tExpSmooth_tick(&p->ppSmooth);
531+ float wLen=tExpSmooth_tick(&p->wlSmooth);
532+ float lowLen=pickP*wLen;
533+ float upLen=(1-pickP)*wLen;
534+ tLinearDelay_setDelay(&p->delLF, lowLen);
535+ tLinearDelay_setDelay(&p->delLB, lowLen);
536+ tLinearDelay_setDelay(&p->delUF, upLen);
537+ tLinearDelay_setDelay(&p->delUB, upLen);
538+ p->curr = fromBridge;
539+ return p->curr;
540+}
541+
542+float tLivingString_sample(tLivingString* const p)
543+{
544+ return p->curr;
545+}
546+
547+///Reed Table model
548+//default values from STK are 0.6 offset and -0.8 slope
549+
550+void tReedTable_init (tReedTable* const p, float offset, float slope)
551+{
552+ p->offset = offset;
553+ p->slope = slope;
554+}
555+
556+void tReedTable_free (tReedTable* const p)
557+{
558+ ;
559+}
560+
561+float tReedTable_tick (tReedTable* const p, float input)
562+{
563+ // The input is differential pressure across the reed.
564+ float output = p->offset + (p->slope * input);
565+
566+ // If output is > 1, the reed has slammed shut and the
567+ // reflection function value saturates at 1.0.
568+ if ( output > 1.0f) output = 1.0f;
569+
570+ // This is nearly impossible in a physical system, but
571+ // a reflection function value of -1.0 corresponds to
572+ // an open end (and no discontinuity in bore profile).
573+ if ( output < -1.0f) output = -1.0f;
574+
575+ return output;
576+}
577+
578+float tReedTable_tanh_tick (tReedTable* const p, float input)
579+{
580+ // The input is differential pressure across the reed.
581+ float output = p->offset + (p->slope * input);
582+
583+ // If output is > 1, the reed has slammed shut and the
584+ // reflection function value saturates at 1.0.
585+ return tanhf(output);
586+}
587+
588+void tReedTable_setOffset (tReedTable* const p, float offset)
589+{
590+ p->offset = offset;
591+}
592+
593+void tReedTable_setSlope (tReedTable* const p, float slope)
594+{
595+ p->slope = slope;
596+}
LEAF/Src/leaf-pitch.c+0−563
@@ -1,563 +0,0 @@
1−/*==============================================================================
2−
3− leaf-pitch.c
4− Created: 30 Nov 2018 11:02:59am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#if _WIN32 || _WIN64
10−
11−#include "..\Inc\leaf-pitch.h"
12−#else
13−
14−#include "../Inc/leaf-pitch.h"
15−
16−#endif
17−
18−static int pitchshifter_attackdetect(tPitchShifter* ps);
19−
20−void tPitchShifter_init(tPitchShifter* const ps, float* in, float* out, int bufSize, int frameSize)
21−{
22− ps->inBuffer = in;
23− ps->outBuffer = out;
24− ps->bufSize = bufSize;
25− ps->frameSize = frameSize;
26− ps->framesPerBuffer = ps->bufSize / ps->frameSize;
27− ps->curBlock = 1;
28− ps->lastBlock = 0;
29− ps->index = 0;
30−
31− ps->hopSize = DEFHOPSIZE;
32− ps->windowSize = DEFWINDOWSIZE;
33− ps->fba = FBA;
34−
35− tEnv_init(&ps->env, ps->windowSize, ps->hopSize, ps->frameSize);
36−
37− tSNAC_init(&ps->snac, DEFOVERLAP);
38−
39− tSOLAD_init(&ps->sola);
40−
41− tHighpass_init(&ps->hp, HPFREQ);
42−
43− tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
44−
45− tPitchShifter_setTimeConstant(ps, DEFTIMECONSTANT);
46−}
47−
48−void tPitchShifter_free(tPitchShifter* const ps)
49−{
50− tEnv_free(&ps->env);
51− tSNAC_free(&ps->snac);
52− tSOLAD_free(&ps->sola);
53− tHighpass_free(&ps->hp);
54−}
55−
56−float tPitchShifter_tick(tPitchShifter* ps, float sample)
57−{
58− float period, out;
59− int i, iLast;
60−
61− i = (ps->curBlock*ps->frameSize);
62− iLast = (ps->lastBlock*ps->frameSize)+ps->index;
63−
64− out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
65− ps->inBuffer[i+ps->index] = sample;
66−
67− ps->index++;
68− if (ps->index >= ps->frameSize)
69− {
70− ps->index = 0;
71−
72− tEnv_processBlock(&ps->env, &(ps->inBuffer[i]));
73−
74− if(pitchshifter_attackdetect(ps) == 1)
75− {
76− ps->fba = 5;
77− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
78− }
79−
80− tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
81− period = tSNAC_getPeriod(&ps->snac);
82−
83− ps->curBlock++;
84− if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
85− ps->lastBlock++;
86− if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
87−
88− //separate here
89−
90− tSOLAD_setPeriod(&ps->sola, period);
91−
92− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
93− tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
94−
95− }
96−
97− return out;
98−}
99−
100−float tPitchShifterToFreq_tick(tPitchShifter* ps, float sample, float freq)
101−{
102− float period, out;
103− int i, iLast;
104−
105− i = (ps->curBlock*ps->frameSize);
106− iLast = (ps->lastBlock*ps->frameSize)+ps->index;
107−
108− out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
109− ps->inBuffer[i+ps->index] = sample;
110−
111− ps->index++;
112− if (ps->index >= ps->frameSize)
113− {
114− ps->index = 0;
115−
116− tEnv_processBlock(&ps->env, &(ps->inBuffer[i]));
117−
118− if(pitchshifter_attackdetect(ps) == 1)
119− {
120− ps->fba = 5;
121− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
122− }
123−
124− tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
125− period = tSNAC_getPeriod(&ps->snac);
126−
127− tSOLAD_setPeriod(&ps->sola, period);
128−
129− ps->pitchFactor = period*freq*leaf.invSampleRate;
130− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
131− tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
132−
133− ps->curBlock++;
134− if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
135− ps->lastBlock++;
136− if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
137− }
138−
139− return out;
140−}
141−
142−float tPitchShifterToFunc_tick(tPitchShifter* ps, float sample, float (*fun)(float))
143−{
144− float period, out;
145− int i, iLast;
146−
147− i = (ps->curBlock*ps->frameSize);
148− iLast = (ps->lastBlock*ps->frameSize)+ps->index;
149−
150− out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
151− ps->inBuffer[i+ps->index] = sample;
152−
153− ps->index++;
154− if (ps->index >= ps->frameSize)
155− {
156− ps->index = 0;
157−
158− tEnv_processBlock(&ps->env, &(ps->inBuffer[i]));
159−
160− if(pitchshifter_attackdetect(ps) == 1)
161− {
162− ps->fba = 5;
163− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
164− }
165−
166− tSNAC_ioSamples(&ps->snac, (&ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
167− period = tSNAC_getPeriod(&ps->snac);
168−
169− tSOLAD_setPeriod(&ps->sola, period);
170−
171− ps->pitchFactor = period/fun(period);
172− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
173− tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
174−
175− ps->curBlock++;
176− if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
177− ps->lastBlock++;
178− if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
179− }
180−
181− return out;
182−}
183−
184−void tPitchShifter_ioSamples(tPitchShifter* ps, float* in, float* out, int size)
185−{
186− float period;
187−
188− tEnv_processBlock(&ps->env, in);
189−
190− if(pitchshifter_attackdetect(ps) == 1)
191− {
192− ps->fba = 5;
193− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
194− }
195−
196− tSNAC_ioSamples(&ps->snac, in, out, size);
197− period = tSNAC_getPeriod(&ps->snac);
198−
199− tSOLAD_setPeriod(&ps->sola, period);
200−
201− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
202− tSOLAD_ioSamples(&ps->sola, in, out, size);
203−
204− for (int cc = 0; cc < size; ++cc)
205− {
206− out[cc] = tHighpass_tick(&ps->hp, out[cc]);
207− }
208−}
209−
210−void tPitchShifter_ioSamples_toFreq(tPitchShifter* ps, float* in, float* out, int size, float toFreq)
211−{
212− float period;
213−
214− tEnv_processBlock(&ps->env, in);
215−
216− if(pitchshifter_attackdetect(ps) == 1)
217− {
218− ps->fba = 5;
219− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
220− }
221−
222− tSNAC_ioSamples(&ps->snac, in, out, size);
223− period = tSNAC_getPeriod(&ps->snac);
224−
225− tSOLAD_setPeriod(&ps->sola, period);
226− ps->pitchFactor = period*toFreq;
227− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
228− tSOLAD_ioSamples(&ps->sola, in, out, size);
229−
230− for (int cc = 0; cc < size; ++cc)
231− {
232− out[cc] = tHighpass_tick(&ps->hp, out[cc]);
233− }
234−}
235−
236−void tPitchShifter_ioSamples_toPeriod(tPitchShifter* ps, float* in, float* out, int size, float toPeriod)
237−{
238− float period;
239−
240− tEnv_processBlock(&ps->env, in);
241−
242− if(pitchshifter_attackdetect(ps) == 1)
243− {
244− ps->fba = 5;
245− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
246− }
247−
248− tSNAC_ioSamples(&ps->snac, in, out, size);
249− period = tSNAC_getPeriod(&ps->snac);
250−
251− tSOLAD_setPeriod(&ps->sola, period);
252− ps->pitchFactor = period/toPeriod;
253− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
254− tSOLAD_ioSamples(&ps->sola, in, out, size);
255−
256− for (int cc = 0; cc < size; ++cc)
257− {
258− out[cc] = tHighpass_tick(&ps->hp, out[cc]);
259− }
260−}
261−
262−void tPitchShifter_ioSamples_toFunc(tPitchShifter* ps, float* in, float* out, int size, float (*fun)(float))
263−{
264− float period;
265−
266− tEnv_processBlock(&ps->env, in);
267−
268− if(pitchshifter_attackdetect(ps) == 1)
269− {
270− ps->fba = 5;
271− tSOLAD_setReadLag(&ps->sola, ps->windowSize);
272− }
273−
274− tSNAC_ioSamples(&ps->snac, in, out, size);
275− period = tSNAC_getPeriod(&ps->snac);
276−
277− tSOLAD_setPeriod(&ps->sola, period);
278− ps->pitchFactor = period/fun(period);
279− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
280− tSOLAD_ioSamples(&ps->sola, in, out, size);
281−
282− for (int cc = 0; cc < size; ++cc)
283− {
284− out[cc] = tHighpass_tick(&ps->hp, out[cc]);
285− }
286−}
287−
288−void tPitchShifter_setPitchFactor(tPitchShifter* ps, float pf)
289−{
290− ps->pitchFactor = pf;
291−}
292−
293−void tPitchShifter_setTimeConstant(tPitchShifter* ps, float tc)
294−{
295− ps->timeConstant = tc;
296− ps->radius = expf(-1000.0f * ps->hopSize * leaf.invSampleRate / ps->timeConstant);
297−}
298−
299−void tPitchShifter_setHopSize(tPitchShifter* ps, int hs)
300−{
301− ps->hopSize = hs;
302−}
303−
304−void tPitchShifter_setWindowSize(tPitchShifter* ps, int ws)
305−{
306− ps->windowSize = ws;
307−}
308−
309−float tPitchShifter_getPeriod(tPitchShifter* ps)
310−{
311− return tSNAC_getPeriod(&ps->snac);
312−}
313−
314−static int pitchshifter_attackdetect(tPitchShifter* ps)
315−{
316− float envout;
317−
318− envout = tEnv_tick(&ps->env);
319−
320− if (envout >= 1.0f)
321− {
322− ps->lastmax = ps->max;
323− if (envout > ps->max)
324− {
325− ps->max = envout;
326− }
327− else
328− {
329− ps->deltamax = envout - ps->max;
330− ps->max = ps->max * ps->radius;
331− }
332− ps->deltamax = ps->max - ps->lastmax;
333− }
334−
335− ps->fba = ps->fba ? (ps->fba - 1) : 0;
336−
337− return (ps->fba == 0 && (ps->max > 60 && ps->deltamax > 6)) ? 1 : 0;
338−}
339−
340−
341−void tPeriod_init (tPeriod* const p, float* in, float* out, int bufSize, int frameSize)
342−{
343− p->inBuffer = in;
344− p->outBuffer = out;
345− p->bufSize = bufSize;
346− p->frameSize = frameSize;
347− p->framesPerBuffer = p->bufSize / p->frameSize;
348− p->curBlock = 1;
349− p->lastBlock = 0;
350− p->index = 0;
351−
352− p->hopSize = DEFHOPSIZE;
353− p->windowSize = DEFWINDOWSIZE;
354− p->fba = FBA;
355−
356− tEnv_init(&p->env, p->windowSize, p->hopSize, p->frameSize);
357−
358− tSNAC_init(&p->snac, DEFOVERLAP);
359−
360− p->timeConstant = DEFTIMECONSTANT;
361− p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
362−}
363−
364−void tPeriod_free (tPeriod* const p)
365−{
366− tEnv_free(&p->env);
367− tSNAC_free(&p->snac);
368−}
369−
370−float tPeriod_findPeriod (tPeriod* p, float sample)
371−{
372− int i, iLast;
373−
374− i = (p->curBlock*p->frameSize);
375− iLast = (p->lastBlock*p->frameSize)+p->index;
376−
377− p->i = i;
378− p->iLast = iLast;
379−
380− p->inBuffer[i+p->index] = sample;
381−
382− p->index++;
383− p->indexstore = p->index;
384− if (p->index >= p->frameSize)
385− {
386− p->index = 0;
387−
388− tEnv_processBlock(&p->env, &(p->inBuffer[i]));
389−
390− tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
391− p->period = tSNAC_getPeriod(&p->snac);
392−
393− p->curBlock++;
394− if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
395− p->lastBlock++;
396− if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
397− }
398−
399− // changed from period to p->period
400− return p->period;
401−}
402−
403−void tPeriod_setHopSize(tPeriod* p, int hs)
404−{
405− p->hopSize = hs;
406−}
407−
408−void tPeriod_setWindowSize(tPeriod* p, int ws)
409−{
410− p->windowSize = ws;
411−}
412−
413−void tPitchShift_setPitchFactor(tPitchShift* ps, float pf)
414−{
415− ps->pitchFactor = pf;
416−}
417−
418−static int pitchshift_attackdetect(tPitchShift* ps)
419−{
420− float envout;
421−
422− envout = tEnv_tick(&ps->p->env);
423−
424− if (envout >= 1.0f)
425− {
426− ps->p->lastmax = ps->p->max;
427− if (envout > ps->p->max)
428− {
429− ps->p->max = envout;
430− }
431− else
432− {
433− ps->p->deltamax = envout - ps->p->max;
434− ps->p->max = ps->p->max * ps->radius;
435− }
436− ps->p->deltamax = ps->p->max - ps->p->lastmax;
437− }
438−
439− ps->p->fba = ps->p->fba ? (ps->p->fba - 1) : 0;
440−
441− return (ps->p->fba == 0 && (ps->p->max > 60 && ps->p->deltamax > 6)) ? 1 : 0;
442−}
443−
444−void tPitchShift_init (tPitchShift* const ps, tPeriod* p, float* out, int bufSize)
445−{
446− ps->p = p;
447−
448− ps->outBuffer = out;
449− ps->bufSize = bufSize;
450− ps->frameSize = p->frameSize;
451− ps->framesPerBuffer = ps->bufSize / ps->frameSize;
452− ps->curBlock = 1;
453− ps->lastBlock = 0;
454− ps->index = 0;
455− ps->pitchFactor = 1.0f;
456−
457− tSOLAD_init(&ps->sola);
458−
459− tHighpass_init(&ps->hp, HPFREQ);
460−
461− tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
462−}
463−
464−void tPitchShift_free(tPitchShift* const ps)
465−{
466− tSOLAD_free(&ps->sola);
467− tHighpass_free(&ps->hp);
468−}
469−
470−float tPitchShift_shift (tPitchShift* ps)
471−{
472− float period, out;
473− int i, iLast;
474−
475− i = ps->p->i;
476− iLast = ps->p->iLast;
477−
478− out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
479−
480− if (ps->p->indexstore >= ps->frameSize)
481− {
482− period = ps->p->period;
483−
484− if(pitchshift_attackdetect(ps) == 1)
485− {
486− ps->p->fba = 5;
487− tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
488− }
489−
490− tSOLAD_setPeriod(&ps->sola, period);
491− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
492−
493− tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
494− }
495−
496− return out;
497−}
498−
499−float tPitchShift_shiftToFreq (tPitchShift* ps, float freq)
500−{
501− float period, out;
502− int i, iLast;
503−
504− i = ps->p->i;
505− iLast = ps->p->iLast;
506−
507− out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
508−
509− if (ps->p->indexstore >= ps->frameSize)
510− {
511− period = ps->p->period;
512−
513− if(pitchshift_attackdetect(ps) == 1)
514− {
515− ps->p->fba = 5;
516− tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
517− }
518−
519− tSOLAD_setPeriod(&ps->sola, period);
520−
521− ps->pitchFactor = period*freq*leaf.invSampleRate;
522− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
523−
524− tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
525− }
526− return out;
527−}
528−
529−float tPitchShift_shiftToFunc (tPitchShift* ps, float (*fun)(float))
530−{
531− float period, out;
532− int i, iLast;
533−
534− i = ps->p->i;
535− iLast = ps->p->iLast;
536−
537− out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
538−
539− if (ps->p->indexstore >= ps->frameSize)
540− {
541− period = ps->p->period;
542−
543− if(pitchshift_attackdetect(ps) == 1)
544− {
545− ps->p->fba = 5;
546− tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
547− }
548−
549− tSOLAD_setPeriod(&ps->sola, period);
550−
551− ps->pitchFactor = period/fun(period);
552− tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
553−
554− tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
555−
556− ps->curBlock++;
557− if (ps->curBlock >= ps->p->framesPerBuffer) ps->curBlock = 0;
558− ps->lastBlock++;
559− if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
560− }
561−
562− return out;
563−}
LEAF/Src/leaf-reverb.c+32−32
@@ -18,8 +18,8 @@ · 17 unmodified lines
1818
1919 #endif
2020
21−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PRCRev ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22−void tPRCRev_init(tPRCRev* const r, float t60)
21+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PRCReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
22+void tPRCReverb_init(tPRCReverb* const r, float t60)
2323 {
2424 if (t60 <= 0.0f) t60 = 0.001f;
2525
@@ -47,20 +47,20 @@ void tPRCRev_init(tPRCRev* const r, float t60) · 21 unmodified lines
4747 tDelay_init(&r->allpassDelays[1], lengths[1], lengths[1] * 2);
4848 tDelay_init(&r->combDelay, lengths[2], lengths[2] * 2);
4949
50− tPRCRev_setT60(r, t60);
50+ tPRCReverb_setT60(r, t60);
5151
5252 r->allpassCoeff = 0.7f;
5353 r->mix = 0.5f;
5454 }
5555
56−void tPRCRev_free(tPRCRev* const r)
56+void tPRCReverb_free(tPRCReverb* const r)
5757 {
5858 tDelay_free(&r->allpassDelays[0]);
5959 tDelay_free(&r->allpassDelays[1]);
6060 tDelay_free(&r->combDelay);
6161 }
6262
63−void tPRCRev_setT60(tPRCRev* const r, float t60)
63+void tPRCReverb_setT60(tPRCReverb* const r, float t60)
6464 {
6565 if ( t60 <= 0.0f ) t60 = 0.001f;
6666
@@ -70,12 +70,12 @@ void tPRCRev_setT60(tPRCRev* const r, float t60) · 3 unmodified lines
7070
7171 }
7272
73−void tPRCRev_setMix(tPRCRev* const r, float mix)
73+void tPRCReverb_setMix(tPRCReverb* const r, float mix)
7474 {
7575 r->mix = mix;
7676 }
7777
78−float tPRCRev_tick(tPRCRev* const r, float input)
78+float tPRCReverb_tick(tPRCReverb* const r, float input)
7979 {
8080 float temp, temp0, temp1, temp2;
8181 float out;
@@ -107,13 +107,13 @@ float tPRCRev_tick(tPRCRev* const r, float input) · 25 unmodified lines
107107 return out;
108108 }
109109
110−void tPRCRevSampleRateChanged (tPRCRev* const r)
110+void tPRCReverbSampleRateChanged (tPRCReverb* const r)
111111 {
112112 r->combCoeff = pow(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf.invSampleRate / r->t60 ));
113113 }
114114
115−/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NRev ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
116−void tNRev_init(tNRev* const r, float t60)
115+/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
116+void tNReverb_init(tNReverb* const r, float t60)
117117 {
118118 if (t60 <= 0.0f) t60 = 0.001f;
119119
@@ -150,12 +150,12 @@ void tNRev_init(tNRev* const r, float t60) · 30 unmodified lines
150150 tDelay_setDelay(&r->combDelays[i], lengths[i+2]);
151151 }
152152
153− tNRev_setT60(r, t60);
153+ tNReverb_setT60(r, t60);
154154 r->allpassCoeff = 0.7f;
155155 r->mix = 0.3f;
156156 }
157157
158−void tNRev_free(tNRev* const r)
158+void tNReverb_free(tNReverb* const r)
159159 {
160160 for (int i = 0; i < 6; i++)
161161 {
@@ -168,7 +168,7 @@ void tNRev_free(tNRev* const r) · 6 unmodified lines
168168 }
169169 }
170170
171−void tNRev_setT60(tNRev* const r, float t60)
171+void tNReverb_setT60(tNReverb* const r, float t60)
172172 {
173173 if (t60 <= 0.0f) t60 = 0.001f;
174174
@@ -178,12 +178,12 @@ void tNRev_setT60(tNRev* const r, float t60) · 3 unmodified lines
178178
179179 }
180180
181−void tNRev_setMix(tNRev* const r, float mix)
181+void tNReverb_setMix(tNReverb* const r, float mix)
182182 {
183183 r->mix = mix;
184184 }
185185
186−float tNRev_tick(tNRev* const r, float input)
186+float tNReverb_tick(tNReverb* const r, float input)
187187 {
188188 r->lastIn = input;
189189
@@ -221,10 +221,10 @@ float tNRev_tick(tNRev* const r, float input) · 31 unmodified lines
221221 out = r->mix * ( -( r->allpassCoeff * temp2 ) + temp );
222222
223223 /*
224− temp = tDelayLGetLastOut(&r->allpassDelays[5]);
224+ temp = tLinearDelayGetLastOut(&r->allpassDelays[5]);
225225 temp3 = r->allpassCoeff * temp;
226226 temp3 += temp1;
227− tDelayLTick(&r->allpassDelays[5], temp3 );
227+ tLinearDelayTick(&r->allpassDelays[5], temp3 );
228228 lastFrame_[1] = effectMix_*( - ( r->allpassCoeff * temp3 ) + temp );
229229 */
230230
@@ -237,7 +237,7 @@ float tNRev_tick(tNRev* const r, float input) · 6 unmodified lines
237237 return out;
238238 }
239239
240−void tNRevSampleRateChanged (tNRev* const r)
240+void tNReverbSampleRateChanged (tNReverb* const r)
241241 {
242242 for (int i=0; i<6; i++) r->combCoeffs[i] = pow(10.0, (-3.0 * tDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / r->t60 ));
243243 }
@@ -250,7 +250,7 @@ float in_allpass_delays[4] = { 4.771f, 3.595f, 12.73f, 9.307f }; · 6 unmodified lines
250250 float in_allpass_gains[4] = { 0.75f, 0.75f, 0.625f, 0.625f };
251251
252252
253−void tDattorro_init (tDattorro* const r)
253+void tDattorroReverb_init (tDattorroReverb* const r)
254254 {
255255 r->size_max = 2.0f;
256256 r->size = 1.f;
@@ -298,20 +298,20 @@ void tDattorro_init (tDattorro* const r) · 41 unmodified lines
298298
299299
300300 // PARAMETERS
301− tDattorro_setMix(r, 0.5f);
301+ tDattorroReverb_setMix(r, 0.5f);
302302
303− tDattorro_setInputDelay(r, 0.f);
303+ tDattorroReverb_setInputDelay(r, 0.f);
304304
305− tDattorro_setInputFilter(r, 10000.f);
305+ tDattorroReverb_setInputFilter(r, 10000.f);
306306
307− tDattorro_setFeedbackFilter(r, 5000.f);
307+ tDattorroReverb_setFeedbackFilter(r, 5000.f);
308308
309− tDattorro_setFeedbackGain(r, 0.4f);
309+ tDattorroReverb_setFeedbackGain(r, 0.4f);
310310
311311
312312 }
313313
314−void tDattorro_free (tDattorro* const r)
314+void tDattorroReverb_free (tDattorroReverb* const r)
315315 {
316316 // INPUT
317317 tTapeDelay_free(&r->in_delay);
@@ -349,7 +349,7 @@ void tDattorro_free (tDattorro* const r) · 31 unmodified lines
349349 tCycle_free(&r->f2_lfo);
350350 }
351351
352−float tDattorro_tick (tDattorro* const r, float input)
352+float tDattorroReverb_tick (tDattorroReverb* const r, float input)
353353 {
354354 // INPUT
355355 float in_sample = tTapeDelay_tick(&r->in_delay, input);
@@ -449,12 +449,12 @@ float tDattorro_tick (tDattorro* const r, float input) · 93 unmodified lines
449449 return (input * (1.0f - r->mix) + sample * r->mix);
450450 }
451451
452−void tDattorro_setMix (tDattorro* const r, float mix)
452+void tDattorroReverb_setMix (tDattorroReverb* const r, float mix)
453453 {
454454 r->mix = LEAF_clip(0.0f, mix, 1.0f);
455455 }
456456
457−void tDattorro_setSize (tDattorro* const r, float size)
457+void tDattorroReverb_setSize (tDattorroReverb* const r, float size)
458458 {
459459 r->size = LEAF_clip(0.01f, size*r->size_max, r->size_max);
460460 r->t = r->size * leaf.sampleRate * 0.001f;
@@ -483,21 +483,21 @@ void tDattorro_setSize (tDattorro* const r, float size) · 22 unmodified lines
483483 tTapeDelay_setDelay(&r->f2_delay_3, SAMP(106.28f));
484484 }
485485
486−void tDattorro_setInputDelay (tDattorro* const r, float preDelay)
486+void tDattorroReverb_setInputDelay (tDattorroReverb* const r, float preDelay)
487487 {
488488 r->predelay = LEAF_clip(0.0f, preDelay, 200.0f);
489489
490490 tTapeDelay_setDelay(&r->in_delay, SAMP(r->predelay));
491491 }
492492
493−void tDattorro_setInputFilter (tDattorro* const r, float freq)
493+void tDattorroReverb_setInputFilter (tDattorroReverb* const r, float freq)
494494 {
495495 r->input_filter = LEAF_clip(0.0f, freq, 20000.0f);
496496
497497 tOnePole_setFreq(&r->in_filter, r->input_filter);
498498 }
499499
500−void tDattorro_setFeedbackFilter (tDattorro* const r, float freq)
500+void tDattorroReverb_setFeedbackFilter (tDattorroReverb* const r, float freq)
501501 {
502502 r->feedback_filter = LEAF_clip(0.0f, freq, 20000.0f);
503503
@@ -505,7 +505,7 @@ void tDattorro_setFeedbackFilter (tDattorro* const r, float freq) · 1 unmodified line
505505 tOnePole_setFreq(&r->f2_filter, r->feedback_filter);
506506 }
507507
508−void tDattorro_setFeedbackGain (tDattorro* const r, float gain)
508+void tDattorroReverb_setFeedbackGain (tDattorroReverb* const r, float gain)
509509 {
510510 r->feedback_gain = gain;
511511 }
LEAF/Src/leaf-sampling.crenamed from LEAF/Src/leaf-sample.c+3−3
@@ -1,7 +1,7 @@
11 /*
22 ==============================================================================
33
4− leaf-sample.c
4+ leaf-sampling.c
55 Created: 20 Jan 2017 12:02:17pm
66 Author: Michael R Mulshine
77
@@ -11,12 +11,12 @@ · 3 unmodified lines
1111
1212 #if _WIN32 || _WIN64
1313
14−#include "..\Inc\leaf-sample.h"
14+#include "..\Inc\leaf-sampling.h"
1515 #include "..\leaf.h"
1616
1717 #else
1818
19−#include "../Inc/leaf-sample.h"
19+#include "../Inc/leaf-sampling.h"
2020 #include "../leaf.h"
2121
2222 #endif
LEAF/Src/leaf-string.c+0−289
@@ -1,289 +0,0 @@
1−/*==============================================================================
2−
3− leaf-string.c
4− Created: 30 Nov 2018 10:41:42am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#if _WIN32 || _WIN64
10−
11−#include "..\Inc\leaf-string.h"
12−
13−#else
14−
15−#include "../Inc/leaf-string.h"
16−
17−#endif
18−
19−/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tPluck ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
20−void tPluck_init (tPluck* const p, float lowestFrequency)
21−{
22− if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f;
23−
24− tNoise_init(&p->noise, WhiteNoise);
25−
26− tOnePole_init(&p->pickFilter, 0.0f);
27−
28− tOneZero_init(&p->loopFilter, 0.0f);
29−
30− tDelayA_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
31−
32− tPluck_setFrequency(p, 220.0f);
33−}
34−
35−void tPluck_free (tPluck* const p)
36−{
37− tNoise_free(&p->noise);
38− tOnePole_free(&p->pickFilter);
39− tOneZero_free(&p->loopFilter);
40− tDelayA_free(&p->delayLine);
41−}
42−
43−float tPluck_getLastOut (tPluck *p)
44−{
45− return p->lastOut;
46−}
47−
48−float tPluck_tick (tPluck *p)
49−{
50− return (p->lastOut = 3.0f * tDelayA_tick(&p->delayLine, tOneZero_tick(&p->loopFilter, tDelayA_getLastOut(&p->delayLine) * p->loopGain ) ));
51−}
52−
53−void tPluck_pluck (tPluck* const p, float amplitude)
54−{
55− if ( amplitude < 0.0f) amplitude = 0.0f;
56− else if (amplitude > 1.0f) amplitude = 1.0f;
57−
58− tOnePole_setPole(&p->pickFilter, 0.999f - (amplitude * 0.15f));
59− tOnePole_setGain(&p->pickFilter, amplitude * 0.5f );
60−
61− // Fill delay with noise additively with current contents.
62− for ( uint32_t i = 0; i < (uint32_t)tDelayA_getDelay(&p->delayLine); i++ )
63− tDelayA_tick(&p->delayLine, 0.6f * tDelayA_getLastOut(&p->delayLine) + tOnePole_tick(&p->pickFilter, tNoise_tick(&p->noise) ) );
64−}
65−
66−// Start a note with the given frequency and amplitude.;
67−void tPluck_noteOn (tPluck* const p, float frequency, float amplitude )
68−{
69− p->lastFreq = frequency;
70− tPluck_setFrequency( p, frequency );
71− tPluck_pluck( p, amplitude );
72−}
73−
74−// Stop a note with the given amplitude (speed of decay).
75−void tPluck_noteOff (tPluck* const p, float amplitude )
76−{
77− if ( amplitude < 0.0f) amplitude = 0.0f;
78− else if (amplitude > 1.0f) amplitude = 1.0f;
79−
80− p->loopGain = 1.0f - amplitude;
81−}
82−
83−// Set instrument parameters for a particular frequency.
84−void tPluck_setFrequency (tPluck* const p, float frequency )
85−{
86− if ( frequency <= 0.0f ) frequency = 0.001f;
87−
88− // Delay = length - filter delay.
89− float delay = ( leaf.sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency );
90−
91− tDelayA_setDelay(&p->delayLine, delay );
92−
93− p->loopGain = 0.99f + (frequency * 0.000005f);
94−
95− if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f;
96−
97−}
98−
99−// Perform the control change specified by \e number and \e value (0.0 - 128.0).
100−void tPluck_controlChange (tPluck* const p, int number, float value)
101−{
102− return;
103−}
104−
105−void tPluckSampleRateChanged(tPluck* const p)
106−{
107− //tPluckSetFrequency(p, p->lastFreq);
108−}
109−
110−/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tStifKarp ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
111−void tStifKarp_init (tStifKarp* const p, float lowestFrequency)
112−{
113− if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f;
114−
115− tDelayA_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
116−
117− tDelayL_init(&p->combDelay, 0.0f, leaf.sampleRate * 2);
118−
119− tOneZero_init(&p->filter, 0.0f);
120−
121− tNoise_init(&p->noise, WhiteNoise);
122−
123− for (int i = 0; i < 4; i++)
124− {
125− tBiQuad_init(&p->biquad[i]);
126− }
127−
128− p->pluckAmplitude = 0.3f;
129− p->pickupPosition = 0.4f;
130−
131− p->stretching = 0.9999f;
132− p->baseLoopGain = 0.995f;
133− p->loopGain = 0.999f;
134−
135− tStifKarp_setFrequency( p, 220.0f );
136−
137−}
138−
139−void tStifKarp_free (tStifKarp* const p)
140−{
141− tDelayA_free(&p->delayLine);
142− tDelayL_free(&p->combDelay);
143− tOneZero_free(&p->filter);
144− tNoise_free(&p->noise);
145−
146− for (int i = 0; i < 4; i++)
147− {
148− tBiQuad_free(&p->biquad[i]);
149− }
150−}
151−
152−float tStifKarp_getLastOut (tStifKarp* const p)
153−{
154− return p->lastOut;
155−}
156−
157−float tStifKarp_tick (tStifKarp* const p)
158−{
159− float temp = tDelayA_getLastOut(&p->delayLine) * p->loopGain;
160−
161− // Calculate allpass stretching.
162− for (int i=0; i<4; i++) temp = tBiQuad_tick(&p->biquad[i],temp);
163−
164− // Moving average filter.
165− temp = tOneZero_tick(&p->filter, temp);
166−
167− float out = tDelayA_tick(&p->delayLine, temp);
168− out = out - tDelayL_tick(&p->combDelay, out);
169− p->lastOut = out;
170−
171− return p->lastOut;
172−}
173−
174−void tStifKarp_pluck (tStifKarp* const p, float amplitude)
175−{
176− if ( amplitude < 0.0f) amplitude = 0.0f;
177− else if (amplitude > 1.0f) amplitude = 1.0f;
178−
179− p->pluckAmplitude = amplitude;
180−
181− for ( uint32_t i=0; i < (uint32_t)tDelayA_getDelay(&p->delayLine); i++ )
182− {
183− // Fill delay with noise additively with current contents.
184− tDelayA_tick(&p->delayLine, (tDelayA_getLastOut(&p->delayLine) * 0.6f) + 0.4f * tNoise_tick(&p->noise) * p->pluckAmplitude );
185− //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
186− }
187−}
188−
189−// Start a note with the given frequency and amplitude.;
190−void tStifKarp_noteOn (tStifKarp* const p, float frequency, float amplitude )
191−{
192− tStifKarp_setFrequency( p, frequency );
193− tStifKarp_pluck( p, amplitude );
194−}
195−
196−// Stop a note with the given amplitude (speed of decay).
197−void tStifKarp_noteOff (tStifKarp* const p, float amplitude )
198−{
199− if ( amplitude < 0.0f) amplitude = 0.0f;
200− else if (amplitude > 1.0f) amplitude = 1.0f;
201−
202− p->loopGain = 1.0f - amplitude;
203−}
204−
205−// Set instrument parameters for a particular frequency.
206−void tStifKarp_setFrequency (tStifKarp* const p, float frequency )
207−{
208− if ( frequency <= 0.0f ) frequency = 0.001f;
209−
210− p->lastFrequency = frequency;
211− p->lastLength = leaf.sampleRate / p->lastFrequency;
212− float delay = p->lastLength - 0.5f;
213− tDelayA_setDelay(&p->delayLine, delay);
214−
215− // MAYBE MODIFY LOOP GAINS
216− p->loopGain = p->baseLoopGain + (frequency * 0.000005f);
217− if (p->loopGain >= 1.0f) p->loopGain = 0.99999f;
218−
219− tStifKarp_setStretch(p, p->stretching);
220−
221− tDelayL_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength );
222−
223−}
224−
225−// Set the stretch "factor" of the string (0.0 - 1.0).
226−void tStifKarp_setStretch (tStifKarp* const p, float stretch )
227−{
228− p->stretching = stretch;
229− float coefficient;
230− float freq = p->lastFrequency * 2.0f;
231− float dFreq = ( (0.5f * leaf.sampleRate) - freq ) * 0.25f;
232− float temp = 0.5f + (stretch * 0.5f);
233− if ( temp > 0.9999f ) temp = 0.9999f;
234−
235− for ( int i=0; i<4; i++ )
236− {
237− coefficient = temp * temp;
238− tBiQuad_setA2(&p->biquad[i], coefficient);
239− tBiQuad_setB0(&p->biquad[i], coefficient);
240− tBiQuad_setB2(&p->biquad[i], 1.0f);
241−
242− coefficient = -2.0f * temp * cos(TWO_PI * freq / leaf.sampleRate);
243− tBiQuad_setA1(&p->biquad[i], coefficient);
244− tBiQuad_setB1(&p->biquad[i], coefficient);
245−
246− freq += dFreq;
247− }
248−}
249−
250−// Set the pluck or "excitation" position along the string (0.0 - 1.0).
251−void tStifKarp_setPickupPosition (tStifKarp* const p, float position )
252−{
253− if (position < 0.0f) p->pickupPosition = 0.0f;
254− else if (position <= 1.0f) p->pickupPosition = position;
255− else p->pickupPosition = 1.0f;
256−
257− tDelayL_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength);
258−}
259−
260−// Set the base loop gain.
261−void tStifKarp_setBaseLoopGain (tStifKarp* const p, float aGain )
262−{
263− p->baseLoopGain = aGain;
264− p->loopGain = p->baseLoopGain + (p->lastFrequency * 0.000005f);
265− if ( p->loopGain > 0.99999f ) p->loopGain = 0.99999f;
266−}
267−
268−// Perform the control change specified by \e number and \e value (0.0 - 128.0).
269−void tStifKarp_controlChange (tStifKarp* const p, SKControlType type, float value)
270−{
271− if ( value < 0.0f ) value = 0.0f;
272− else if (value > 128.0f) value = 128.0f;
273−
274− float normalizedValue = value * INV_128;
275−
276− if (type == SKPickPosition) // 4
277− tStifKarp_setPickupPosition( p, normalizedValue );
278− else if (type == SKStringDamping) // 11
279− tStifKarp_setBaseLoopGain( p, 0.97f + (normalizedValue * 0.03f) );
280− else if (type == SKDetune) // 1
281− tStifKarp_setStretch( p, 0.91f + (0.09f * (1.0f - normalizedValue)) );
282−
283−}
284−
285−void tStifKarpSampleRateChanged (tStifKarp* const c)
286−{
287− tStifKarp_setFrequency(c, c->lastFrequency);
288− tStifKarp_setStretch(c, c->stretching);
289−}
LEAF/Src/leaf-utilities.c+0−2227
@@ -1,2227 +0,0 @@
1−/*
2− ==============================================================================
3−
4− LEAFUtilities.c
5− Created: 20 Jan 2017 12:02:17pm
6− Author: Michael R Mulshine
7−
8− ==============================================================================
9−*/
10−
11−
12−#if _WIN32 || _WIN64
13−
14−#include "..\Inc\leaf-utilities.h"
15−#include "..\Inc\leaf-tables.h"
16−#include "..\leaf.h"
17−#include "..\Inc\d_fft_mayer.h"
18−
19−#else
20−
21−#include "../Inc/leaf-utilities.h"
22−#include "../Inc/leaf-tables.h"
23−#include "../leaf.h"
24−#include "../Externals/d_fft_mayer.h"
25−
26−#endif
27−
28−#define LOGTEN 2.302585092994
29−
30−float mtof(float f)
31−{
32− if (f <= -1500.0f) return(0);
33− else if (f > 1499.0f) return(mtof(1499.0f));
34− else return (8.17579891564f * expf(0.0577622650f * f));
35−}
36−
37−float ftom(float f)
38−{
39− return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
40−}
41−
42−float powtodb(float f)
43−{
44− if (f <= 0) return (0);
45− else
46− {
47− float val = 100 + 10.f/LOGTEN * logf(f);
48− return (val < 0 ? 0 : val);
49− }
50−}
51−
52−float rmstodb(float f)
53−{
54− if (f <= 0) return (0);
55− else
56− {
57− float val = 100 + 20.f/LOGTEN * log(f);
58− return (val < 0 ? 0 : val);
59− }
60−}
61−
62−float dbtopow(float f)
63−{
64− if (f <= 0)
65− return(0);
66− else
67− {
68− if (f > 870.0f)
69− f = 870.0f;
70− return (expf((LOGTEN * 0.1f) * (f-100.0f)));
71− }
72−}
73−
74−float dbtorms(float f)
75−{
76− if (f <= 0)
77− return(0);
78− else
79− {
80− if (f > 485.0f)
81− f = 485.0f;
82− }
83− return (expf((LOGTEN * 0.05f) * (f-100.0f)));
84−}
85−
86−/* ---------------- env~ - simple envelope follower. ----------------- */
87−void tEnv_init(tEnv* const x, int ws, int hs, int bs)
88−{
89− int period = hs, npoints = ws;
90−
91− int i;
92−
93− if (npoints < 1) npoints = 1024;
94− if (period < 1) period = npoints/2;
95− if (period < npoints / MAXOVERLAP + 1)
96− period = npoints / MAXOVERLAP + 1;
97−
98− x->x_npoints = npoints;
99− x->x_phase = 0;
100− x->x_period = period;
101−
102− x->windowSize = npoints;
103− x->hopSize = period;
104− x->blockSize = bs;
105−
106− for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
107− for (i = 0; i < npoints; i++)
108− x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints;
109− for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0;
110−
111− x->x_f = 0;
112−
113− x->x_allocforvs = INITVSTAKEN;
114−
115− // ~ ~ ~ dsp ~ ~ ~
116− if (x->x_period % x->blockSize)
117− {
118− x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize);
119− }
120− else
121− {
122− x->x_realperiod = x->x_period;
123− }
124− // ~ ~ ~ ~ ~ ~ ~ ~
125−}
126−
127−void tEnv_free (tEnv* const x)
128−{
129−
130−}
131−
132−float tEnv_tick (tEnv* const x)
133−{
134− return powtodb(x->x_result);
135−}
136−
137−void tEnv_processBlock(tEnv* const x, float* in)
138−{
139− int n = x->blockSize;
140−
141− int count;
142− t_sample *sump;
143− in += n;
144− for (count = x->x_phase, sump = x->x_sumbuf;
145− count < x->x_npoints; count += x->x_realperiod, sump++)
146− {
147− t_sample *hp = x->buf + count;
148− t_sample *fp = in;
149− t_sample sum = *sump;
150− int i;
151−
152− for (i = 0; i < n; i++)
153− {
154− fp--;
155− sum += *hp++ * (*fp * *fp);
156− }
157− *sump = sum;
158− }
159− sump[0] = 0;
160− x->x_phase -= n;
161− if (x->x_phase < 0)
162− {
163− x->x_result = x->x_sumbuf[0];
164− for (count = x->x_realperiod, sump = x->x_sumbuf;
165− count < x->x_npoints; count += x->x_realperiod, sump++)
166− sump[0] = sump[1];
167− sump[0] = 0;
168− x->x_phase = x->x_realperiod - n;
169− }
170−}
171−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Compressor ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
172−
173−/*
174−tCompressor* tCompressorInit(int tauAttack, int tauRelease)
175−{
176− tCompressor* c = &leaf.tCompressorRegistry[leaf.registryIndex[T_COMPRESSOR]++];
177−
178− c->tauAttack = tauAttack;
179− c->tauRelease = tauRelease;
180−
181− c->x_G[0] = 0.0f, c->x_G[1] = 0.0f,
182− c->y_G[0] = 0.0f, c->y_G[1] = 0.0f,
183− c->x_T[0] = 0.0f, c->x_T[1] = 0.0f,
184− c->y_T[0] = 0.0f, c->y_T[1] = 0.0f;
185−
186− c->T = 0.0f; // Threshold
187− c->R = 1.0f; // compression Ratio
188− c->M = 0.0f; // decibel Make-up gain
189− c->W = 0.0f; // decibel Width of knee transition
190−
191− return c;
192−}
193−*/
194−void tCompressor_init(tCompressor* const c)
195−{
196− c->tauAttack = 100;
197− c->tauRelease = 100;
198−
199− c->isActive = OFALSE;
200−
201− c->T = 0.0f; // Threshold
202− c->R = 0.5f; // compression Ratio
203− c->M = 3.0f; // decibel Width of knee transition
204− c->W = 1.0f; // decibel Make-up gain
205−}
206−
207−void tCompressor_free(tCompressor* const c)
208−{
209−
210−}
211−
212−int ccount = 0;
213−float tCompressor_tick(tCompressor* const c, float in)
214−{
215− float slope, overshoot;
216− float alphaAtt, alphaRel;
217−
218− float in_db = 20.0f * log10f( fmaxf( fabsf( in), 0.000001f)), out_db = 0.0f;
219−
220− c->y_T[1] = c->y_T[0];
221−
222− slope = c->R - 1.0f; // feed-forward topology; was 1/C->R - 1
223−
224− overshoot = in_db - c->T;
225−
226−
227− if (overshoot <= -(c->W * 0.5f))
228− {
229− out_db = in_db;
230− c->isActive = OFALSE;
231− }
232− else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f)))
233− {
234− out_db = in_db + slope * (powf((overshoot + c->W*0.5f),2) / (2.0f * c->W)); // .^ 2 ???
235− c->isActive = OTRUE;
236− }
237− else if (overshoot >= (c->W * 0.5f))
238− {
239− out_db = in_db + slope * overshoot;
240− c->isActive = OTRUE;
241− }
242−
243−
244−
245− c->x_T[0] = out_db - in_db;
246−
247− alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * leaf.sampleRate));
248− alphaRel = expf(-1.0f/(0.001f * c->tauRelease * leaf.sampleRate));
249−
250− if (c->x_T[0] > c->y_T[1])
251− c->y_T[0] = alphaAtt * c->y_T[1] + (1-alphaAtt) * c->x_T[0];
252− else
253− c->y_T[0] = alphaRel * c->y_T[1] + (1-alphaRel) * c->x_T[0];
254−
255− float attenuation = powf(10.0f, ((c->M - c->y_T[0])/20.0f));
256−
257− /*
258− if (++ccount > 5000)
259− {
260−
261− ccount = 0;
262− DBG(".5width: " + String(c->W * 0.5f));
263− DBG("slope: " + String(slope) + " overshoot: " + String(overshoot));
264− DBG("attenuation: " + String(attenuation));
265− }
266− */
267− return attenuation * in;
268−
269−
270−}
271−
272−// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
273−void tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
274−{
275− env->exp_buff = exp_decay;
276− env->inc_buff = attack_decay_inc;
277− env->buff_size = sizeof(exp_decay);
278−
279− env->loop = loop;
280−
281− if (attack > 8192.0f)
282− attack = 8192.0f;
283− if (attack < 0.0f)
284− attack = 0.0f;
285−
286− if (decay > 8192.0f)
287− decay = 8192.0f;
288− if (decay < 0.0f)
289− decay = 0.0f;
290−
291− int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
292− int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
293− int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
294−
295− if (attackIndex < 0)
296− attackIndex = 0;
297− if (decayIndex < 0)
298− decayIndex = 0;
299− if (rampIndex < 0)
300− rampIndex = 0;
301−
302− env->inRamp = OFALSE;
303− env->inAttack = OFALSE;
304− env->inDecay = OFALSE;
305−
306− env->attackInc = env->inc_buff[attackIndex];
307− env->decayInc = env->inc_buff[decayIndex];
308− env->rampInc = env->inc_buff[rampIndex];
309−
310−}
311−
312−void tEnvelope_free(tEnvelope* const env)
313−{
314−
315−}
316−
317−int tEnvelope_setAttack(tEnvelope* const env, float attack)
318−{
319− int32_t attackIndex;
320−
321− if (attack < 0.0f) {
322− attackIndex = 0.0f;
323− } else if (attack < 8192.0f) {
324− attackIndex = ((int32_t)(attack * 8.0f))-1;
325− } else {
326− attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
327− }
328−
329− env->attackInc = env->inc_buff[attackIndex];
330−
331− return 0;
332−}
333−
334−int tEnvelope_setDecay(tEnvelope* const env, float decay)
335−{
336− int32_t decayIndex;
337−
338− if (decay < 0.0f) {
339− decayIndex = 0.0f;
340− } else if (decay < 8192.0f) {
341− decayIndex = ((int32_t)(decay * 8.0f)) - 1;
342− } else {
343− decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
344− }
345−
346− env->decayInc = env->inc_buff[decayIndex];
347−
348− return 0;
349−}
350−
351−int tEnvelope_loop(tEnvelope* const env, oBool loop)
352−{
353− env->loop = loop;
354−
355− return 0;
356−}
357−
358−
359−int tEnvelope_on(tEnvelope* const env, float velocity)
360−{
361− if (env->inAttack || env->inDecay) // In case envelope retriggered while it is still happening.
362− {
363− env->rampPhase = 0;
364− env->inRamp = OTRUE;
365− env->rampPeak = env->next;
366− }
367− else // Normal start.
368− {
369− env->inAttack = OTRUE;
370− }
371−
372−
373− env->attackPhase = 0;
374− env->decayPhase = 0;
375− env->inDecay = OFALSE;
376− env->gain = velocity;
377−
378− return 0;
379−}
380−
381−float tEnvelope_tick(tEnvelope* const env)
382−{
383− if (env->inRamp)
384− {
385− if (env->rampPhase > UINT16_MAX)
386− {
387− env->inRamp = OFALSE;
388− env->inAttack = OTRUE;
389− env->next = 0.0f;
390− }
391− else
392− {
393− env->next = env->rampPeak * env->exp_buff[(uint32_t)env->rampPhase];
394− }
395−
396− env->rampPhase += env->rampInc;
397− }
398−
399− if (env->inAttack)
400− {
401−
402− // If attack done, time to turn around.
403− if (env->attackPhase > UINT16_MAX)
404− {
405− env->inDecay = OTRUE;
406− env->inAttack = OFALSE;
407− env->next = env->gain * 1.0f;
408− }
409− else
410− {
411− // do interpolation !
412− env->next = env->gain * env->exp_buff[UINT16_MAX - (uint32_t)env->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
413− }
414−
415− // Increment envelope attack.
416− env->attackPhase += env->attackInc;
417−
418− }
419−
420− if (env->inDecay)
421− {
422−
423− // If decay done, finish.
424− if (env->decayPhase >= UINT16_MAX)
425− {
426− env->inDecay = OFALSE;
427−
428− if (env->loop)
429− {
430− env->attackPhase = 0;
431− env->decayPhase = 0;
432− env->inAttack = OTRUE;
433− }
434− else
435− {
436− env->next = 0.0f;
437− }
438−
439− } else {
440−
441− env->next = env->gain * (env->exp_buff[(uint32_t)env->decayPhase]); // do interpolation !
442− }
443−
444− // Increment envelope decay;
445− env->decayPhase += env->decayInc;
446− }
447−
448− return env->next;
449−}
450−
451−/* ADSR */
452−void tADSR_init(tADSR* const adsr, float attack, float decay, float sustain, float release)
453−{
454− adsr->exp_buff = exp_decay;
455− adsr->inc_buff = attack_decay_inc;
456− adsr->buff_size = sizeof(exp_decay);
457−
458− if (attack > 8192.0f)
459− attack = 8192.0f;
460− if (attack < 0.0f)
461− attack = 0.0f;
462−
463− if (decay > 8192.0f)
464− decay = 8192.0f;
465− if (decay < 0.0f)
466− decay = 0.0f;
467−
468− if (sustain > 1.0f)
469− sustain = 1.0f;
470− if (sustain < 0.0f)
471− sustain = 0.0f;
472−
473− if (release > 8192.0f)
474− release = 8192.0f;
475− if (release < 0.0f)
476− release = 0.0f;
477−
478− int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
479− int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
480− int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
481− int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
482−
483− if (attackIndex < 0)
484− attackIndex = 0;
485− if (decayIndex < 0)
486− decayIndex = 0;
487− if (releaseIndex < 0)
488− releaseIndex = 0;
489− if (rampIndex < 0)
490− rampIndex = 0;
491−
492− adsr->inRamp = OFALSE;
493− adsr->inAttack = OFALSE;
494− adsr->inDecay = OFALSE;
495− adsr->inSustain = OFALSE;
496− adsr->inRelease = OFALSE;
497−
498− adsr->sustain = sustain;
499−
500− adsr->attackInc = adsr->inc_buff[attackIndex];
501− adsr->decayInc = adsr->inc_buff[decayIndex];
502− adsr->releaseInc = adsr->inc_buff[releaseIndex];
503− adsr->rampInc = adsr->inc_buff[rampIndex];
504−}
505−
506−void tADSR_free(tADSR* const adsr)
507−{
508−
509−}
510−
511−int tADSR_setAttack(tADSR* const adsr, float attack)
512−{
513− int32_t attackIndex;
514−
515− if (attack < 0.0f) {
516− attackIndex = 0.0f;
517− } else if (attack < 8192.0f) {
518− attackIndex = ((int32_t)(attack * 8.0f))-1;
519− } else {
520− attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
521− }
522−
523− adsr->attackInc = adsr->inc_buff[attackIndex];
524−
525− return 0;
526−}
527−
528−int tADSR_detDecay(tADSR* const adsr, float decay)
529−{
530− int32_t decayIndex;
531−
532− if (decay < 0.0f) {
533− decayIndex = 0.0f;
534− } else if (decay < 8192.0f) {
535− decayIndex = ((int32_t)(decay * 8.0f)) - 1;
536− } else {
537− decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
538− }
539−
540− adsr->decayInc = adsr->inc_buff[decayIndex];
541−
542− return 0;
543−}
544−
545−int tADSR_setSustain(tADSR *const adsr, float sustain)
546−{
547− if (sustain > 1.0f) adsr->sustain = 1.0f;
548− else if (sustain < 0.0f) adsr->sustain = 0.0f;
549− else adsr->sustain = sustain;
550−
551− return 0;
552−}
553−
554−int tADSR_setRelease(tADSR* const adsr, float release)
555−{
556− int32_t releaseIndex;
557−
558− if (release < 0.0f) {
559− releaseIndex = 0.0f;
560− } else if (release < 8192.0f) {
561− releaseIndex = ((int32_t)(release * 8.0f)) - 1;
562− } else {
563− releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
564− }
565−
566− adsr->releaseInc = adsr->inc_buff[releaseIndex];
567−
568− return 0;
569−}
570−
571−int tADSR_on(tADSR* const adsr, float velocity)
572−{
573− if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.
574− {
575− adsr->rampPhase = 0;
576− adsr->inRamp = OTRUE;
577− adsr->rampPeak = adsr->next;
578− }
579− else // Normal start.
580− {
581− adsr->inAttack = OTRUE;
582− }
583−
584− adsr->attackPhase = 0;
585− adsr->decayPhase = 0;
586− adsr->releasePhase = 0;
587− adsr->inDecay = OFALSE;
588− adsr->inSustain = OFALSE;
589− adsr->inRelease = OFALSE;
590− adsr->gain = velocity;
591−
592− return 0;
593−}
594−
595−int tADSR_off(tADSR* const adsr)
596−{
597− if (adsr->inRelease) return 0;
598−
599− adsr->inAttack = OFALSE;
600− adsr->inDecay = OFALSE;
601− adsr->inSustain = OFALSE;
602− adsr->inRelease = OTRUE;
603−
604− adsr->releasePeak = adsr->next;
605−
606− return 0;
607−}
608−
609−float tADSR_tick(tADSR* const adsr)
610−{
611− if (adsr->inRamp)
612− {
613− if (adsr->rampPhase > UINT16_MAX)
614− {
615− adsr->inRamp = OFALSE;
616− adsr->inAttack = OTRUE;
617− adsr->next = 0.0f;
618− }
619− else
620− {
621− adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
622− }
623−
624− adsr->rampPhase += adsr->rampInc;
625− }
626−
627− if (adsr->inAttack)
628− {
629−
630− // If attack done, time to turn around.
631− if (adsr->attackPhase > UINT16_MAX)
632− {
633− adsr->inDecay = OTRUE;
634− adsr->inAttack = OFALSE;
635− adsr->next = adsr->gain * 1.0f;
636− }
637− else
638− {
639− // do interpolation !
640− adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
641− }
642−
643− // Increment ADSR attack.
644− adsr->attackPhase += adsr->attackInc;
645−
646− }
647−
648− if (adsr->inDecay)
649− {
650−
651− // If decay done, sustain.
652− if (adsr->decayPhase >= UINT16_MAX)
653− {
654− adsr->inDecay = OFALSE;
655− adsr->inSustain = OTRUE;
656− adsr->next = adsr->gain * adsr->sustain;
657− }
658−
659− else
660− {
661− adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation !
662− }
663−
664− // Increment ADSR decay.
665− adsr->decayPhase += adsr->decayInc;
666− }
667−
668− if (adsr->inRelease)
669− {
670− // If release done, finish.
671− if (adsr->releasePhase >= UINT16_MAX)
672− {
673− adsr->inRelease = OFALSE;
674− adsr->next = 0.0f;
675− }
676− else {
677−
678− adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation !
679− }
680−
681− // Increment envelope release;
682− adsr->releasePhase += adsr->releaseInc;
683− }
684−
685− return adsr->next;
686−}
687−
688−/* Envelope Follower */
689−void tEnvelopeFollower_init(tEnvelopeFollower* const e, float attackThreshold, float decayCoeff)
690−{
691− e->y = 0.0f;
692− e->a_thresh = attackThreshold;
693− e->d_coeff = decayCoeff;
694−}
695−
696−void tEnvelopeFollower_free(tEnvelopeFollower* const e)
697−{
698−
699−}
700−
701−float tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)
702−{
703− if (x < 0.0f ) x = -x; /* Absolute value. */
704−
705− if ((x >= ef->y) && (x > ef->a_thresh)) ef->y = x; /* If we hit a peak, ride the peak to the top. */
706− else ef->y = ef->y * ef->d_coeff; /* Else, exponential decay of output. */
707−
708− //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?
709− //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff; // too expensive
710−
711− if( ef->y < VSF) ef->y = 0.0f;
712−
713− return ef->y;
714−}
715−
716−int tEnvelopeFollower_decayCoeff(tEnvelopeFollower* const ef, float decayCoeff)
717−{
718− return ef->d_coeff = decayCoeff;
719−}
720−
721−int tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attackThresh)
722−{
723− return ef->a_thresh = attackThresh;
724−}
725−
726−/* Ramp */
727−void tRamp_init(tRamp* const ramp, float time, int samples_per_tick)
728−{
729− ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f);
730− ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
731− ramp->curr = 0.0f;
732− ramp->dest = 0.0f;
733−
734− if (time < ramp->minimum_time)
735− {
736− ramp->time = ramp->minimum_time;
737− }
738− else
739− {
740− ramp->time = time;
741− }
742−
743− ramp->samples_per_tick = samples_per_tick;
744− ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick;
745−}
746−
747−void tRamp_free(tRamp* const ramp)
748−{
749−
750−}
751−
752−int tRamp_setTime(tRamp* const r, float time)
753−{
754− if (time < r->minimum_time)
755− {
756− r->time = r->minimum_time;
757− }
758− else
759− {
760− r->time = time;
761− }
762− r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
763− return 0;
764−}
765−
766−int tRamp_setDest(tRamp* const r, float dest)
767−{
768− r->dest = dest;
769− r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
770− return 0;
771−}
772−
773−int tRamp_setVal(tRamp* const r, float val)
774−{
775− r->curr = val;
776− r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
777− return 0;
778−}
779−
780−float tRamp_tick(tRamp* const r) {
781−
782− r->curr += r->inc;
783−
784− if (((r->curr >= r->dest) && (r->inc > 0.0f)) || ((r->curr <= r->dest) && (r->inc < 0.0f))) r->inc = 0.0f;
785− // Palle: There is a slight risk that you overshoot here and stay on dest+inc, which with a large inc value could be a real problem
786− // I suggest you add: r->curr=r->dest in the true if case
787−
788− return r->curr;
789−}
790−
791−float tRamp_sample(tRamp* const r) {
792−
793− return r->curr;
794−}
795−
796−void tRampSampleRateChanged(tRamp* const r)
797−{
798− r->inv_sr_ms = 1.0f / (leaf.sampleRate * 0.001f);
799− r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms)*((float)r->samples_per_tick);
800−}
801−
802−
803−/* Exponential Smoother */
804−void tExpSmooth_init(tExpSmooth* const smooth, float val, float factor)
805−{ // factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
806− smooth->curr=val;
807− smooth->dest=val;
808− if (factor<0) factor=0;
809− if (factor>1) factor=1;
810− smooth->factor=factor;
811− smooth->oneminusfactor=1.0f-factor;
812−}
813−
814−void tExpSmooth_free(tExpSmooth* const smooth)
815−{
816−
817−}
818−
819−int tExpSmooth_setFactor(tExpSmooth* const smooth, float factor)
820−{ // factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
821− if (factor<0)
822− factor=0;
823− else
824− if (factor>1) factor=1;
825− smooth->factor=factor;
826− smooth->oneminusfactor=1.0f-factor;
827− return 0;
828−}
829−
830−int tExpSmooth_setDest(tExpSmooth* const smooth, float dest)
831−{
832− smooth->dest=dest;
833− return 0;
834−}
835−
836−int tExpSmooth_setVal(tExpSmooth* const smooth, float val)
837−{
838− smooth->curr=val;
839− return 0;
840−}
841−
842−float tExpSmooth_tick(tExpSmooth* const smooth)
843−{
844− smooth->curr = smooth->factor*smooth->dest+smooth->oneminusfactor*smooth->curr;
845− return smooth->curr;
846−}
847−
848−float tExpSmooth_sample(tExpSmooth* const smooth)
849−{
850− return smooth->curr;
851−}
852−
853−
854−/* Power Follower */
855−
856−void tPwrFollow_init(tPwrFollow* const p, float factor)
857−{
858− p->curr=0.0f;
859− p->factor=factor;
860− p->oneminusfactor=1.0f-factor;
861−}
862−
863−void tPwrFollow_free(tPwrFollow* const p)
864−{
865−
866−}
867−
868−int tPwrFollow_setFactor(tPwrFollow* const p, float factor)
869−{
870− if (factor<0) factor=0;
871− if (factor>1) factor=1;
872− p->factor=factor;
873− p->oneminusfactor=1.0f-factor;
874− return 0;
875−}
876−
877−float tPwrFollow_tick(tPwrFollow* const p, float input)
878−{
879− p->curr = p->factor*input*input+p->oneminusfactor*p->curr;
880− return p->curr;
881−}
882−
883−float tPwrFollow_sample(tPwrFollow* const p)
884−{
885− return p->curr;
886−}
887−
888−/* Feedback Leveler */
889−
890−void tFBleveller_init(tFBleveller* const p, float targetLevel, float factor, float strength, int mode)
891−{
892− p->curr=0.0f;
893− p->targetLevel=targetLevel;
894− tPwrFollow_init(&p->pwrFlw,factor);
895− p->mode=mode;
896− p->strength=strength;
897−}
898−
899−void tFBleveller_free(tFBleveller* const p)
900−{
901− tPwrFollow_free(&p->pwrFlw);
902−}
903−
904−int tFBleveller_setStrength(tFBleveller* const p, float strength)
905−{ // strength is how strongly level diff is affecting the amp ratio
906− // try 0.125 for a start
907− p->strength=strength;
908− return 0;
909−}
910−
911−int tFBleveller_setFactor(tFBleveller* const p, float factor)
912−{
913− tPwrFollow_setFactor(&p->pwrFlw,factor);
914− return 0;
915−}
916−
917−int tFBleveller_setMode(tFBleveller* const p, int mode)
918−{ // 0 for decaying with upwards lev limiting, 1 for constrained absolute level (also downwards limiting)
919− p->mode=mode;
920− return 0;
921−}
922−
923−float tFBleveller_tick(tFBleveller* const p, float input)
924−{
925− float levdiff=(tPwrFollow_tick(&p->pwrFlw, input)-p->targetLevel);
926− if (p->mode==0 && levdiff<0) levdiff=0;
927− p->curr=input*(1-p->strength*levdiff);
928− return p->curr;
929−}
930−
931−float tFBleveller_sample(tFBleveller* const p)
932−{
933− return p->curr;
934−}
935−
936−
937−int tFBleveller_setTargetLevel (tFBleveller* const p, float TargetLevel)
938−{
939− p->targetLevel=TargetLevel;
940−}
941−
942−///Reed Table model
943−//default values from STK are 0.6 offset and -0.8 slope
944−
945−void tReedTable_init (tReedTable* const p, float offset, float slope)
946−{
947− p->offset = offset;
948− p->slope = slope;
949−}
950−
951−void tReedTable_free (tReedTable* const p)
952−{
953− ;
954−}
955−
956−float tReedTable_tick (tReedTable* const p, float input)
957−{
958− // The input is differential pressure across the reed.
959− float output = p->offset + (p->slope * input);
960−
961− // If output is > 1, the reed has slammed shut and the
962− // reflection function value saturates at 1.0.
963− if ( output > 1.0f) output = 1.0f;
964−
965− // This is nearly impossible in a physical system, but
966− // a reflection function value of -1.0 corresponds to
967− // an open end (and no discontinuity in bore profile).
968− if ( output < -1.0f) output = -1.0f;
969−
970− return output;
971−}
972−
973−float tReedTable_tanh_tick (tReedTable* const p, float input)
974−{
975− // The input is differential pressure across the reed.
976− float output = p->offset + (p->slope * input);
977−
978− // If output is > 1, the reed has slammed shut and the
979− // reflection function value saturates at 1.0.
980− return tanhf(output);
981−}
982−
983−void tReedTable_setOffset (tReedTable* const p, float offset)
984−{
985− p->offset = offset;
986−}
987−
988−void tReedTable_setSlope (tReedTable* const p, float slope)
989−{
990− p->slope = slope;
991−}
992−
993−
994−
995−/* Simple Living String*/
996−
997−void tSimpleLivingString_init(tSimpleLivingString* const p, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
998−{
999− p->curr=0.0f;
1000− tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
1001− tSimpleLivingString_setFreq(p, freq);
1002− tDelayL_init(&p->delayLine,p->waveLengthInSamples, 2400);
1003− tOnePole_init(&p->bridgeFilter, dampFreq);
1004− tHighpass_init(&p->DCblocker,13);
1005− p->decay=decay;
1006− tFBleveller_init(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode);
1007− p->levMode=levMode;
1008−}
1009−
1010−void tSimpleLivingString_free(tSimpleLivingString* const p)
1011−{
1012− tExpSmooth_free(&p->wlSmooth);
1013− tDelayL_free(&p->delayLine);
1014− tOnePole_free(&p->bridgeFilter);
1015− tHighpass_free(&p->DCblocker);
1016− tFBleveller_free(&p->fbLev);
1017−}
1018−
1019−int tSimpleLivingString_setFreq(tSimpleLivingString* const p, float freq)
1020−{
1021− if (freq<20) freq=20;
1022− else if (freq>10000) freq=10000;
1023− p->waveLengthInSamples = leaf.sampleRate/freq;
1024− tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
1025− return 0;
1026−}
1027−
1028−int tSimpleLivingString_setWaveLength(tSimpleLivingString* const p, float waveLength)
1029−{
1030− if (waveLength<4.8) waveLength=4.8;
1031− else if (waveLength>2400) waveLength=2400;
1032− p->waveLengthInSamples = waveLength;
1033− tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
1034− return 0;
1035−}
1036−
1037−int tSimpleLivingString_setDampFreq(tSimpleLivingString* const p, float dampFreq)
1038−{
1039− tOnePole_setFreq(&p->bridgeFilter, dampFreq);
1040− return 0;
1041−}
1042−
1043−int tSimpleLivingString_setDecay(tSimpleLivingString* const p, float decay)
1044−{
1045− p->decay=decay;
1046− return 0;
1047−}
1048−
1049−int tSimpleLivingString_setTargetLev(tSimpleLivingString* const p, float targetLev)
1050−{
1051− tFBleveller_setTargetLevel(&p->fbLev, targetLev);
1052− return 0;
1053−}
1054−
1055−int tSimpleLivingString_setLevSmoothFactor(tSimpleLivingString* const p, float levSmoothFactor)
1056−{
1057− tFBleveller_setFactor(&p->fbLev, levSmoothFactor);
1058− return 0;
1059−}
1060−
1061−int tSimpleLivingString_setLevStrength(tSimpleLivingString* const p, float levStrength)
1062−{
1063− tFBleveller_setStrength(&p->fbLev, levStrength);
1064− return 0;
1065−}
1066−
1067−int tSimpleLivingString_setLevMode(tSimpleLivingString* const p, int levMode)
1068−{
1069− tFBleveller_setMode(&p->fbLev, levMode);
1070− p->levMode=levMode;
1071− return 0;
1072−}
1073−
1074−float tSimpleLivingString_tick(tSimpleLivingString* const p, float input)
1075−{
1076− float stringOut=tOnePole_tick(&p->bridgeFilter,tDelayL_tickOut(&p->delayLine));
1077− float stringInput=tHighpass_tick(&p->DCblocker, tFBleveller_tick(&p->fbLev, (p->levMode==0?p->decay*stringOut:stringOut)+input));
1078− tDelayL_tickIn(&p->delayLine, stringInput);
1079− tDelayL_setDelay(&p->delayLine, tExpSmooth_tick(&p->wlSmooth));
1080− p->curr = stringOut;
1081− return p->curr;
1082−}
1083−
1084−float tSimpleLivingString_sample(tSimpleLivingString* const p)
1085−{
1086− return p->curr;
1087−}
1088−
1089−/* Living String*/
1090−
1091−void tLivingString_init(tLivingString* const p, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
1092−{
1093− p->curr=0.0f;
1094− tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
1095− tLivingString_setFreq(p, freq);
1096− tExpSmooth_init(&p->ppSmooth, pickPos, 0.01); // smoother for pick position
1097− tLivingString_setPickPos(p, pickPos);
1098− p->prepIndex=prepIndex;
1099− tDelayL_init(&p->delLF,p->waveLengthInSamples, 2400);
1100− tDelayL_init(&p->delUF,p->waveLengthInSamples, 2400);
1101− tDelayL_init(&p->delUB,p->waveLengthInSamples, 2400);
1102− tDelayL_init(&p->delLB,p->waveLengthInSamples, 2400);
1103− tOnePole_init(&p->bridgeFilter, dampFreq);
1104− tOnePole_init(&p->nutFilter, dampFreq);
1105− tOnePole_init(&p->prepFilterU, dampFreq);
1106− tOnePole_init(&p->prepFilterL, dampFreq);
1107− tHighpass_init(&p->DCblockerU,13);
1108− tHighpass_init(&p->DCblockerL,13);
1109− p->decay=decay;
1110− tFBleveller_init(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode);
1111− tFBleveller_init(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode);
1112− p->levMode=levMode;
1113−}
1114−
1115−void tLivingString_free(tLivingString* const p)
1116−{
1117− tExpSmooth_free(&p->wlSmooth);
1118− tExpSmooth_free(&p->ppSmooth);
1119− tDelayL_free(&p->delLF);
1120− tDelayL_free(&p->delUF);
1121− tDelayL_free(&p->delUB);
1122− tDelayL_free(&p->delLB);
1123− tOnePole_free(&p->bridgeFilter);
1124− tOnePole_free(&p->nutFilter);
1125− tOnePole_free(&p->prepFilterU);
1126− tOnePole_free(&p->prepFilterL);
1127− tHighpass_free(&p->DCblockerU);
1128− tHighpass_free(&p->DCblockerL);
1129− tFBleveller_free(&p->fbLevU);
1130− tFBleveller_free(&p->fbLevL);
1131−}
1132−
1133−int tLivingString_setFreq(tLivingString* const p, float freq)
1134−{ // NOTE: It is faster to set wavelength in samples directly
1135− if (freq<20) freq=20;
1136− else if (freq>10000) freq=10000;
1137− p->waveLengthInSamples = leaf.sampleRate/freq;
1138− tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
1139− return 0;
1140−}
1141−
1142−int tLivingString_setWaveLength(tLivingString* const p, float waveLength)
1143−{
1144− if (waveLength<4.8) waveLength=4.8;
1145− else if (waveLength>2400) waveLength=2400;
1146− p->waveLengthInSamples = waveLength;
1147− tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
1148− return 0;
1149−}
1150−
1151−int tLivingString_setPickPos(tLivingString* const p, float pickPos)
1152−{ // between 0 and 1
1153− if (pickPos<0.f) pickPos=0.f;
1154− else if (pickPos>1.f) pickPos=1.f;
1155− p->pickPos = pickPos;
1156− tExpSmooth_setDest(&p->ppSmooth, p->pickPos);
1157− return 0;
1158−}
1159−
1160−int tLivingString_setPrepIndex(tLivingString* const p, float prepIndex)
1161−{ // between 0 and 1
1162− if (prepIndex<0.f) prepIndex=0.f;
1163− else if (prepIndex>1.f) prepIndex=1.f;
1164− p->prepIndex = prepIndex;
1165− return 0;
1166−}
1167−
1168−int tLivingString_setDampFreq(tLivingString* const p, float dampFreq)
1169−{
1170− tOnePole_setFreq(&p->bridgeFilter, dampFreq);
1171− tOnePole_setFreq(&p->nutFilter, dampFreq);
1172− tOnePole_setFreq(&p->prepFilterU, dampFreq);
1173− tOnePole_setFreq(&p->prepFilterL, dampFreq);
1174− return 0;
1175−}
1176−
1177−int tLivingString_setDecay(tLivingString* const p, float decay)
1178−{
1179− p->decay=decay;
1180− return 0;
1181−}
1182−
1183−int tLivingString_setTargetLev(tLivingString* const p, float targetLev)
1184−{
1185− tFBleveller_setTargetLevel(&p->fbLevU, targetLev);
1186− tFBleveller_setTargetLevel(&p->fbLevL, targetLev);
1187− return 0;
1188−}
1189−
1190−int tLivingString_setLevSmoothFactor(tLivingString* const p, float levSmoothFactor)
1191−{
1192− tFBleveller_setFactor(&p->fbLevU, levSmoothFactor);
1193− tFBleveller_setFactor(&p->fbLevL, levSmoothFactor);
1194− return 0;
1195−}
1196−
1197−int tLivingString_setLevStrength(tLivingString* const p, float levStrength)
1198−{
1199− tFBleveller_setStrength(&p->fbLevU, levStrength);
1200− tFBleveller_setStrength(&p->fbLevL, levStrength);
1201− return 0;
1202−}
1203−
1204−int tLivingString_setLevMode(tLivingString* const p, int levMode)
1205−{
1206− tFBleveller_setMode(&p->fbLevU, levMode);
1207− tFBleveller_setMode(&p->fbLevL, levMode);
1208− p->levMode=levMode;
1209− return 0;
1210−}
1211−
1212−float tLivingString_tick(tLivingString* const p, float input)
1213−{
1214− // from pickPos upwards=forwards
1215− float fromLF=tDelayL_tickOut(&p->delLF);
1216− float fromUF=tDelayL_tickOut(&p->delUF);
1217− float fromUB=tDelayL_tickOut(&p->delUB);
1218− float fromLB=tDelayL_tickOut(&p->delLB);
1219− // into upper half of string, from nut, going backwards
1220− float fromNut=-tFBleveller_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->nutFilter, fromUF)));
1221− tDelayL_tickIn(&p->delUB, fromNut);
1222− // into lower half of string, from pickpoint, going backwards
1223− float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
1224− float intoLower=p->prepIndex*fromLowerPrep+(1-p->prepIndex)*fromUB+input;
1225− tDelayL_tickIn(&p->delLB, intoLower);
1226− // into lower half of string, from bridge
1227− float fromBridge=-tFBleveller_tick(&p->fbLevL, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB)));
1228− tDelayL_tickIn(&p->delLF, fromBridge);
1229− // into upper half of string, from pickpoint, going forwards/upwards
1230− float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
1231− float intoUpper=p->prepIndex*fromUpperPrep+(1-p->prepIndex)*fromLF+input;
1232− tDelayL_tickIn(&p->delUF, intoUpper);
1233− // update all delay lengths
1234− float pickP=tExpSmooth_tick(&p->ppSmooth);
1235− float wLen=tExpSmooth_tick(&p->wlSmooth);
1236− float lowLen=pickP*wLen;
1237− float upLen=(1-pickP)*wLen;
1238− tDelayL_setDelay(&p->delLF, lowLen);
1239− tDelayL_setDelay(&p->delLB, lowLen);
1240− tDelayL_setDelay(&p->delUF, upLen);
1241− tDelayL_setDelay(&p->delUB, upLen);
1242− p->curr = fromBridge;
1243− return p->curr;
1244−}
1245−
1246−float tLivingString_sample(tLivingString* const p)
1247−{
1248− return p->curr;
1249−}
1250−
1251−
1252−/* Stack */
1253−
1254−void tStack_init(tStack* const ns)
1255−{
1256− ns->ordered = OFALSE;
1257− ns->size = 0;
1258− ns->pos = 0;
1259− ns->capacity = STACK_SIZE;
1260−
1261− for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
1262−}
1263−
1264−void tStack_free(tStack* const ns)
1265−{
1266−
1267−}
1268−
1269−// If stack contains note, returns index. Else returns -1;
1270−int tStack_contains(tStack* const ns, uint16_t noteVal)
1271−{
1272− for (int i = 0; i < ns->size; i++)
1273− {
1274− if (ns->data[i] == noteVal) return i;
1275− }
1276− return -1;
1277−}
1278−
1279−void tStack_add(tStack* const ns, uint16_t noteVal)
1280−{
1281− uint8_t j;
1282−
1283− int whereToInsert = 0;
1284− if (ns->ordered)
1285− {
1286− for (j = 0; j < ns->size; j++)
1287− {
1288− if (noteVal > ns->data[j])
1289− {
1290− if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
1291− {
1292− whereToInsert = j+1;
1293− break;
1294− }
1295− }
1296− }
1297− }
1298−
1299− //first move notes that are already in the stack one position to the right
1300− for (j = ns->size; j > whereToInsert; j--)
1301− {
1302− ns->data[j] = ns->data[(j - 1)];
1303− }
1304−
1305− //then, insert the new note into the front of the stack
1306− ns->data[whereToInsert] = noteVal;
1307−
1308− ns->size++;
1309−}
1310−
1311−int tStack_addIfNotAlreadyThere(tStack* const ns, uint16_t noteVal)
1312−{
1313− uint8_t j;
1314−
1315− int added = 0;
1316−
1317− if (tStack_contains(ns, noteVal) == -1)
1318− {
1319− int whereToInsert = 0;
1320− if (ns->ordered)
1321− {
1322− for (j = 0; j < ns->size; j++)
1323− {
1324− if (noteVal > ns->data[j])
1325− {
1326− if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
1327− {
1328− whereToInsert = j+1;
1329− break;
1330− }
1331− }
1332− }
1333− }
1334−
1335− //first move notes that are already in the stack one position to the right
1336− for (j = ns->size; j > whereToInsert; j--)
1337− {
1338− ns->data[j] = ns->data[(j - 1)];
1339− }
1340−
1341− //then, insert the new note into the front of the stack
1342− ns->data[whereToInsert] = noteVal;
1343−
1344− ns->size++;
1345−
1346− added = 1;
1347− }
1348−
1349− return added;
1350−}
1351−
1352−
1353−// Remove noteVal. return 1 if removed, 0 if not
1354−int tStack_remove(tStack* const ns, uint16_t noteVal)
1355−{
1356− uint8_t k;
1357− int foundIndex = tStack_contains(ns, noteVal);
1358− int removed = 0;
1359−
1360− if (foundIndex >= 0)
1361− {
1362− for (k = 0; k < (ns->size - foundIndex); k++)
1363− {
1364− if ((k+foundIndex) >= (ns->capacity - 1))
1365− {
1366− ns->data[k + foundIndex] = -1;
1367− }
1368− else
1369− {
1370− ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
1371− if ((k + foundIndex) == (ns->size - 1))
1372− {
1373− ns->data[k + foundIndex + 1] = -1;
1374− }
1375− }
1376−
1377− }
1378− // in case it got put on the stack multiple times
1379− foundIndex--;
1380− ns->size--;
1381− removed = 1;
1382− }
1383−
1384−
1385−
1386− return removed;
1387−}
1388−
1389−// Doesn't change size of data types
1390−void tStack_setCapacity(tStack* const ns, uint16_t cap)
1391−{
1392− if (cap <= 0)
1393− ns->capacity = 1;
1394− else if (cap <= STACK_SIZE)
1395− ns->capacity = cap;
1396− else
1397− ns->capacity = STACK_SIZE;
1398−
1399− for (int i = cap; i < STACK_SIZE; i++)
1400− {
1401− if ((int)ns->data[i] != -1)
1402− {
1403− ns->data[i] = -1;
1404− ns->size -= 1;
1405− }
1406− }
1407−
1408− if (ns->pos >= cap)
1409− {
1410− ns->pos = 0;
1411− }
1412−}
1413−
1414−int tStack_getSize(tStack* const ns)
1415−{
1416− return ns->size;
1417−}
1418−
1419−void tStack_clear(tStack* const ns)
1420−{
1421− for (int i = 0; i < STACK_SIZE; i++)
1422− {
1423− ns->data[i] = -1;
1424− }
1425− ns->pos = 0;
1426− ns->size = 0;
1427−}
1428−
1429−// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
1430−int tStack_next(tStack* const ns)
1431−{
1432− int step = 0;
1433− if (ns->size != 0) // if there is at least one note in the stack
1434− {
1435− if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest)
1436− {
1437− ns->pos--;
1438− }
1439− else
1440− {
1441− ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
1442− }
1443−
1444− step = ns->data[ns->pos];
1445− return step;
1446− }
1447− else
1448− {
1449− return -1;
1450− }
1451−}
1452−
1453−int tStack_get(tStack* const ns, int which)
1454−{
1455− return ns->data[which];
1456−}
1457−
1458−int tStack_first(tStack* const ns)
1459−{
1460− return ns->data[0];
1461−}
1462−/******************************************************************************/
1463−/***************** static function declarations *******************************/
1464−/******************************************************************************/
1465−
1466−static void solad_init(tSOLAD *w);
1467−static inline float read_sample(tSOLAD *w, float floatindex);
1468−static void pitchdown(tSOLAD *w, float *out);
1469−static void pitchup(tSOLAD *w, float *out);
1470−
1471−/******************************************************************************/
1472−/***************** public access functions ************************************/
1473−/******************************************************************************/
1474−
1475−// init
1476−void tSOLAD_init(tSOLAD* const w)
1477−{
1478− w->pitchfactor = 1.;
1479− w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16));
1480− solad_init(w);
1481−}
1482−
1483−void tSOLAD_free(tSOLAD* const w)
1484−{
1485−}
1486−
1487−// send one block of input samples, receive one block of output samples
1488−void tSOLAD_ioSamples(tSOLAD* const w, float* in, float* out, int blocksize)
1489−{
1490− int i = w->timeindex;
1491− int n = w->blocksize = blocksize;
1492−
1493− if(!i) w->delaybuf[LOOPSIZE] = in[0]; // copy one sample for interpolation
1494− while(n--) w->delaybuf[i++] = *in++; // copy one input block to delay buffer
1495−
1496− if(w->pitchfactor > 1) pitchup(w, out);
1497− else pitchdown(w, out);
1498−
1499− w->timeindex += blocksize;
1500− w->timeindex &= LOOPMASK;
1501−}
1502−
1503−// set periodicity analysis data
1504−void tSOLAD_setPeriod(tSOLAD* const w, float period)
1505−{
1506− if(period > MAXPERIOD) period = MAXPERIOD;
1507− if(period > MINPERIOD) w->period = period; // ignore period when too small
1508−}
1509−
1510−// set pitch factor between 0.25 and 4
1511−void tSOLAD_setPitchFactor(tSOLAD* const w, float pitchfactor)
1512−{
1513− if(pitchfactor < 0.25) pitchfactor = 0.25;
1514− else if(pitchfactor > 4.) pitchfactor = 4.;
1515− w->pitchfactor = pitchfactor;
1516−}
1517−
1518−// force readpointer lag
1519−void tSOLAD_setReadLag(tSOLAD* const w, float readlag)
1520−{
1521− if(readlag < 0) readlag = 0;
1522− if(readlag < w->readlag) // do not jump backward, only forward
1523− {
1524− w->jump = w->readlag - readlag;
1525− w->readlag = readlag;
1526− w->xfadelength = readlag;
1527− w->xfadevalue = 1;
1528− }
1529−}
1530−
1531−// reset state variables
1532−void tSOLAD_resetState(tSOLAD* const w)
1533−{
1534− int n = LOOPSIZE + 1;
1535− float *buf = w->delaybuf;
1536−
1537− while(n--) *buf++ = 0;
1538− solad_init(w);
1539−}
1540−
1541−/******************************************************************************/
1542−/******************** private procedures **************************************/
1543−/******************************************************************************/
1544−
1545−/*
1546− Function pitchdown() is called to read samples from the delay buffer when pitch
1547− factor is between 0.25 and 1. The read pointer lags behind because of the slowed
1548− down speed, and it must jump forward towards the write pointer soon as there is
1549− sufficient space to jump. That is, if there is at least one period of the input
1550− signal between read pointer and write pointer. When short periods follow up on
1551− long periods, the read pointer may have space to jump over more than one period
1552− lenghts. Jump length must be [periodlength ^ 2] in any case.
1553−
1554− A linear crossfade function joins the jump-from point with the jump-to point.
1555− The crossfade must be completed before another read pointer jump is allowed.
1556− Length of the crossfade function is stored as a number of samples in terms of
1557− the input sample rate. This length is dynamically translated
1558− to a crossfade length expressed in output reading rate, according to pitch
1559− factor which can change before the crossfade is completed. Crossfade length does
1560− not cover an invariable length in periods for all pitch transposition factors.
1561− For pitch factors from 0.5 till 1, crossfade length is stretched in the
1562− output just as much as the signal itself, as crossfade speed is set to equal
1563− pitch factor. For pitch factors below 0.5, the read pointer wants to jump
1564− forward before one period is read, therefore the crossfade length as expressed
1565− in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
1566− for those cases. Pitch factor 0.5 is the natural switch point between crossfade
1567− speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
1568− speed modification for pitch factors below 0.5 also means that much of the
1569− original signal content will be skipped.
1570− */
1571−
1572−
1573−static void pitchdown(tSOLAD* const w, float *out)
1574−{
1575− int n = w->blocksize;
1576− float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
1577− float pitchfactor = w->pitchfactor;
1578− float period = w->period;
1579− float readlag = w->readlag;
1580− float readlagstep = 1 - pitchfactor;
1581− float jump = w->jump;
1582− float xfadevalue = w->xfadevalue;
1583− float xfadelength = w->xfadelength;
1584− float xfadespeed, xfadestep, readindex, outputsample;
1585−
1586− if(pitchfactor > 0.5) xfadespeed = pitchfactor;
1587− else xfadespeed = 1 - pitchfactor;
1588− xfadestep = xfadespeed / xfadelength;
1589−
1590− while(n--)
1591− {
1592− if(readlag > period) // check if read pointer may jump forward...
1593− {
1594− if(xfadevalue <= 0) // ...but do not interrupt crossfade
1595− {
1596− jump = period; // jump forward
1597− while((jump * 2) < readlag) jump *= 2; // use available space
1598− readlag -= jump; // reduce read pointer lag
1599− xfadevalue = 1; // start crossfade
1600− xfadelength = period - 1;
1601− xfadestep = xfadespeed / xfadelength;
1602− }
1603− }
1604−
1605− readindex = refindex - readlag;
1606− outputsample = read_sample(w, readindex);
1607−
1608− if(xfadevalue > 0)
1609− {
1610− outputsample *= (1 - xfadevalue); // fadein
1611− outputsample += read_sample(w, readindex - jump) * xfadevalue; // fadeout
1612− xfadevalue -= xfadestep;
1613− }
1614−
1615− *out++ = outputsample;
1616− refindex += 1;
1617− readlag += readlagstep;
1618− }
1619−
1620− w->jump = jump; // state variables
1621− w->readlag = readlag;
1622− w->xfadevalue = xfadevalue;
1623− w->xfadelength = xfadelength;
1624−}
1625−
1626−
1627−/*
1628− Function pitchup() for pitch factors above 1 is more complicated than
1629− pitchdown(). The read pointer increments faster than the write pointer and a
1630− backward jump must happen in time, reckoning with the crossfade region. The read
1631− pointer backward jump length is always one period. In order to minimize the area
1632− of signal duplicates, crossfade length is aimed at [period / pitchfactor].
1633− This leads to a crossfade speed of [pitchfactor * pitchfactor].
1634−
1635− Some samples for the fade out (but not all of them) must already be in the
1636− buffer, otherwise we will run out of input samples before the crossfade is
1637− completed. The ratio of past samples and future samples for a crossfade of any
1638− length is as follows:
1639−
1640− past samples: xfadelength * (1 - 1 / pitchfactor)
1641− future samples: xfadelength * (1 / pitchfactor)
1642−
1643− For example in the case of pitch factor 1.5 this would be:
1644−
1645− past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3
1646− future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3
1647−
1648− In the case of pitch factor 4 this would be:
1649−
1650− past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4
1651− future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4
1652−
1653− The read pointer lag must therefore preserve a minimum dependent on pitch
1654− factor. The minimum is called 'limit' here:
1655−
1656− limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor
1657−
1658− Components of this expression are combined to reuse them in operations, while
1659− (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical
1660− resolution issues for pitch factors slightly above 1:
1661−
1662− xfadespeed = pitchfactor * pitchfactor
1663− limitfactor = (pitchfactor - 0.99) / xfadespeed
1664− limit = period * limitfactor
1665−
1666− When read lag is smaller than this limit, the read pointer must preferably
1667− jump backward, unless a previous crossfade is not yet completed. Crossfades must
1668− preferably be completed, unless the read pointer lag becomes smaller than zero.
1669− With fluctuating period lengths and pitch factors, the readpointer lag limit may
1670− change from one input block to the next in such a way that the actual lag is
1671− suddenly much smaller than the limit, and the intended crossfade length can not
1672− be applied. Therefore the crossfade length is simply calculated from the
1673− available amount of samples for all cases, like so:
1674−
1675− xfadelength = readlag / limitfactor
1676−
1677− For most occurrences, this will amount to a crossfade length reduced to
1678− [period / pitchfactor] in the output for pitch factors above 1, while in some
1679− cases it will be considerably shorter. Fortunately, an incidental aberration of
1680− the intended crossfade length hardly ever creates an audible artifact. The
1681− reason to specify preferred crossfade length according to pitch factor is to
1682− minimize the impression of echoes without sacrificing too much of the signal
1683− content. The readpointer jump length remains one period in any case.
1684−
1685− Sometimes, the input signal periodicity may decrease substantially between one
1686− signal block and the next. In such cases it may be possible for the read pointer
1687− to jump forward and reduce latency. For every signal block, a check on this
1688− possibility is done. A previous crossfade must be completed before a forward
1689− jump is allowed.
1690− */
1691−static void pitchup(tSOLAD* const w, float *out)
1692−{
1693− int n = w->blocksize;
1694− float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
1695− float pitchfactor = w->pitchfactor;
1696− float period = w->period;
1697− float readlag = w->readlag;
1698− float jump = w->jump;
1699− float xfadevalue = w->xfadevalue;
1700− float xfadelength = w->xfadelength;
1701−
1702− float readlagstep = pitchfactor - 1;
1703− float xfadespeed = pitchfactor * pitchfactor;
1704− float xfadestep = xfadespeed / xfadelength;
1705− float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;
1706− float limit = period * limitfactor;
1707− float readindex, outputsample;
1708−
1709− if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
1710− {
1711− jump = period; // jump forward
1712− while((jump * 2) < (readlag - 2 * limit)) jump *= 2; // use available space
1713− readlag -= jump; // reduce read pointer lag
1714− xfadevalue = 1; // start crossfade
1715− xfadelength = period - 1;
1716− xfadestep = xfadespeed / xfadelength;
1717− }
1718−
1719− while(n--)
1720− {
1721− if(readlag < limit) // check if read pointer should jump backward...
1722− {
1723− if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade
1724− {
1725− xfadelength = readlag / limitfactor;
1726− if(xfadelength < 1) xfadelength = 1;
1727− xfadestep = xfadespeed / xfadelength;
1728−
1729− jump = -period; // jump backward
1730− readlag += period; // increase read pointer lag
1731− xfadevalue = 1; // start crossfade
1732− }
1733− }
1734−
1735− readindex = refindex - readlag;
1736− outputsample = read_sample(w, readindex);
1737−
1738− if(xfadevalue > 0)
1739− {
1740− outputsample *= (1 - xfadevalue);
1741− outputsample += read_sample(w, readindex - jump) * xfadevalue;
1742− xfadevalue -= xfadestep;
1743− }
1744−
1745− *out++ = outputsample;
1746− refindex += 1;
1747− readlag -= readlagstep;
1748− }
1749−
1750− w->readlag = readlag; // state variables
1751− w->jump = jump;
1752− w->xfadelength = xfadelength;
1753− w->xfadevalue = xfadevalue;
1754−}
1755−
1756−// read one sample from delay buffer, with linear interpolation
1757−static inline float read_sample(tSOLAD* const w, float floatindex)
1758−{
1759− int index = (int)floatindex;
1760− float fraction = floatindex - (float)index;
1761− float *buf = w->delaybuf;
1762− index &= LOOPMASK;
1763−
1764− return (buf[index] + (fraction * (buf[index+1] - buf[index])));
1765−}
1766−
1767−static void solad_init(tSOLAD* const w)
1768−{
1769− w->timeindex = 0;
1770− w->xfadevalue = -1;
1771− w->period = INITPERIOD;
1772− w->readlag = INITPERIOD;
1773− w->blocksize = INITPERIOD;
1774−}
1775−
1776−/******************************************************************************/
1777−/***************************** private procedures *****************************/
1778−/******************************************************************************/
1779−
1780−#define REALFFT mayer_realfft
1781−#define REALIFFT mayer_realifft
1782−
1783−static void snac_analyzeframe(tSNAC* const s);
1784−static void snac_autocorrelation(tSNAC* const s);
1785−static void snac_normalize(tSNAC* const s);
1786−static void snac_pickpeak(tSNAC* const s);
1787−static void snac_periodandfidelity(tSNAC* const s);
1788−static void snac_biasbuf(tSNAC* const s);
1789−static float snac_spectralpeak(tSNAC* const s, float periodlength);
1790−
1791−
1792−/******************************************************************************/
1793−/******************************** constructor, destructor *********************/
1794−/******************************************************************************/
1795−
1796−
1797−void tSNAC_init(tSNAC* const s, int overlaparg)
1798−{
1799− s->biasfactor = DEFBIAS;
1800− s->timeindex = 0;
1801− s->periodindex = 0;
1802− s->periodlength = 0.;
1803− s->fidelity = 0.;
1804− s->minrms = DEFMINRMS;
1805− s->framesize = SNAC_FRAME_SIZE;
1806−
1807− s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
1808− s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2));
1809− s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2));
1810− s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
1811−
1812− snac_biasbuf(s);
1813− tSNAC_setOverlap(s, overlaparg);
1814−}
1815−
1816−void tSNAC_free(tSNAC* const s)
1817−{
1818− leaf_free(s->inputbuf);
1819− leaf_free(s->processbuf);
1820− leaf_free(s->spectrumbuf);
1821− leaf_free(s->biasbuf);
1822−}
1823−/******************************************************************************/
1824−/************************** public access functions****************************/
1825−/******************************************************************************/
1826−
1827−
1828−void tSNAC_ioSamples(tSNAC* const s, float *in, float *out, int size)
1829−{
1830− int timeindex = s->timeindex;
1831− int mask = s->framesize - 1;
1832− int outindex = 0;
1833− float *inputbuf = s->inputbuf;
1834− float *processbuf = s->processbuf;
1835−
1836− // call analysis function when it is time
1837− if(!(timeindex & (s->framesize / s->overlap - 1))) snac_analyzeframe(s);
1838−
1839− while(size--)
1840− {
1841− inputbuf[timeindex] = *in++;
1842− out[outindex++] = processbuf[timeindex++];
1843− timeindex &= mask;
1844− }
1845− s->timeindex = timeindex;
1846−}
1847−
1848−void tSNAC_setOverlap(tSNAC* const s, int lap)
1849−{
1850− if(!((lap==1)|(lap==2)|(lap==4)|(lap==8))) lap = DEFOVERLAP;
1851− s->overlap = lap;
1852−}
1853−
1854−
1855−void tSNAC_setBias(tSNAC* const s, float bias)
1856−{
1857− if(bias > 1.) bias = 1.;
1858− if(bias < 0.) bias = 0.;
1859− s->biasfactor = bias;
1860− snac_biasbuf(s);
1861− return;
1862−}
1863−
1864−
1865−void tSNAC_setMinRMS(tSNAC* const s, float rms)
1866−{
1867− if(rms > 1.) rms = 1.;
1868− if(rms < 0.) rms = 0.;
1869− s->minrms = rms;
1870− return;
1871−}
1872−
1873−
1874−float tSNAC_getPeriod(tSNAC* const s)
1875−{
1876− return(s->periodlength);
1877−}
1878−
1879−
1880−float tSNAC_getFidelity(tSNAC* const s)
1881−{
1882− return(s->fidelity);
1883−}
1884−
1885−
1886−/******************************************************************************/
1887−/***************************** private procedures *****************************/
1888−/******************************************************************************/
1889−
1890−
1891−// main analysis function
1892−static void snac_analyzeframe(tSNAC* const s)
1893−{
1894− int n, tindex = s->timeindex;
1895− int framesize = s->framesize;
1896− int mask = framesize - 1;
1897− float norm = 1. / sqrt((float)(framesize * 2));
1898−
1899− float *inputbuf = s->inputbuf;
1900− float *processbuf = s->processbuf;
1901−
1902− // copy input to processing buffers
1903− for(n=0; n<framesize; n++)
1904− {
1905− processbuf[n] = inputbuf[tindex] * norm;
1906− tindex++;
1907− tindex &= mask;
1908− }
1909−
1910− // zeropadding
1911− for(n=framesize; n<(framesize<<1); n++) processbuf[n] = 0.;
1912−
1913− // call analysis procedures
1914− snac_autocorrelation(s);
1915− snac_normalize(s);
1916− snac_pickpeak(s);
1917− snac_periodandfidelity(s);
1918−}
1919−
1920−
1921−static void snac_autocorrelation(tSNAC* const s)
1922−{
1923− int n, m;
1924− int framesize = s->framesize;
1925− int fftsize = framesize * 2;
1926− float *processbuf = s->processbuf;
1927− float *spectrumbuf = s->spectrumbuf;
1928−
1929− REALFFT(fftsize, processbuf);
1930−
1931− // compute power spectrum
1932− processbuf[0] *= processbuf[0]; // DC
1933− processbuf[framesize] *= processbuf[framesize]; // Nyquist
1934−
1935− for(n=1; n<framesize; n++)
1936− {
1937− processbuf[n] = processbuf[n] * processbuf[n]
1938− + processbuf[fftsize-n] * processbuf[fftsize-n]; // imag coefficients appear reversed
1939− processbuf[fftsize-n] = 0.;
1940− }
1941−
1942− // store power spectrum up to SR/4 for possible later use
1943− for(m=0; m<(framesize>>1); m++)
1944− {
1945− spectrumbuf[m] = processbuf[m];
1946− }
1947−
1948− // transform power spectrum to autocorrelation function
1949− REALIFFT(fftsize, processbuf);
1950− return;
1951−}
1952−
1953−
1954−static void snac_normalize(tSNAC* const s)
1955−{
1956− int framesize = s->framesize;
1957− int framesizeplustimeindex = s->framesize + s->timeindex;
1958− int timeindexminusone = s->timeindex - 1;
1959− int n, m;
1960− int mask = framesize - 1;
1961− int seek = framesize * SEEK;
1962− float *inputbuf = s->inputbuf;
1963− float *processbuf= s->processbuf;
1964− float signal1, signal2;
1965−
1966− // minimum RMS implemented as minimum autocorrelation at index 0
1967− // functionally equivalent to white noise floor
1968− float rms = s->minrms / sqrt(1.0f / (float)framesize);
1969− float minrzero = rms * rms;
1970− float rzero = processbuf[0];
1971− if(rzero < minrzero) rzero = minrzero;
1972− double normintegral = (double)rzero * 2.;
1973−
1974− // normalize biased autocorrelation function
1975− // inputbuf is circular buffer: timeindex may be non-zero when overlap > 1
1976− processbuf[0] = 1;
1977− for(n=1, m=s->timeindex+1; n<seek; n++, m++)
1978− {
1979− signal1 = inputbuf[(n + timeindexminusone)&mask];
1980− signal2 = inputbuf[(framesizeplustimeindex - n)&mask];
1981− normintegral -= (double)(signal1 * signal1 + signal2 * signal2);
1982− processbuf[n] /= (float)normintegral * 0.5f;
1983− }
1984−
1985− // flush instable function tail
1986− for(n = seek; n<framesize; n++) processbuf[n] = 0.;
1987− return;
1988−}
1989−
1990−
1991−static void snac_periodandfidelity(tSNAC* const s)
1992−{
1993− float periodlength;
1994−
1995− if(s->periodindex)
1996− {
1997− periodlength = (float)s->periodindex +
1998− interpolate3phase(s->processbuf, s->periodindex);
1999− if(periodlength < 8) periodlength = snac_spectralpeak(s, periodlength);
2000− s->periodlength = periodlength;
2001− s->fidelity = interpolate3max(s->processbuf, s->periodindex);
2002− }
2003− return;
2004−}
2005−
2006−// select the peak which most probably represents period length
2007−static void snac_pickpeak(tSNAC* const s)
2008−{
2009− int n, peakindex=0;
2010− int seek = s->framesize * SEEK;
2011− float *processbuf= s->processbuf;
2012− float maxvalue = 0.;
2013− float biasedpeak;
2014− float *biasbuf = s->biasbuf;
2015−
2016− // skip main lobe
2017− for(n=1; n<seek; n++)
2018− {
2019− if(processbuf[n] < 0.) break;
2020− }
2021−
2022− // find interpolated / biased maximum in SNAC function
2023− // interpolation finds the 'real maximum'
2024− // biasing favours the first candidate
2025− for(; n<seek-1; n++)
2026− {
2027− if(processbuf[n] >= processbuf[n-1])
2028− {
2029− if(processbuf[n] > processbuf[n+1]) // we have a local peak
2030− {
2031− biasedpeak = interpolate3max(processbuf, n) * biasbuf[n];
2032−
2033− if(biasedpeak > maxvalue)
2034− {
2035− maxvalue = biasedpeak;
2036− peakindex = n;
2037− }
2038− }
2039− }
2040− }
2041− s->periodindex = peakindex;
2042− return;
2043−}
2044−
2045−
2046−// verify period length via frequency domain (up till SR/4)
2047−// frequency domain is more precise than lag domain for period lengths < 8
2048−// argument 'periodlength' is initial estimation from autocorrelation
2049−static float snac_spectralpeak(tSNAC* const s, float periodlength)
2050−{
2051− if(periodlength < 4.) return periodlength;
2052−
2053− float max = 0.;
2054− int n, startbin, stopbin, peakbin = 0;
2055− int spectrumsize = s->framesize>>1;
2056− float *spectrumbuf = s->spectrumbuf;
2057− float peaklocation = (float)(s->framesize * 2.) / periodlength;
2058−
2059− startbin = (int)(peaklocation * 0.8 + 0.5);
2060− if(startbin < 1) startbin = 1;
2061− stopbin = (int)(peaklocation * 1.25 + 0.5);
2062− if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;
2063−
2064− for(n=startbin; n<stopbin; n++)
2065− {
2066− if(spectrumbuf[n] >= spectrumbuf[n-1])
2067− {
2068− if(spectrumbuf[n] > spectrumbuf[n+1])
2069− {
2070− if(spectrumbuf[n] > max)
2071− {
2072− max = spectrumbuf[n];
2073− peakbin = n;
2074− }
2075− }
2076− }
2077− }
2078−
2079− // calculate amplitudes in peak region
2080− for(n=(peakbin-1); n<(peakbin+2); n++)
2081− {
2082− spectrumbuf[n] = sqrt(spectrumbuf[n]);
2083− }
2084−
2085− peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);
2086− periodlength = (float)(s->framesize * 2.0f) / peaklocation;
2087−
2088− return periodlength;
2089−}
2090−
2091−
2092−// modified logarithmic bias function
2093−static void snac_biasbuf(tSNAC* const s)
2094−{
2095− int n;
2096− int maxperiod = (int)(s->framesize * (float)SEEK);
2097− float bias = s->biasfactor / log((float)(maxperiod - 4));
2098− float *biasbuf = s->biasbuf;
2099−
2100− for(n=0; n<5; n++) // periods < 5 samples can't be tracked
2101− {
2102− biasbuf[n] = 0.;
2103− }
2104−
2105− for(n=5; n<maxperiod; n++)
2106− {
2107− biasbuf[n] = 1.0f - (float)log(n - 4) * bias;
2108− }
2109−}
2110−
2111−/********Private function prototypes**********/
2112−static void atkdtk_init(tAtkDtk* const a, int blocksize, int atk, int rel);
2113−static void atkdtk_envelope(tAtkDtk* const a, float *in);
2114−
2115−/********Constructor/Destructor***************/
2116−
2117−void tAtkDtk_init(tAtkDtk* const a, int blocksize)
2118−{
2119− atkdtk_init(a, blocksize, DEFATTACK, DEFRELEASE);
2120−}
2121−
2122−void tAtkDtk_init_expanded(tAtkDtk* const a, int blocksize, int atk, int rel)
2123−{
2124− atkdtk_init(a, blocksize, atk, rel);
2125−}
2126−
2127−void tAtkDtk_free(tAtkDtk *a)
2128−{
2129−
2130−}
2131−
2132−/*******Public Functions***********/
2133−
2134−
2135−void tAtkDtk_setBlocksize(tAtkDtk* const a, int size)
2136−{
2137−
2138− if(!((size==64)|(size==128)|(size==256)|(size==512)|(size==1024)|(size==2048)))
2139− size = DEFBLOCKSIZE;
2140− a->blocksize = size;
2141−
2142− return;
2143−
2144−}
2145−
2146−void tAtkDtk_setSamplerate(tAtkDtk* const a, int inRate)
2147−{
2148− a->samplerate = inRate;
2149−
2150− //Reset atk and rel to recalculate coeff
2151− tAtkDtk_setAtk(a, a->atk);
2152− tAtkDtk_setRel(a, a->rel);
2153−
2154− return;
2155−}
2156−
2157−void tAtkDtk_setThreshold(tAtkDtk* const a, float thres)
2158−{
2159− a->threshold = thres;
2160− return;
2161−}
2162−
2163−void tAtkDtk_setAtk(tAtkDtk* const a, int inAtk)
2164−{
2165− a->atk = inAtk;
2166− a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));
2167−
2168− return;
2169−}
2170−
2171−void tAtkDtk_setRel(tAtkDtk* const a, int inRel)
2172−{
2173− a->rel = inRel;
2174− a->rel_coeff = pow(0.01, 1.0/(a->rel * a->samplerate * 0.001));
2175−
2176− return;
2177−}
2178−
2179−
2180−int tAtkDtk_detect(tAtkDtk* const a, float *in)
2181−{
2182− int result;
2183−
2184− atkdtk_envelope(a, in);
2185−
2186− if(a->env >= a->prevAmp*2) //2 times greater = 6dB increase
2187− result = 1;
2188− else
2189− result = 0;
2190−
2191− a->prevAmp = a->env;
2192−
2193− return result;
2194−
2195−}
2196−
2197−/*******Private Functions**********/
2198−
2199−static void atkdtk_init(tAtkDtk* const a, int blocksize, int atk, int rel)
2200−{
2201− a->env = 0;
2202− a->blocksize = blocksize;
2203− a->threshold = DEFTHRESHOLD;
2204− a->samplerate = leaf.sampleRate;
2205− a->prevAmp = 0;
2206−
2207− a->env = 0;
2208−
2209− tAtkDtk_setAtk(a, atk);
2210− tAtkDtk_setRel(a, rel);
2211−}
2212−
2213−static void atkdtk_envelope(tAtkDtk* const a, float *in)
2214−{
2215− int i = 0;
2216− float tmp;
2217− for(i = 0; i < a->blocksize; ++i){
2218− tmp = fastabs(in[i]);
2219−
2220− if(tmp > a->env)
2221− a->env = a->atk_coeff * (a->env - tmp) + tmp;
2222− else
2223− a->env = a->rel_coeff * (a->env - tmp) + tmp;
2224− }
2225−
2226−}
2227−
LEAF/Src/leaf-vocoder.c+0−400
@@ -1,400 +0,0 @@
1−/*==============================================================================
2−
3− leaf-vocoder.c
4− Created: 20 Jan 2017 12:01:54pm
5− Author: Michael R Mulshine
6−
7−==============================================================================*/
8−
9−#if _WIN32 || _WIN64
10−
11−#include "..\Inc\leaf-vocoder.h"
12−#include "..\leaf.h"
13−
14−#else
15−
16−#include "../Inc/leaf-vocoder.h"
17−#include "../leaf.h"
18−
19−#endif
20−
21−
22−
23−/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
24− *
25− *
26− *
27− * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
28−
29−void tTalkbox_init(tTalkbox* const v, int bufsize)
30−{
31− v->param[0] = 0.5f; //wet
32− v->param[1] = 0.0f; //dry
33− v->param[2] = 0; // Swap
34− v->param[3] = 1.0f; //quality
35−
36− v->bufsize = bufsize;
37−
38− v->car0 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
39− v->car1 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
40− v->window = (float*) leaf_alloc(sizeof(float) * v->bufsize);
41− v->buf0 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
42− v->buf1 = (float*) leaf_alloc(sizeof(float) * v->bufsize);
43−
44− tTalkbox_update(v);
45−}
46−
47−void tTalkbox_free(tTalkbox* const v)
48−{
49− leaf_free(v->car0);
50− leaf_free(v->car1);
51− leaf_free(v->window);
52− leaf_free(v->buf0);
53− leaf_free(v->buf1);
54−}
55−
56−void tTalkbox_update(tTalkbox* const v) ///update internal parameters...
57−{
58− float fs = leaf.sampleRate;
59− if(fs < 8000.0f) fs = 8000.0f;
60− if(fs > 96000.0f) fs = 96000.0f;
61−
62− int32_t n = (int32_t)(0.01633f * fs);
63− if(n > v->bufsize) n = v->bufsize;
64−
65− //O = (VstInt32)(0.0005f * fs);
66− v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs);
67−
68− if(n != v->N) //recalc hanning window
69− {
70− v->N = n;
71− float dp = TWO_PI / v->N;
72− float p = 0.0f;
73− for(n=0; n<v->N; n++)
74− {
75− v->window[n] = 0.5f - 0.5f * cosf(p);
76− p += dp;
77− }
78− }
79− v->wet = 0.5f * v->param[0] * v->param[0];
80− v->dry = 2.0f * v->param[1] * v->param[1];
81−}
82−
83−void tTalkbox_suspend(tTalkbox* const v) ///clear any buffers...
84−{
85− v->pos = v->K = 0;
86− v->emphasis = 0.0f;
87− v->FX = 0;
88−
89− v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f;
90− v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f;
91−
92− for (int32_t i = 0; i < v->bufsize; i++)
93− {
94− v->buf0[i] = 0;
95− v->buf1[i] = 0;
96− v->car0[i] = 0;
97− v->car1[i] = 0;
98− }
99−}
100−
101−
102−#define ORD_MAX 100 // Was 50. Increasing this gets rid of glitchiness, lowering it breaks it; not sure how it affects performance
103−void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o)
104−{
105− float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;
106− int32_t i, j, nn=n;
107−
108− for(j=0; j<=o; j++, nn--) //buf[] is already emphasized and windowed
109− {
110− z[j] = r[j] = 0.0f;
111− for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
112− }
113− r[0] *= 1.001f; //stability fix
114−
115− float min = 0.00001f;
116− if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; }
117−
118− tTalkbox_lpcDurbin(r, o, k, &G); //calc reflection coeffs
119−
120− for(i=0; i<=o; i++)
121− {
122− if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;
123− }
124−
125− for(i=0; i<n; i++)
126− {
127− x = G * car[i];
128− for(j=o; j>0; j--) //lattice filter
129− {
130− x -= k[j] * z[j-1];
131− z[j] = z[j-1] + k[j] * x;
132− }
133− buf[i] = z[0] = x; //output buf[] will be windowed elsewhere
134− }
135−}
136−
137−
138−void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
139−{
140− int i, j;
141− float a[ORD_MAX], at[ORD_MAX], e=r[0];
142−
143− for(i=0; i<=p; i++) a[i] = at[i] = 0.0f; //probably don't need to clear at[] or k[]
144−
145− for(i=1; i<=p; i++)
146− {
147− k[i] = -r[i];
148−
149− for(j=1; j<i; j++)
150− {
151− at[j] = a[j];
152− k[i] -= a[j] * r[i-j];
153− }
154− if(fabs(e) < 1.0e-20f) { e = 0.0f; break; }
155− k[i] /= e; // This might be costing us
156−
157− a[i] = k[i];
158− for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
159−
160− e *= 1.0f - k[i] * k[i];
161− }
162−
163− if(e < 1.0e-20f) e = 0.0f;
164− *g = sqrtf(e);
165−}
166−
167−float tTalkbox_tick(tTalkbox* const v, float synth, float voice)
168−{
169−
170− int32_t p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
171− float e=v->emphasis, w, o, x, dr, fx=v->FX;
172− float p, q, h0=0.3f, h1=0.77f;
173−
174− o = voice;
175− x = synth;
176−
177− dr = o;
178−
179− p = v->d0 + h0 * x; v->d0 = v->d1; v->d1 = x - h0 * p;
180− q = v->d2 + h1 * v->d4; v->d2 = v->d3; v->d3 = v->d4 - h1 * q;
181− v->d4 = x;
182− x = p + q;
183−
184− if(v->K++)
185− {
186− v->K = 0;
187−
188− v->car0[p0] = v->car1[p1] = x; //carrier input
189−
190− x = o - e; e = o; //6dB/oct pre-emphasis
191−
192− w = v->window[p0]; fx = v->buf0[p0] * w; v->buf0[p0] = x * w; //50% overlapping hanning windows
193− if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O); p0 = 0; }
194−
195− w = 1.0f - w; fx += v->buf1[p1] * w; v->buf1[p1] = x * w;
196− if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O); p1 = 0; }
197− }
198−
199− p = v->u0 + h0 * fx; v->u0 = v->u1; v->u1 = fx - h0 * p;
200− q = v->u2 + h1 * v->u4; v->u2 = v->u3; v->u3 = v->u4 - h1 * q;
201− v->u4 = fx;
202− x = p + q;
203−
204− o = x;
205−
206− v->emphasis = e;
207− v->pos = p0;
208− v->FX = fx;
209−
210− float den = 1.0e-10f; //(float)pow(10.0f, -10.0f * param[4]);
211− if(fabs(v->d0) < den) v->d0 = 0.0f; //anti-denormal (doesn't seem necessary but P4?)
212− if(fabs(v->d1) < den) v->d1 = 0.0f;
213− if(fabs(v->d2) < den) v->d2 = 0.0f;
214− if(fabs(v->d3) < den) v->d3 = 0.0f;
215− if(fabs(v->u0) < den) v->u0 = 0.0f;
216− if(fabs(v->u1) < den) v->u1 = 0.0f;
217− if(fabs(v->u2) < den) v->u2 = 0.0f;
218− if(fabs(v->u3) < den) v->u3 = 0.0f;
219− return o;
220−}
221−
222−void tTalkbox_setQuality(tTalkbox* const v, float quality)
223−{
224− v->param[3] = quality;
225− v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
226−}
227−
228−void tVocoder_init (tVocoder* const v)
229−{
230− v->param[0] = 0.33f; //input select
231− v->param[1] = 0.50f; //output dB
232− v->param[2] = 0.40f; //hi thru
233− v->param[3] = 0.40f; //hi band
234− v->param[4] = 0.16f; //envelope
235− v->param[5] = 0.55f; //filter q
236− v->param[6] = 0.6667f;//freq range
237− v->param[7] = 0.33f; //num bands
238−
239− tVocoder_update(v);
240−}
241−
242−void tVocoder_free (tVocoder* const v)
243−{
244−
245−}
246−
247−void tVocoder_update (tVocoder* const v)
248−{
249− float tpofs = 6.2831853f * leaf.invSampleRate;
250−
251− float rr, th, re;
252−
253− float sh;
254−
255− int32_t i;
256−
257− v->gain = (float)pow(10.0f, 2.0f * v->param[1] - 3.0f * v->param[5] - 2.0f);
258−
259− v->thru = (float)pow(10.0f, 0.5f + 2.0f * v->param[1]);
260− v->high = v->param[3] * v->param[3] * v->param[3] * v->thru;
261− v->thru *= v->param[2] * v->param[2] * v->param[2];
262−
263− if(v->param[7]<0.5f)
264− {
265− v->nbnd=8;
266− re=0.003f;
267− v->f[1][2] = 3000.0f;
268− v->f[2][2] = 2200.0f;
269− v->f[3][2] = 1500.0f;
270− v->f[4][2] = 1080.0f;
271− v->f[5][2] = 700.0f;
272− v->f[6][2] = 390.0f;
273− v->f[7][2] = 190.0f;
274− }
275− else
276− {
277− v->nbnd=16;
278− re=0.0015f;
279− v->f[ 1][2] = 5000.0f; //+1000
280− v->f[ 2][2] = 4000.0f; //+750
281− v->f[ 3][2] = 3250.0f; //+500
282− v->f[ 4][2] = 2750.0f; //+450
283− v->f[ 5][2] = 2300.0f; //+300
284− v->f[ 6][2] = 2000.0f; //+250
285− v->f[ 7][2] = 1750.0f; //+250
286− v->f[ 8][2] = 1500.0f; //+250
287− v->f[ 9][2] = 1250.0f; //+250
288− v->f[10][2] = 1000.0f; //+250
289− v->f[11][2] = 750.0f; //+210
290− v->f[12][2] = 540.0f; //+190
291− v->f[13][2] = 350.0f; //+155
292− v->f[14][2] = 195.0f; //+100
293− v->f[15][2] = 95.0f;
294− }
295−
296− if(v->param[4]<0.05f) //freeze
297− {
298− for(i=0;i<v->nbnd;i++) v->f[i][12]=0.0f;
299− }
300− else
301− {
302− v->f[0][12] = (float)pow(10.0, -1.7 - 2.7f * v->param[4]); //envelope speed
303−
304− rr = 0.022f / (float)v->nbnd; //minimum proportional to frequency to stop distortion
305− for(i=1;i<v->nbnd;i++)
306− {
307− v->f[i][12] = (float)(0.025 - rr * (double)i);
308− if(v->f[0][12] < v->f[i][12]) v->f[i][12] = v->f[0][12];
309− }
310− v->f[0][12] = 0.5f * v->f[0][12]; //only top band is at full rate
311− }
312−
313− rr = 1.0 - pow(10.0f, -1.0f - 1.2f * v->param[5]);
314− sh = (float)pow(2.0f, 3.0f * v->param[6] - 1.0f); //filter bank range shift
315−
316− for(i=1;i<v->nbnd;i++)
317− {
318− v->f[i][2] *= sh;
319− th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
320− v->f[i][0] = (float)(2.0 * rr * cos(th)); //a0
321− v->f[i][1] = (float)(-rr * rr); //a1
322− //was .98
323− v->f[i][2] *= 0.96f; //shift 2nd stage slightly to stop high resonance peaks
324− th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
325− v->f[i][2] = (float)(2.0 * rr * cos(th));
326− }
327−}
328−
329−float tVocoder_tick (tVocoder* const v, float synth, float voice)
330−{
331− float a, b, o=0.0f, aa, bb, oo = v->kout, g = v->gain, ht = v->thru, hh = v->high, tmp;
332− uint32_t i, k = v->kval, nb = v->nbnd;
333−
334− a = voice; //speech
335− b = synth; //synth
336−
337− tmp = a - v->f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis
338− v->f[0][7] = a;
339− a = tmp;
340−
341− if(tmp<0.0f) tmp = -tmp;
342− v->f[0][11] -= v->f[0][12] * (v->f[0][11] - tmp); //high band envelope
343− o = v->f[0][11] * (ht * a + hh * (b - v->f[0][3])); //high band + high thru
344−
345− v->f[0][3] = b; //integrate carrier for HF band
346−
347− if(++k & 0x1) //this block runs at half sample rate
348− {
349− oo = 0.0f;
350− aa = a + v->f[0][9] - v->f[0][8] - v->f[0][8]; //apply zeros here instead of in each reson
351− v->f[0][9] = v->f[0][8]; v->f[0][8] = a;
352− bb = b + v->f[0][5] - v->f[0][4] - v->f[0][4];
353− v->f[0][5] = v->f[0][4]; v->f[0][4] = b;
354−
355− for(i=1; i<nb; i++) //filter bank: 4th-order band pass
356− {
357− tmp = v->f[i][0] * v->f[i][3] + v->f[i][1] * v->f[i][4] + bb;
358− v->f[i][4] = v->f[i][3];
359− v->f[i][3] = tmp;
360− tmp += v->f[i][2] * v->f[i][5] + v->f[i][1] * v->f[i][6];
361− v->f[i][6] = v->f[i][5];
362− v->f[i][5] = tmp;
363−
364− tmp = v->f[i][0] * v->f[i][7] + v->f[i][1] * v->f[i][8] + aa;
365− v->f[i][8] = v->f[i][7];
366− v->f[i][7] = tmp;
367− tmp += v->f[i][2] * v->f[i][9] + v->f[i][1] * v->f[i][10];
368− v->f[i][10] = v->f[i][9];
369− v->f[i][9] = tmp;
370−
371− if(tmp<0.0f) tmp = -tmp;
372− v->f[i][11] -= v->f[i][12] * (v->f[i][11] - tmp);
373− oo += v->f[i][5] * v->f[i][11];
374− }
375− }
376− o += oo * g; //effect of interpolating back up to Fs would be minimal (aliasing >16kHz)
377−
378− v->kout = oo;
379− v->kval = k & 0x1;
380− if(fabs(v->f[0][11])<1.0e-10) v->f[0][11] = 0.0f; //catch HF envelope denormal
381−
382− for(i=1;i<nb;i++)
383− if(fabs(v->f[i][3])<1.0e-10 || fabs(v->f[i][7])<1.0e-10)
384− for(k=3; k<12; k++) v->f[i][k] = 0.0f; //catch reson & envelope denormals
385−
386− if(fabs(o)>10.0f) tVocoder_suspend(v); //catch instability
387−
388− return o;
389−
390−}
391−
392−void tVocoder_suspend (tVocoder* const v)
393−{
394− int32_t i, j;
395−
396− for(i=0; i<v->nbnd; i++) for(j=3; j<12; j++) v->f[i][j] = 0.0f; //zero band filters and envelopes
397− v->kout = 0.0f;
398− v->kval = 0;
399−}
400−
LEAF/Src/leaf-wavefolder.c+0−114
@@ -1,114 +0,0 @@
1−/*==============================================================================
2−
3− leaf-wavefolder.c
4− Created: 30 Nov 2018 11:56:49am
5− Author: airship
6−
7−==============================================================================*/
8−
9−#if _WIN32 || _WIN64
10−
11−#include "..\Inc\leaf-wavefolder.h"
12−
13−#else
14−
15−#include "../Inc/leaf-wavefolder.h"
16−
17−#endif
18−
19−void tLockhartWavefolder_init(tLockhartWavefolder* const w)
20−{
21− w->Ln1 = 0.0;
22− w->Fn1 = 0.0;
23− w->xn1 = 0.0f;
24−}
25−
26−void tLockhardWavefolder_free(tLockhartWavefolder* const w)
27−{
28−
29−}
30−
31−double tLockhartWavefolderLambert(double x, double ln)
32−{
33− double thresh, w, expw, p, r, s, err;
34− // Error threshold
35− thresh = 10e-6;
36− // Initial guess (use previous value)
37− w = ln;
38−
39− // Haley's method (Sec. 4.2 of the paper)
40− for(int i=0; i<100; i+=1) {
41−
42− expw = exp(w);
43−
44− p = w*expw - x;
45− r = (w+1.0)*expw;
46− s = (w+2.0)/(2.0*(w+1.0)); err = (p/(r-(p*s)));
47−
48− if (fabs(err)<thresh) {
49− break;
50− }
51− if (isnan(err))
52− {
53− break;
54− }
55−
56− w = w - err;
57− }
58− return w;
59−}
60−
61−float tLockhartWavefolder_tick(tLockhartWavefolder* const w, float samp)
62−{
63−
64− float out = 0.0f;
65− // Constants
66− double RL = 7.5e3;
67− double R = 15e3;
68− double VT = 26e-3;
69− double Is = 10e-16;
70−
71− double a = 2.0*RL/R;
72− double b = (R+2.0*RL)/(VT*R);
73− double d = (RL*Is)/VT;
74−
75− // Antialiasing error threshold
76− double thresh = 10e-10;
77−
78− // Compute Antiderivative
79− int l = (samp > 0) - (samp < 0);
80− double u = d*exp(l*b*samp);
81− double Ln = tLockhartWavefolderLambert(u,w->Ln1);
82− double Fn = (0.5*VT/b)*(Ln*(Ln + 2.0)) - 0.5*a*samp*samp;
83−
84− // Check for ill-conditioning
85− if (fabs(samp-w->xn1)<thresh) {
86−
87− // Compute Averaged Wavefolder Output
88− double xn = 0.5*(samp+w->xn1);
89− u = d*exp(l*b*xn);
90− Ln = tLockhartWavefolderLambert(u,w->Ln1);
91− out = (float) (l*VT*Ln - a*xn);
92− if (isnan(out))
93− {
94− ;
95− }
96−
97− }
98− else {
99−
100− // Apply AA Form
101− out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
102− if (isnan(out))
103− {
104− ;
105− }
106− }
107−
108− // Update States
109− w->Ln1 = Ln;
110− w->Fn1 = Fn;
111− w->xn1 = samp;
112−
113− return out;
114−}
LEAF/leaf.h+24−27
@@ -22,45 +22,42 @@ · 21 unmodified lines
2222 #include ".\Inc\leaf-global.h"
2323 #include ".\Inc\leaf-math.h"
2424 #include ".\Inc\leaf-mempool.h"
25−#include ".\Inc\leaf-utilities.h"
25+#include ".\Inc\leaf-tables.h"
26+#include ".\Inc\leaf-tables.h"
27+#include ".\Inc\leaf-oscillators.h"
28+#include ".\Inc\leaf-filters.h"
2629 #include ".\Inc\leaf-delay.h"
27−#include ".\Inc\leaf-filter.h"
28−#include ".\Inc\leaf-oscillator.h"
29−#include ".\Inc\leaf-oversampler.h"
3030 #include ".\Inc\leaf-reverb.h"
31−#include ".\Inc\leaf-vocoder.h"
32−#include ".\Inc\leaf-808.h"
33−#include ".\Inc\leaf-string.h"
34−#include ".\Inc\leaf-pitch.h"
35−#include ".\Inc\leaf-formant.h"
31+#include ".\Inc\leaf-effects.h"
32+#include ".\Inc\leaf-envelopes.h"
33+#include ".\Inc\leaf-dynamics.h"
34+#include ".\Inc\leaf-analysis.h"
35+#include ".\Inc\leaf-instruments.h"
3636 #include ".\Inc\leaf-midi.h"
37−#include ".\Inc\leaf-sample.h"
38−#include ".\Inc\leaf-crusher.h"
39−#include ".\Inc\leaf-wavefolder.h"
40−#include ".\Inc\leaf-tables.h"
37+#include ".\Inc\leaf-sampling.h"
38+#include ".\Inc\leaf-physical.h"
39+#include ".\Inc\leaf-electrical.h"
4140
4241 #else
4342
4443 #include "./Inc/leaf-global.h"
4544 #include "./Inc/leaf-math.h"
4645 #include "./Inc/leaf-mempool.h"
47−#include "./Inc/leaf-utilities.h"
46+#include "./Inc/leaf-tables.h"
47+#include "./Inc/leaf-tables.h"
48+#include "./Inc/leaf-oscillators.h"
49+#include "./Inc/leaf-filters.h"
4850 #include "./Inc/leaf-delay.h"
49−#include "./Inc/leaf-filter.h"
50−#include "./Inc/leaf-oscillator.h"
51−#include "./Inc/leaf-oversampler.h"
5251 #include "./Inc/leaf-reverb.h"
53−#include "./Inc/leaf-vocoder.h"
54−#include "./Inc/leaf-808.h"
55−#include "./Inc/leaf-string.h"
56−#include "./Inc/leaf-pitch.h"
57−#include "./Inc/leaf-formant.h"
52+#include "./Inc/leaf-effects.h"
53+#include "./Inc/leaf-envelopes.h"
54+#include "./Inc/leaf-dynamics.h"
55+#include "./Inc/leaf-analysis.h"
56+#include "./Inc/leaf-instruments.h"
5857 #include "./Inc/leaf-midi.h"
59−#include "./Inc/leaf-sample.h"
60−#include "./Inc/leaf-crusher.h"
61−#include "./Inc/leaf-wavefolder.h"
62−#include "./Inc/leaf-tables.h"
63−#include "./Inc/leaf-WDF.h"
58+#include "./Inc/leaf-sampling.h"
59+#include "./Inc/leaf-physical.h"
60+#include "./Inc/leaf-electrical.h"
6461
6562 #endif
6663
LEAF_JUCEPlugin/LEAF.jucer+38−40
@@ -26,53 +26,51 @@ · 25 unmodified lines
2626 <FILE id="IwBoc4" name="leaf-global.h" compile="0" resource="0" file="../LEAF/Inc/leaf-global.h"/>
2727 <FILE id="cmehFw" name="leaf-math.h" compile="0" resource="0" file="../LEAF/Inc/leaf-math.h"/>
2828 <FILE id="XQTGHV" name="leaf-mempool.h" compile="0" resource="0" file="../LEAF/Inc/leaf-mempool.h"/>
29− <FILE id="k0yQ8k" name="leaf-808.h" compile="0" resource="0" file="../LEAF/Inc/leaf-808.h"/>
29+ <FILE id="JvZKsP" name="leaf-tables.h" compile="0" resource="0" file="../LEAF/Inc/leaf-tables.h"/>
30+ <FILE id="ZBcTKF" name="leaf-oscillators.h" compile="0" resource="0"
31+ file="../LEAF/Inc/leaf-oscillators.h"/>
32+ <FILE id="EnRmjE" name="leaf-filters.h" compile="0" resource="0" file="../LEAF/Inc/leaf-filters.h"/>
3033 <FILE id="wn8tAr" name="leaf-delay.h" compile="0" resource="0" file="../LEAF/Inc/leaf-delay.h"/>
31− <FILE id="EnRmjE" name="leaf-filter.h" compile="0" resource="0" file="../LEAF/Inc/leaf-filter.h"/>
32− <FILE id="dWHebV" name="leaf-formant.h" compile="0" resource="0" file="../LEAF/Inc/leaf-formant.h"/>
33− <FILE id="pXe6b5" name="leaf-midi.h" compile="0" resource="0" file="../LEAF/Inc/leaf-midi.h"/>
34− <FILE id="ZBcTKF" name="leaf-oscillator.h" compile="0" resource="0"
35− file="../LEAF/Inc/leaf-oscillator.h"/>
36− <FILE id="LPMRGU" name="leaf-oversampler.h" compile="0" resource="0"
37− file="../LEAF/Inc/leaf-oversampler.h"/>
38− <FILE id="NekKkK" name="leaf-pitch.h" compile="0" resource="0" file="../LEAF/Inc/leaf-pitch.h"/>
3934 <FILE id="XmL4ZE" name="leaf-reverb.h" compile="0" resource="0" file="../LEAF/Inc/leaf-reverb.h"/>
40− <FILE id="KQca5l" name="leaf-string.h" compile="0" resource="0" file="../LEAF/Inc/leaf-string.h"/>
41− <FILE id="OS2D83" name="leaf-utilities.h" compile="0" resource="0"
42− file="../LEAF/Inc/leaf-utilities.h"/>
43− <FILE id="Szb5LP" name="leaf-vocoder.h" compile="0" resource="0" file="../LEAF/Inc/leaf-vocoder.h"/>
44− <FILE id="T6KXi7" name="leaf-sample.h" compile="0" resource="0" file="../LEAF/Inc/leaf-sample.h"/>
45− <FILE id="bpUZCA" name="leaf-crusher.h" compile="0" resource="0" file="../LEAF/Inc/leaf-crusher.h"/>
46− <FILE id="PRkOp2" name="leaf-wavefolder.h" compile="0" resource="0"
47− file="../LEAF/Inc/leaf-wavefolder.h"/>
48− <FILE id="lJdTFA" name="leaf-WDF.h" compile="0" resource="0" file="../LEAF/Inc/leaf-WDF.h"/>
49− <FILE id="JvZKsP" name="leaf-tables.h" compile="0" resource="0" file="../LEAF/Inc/leaf-tables.h"/>
35+ <FILE id="dWHebV" name="leaf-distortion.h" compile="0" resource="0"
36+ file="../LEAF/Inc/leaf-distortion.h"/>
37+ <FILE id="Szb5LP" name="leaf-effects.h" compile="0" resource="0" file="../LEAF/Inc/leaf-effects.h"/>
38+ <FILE id="OS2D83" name="leaf-envelopes.h" compile="0" resource="0"
39+ file="../LEAF/Inc/leaf-envelopes.h"/>
40+ <FILE id="PRkOp2" name="leaf-dynamics.h" compile="0" resource="0" file="../LEAF/Inc/leaf-dynamics.h"/>
41+ <FILE id="LPMRGU" name="leaf-analysis.h" compile="0" resource="0" file="../LEAF/Inc/leaf-analysis.h"/>
42+ <FILE id="k0yQ8k" name="leaf-instruments.h" compile="0" resource="0"
43+ file="../LEAF/Inc/leaf-instruments.h"/>
44+ <FILE id="pXe6b5" name="leaf-midi.h" compile="0" resource="0" file="../LEAF/Inc/leaf-midi.h"/>
45+ <FILE id="T6KXi7" name="leaf-sampling.h" compile="0" resource="0" file="../LEAF/Inc/leaf-sampling.h"/>
46+ <FILE id="KQca5l" name="leaf-physical.h" compile="0" resource="0" file="../LEAF/Inc/leaf-physical.h"/>
47+ <FILE id="lJdTFA" name="leaf-electrical.h" compile="0" resource="0"
48+ file="../LEAF/Inc/leaf-electrical.h"/>
5049 </GROUP>
5150 <GROUP id="{A3AE8C8C-29BA-ADB3-DD7D-EEDC2F7B58F3}" name="Src">
52− <FILE id="HbG7LO" name="leaf-808.c" compile="1" resource="0" file="../LEAF/Src/leaf-808.c"/>
53− <FILE id="lLb7eq" name="leaf-delay.c" compile="1" resource="0" file="../LEAF/Src/leaf-delay.c"/>
54− <FILE id="nh9xAo" name="leaf-filter.c" compile="1" resource="0" file="../LEAF/Src/leaf-filter.c"/>
55− <FILE id="DPGZGc" name="leaf-formant.c" compile="1" resource="0" file="../LEAF/Src/leaf-formant.c"/>
51+ <FILE id="BFkVGu" name="leaf.c" compile="1" resource="0" file="../LEAF/Src/leaf.c"/>
5652 <FILE id="g41P2E" name="leaf-math.c" compile="1" resource="0" file="../LEAF/Src/leaf-math.c"/>
5753 <FILE id="Uc4jO6" name="leaf-mempool.c" compile="1" resource="0" file="../LEAF/Src/leaf-mempool.c"/>
58− <FILE id="LuoIDh" name="leaf-midi.c" compile="1" resource="0" file="../LEAF/Src/leaf-midi.c"/>
59− <FILE id="q5y59A" name="leaf-oscillator.c" compile="1" resource="0"
60− file="../LEAF/Src/leaf-oscillator.c"/>
61− <FILE id="E8JjWS" name="leaf-oversampler.c" compile="1" resource="0"
62− file="../LEAF/Src/leaf-oversampler.c"/>
63− <FILE id="eHUTvP" name="leaf-pitch.c" compile="1" resource="0" file="../LEAF/Src/leaf-pitch.c"/>
64− <FILE id="uyYwEd" name="leaf-reverb.c" compile="1" resource="0" file="../LEAF/Src/leaf-reverb.c"/>
65− <FILE id="dgAVr5" name="leaf-string.c" compile="1" resource="0" file="../LEAF/Src/leaf-string.c"/>
66− <FILE id="uKHzgz" name="leaf-utilities.c" compile="1" resource="0"
67− file="../LEAF/Src/leaf-utilities.c"/>
68− <FILE id="u1aLLR" name="leaf-vocoder.c" compile="1" resource="0" file="../LEAF/Src/leaf-vocoder.c"/>
69− <FILE id="nmtoFJ" name="leaf-sample.c" compile="1" resource="0" file="../LEAF/Src/leaf-sample.c"/>
70− <FILE id="Oymcac" name="leaf-crusher.c" compile="1" resource="0" file="../LEAF/Src/leaf-crusher.c"/>
71− <FILE id="LVoaGm" name="leaf-wavefolder.c" compile="1" resource="0"
72− file="../LEAF/Src/leaf-wavefolder.c"/>
73− <FILE id="Oh72PT" name="leaf-WDF.c" compile="1" resource="0" file="../LEAF/Src/leaf-WDF.c"/>
7454 <FILE id="TxA1Gg" name="leaf-tables.c" compile="1" resource="0" file="../LEAF/Src/leaf-tables.c"/>
75− <FILE id="BFkVGu" name="leaf.c" compile="1" resource="0" file="../LEAF/Src/leaf.c"/>
55+ <FILE id="q5y59A" name="leaf-oscillators.c" compile="1" resource="0"
56+ file="../LEAF/Src/leaf-oscillators.c"/>
57+ <FILE id="nh9xAo" name="leaf-filters.c" compile="1" resource="0" file="../LEAF/Src/leaf-filters.c"/>
58+ <FILE id="lLb7eq" name="leaf-delay.c" compile="1" resource="0" file="../LEAF/Src/leaf-delay.c"/>
59+ <FILE id="uyYwEd" name="leaf-reverb.c" compile="1" resource="0" file="../LEAF/Src/leaf-reverb.c"/>
60+ <FILE id="E8JjWS" name="leaf-distortion.c" compile="1" resource="0"
61+ file="../LEAF/Src/leaf-distortion.c"/>
62+ <FILE id="u1aLLR" name="leaf-effects.c" compile="1" resource="0" file="../LEAF/Src/leaf-effects.c"/>
63+ <FILE id="uKHzgz" name="leaf-envelopes.c" compile="1" resource="0"
64+ file="../LEAF/Src/leaf-envelopes.c"/>
65+ <FILE id="Oymcac" name="leaf-dynamics.c" compile="1" resource="0" file="../LEAF/Src/leaf-dynamics.c"/>
66+ <FILE id="LVoaGm" name="leaf-analysis.c" compile="1" resource="0" file="../LEAF/Src/leaf-analysis.c"/>
67+ <FILE id="HbG7LO" name="leaf-instruments.c" compile="1" resource="0"
68+ file="../LEAF/Src/leaf-instruments.c"/>
69+ <FILE id="LuoIDh" name="leaf-midi.c" compile="1" resource="0" file="../LEAF/Src/leaf-midi.c"/>
70+ <FILE id="nmtoFJ" name="leaf-sampling.c" compile="1" resource="0" file="../LEAF/Src/leaf-sampling.c"/>
71+ <FILE id="dgAVr5" name="leaf-physical.c" compile="1" resource="0" file="../LEAF/Src/leaf-physical.c"/>
72+ <FILE id="Oh72PT" name="leaf-electrical.c" compile="1" resource="0"
73+ file="../LEAF/Src/leaf-electrical.c"/>
7674 </GROUP>
7775 <FILE id="dmljDQ" name="leaf.h" compile="0" resource="0" file="../LEAF/leaf.h"/>
7876 </GROUP>
LEAF_JUCEPlugin/Source/MyTest.cpp+3−1
@@ -37,6 +37,8 @@ void LEAFTest_init (float sampleRate, int blockSize) · 36 unmodified lines
3737 tCycle_init(&sine);
3838 tCycle_setFreq(&sine, 200);
3939 tDelay_init(&delay, 44100, 44100);
40+ tDelay_free(&delay); //most basic free test
41+ tDelay_init(&delay, 44100, 44100);
4042 }
4143
4244 float LEAFTest_tick (float input)
@@ -98,7 +100,7 @@ void leaf_pool_report(void) · 55 unmodified lines
98100 void leaf_pool_dump(void)
99101 {
100102 float* buff = (float*)leaf_pool_get_pool();
101− int siz = leaf_pool_get_size();
103+ unsigned long siz = leaf_pool_get_size();
102104 siz /= sizeof(float);
103105 for (int i = 0; i < siz; i++)
104106 {

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