History

tWavetable; untested

Matthew Wang committed 5 years ago

Commit 32f24271 parent 4317a559 files · +250 −53Browse files

Unified · Split

9 files
  1. Examples/basic-oscillators.c +4 −2
  2. Examples/basic-oscillators.h +1 −1
  3. TestPlugin/LEAF.jucer +1 −1
  4. leaf/Inc/leaf-analysis.h +2 −2
  5. leaf/Inc/leaf-filters.h +9 −5
  6. leaf/Inc/leaf-oscillators.h +68 −5
  7. leaf/Src/leaf-filters.c +42 −36
  8. leaf/Src/leaf-oscillators.c +119 −1
  9. leaf/leaf-config.h +4 −0
Examples/basic-oscillators.c+4−2
@@ -12,9 +12,11 @@ · 11 unmodified lines
1212
1313 void exampleInit()
1414 {
15− LEAF_init(44100, 64, mempool, 1000, &exampleRandom);
15+ LEAF leaf;
1616
17− tCycle_init(&cycle);
17+ LEAF_init(&leaf, 44100, 128, mempool, 1000, &exampleRandom);
18+
19+ tCycle_init(&cycle, &leaf);
1820 tCycle_setFreq(&cycle, 220);
1921 }
2022
Examples/basic-oscillators.h+1−1
@@ -8,7 +8,7 @@ · 7 unmodified lines
88 ==============================================================================
99 */
1010
11−#include "../LEAF/leaf.h"
11+#include "../leaf/leaf.h"
1212
1313 char mempool[1000];
1414 tCycle cycle;
TestPlugin/LEAF.jucer+1−1
@@ -15,7 +15,7 @@ · 14 unmodified lines
1515 jucerFormatVersion="1">
1616 <MAINGROUP id="F7Bywq" name="LEAF">
1717 <GROUP id="{F7096CF4-1A84-4CC8-A236-06FAE894451E}" name="Examples">
18− <FILE id="hMMOsl" name="basic-oscillators.c" compile="0" resource="0"
18+ <FILE id="hMMOsl" name="basic-oscillators.c" compile="1" resource="0"
1919 file="../Examples/basic-oscillators.c"/>
2020 <FILE id="mVSe2h" name="basic-oscillators.h" compile="0" resource="0"
2121 file="../Examples/basic-oscillators.h"/>
leaf/Inc/leaf-analysis.h+2−2
@@ -963,9 +963,9 @@ extern "C" { · 962 unmodified lines
963963 //==============================================================================
964964
965965 /*!
966− @defgroup tdualpitchdetector tPitchDetector
966+ @defgroup tdualpitchdetector tDualPitchDetector
967967 @ingroup analysis
968− @brief Combined pitch detection algorithm using boht Joel de Guzman's Q Audio DSP Library and Katya Vetters algorithms
968+ @brief Combined pitch detection algorithm using both Joel de Guzman's Q Audio DSP Library and Katya Vetters algorithms
969969 @{
970970
971971 @fn void tDualPitchDetector_init (tDualPitchDetector* const detector, float lowestFreq, float highestFreq, float* inBuffer, int bufSize, LEAF* const leaf)
leaf/Inc/leaf-filters.h+9−5
@@ -777,11 +777,17 @@ extern "C" { · 776 unmodified lines
777777 @brief Initialize a tButterworth to the default mempool of a LEAF instance.
778778 @param filter A pointer to the tButterworth to initialize.
779779 @param leaf A pointer to the leaf instance.
780+ @param order Order of the filter.
781+ @param lowCutoff Lower cutoff frequency.
782+ @param upperCutoff Upper cutoff frequency.
780783
781784 @fn void tButterworth_initToPool (tButterworth* const, int N, float f1, float f2, tMempool* const)
782785 @brief Initialize a tButterworth to a specified mempool.
783786 @param filter A pointer to the tButterworth to initialize.
784787 @param mempool A pointer to the tMempool to use.
788+ @param order Order of the filter.
789+ @param lowCutoff Lower cutoff frequency.
790+ @param upperCutoff Upper cutoff frequency.
785791
786792 @fn void tButterworth_free (tButterworth* const)
787793 @brief Free a tButterworth from its mempool.
@@ -808,15 +814,13 @@ extern "C" { · 20 unmodified lines
808814 #define NUM_SVF_BW 16
809815 typedef struct _tButterworth
810816 {
811−
812817 tMempool mempool;
813818
814819 float gain;
820+ int order;
821+ int numSVF;
815822
816− int N;
817−
818− tSVF low[NUM_SVF_BW];
819− tSVF high[NUM_SVF_BW];
823+ tSVF* svf;
820824
821825 float f1,f2;
822826 } _tButterworth;
leaf/Inc/leaf-oscillators.h+68−5
@@ -31,20 +31,20 @@ extern "C" { · 30 unmodified lines
3131 /*!
3232 @defgroup ttable tTable
3333 @ingroup oscillators
34− @brief General wavetable oscillator.
34+ @brief Simple aliasing wavetable oscillator.
3535 @{
3636
3737 @fn void tTable_init (tTable* const osc, float* table, int size, LEAF* const leaf)
3838 @brief Initialize a tTable to the default mempool of a LEAF instance.
3939 @param osc A pointer to the tTable to initialize.
40− @param table A pointer to the wave table data.
41− @param size The number of samples in the wave table.
40+ @param table A pointer to the wavetable data.
41+ @param size The number of samples in the wavetable.
4242 @param leaf A pointer to the leaf instance.
4343
4444 @fn void tTable_initToPool (tTable* const osc, float* table, int size, tMempool* const mempool)
4545 @brief Initialize a tTable to a specified mempool.
4646 @param osc A pointer to the tTable to initialize.
47− @param table A pointer to the wave table data.
47+ @param table A pointer to the wavetable data.
4848 @param size The number of samples in the wave table.
4949 @param mempool A pointer to the tMempool to use.
5050
@@ -66,7 +66,6 @@ extern "C" { · 15 unmodified lines
6666
6767 typedef struct _tTable
6868 {
69−
7069 tMempool mempool;
7170
7271 float* waveTable;
@@ -86,6 +85,70 @@ extern "C" { · 13 unmodified lines
8685
8786 //==============================================================================
8887
88+ /*!
89+ @defgroup twavetable tWavetable
90+ @ingroup oscillators
91+ @brief Anti-aliased wavetable oscillator.
92+ @{
93+
94+ @fn void tWavetable_init (tTable* const osc, float* table, int size, LEAF* const leaf)
95+ @brief Initialize a tWavetable to the default mempool of a LEAF instance.
96+ @param osc A pointer to the tWavetable to initialize.
97+ @param table A pointer to the wavetable data.
98+ @param size The number of samples in the wavetable.
99+ @param leaf A pointer to the leaf instance.
100+
101+ @fn void tWavetable_initToPool (tTable* const osc, float* table, int size, tMempool* const mempool)
102+ @brief Initialize a tWavetable to a specified mempool.
103+ @param osc A pointer to the tWavetable to initialize.
104+ @param table A pointer to the wavetable data.
105+ @param size The number of samples in the wave table.
106+ @param mempool A pointer to the tMempool to use.
107+
108+ @fn void tWavetable_free (tTable* const osc)
109+ @brief Free a tWavetable from its mempool.
110+ @param osc A pointer to the tWavetable to free.
111+
112+ @fn float tWavetable_tick (tTable* const osc)
113+ @brief Tick a tWavetable oscillator.
114+ @param osc A pointer to the relevant tWavetable.
115+ @return The ticked sample as a float from -1 to 1.
116+
117+ @fn void tWavetable_setFreq (tTable* const osc, float freq)
118+ @brief Set the frequency of a tWavetable oscillator.
119+ @param osc A pointer to the relevant tWavetable.
120+ @param freq The frequency to set the oscillator to.
121+
122+ @} */
123+
124+ typedef struct _tWavetable
125+ {
126+ tMempool mempool;
127+
128+ float** tables;
129+ int size;
130+ int numTables;
131+ float baseFreq, invBaseFreq;
132+ float inc, freq;
133+ float phase;
134+
135+ int oct;
136+ float w;
137+
138+ tButterworth bl;
139+ } _tWavetable;
140+
141+ typedef _tWavetable* tWavetable;
142+
143+ void tWavetable_init(tWavetable* const osc, float* table, int size, LEAF* const leaf);
144+ void tWavetable_initToPool(tWavetable* const osc, float* table, int size, tMempool* const mempool);
145+ void tWavetable_free(tWavetable* const osc);
146+
147+ float tWavetable_tick(tWavetable* const osc);
148+ void tWavetable_setFreq(tWavetable* const osc, float freq);
149+
150+ //==============================================================================
151+
89152 /*!
90153 @defgroup tcycle tCycle
91154 @ingroup oscillators
leaf/Src/leaf-filters.c+42−36
@@ -828,7 +828,6 @@ void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q · 827 unmodified lines
828828 svf->cL = 0.0f;
829829 }
830830
831−
832831 else if (type == SVFTypePeak)
833832 {
834833 svf->cH = 1.0f;
@@ -974,12 +973,12 @@ void tEfficientSVF_setQ(tEfficientSVF* const svff, float Q) · 139 unmodified lines
974973 #endif // LEAF_INCLUDE_FILTERTAN_TABLE
975974
976975 /* Highpass */
977−void tHighpass_init(tHighpass* const ft, float freq, LEAF* const leaf)
976+void tHighpass_init(tHighpass* const ft, float freq, LEAF* const leaf)
978977 {
979978 tHighpass_initToPool(ft, freq, &leaf->mempool);
980979 }
981980
982−void tHighpass_initToPool (tHighpass* const ft, float freq, tMempool* const mp)
981+void tHighpass_initToPool (tHighpass* const ft, float freq, tMempool* const mp)
983982 {
984983 _tMempool* m = *mp;
985984 _tHighpass* f = *ft = (_tHighpass*) mpool_calloc(sizeof(_tHighpass), m);
@@ -994,14 +993,14 @@ void tHighpass_initToPool (tHighpass* const ft, float freq, tMempool* cons · 8 unmodified lines
994993 f->frequency = freq;
995994 }
996995
997−void tHighpass_free (tHighpass* const ft)
996+void tHighpass_free (tHighpass* const ft)
998997 {
999998 _tHighpass* f = *ft;
1000999
10011000 mpool_free((char*)f, f->mempool);
10021001 }
10031002
1004−void tHighpass_setFreq(tHighpass* const ft, float freq)
1003+void tHighpass_setFreq(tHighpass* const ft, float freq)
10051004 {
10061005 _tHighpass* f = *ft;
10071006 LEAF* leaf = f->mempool->leaf;
@@ -1011,14 +1010,14 @@ void tHighpass_setFreq(tHighpass* const ft, float freq) · 3 unmodified lines
10111010
10121011 }
10131012
1014−float tHighpass_getFreq(tHighpass* const ft)
1013+float tHighpass_getFreq(tHighpass* const ft)
10151014 {
10161015 _tHighpass* f = *ft;
10171016 return f->frequency;
10181017 }
10191018
10201019 // From JOS DC Blocker
1021−float tHighpass_tick(tHighpass* const ft, float x)
1020+float tHighpass_tick(tHighpass* const ft, float x)
10221021 {
10231022 _tHighpass* f = *ft;
10241023 f->ys = x - f->xs + f->R * f->ys;
@@ -1034,12 +1033,12 @@ void tHighpassSampleRateChanged(tHighpass* const ft) · 9 unmodified lines
10341033 f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf->invSampleRate));
10351034 }
10361035
1037−void tButterworth_init(tButterworth* const ft, int N, float f1, float f2, LEAF* const leaf)
1036+void tButterworth_init(tButterworth* const ft, int order, float f1, float f2, LEAF* const leaf)
10381037 {
1039− tButterworth_initToPool(ft, N, f1, f2, &leaf->mempool);
1038+ tButterworth_initToPool(ft, order, f1, f2, &leaf->mempool);
10401039 }
10411040
1042−void tButterworth_initToPool (tButterworth* const ft, int N, float f1, float f2, tMempool* const mp)
1041+void tButterworth_initToPool (tButterworth* const ft, int order, float f1, float f2, tMempool* const mp)
10431042 {
10441043 _tMempool* m = *mp;
10451044 _tButterworth* f = *ft = (_tButterworth*) mpool_alloc(sizeof(_tButterworth), m);
@@ -1049,14 +1048,19 @@ void tButterworth_initToPool (tButterworth* const ft, int N, float f1, fl · 3 unmodified lines
10491048 f->f2 = f2;
10501049 f->gain = 1.0f;
10511050
1052− f->N = N;
1051+ f->numSVF = f->order = order;
1052+ if (f1 >= 0.0f && f2 >= 0.0f) f->numSVF *= 2;
10531053
1054− if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
1054+ f->svf = (tSVF*) mpool_alloc(sizeof(tSVF) * f->numSVF, m);
10551055
1056− for(int i = 0; i < N/2; ++i)
1056+ int o = 0;
1057+ if (f1 >= 0.0f) o = f->order;
1058+ for(int i = 0; i < f->order; ++i)
10571059 {
1058− tSVF_initToPool(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp);
1059− tSVF_initToPool(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)), mp);
1060+ if (f1 >= 0.0f)
1061+ tSVF_initToPool(&f->svf[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*f->order)), mp);
1062+ if (f2 >= 0.0f)
1063+ tSVF_initToPool(&f->svf[i+o], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*f->order)), mp);
10601064 }
10611065 }
10621066
@@ -1064,11 +1068,8 @@ void tButterworth_free (tButterworth* const ft) · 1 unmodified line
10641068 {
10651069 _tButterworth* f = *ft;
10661070
1067− for(int i = 0; i < f->N/2; ++i)
1068− {
1069− tSVF_free(&f->low[i]);
1070− tSVF_free(&f->high[i]);
1071− }
1071+ for(int i = 0; i < f->numSVF; ++i)
1072+ tSVF_free(&f->svf[i]);
10721073
10731074 mpool_free((char*)f, f->mempool);
10741075 }
@@ -1077,11 +1078,9 @@ float tButterworth_tick(tButterworth* const ft, float samp) · 2 unmodified lines
10771078 {
10781079 _tButterworth* f = *ft;
10791080
1080− for(int i = 0; i < ((f->N)/2); ++i)
1081− {
1082− samp = tSVF_tick(&f->low[i],samp);
1083− samp = tSVF_tick(&f->high[i],samp);
1084− }
1081+ for(int i = 0; i < f->numSVF; ++i)
1082+ samp = tSVF_tick(&f->svf[i], samp);
1083+
10851084 return samp;
10861085 }
10871086
@@ -1089,29 +1088,36 @@ void tButterworth_setF1(tButterworth* const ft, float f1) · 1 unmodified line
10891088 {
10901089 _tButterworth* f = *ft;
10911090
1091+ if (f->f1 < 0.0f || f1 < 0.0f) return;
1092+
10921093 f->f1 = f1;
1093− for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1);
1094+ for (int i = 0; i < f->order; ++i) tSVF_setFreq(&f->svf[i], f1);
10941095 }
10951096
10961097 void tButterworth_setF2(tButterworth* const ft, float f2)
10971098 {
10981099 _tButterworth* f = *ft;
10991100
1101+ if (f->f2 < 0.0f || f2 < 0.0f) return;
1102+
1103+ int o = 0;
1104+ if (f->f1 >= 0.0f) o = f->order;
11001105 f->f2 = f2;
1101− for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2);
1106+ for (int i = 0; i < f->order; ++i) tSVF_setFreq(&f->svf[i+o], f2);
11021107 }
11031108
11041109 void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2)
11051110 {
1106− _tButterworth* f = *ft;
1107−
1108− f->f1 = f1;
1109− f->f2 = f2;
1110− for(int i = 0; i < ((f->N)/2); ++i)
1111− {
1112− tSVF_setFreq(&f->low[i], f1);
1113− tSVF_setFreq(&f->high[i], f2);
1114− }
1111+// _tButterworth* f = *ft;
1112+ tButterworth_setF1(ft, f1);
1113+ tButterworth_setF1(ft, f2);
1114+// f->f1 = f1;
1115+// f->f2 = f2;
1116+// for(int i = 0; i < ((f->N)/2); ++i)
1117+// {
1118+// tSVF_setFreq(&f->low[i], f1);
1119+// tSVF_setFreq(&f->high[i], f2);
1120+// }
11151121 }
11161122
11171123 void tFIR_init(tFIR* const firf, float* coeffs, int numTaps, LEAF* const leaf)
leaf/Src/leaf-oscillators.c+119−1
@@ -86,6 +86,123 @@ void tTableSampleRateChanged(tTable* const cy) · 85 unmodified lines
8686 c->inc = c->freq * leaf->invSampleRate;
8787 }
8888
89+void tWavetable_init(tWavetable* const cy, float* table, int size, LEAF* const leaf)
90+{
91+ tWavetable_initToPool(cy, table, size, &leaf->mempool);
92+}
93+
94+void tWavetable_initToPool(tWavetable* const cy, float* table, int size, tMempool* const mp)
95+{
96+ _tMempool* m = *mp;
97+ _tWavetable* c = *cy = (_tWavetable*)mpool_alloc(sizeof(_tTable), m);
98+ c->mempool = m;
99+
100+ // Determine base frequency
101+ c->baseFreq = m->leaf->sampleRate / (float) size;
102+ c->invBaseFreq = 1.0f / c->baseFreq;
103+
104+ // Determine how many tables we need
105+ c->numTables = 1;
106+ float f = c->baseFreq;
107+ while (f < 20000.f)
108+ {
109+ c->numTables++;
110+ f *= 2.0f; // pass this multiplier in to set spacing of tables?
111+ }
112+
113+ c->size = size;
114+
115+ // Allocate memory for the tables
116+ c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, m);
117+ for (int t = 0; t < c->numTables; ++t)
118+ {
119+ c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->size, m);
120+ }
121+
122+ // Copy table
123+ for (int i = 0; i < c->size; ++i)
124+ {
125+ c->tables[0][i] = table[i];
126+ }
127+
128+ // Make bandlimited copies at
129+ f = m->leaf->sampleRate * 0.25f; //start at half nyquist
130+ for (int t = 1; t < c->numTables; ++t)
131+ {
132+ tButterworth_initToPool(&c->bl, 4, -1.0f, f, mp);
133+ for (int i = 0; i < c->size; ++i)
134+ {
135+ c->tables[t][i] = tButterworth_tick(&c->bl, table[i]);
136+ }
137+ tButterworth_free(&c->bl);
138+ f *= 0.5f; //half the cutoff for next pass
139+ }
140+
141+ c->inc = 0.0f;
142+ c->phase = 0.0f;
143+
144+ tWavetable_setFreq(cy, 220);
145+}
146+
147+void tWavetable_free(tWavetable* const cy)
148+{
149+ _tWavetable* c = *cy;
150+
151+ for (int t = 0; t < c->numTables; ++t)
152+ {
153+ mpool_free((char*)c->tables[t], c->mempool);
154+ }
155+ mpool_free((char*)c->tables, c->mempool);
156+
157+ mpool_free((char*)c, c->mempool);
158+}
159+
160+float tWavetable_tick(tWavetable* const cy)
161+{
162+ _tWavetable* c = *cy;
163+
164+ float temp;
165+ int idx;
166+ float fracPart;
167+ float samp0;
168+ float samp1;
169+
170+ // Phasor increment
171+ c->phase += c->inc;
172+ while (c->phase >= 1.0f) c->phase -= 1.0f;
173+ while (c->phase < 0.0f) c->phase += 1.0f;
174+
175+ // Wavetable synthesis
176+ temp = c->size * c->phase;
177+ idx = (int)temp;
178+ fracPart = temp - (float)idx;
179+ samp0 = c->tables[c->oct+1][idx] +
180+ (c->tables[c->oct][idx] - c->tables[c->oct+1][idx]) * c->w;
181+ if (++idx >= c->size) idx = 0;
182+ samp1 = c->tables[c->oct+1][idx] +
183+ (c->tables[c->oct][idx] - c->tables[c->oct+1][idx]) * c->w;
184+
185+ return (samp0 + (samp1 - samp0) * fracPart);
186+}
187+
188+void tWavetable_setFreq(tWavetable* const cy, float freq)
189+{
190+ _tWavetable* c = *cy;
191+
192+ LEAF* leaf = c->mempool->leaf;
193+
194+ c->freq = freq;
195+
196+ c->inc = c->freq * leaf->invSampleRate;
197+
198+ c->w = c->freq * c->invBaseFreq;
199+ for (c->oct = 0; c->w > 2.0f; c->oct++)
200+ {
201+ c->w = 0.5f * c->w;
202+ }
203+ c->w = 2.0f - c->w;
204+}
205+
89206 #if LEAF_INCLUDE_SINE_TABLE
90207 // Cycle
91208 void tCycle_init(tCycle* const cy, LEAF* const leaf)
@@ -338,6 +455,7 @@ void tSawtooth_setFreq(tSawtooth* const cy, float freq) · 246 unmodified lines
338455
339456 c->inc = c->freq * leaf->invSampleRate;
340457
458+ // base freq 20
341459 c->w = c->freq * INV_20;
342460 for (c->oct = 0; c->w > 2.0f; c->oct++)
343461 {
@@ -361,7 +479,7 @@ float tSawtooth_tick(tSawtooth* const cy) · 17 unmodified lines
361479
362480 // Wavetable synthesis
363481 out = __leaf_table_sawtooth[c->oct+1][idx] +
364− (__leaf_table_sawtooth[c->oct][idx] - __leaf_table_sawtooth[c->oct+1][idx]) * c->w;
482+ (__leaf_table_sawtooth[c->oct][idx] - __leaf_table_sawtooth[c->oct+1][idx]) * c->w;
365483
366484 return out;
367485 }
leaf/leaf-config.h+4−0
@@ -54,6 +54,10 @@ · 53 unmodified lines
5454 //! Include tables for minblep insertion, required for all tMB objects.
5555 #define LEAF_INCLUDE_MINBLEP_TABLES 1
5656
57+#define LEAF_NO_DENORMAL_CHECK 0
58+
59+#define LEAF_USE_CMSIS 0
60+
5761 //==============================================================================
5862
5963 #endif // LEAF_CONFIG_H_INCLUDED

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