History

improved wavetable oscs; added tCompactWavetable

Matthew Wang committed 5 years ago

Commit 0400bc11 parent 32f24278 files · +418 −104Browse files

Unified · Split

8 files
  1. TestPlugin/LEAF.jucer +6 −6
  2. TestPlugin/Source/MyTest.cpp +15 −12
  3. leaf/Inc/leaf-global.h +6 −0
  4. leaf/Inc/leaf-math.h +1 −0
  5. leaf/Inc/leaf-oscillators.h +79 −8
  6. leaf/Src/leaf-filters.c +3 −2
  7. leaf/Src/leaf-oscillators.c +307 −75
  8. leaf/leaf-config.h +1 −1
TestPlugin/LEAF.jucer+6−6
@@ -109,8 +109,8 @@ · 108 unmodified lines
109 <EXPORTFORMATS>109 <EXPORTFORMATS>
110 <XCODE_MAC targetFolder="Builds/MacOSX" microphonePermissionNeeded="1">110 <XCODE_MAC targetFolder="Builds/MacOSX" microphonePermissionNeeded="1">
111 <CONFIGURATIONS>111 <CONFIGURATIONS>
112 <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="OOPS" enablePluginBinaryCopyStep="1"/>112 <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="LEAF" enablePluginBinaryCopyStep="1"/>
113 <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="OOPS"113 <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="LEAF"
114 enablePluginBinaryCopyStep="1"/>114 enablePluginBinaryCopyStep="1"/>
115 </CONFIGURATIONS>115 </CONFIGURATIONS>
116 <MODULEPATHS>116 <MODULEPATHS>
@@ -136,8 +136,8 @@ · 19 unmodified lines
136 iosBackgroundAudio="1" iPadScreenOrientation="UIInterfaceOrientationPortrait,UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight"136 iosBackgroundAudio="1" iPadScreenOrientation="UIInterfaceOrientationPortrait,UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight"
137 iosDeviceFamily="1,2">137 iosDeviceFamily="1,2">
138 <CONFIGURATIONS>138 <CONFIGURATIONS>
139 <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="OOPS" enablePluginBinaryCopyStep="1"/>139 <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="LEAF" enablePluginBinaryCopyStep="1"/>
140 <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="OOPS"140 <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="LEAF"
141 enablePluginBinaryCopyStep="1"/>141 enablePluginBinaryCopyStep="1"/>
142 </CONFIGURATIONS>142 </CONFIGURATIONS>
143 <MODULEPATHS>143 <MODULEPATHS>
@@ -161,10 +161,10 @@ · 17 unmodified lines
161 <VS2017 targetFolder="Builds/VisualStudio2017">161 <VS2017 targetFolder="Builds/VisualStudio2017">
162 <CONFIGURATIONS>162 <CONFIGURATIONS>
163 <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"163 <CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
164 isDebug="1" optimisation="1" targetName="OOPS" debugInformationFormat="ProgramDatabase"164 isDebug="1" optimisation="1" targetName="LEAF" debugInformationFormat="ProgramDatabase"
165 enablePluginBinaryCopyStep="0"/>165 enablePluginBinaryCopyStep="0"/>
166 <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="x64"166 <CONFIGURATION name="Release" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
167 isDebug="0" optimisation="3" targetName="OOPS" debugInformationFormat="ProgramDatabase"167 isDebug="0" optimisation="3" targetName="LEAF" debugInformationFormat="ProgramDatabase"
168 enablePluginBinaryCopyStep="0" linkTimeOptimisation="1"/>168 enablePluginBinaryCopyStep="0" linkTimeOptimisation="1"/>
169 </CONFIGURATIONS>169 </CONFIGURATIONS>
170 <MODULEPATHS>170 <MODULEPATHS>
TestPlugin/Source/MyTest.cpp+15−12
@@ -9,7 +9,6 @@ · 8 unmodified lines
9#include "LEAFTest.h"9#include "LEAFTest.h"
10#include "MyTest.h"10#include "MyTest.h"
11 11
12
13static void leaf_pool_report(void);12static void leaf_pool_report(void);
14static void leaf_pool_dump(void);13static void leaf_pool_dump(void);
15static void run_pool_test(void);14static void run_pool_test(void);
@@ -18,11 +17,6 @@ tMBSaw bsaw; · 2 unmodified lines
18tMBTriangle btri;17tMBTriangle btri;
19tMBPulse bpulse;18tMBPulse bpulse;
20 19
21tRetune retune;
22tSimpleRetune sretune;
23
24tCompressor compressor;
25
26tSVF lp, hp;20tSVF lp, hp;
27 21
28tPeriodDetection pd;22tPeriodDetection pd;
@@ -32,6 +26,12 @@ tEnvelopeFollower ef; · 3 unmodified lines
32 26
33tTriangle tri;27tTriangle tri;
34 28
29tNoise noise;
30tButterworth bw;
31
32tWavetable wt;
33tCompactWavetable cwt;
34
35tBuffer samp;35tBuffer samp;
36tMBSampler sampler;36tMBSampler sampler;
37 37
@@ -55,9 +55,8 @@ void LEAFTest_init (float sampleRate, int blockSize) · 17 unmodified lines
55{55{
56 LEAF_init(&leaf, sampleRate, blockSize, memory, MSIZE, &getRandomFloat);56 LEAF_init(&leaf, sampleRate, blockSize, memory, MSIZE, &getRandomFloat);
57 57
58 tRetune_init(&retune, 1, mtof(48), mtof(72), 2048, &leaf);58 tWavetable_init(&wt, __leaf_table_sawtooth[0], 2048, 10000.f, &leaf);
59 tSimpleRetune_init(&sretune, 1, mtof(48), mtof(72), 2048, &leaf);59 tCompactWavetable_init(&cwt, __leaf_table_sawtooth[0], 2048, 10000.f, &leaf);
60 tSimpleRetune_setMode(&sretune, 1);
61}60}
62 61
63inline double getSawFall(double angle) {62inline double getSawFall(double angle) {
@@ -72,7 +71,9 @@ inline double getSawFall(double angle) { · 8 unmodified lines
72float LEAFTest_tick (float input)71float LEAFTest_tick (float input)
73{72{
74// return tRetune_tick(&retune, input)[0];73// return tRetune_tick(&retune, input)[0];
75 return tSimpleRetune_tick(&sretune, input);74// return tSimpleRetune_tick(&sretune, input);
75 return tWavetable_tick(&wt);
76 return tCompactWavetable_tick(&cwt);
76}77}
77 78
78int firstFrame = 1;79int firstFrame = 1;
@@ -80,8 +81,10 @@ bool lastState = false, lastPlayState = false; · 1 unmodified line
80void LEAFTest_block (void)81void LEAFTest_block (void)
81{82{
82 float val = getSliderValue("slider1");83 float val = getSliderValue("slider1");
83 tRetune_tuneVoice(&retune, 0, val * 3.0f + 0.5f);84 tWavetable_setFreq(&wt, val * 40000.);
84 tSimpleRetune_tuneVoice(&sretune, 0, 300);85 tCompactWavetable_setFreq(&cwt, val * 10000.);
86// tRetune_tuneVoice(&retune, 0, val * 3.0f + 0.5f);
87// tSimpleRetune_tuneVoice(&sretune, 0, 300);
85 88
86 val = getSliderValue("slider2");89 val = getSliderValue("slider2");
87// tRetune_setPitchFactor(&retune, val * 3.0f + 0.5f, 1);90// tRetune_setPitchFactor(&retune, val * 3.0f + 0.5f, 1);
leaf/Inc/leaf-global.h+6−0
@@ -17,6 +17,12 @@ extern "C" { · 16 unmodified lines
17 17
18#include "leaf-mempool.h"18#include "leaf-mempool.h"
19 19
20#if _WIN32 || _WIN64
21#include "..\leaf-config.h"
22#else
23#include "../leaf-config.h"
24#endif
25
20 /*!26 /*!
21 * @ingroup leaf27 * @ingroup leaf
22 * @brief Struct for an instance of LEAF.28 * @brief Struct for an instance of LEAF.
leaf/Inc/leaf-math.h+1−0
@@ -35,6 +35,7 @@ extern "C" { · 34 unmodified lines
35 };35 };
36 36
37#define SQRT8 2.82842712475f37#define SQRT8 2.82842712475f
38#define LEAF_SQRT2 1.41421356237f
38#define WSCALE 1.30612244898f39#define WSCALE 1.30612244898f
39#define PI (3.14159265358979f)40#define PI (3.14159265358979f)
40#define TWO_PI (6.28318530717958f)41#define TWO_PI (6.28318530717958f)
leaf/Inc/leaf-oscillators.h+79−8
@@ -17,7 +17,7 @@ extern "C" { · 16 unmodified lines
17#include "leaf-mempool.h"17#include "leaf-mempool.h"
18#include "leaf-tables.h"18#include "leaf-tables.h"
19#include "leaf-filters.h"19#include "leaf-filters.h"
20 20#include "leaf-distortion.h"
21 21
22 /*!22 /*!
23 Header.23 Header.
@@ -91,30 +91,30 @@ extern "C" { · 67 unmodified lines
91 @brief Anti-aliased wavetable oscillator.91 @brief Anti-aliased wavetable oscillator.
92 @{92 @{
93 93
94 @fn void tWavetable_init (tTable* const osc, float* table, int size, LEAF* const leaf)94 @fn void tWavetable_init (tWavetable* const osc, float* table, int size, LEAF* const leaf)
95 @brief Initialize a tWavetable to the default mempool of a LEAF instance.95 @brief Initialize a tWavetable to the default mempool of a LEAF instance.
96 @param osc A pointer to the tWavetable to initialize.96 @param osc A pointer to the tWavetable to initialize.
97 @param table A pointer to the wavetable data.97 @param table A pointer to the wavetable data.
98 @param size The number of samples in the wavetable.98 @param size The number of samples in the wavetable.
99 @param leaf A pointer to the leaf instance.99 @param leaf A pointer to the leaf instance.
100 100
101 @fn void tWavetable_initToPool (tTable* const osc, float* table, int size, tMempool* const mempool)101 @fn void tWavetable_initToPool (tWavetable* const osc, float* table, int size, tMempool* const mempool)
102 @brief Initialize a tWavetable to a specified mempool.102 @brief Initialize a tWavetable to a specified mempool.
103 @param osc A pointer to the tWavetable to initialize.103 @param osc A pointer to the tWavetable to initialize.
104 @param table A pointer to the wavetable data.104 @param table A pointer to the wavetable data.
105 @param size The number of samples in the wave table.105 @param size The number of samples in the wave table.
106 @param mempool A pointer to the tMempool to use.106 @param mempool A pointer to the tMempool to use.
107 107
108 @fn void tWavetable_free (tTable* const osc)108 @fn void tWavetable_free (tWavetable* const osc)
109 @brief Free a tWavetable from its mempool.109 @brief Free a tWavetable from its mempool.
110 @param osc A pointer to the tWavetable to free.110 @param osc A pointer to the tWavetable to free.
111 111
112 @fn float tWavetable_tick (tTable* const osc)112 @fn float tWavetable_tick (tWavetable* const osc)
113 @brief Tick a tWavetable oscillator.113 @brief Tick a tWavetable oscillator.
114 @param osc A pointer to the relevant tWavetable.114 @param osc A pointer to the relevant tWavetable.
115 @return The ticked sample as a float from -1 to 1.115 @return The ticked sample as a float from -1 to 1.
116 116
117 @fn void tWavetable_setFreq (tTable* const osc, float freq)117 @fn void tWavetable_setFreq (tWavetable* const osc, float freq)
118 @brief Set the frequency of a tWavetable oscillator.118 @brief Set the frequency of a tWavetable oscillator.
119 @param osc A pointer to the relevant tWavetable.119 @param osc A pointer to the relevant tWavetable.
120 @param freq The frequency to set the oscillator to.120 @param freq The frequency to set the oscillator to.
@@ -134,18 +134,89 @@ extern "C" { · 13 unmodified lines
134 134
135 int oct;135 int oct;
136 float w;136 float w;
137 float aa;
137 138
138 tButterworth bl;139 tButterworth bl;
139 } _tWavetable;140 } _tWavetable;
140 141
141 typedef _tWavetable* tWavetable;142 typedef _tWavetable* tWavetable;
142 143
143 void tWavetable_init(tWavetable* const osc, float* table, int size, LEAF* const leaf);144 void tWavetable_init(tWavetable* const osc, const float* table, int size, float maxFreq, LEAF* const leaf);
144 void tWavetable_initToPool(tWavetable* const osc, float* table, int size, tMempool* const mempool);145 void tWavetable_initToPool(tWavetable* const osc, const float* table, int size, float maxFreq, tMempool* const mempool);
145 void tWavetable_free(tWavetable* const osc);146 void tWavetable_free(tWavetable* const osc);
146 147
147 float tWavetable_tick(tWavetable* const osc);148 float tWavetable_tick(tWavetable* const osc);
148 void tWavetable_setFreq(tWavetable* const osc, float freq);149 void tWavetable_setFreq(tWavetable* const osc, float freq);
150 void tWavetable_setAntiAliasing(tWavetable* const osc, float aa);
151
152 //==============================================================================
153
154 /*!
155 @defgroup tcompactwavetable tCompactWavetable
156 @ingroup oscillators
157 @brief A more space-efficient anti-aliased wavetable oscillator than tWavetable but with slightly worse fidelity.
158 @{
159
160 @fn void tCompactWavetable_init (tCompactWavetable* const osc, float* table, int size, LEAF* const leaf)
161 @brief Initialize a tCompactWavetable to the default mempool of a LEAF instance.
162 @param osc A pointer to the tCompactWavetable to initialize.
163 @param table A pointer to the wavetable data.
164 @param size The number of samples in the wavetable.
165 @param leaf A pointer to the leaf instance.
166
167 @fn void tCompactWavetable_initToPool (tCompactWavetable* const osc, float* table, int size, tMempool* const mempool)
168 @brief Initialize a tCompactWavetable to a specified mempool.
169 @param osc A pointer to the tCompactWavetable to initialize.
170 @param table A pointer to the wavetable data.
171 @param size The number of samples in the wave table.
172 @param mempool A pointer to the tMempool to use.
173
174 @fn void tCompactWavetable_free (tCompactWavetable* const osc)
175 @brief Free a tCompactWavetable from its mempool.
176 @param osc A pointer to the tCompactWavetable to free.
177
178 @fn float tCompactWavetable_tick (tCompactWavetable* const osc)
179 @brief Tick a tCompactWavetable oscillator.
180 @param osc A pointer to the relevant tCompactWavetable.
181 @return The ticked sample as a float from -1 to 1.
182
183 @fn void tCompactWavetable_setFreq (tCompactWavetable* const osc, float freq)
184 @brief Set the frequency of a tCompactWavetable oscillator.
185 @param osc A pointer to the relevant tCompactWavetable.
186 @param freq The frequency to set the oscillator to.
187
188 @} */
189
190 typedef struct _tCompactWavetable
191 {
192 tMempool mempool;
193
194 float** tables;
195 int numTables;
196 int* sizes;
197 float baseFreq, invBaseFreq;
198 float inc, freq;
199 float phase;
200
201 int oct;
202 float w;
203 float aa;
204
205 tButterworth bl;
206
207 float dsBuffer[2];
208 tOversampler ds;
209 } _tCompactWavetable;
210
211 typedef _tCompactWavetable* tCompactWavetable;
212
213 void tCompactWavetable_init(tCompactWavetable* const osc, const float* table, int size, float maxFreq, LEAF* const leaf);
214 void tCompactWavetable_initToPool(tCompactWavetable* const osc, const float* table, int size, float maxFreq, tMempool* const mempool);
215 void tCompactWavetable_free(tCompactWavetable* const osc);
216
217 float tCompactWavetable_tick(tCompactWavetable* const osc);
218 void tCompactWavetable_setFreq(tCompactWavetable* const osc, float freq);
219 void tCompactWavetable_setAntiAliasing(tCompactWavetable* const osc, float aa);
149 220
150 //==============================================================================221 //==============================================================================
151 222
leaf/Src/leaf-filters.c+3−2
@@ -1058,9 +1058,9 @@ void tButterworth_initToPool (tButterworth* const ft, int order, float f1 · 1057 unmodified lines
1058 for(int i = 0; i < f->order; ++i)1058 for(int i = 0; i < f->order; ++i)
1059 {1059 {
1060 if (f1 >= 0.0f)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);1061 tSVF_initToPool(&f->svf[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(4*f->order)), mp);
1062 if (f2 >= 0.0f)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);1063 tSVF_initToPool(&f->svf[i+o], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(4*f->order)), mp);
1064 }1064 }
1065}1065}
1066 1066
@@ -1071,6 +1071,7 @@ void tButterworth_free (tButterworth* const ft) · 4 unmodified lines
1071 for(int i = 0; i < f->numSVF; ++i)1071 for(int i = 0; i < f->numSVF; ++i)
1072 tSVF_free(&f->svf[i]);1072 tSVF_free(&f->svf[i]);
1073 1073
1074 mpool_free((char*)f->svf, f->mempool);
1074 mpool_free((char*)f, f->mempool);1075 mpool_free((char*)f, f->mempool);
1075}1076}
1076 1077
leaf/Src/leaf-oscillators.c+307−75
@@ -86,15 +86,15 @@ void tTableSampleRateChanged(tTable* const cy) · 85 unmodified lines
86 c->inc = c->freq * leaf->invSampleRate;86 c->inc = c->freq * leaf->invSampleRate;
87}87}
88 88
89void tWavetable_init(tWavetable* const cy, float* table, int size, LEAF* const leaf)89void tWavetable_init(tWavetable* const cy, const float* table, int size, float maxFreq, LEAF* const leaf)
90{90{
91 tWavetable_initToPool(cy, table, size, &leaf->mempool);91 tWavetable_initToPool(cy, table, size, maxFreq, &leaf->mempool);
92}92}
93 93
94void tWavetable_initToPool(tWavetable* const cy, float* table, int size, tMempool* const mp)94void tWavetable_initToPool(tWavetable* const cy, const float* table, int size, float maxFreq, tMempool* const mp)
95{95{
96 _tMempool* m = *mp;96 _tMempool* m = *mp;
97 _tWavetable* c = *cy = (_tWavetable*)mpool_alloc(sizeof(_tTable), m);97 _tWavetable* c = *cy = (_tWavetable*) mpool_alloc(sizeof(_tWavetable), m);
98 c->mempool = m;98 c->mempool = m;
99 99
100 // Determine base frequency100 // Determine base frequency
@@ -102,12 +102,13 @@ void tWavetable_initToPool(tWavetable* const cy, float* table, int size, tMem · 1 unmodified line
102 c->invBaseFreq = 1.0f / c->baseFreq;102 c->invBaseFreq = 1.0f / c->baseFreq;
103 103
104 // Determine how many tables we need104 // Determine how many tables we need
105 c->numTables = 1;105 // Assume we need at least 2, the fundamental + one to account for setting extra anti aliasing
106 c->numTables = 2;
106 float f = c->baseFreq;107 float f = c->baseFreq;
107 while (f < 20000.f)108 while (f < maxFreq)
108 {109 {
109 c->numTables++;110 c->numTables++;
110 f *= 2.0f; // pass this multiplier in to set spacing of tables?111 f *= 2.0f; // pass this multiplier in to set spacing of tables? would need to change setFreq too
111 }112 }
112 113
113 c->size = size;114 c->size = size;
@@ -125,26 +126,36 @@ void tWavetable_initToPool(tWavetable* const cy, float* table, int size, tMem · 11 unmodified lines
125 c->tables[0][i] = table[i];126 c->tables[0][i] = table[i];
126 }127 }
127 128
128 // Make bandlimited copies at129 // Make bandlimited copies
129 f = m->leaf->sampleRate * 0.25f; //start at half nyquist130 f = m->leaf->sampleRate * 0.25; //start at half nyquist
131 // Not worth going over order 8 I think, and even 8 is only marginally better than 4.
132 tButterworth_initToPool(&c->bl, 8, -1.0f, f, mp);
130 for (int t = 1; t < c->numTables; ++t)133 for (int t = 1; t < c->numTables; ++t)
131 {134 {
132 tButterworth_initToPool(&c->bl, 4, -1.0f, f, mp);135 tButterworth_setF2(&c->bl, f);
133 for (int i = 0; i < c->size; ++i)136 // Do several passes here to prevent errors at the beginning of the waveform
137 // Not sure how many passes to do, seem to need more as the filter cutoff goes down
138 // 12 might be excessive but seems to work for now.
139 for (int p = 0; p < 12; ++p)
134 {140 {
135 c->tables[t][i] = tButterworth_tick(&c->bl, table[i]);141 for (int i = 0; i < c->size; ++i)
142 {
143 c->tables[t][i] = tButterworth_tick(&c->bl, c->tables[t-1][i]);
144 }
136 }145 }
137 tButterworth_free(&c->bl);146 f *= 0.5f; //halve the cutoff for next pass
138 f *= 0.5f; //half the cutoff for next pass
139 }147 }
148 tButterworth_free(&c->bl);
149
140 150
141 c->inc = 0.0f;151 c->inc = 0.0f;
142 c->phase = 0.0f;152 c->phase = 0.0f;
153 c->aa = 0.5f;
143 154
144 tWavetable_setFreq(cy, 220);155 tWavetable_setFreq(cy, 220);
145}156}
146 157
147void tWavetable_free(tWavetable* const cy)158void tWavetable_free(tWavetable* const cy)
148{159{
149 _tWavetable* c = *cy;160 _tWavetable* c = *cy;
150 161
@@ -153,17 +164,16 @@ void tWavetable_free(tWavetable* const cy) · 2 unmodified lines
153 mpool_free((char*)c->tables[t], c->mempool);164 mpool_free((char*)c->tables[t], c->mempool);
154 }165 }
155 mpool_free((char*)c->tables, c->mempool);166 mpool_free((char*)c->tables, c->mempool);
156
157 mpool_free((char*)c, c->mempool);167 mpool_free((char*)c, c->mempool);
158}168}
159 169
160float tWavetable_tick(tWavetable* const cy)170float tWavetable_tick(tWavetable* const cy)
161{171{
162 _tWavetable* c = *cy;172 _tWavetable* c = *cy;
163 173
164 float temp;174 float temp;
165 int idx;175 int idx;
166 float fracPart;176 float frac;
167 float samp0;177 float samp0;
168 float samp1;178 float samp1;
169 179
@@ -174,18 +184,26 @@ float tWavetable_tick(tWavetable* const cy) · 4 unmodified lines
174 184
175 // Wavetable synthesis185 // Wavetable synthesis
176 temp = c->size * c->phase;186 temp = c->size * c->phase;
187
177 idx = (int)temp;188 idx = (int)temp;
178 fracPart = temp - (float)idx;189 frac = temp - (float)idx;
179 samp0 = c->tables[c->oct+1][idx] +190 samp0 = c->tables[c->oct][idx];
180 (c->tables[c->oct][idx] - c->tables[c->oct+1][idx]) * c->w;
181 if (++idx >= c->size) idx = 0;191 if (++idx >= c->size) idx = 0;
182 samp1 = c->tables[c->oct+1][idx] +192 samp1 = c->tables[c->oct][idx];
183 (c->tables[c->oct][idx] - c->tables[c->oct+1][idx]) * c->w;
184 193
185 return (samp0 + (samp1 - samp0) * fracPart);194 float oct0 = (samp0 + (samp1 - samp0) * frac);
195
196 idx = (int)temp;
197 samp0 = c->tables[c->oct+1][idx];
198 if (++idx >= c->size) idx = 0;
199 samp1 = c->tables[c->oct+1][idx];
200
201 float oct1 = (samp0 + (samp1 - samp0) * frac);
202
203 return oct0 + (oct1 - oct0) * c->w;
186}204}
187 205
188void tWavetable_setFreq(tWavetable* const cy, float freq)206void tWavetable_setFreq(tWavetable* const cy, float freq)
189{207{
190 _tWavetable* c = *cy;208 _tWavetable* c = *cy;
191 209
@@ -195,12 +213,173 @@ void tWavetable_setFreq(tWavetable* const cy, float freq) · 3 unmodified lines
195 213
196 c->inc = c->freq * leaf->invSampleRate;214 c->inc = c->freq * leaf->invSampleRate;
197 215
198 c->w = c->freq * c->invBaseFreq;216 // abs for negative frequencies
199 for (c->oct = 0; c->w > 2.0f; c->oct++)217 c->w = fabsf(c->freq * c->invBaseFreq);
218
219 // Probably ok to use a log2 approx here; won't effect tuning at all, just crossfading between octave tables
220 c->w = log2f_approx(c->w) + c->aa; // adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
221 if (c->w < 0.0f) c->w = 0.0f; // If c->w is < 0.0f, then freq is less than our base freq
222 c->oct = (int)c->w;
223 c->w -= c->oct;
224
225 // When out of range of our tables, this will prevent a crash.
226 // Also causes a blip but fine since we're above maxFreq at this point.
227 if (c->oct >= c->numTables - 1) c->oct = c->numTables - 2;
228}
229
230void tWavetable_setAntiAliasing(tWavetable* const cy, float aa)
231{
232 _tWavetable* c = *cy;
233
234 c->aa = aa;
235 tWavetable_setFreq(cy, c->freq);
236}
237
238void tCompactWavetable_init(tCompactWavetable* const cy, const float* table, int size, float maxFreq, LEAF* const leaf)
239{
240 tCompactWavetable_initToPool(cy, table, size, maxFreq, &leaf->mempool);
241}
242
243void tCompactWavetable_initToPool(tCompactWavetable* const cy, const float* table, int size, float maxFreq, tMempool* const mp)
244{
245 _tMempool* m = *mp;
246 _tCompactWavetable* c = *cy = (_tCompactWavetable*) mpool_alloc(sizeof(_tCompactWavetable), m);
247 c->mempool = m;
248
249 // Determine base frequency
250 c->baseFreq = m->leaf->sampleRate / (float) size;
251 c->invBaseFreq = 1.0f / c->baseFreq;
252
253 // Determine how many tables we need
254 c->numTables = 2;
255 float f = c->baseFreq;
256 while (f < maxFreq)
200 {257 {
201 c->w = 0.5f * c->w;258 c->numTables++;
259 f *= 2.0f; // pass this multiplier in to set spacing of tables?
202 }260 }
203 c->w = 2.0f - c->w;261
262 // Allocate memory for the tables
263 c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, c->mempool);
264 c->sizes = (int*) mpool_alloc(sizeof(int) * c->numTables, c->mempool);
265 int n = size;
266 for (int t = 0; t < c->numTables; ++t)
267 {
268 c->sizes[t] = n;
269 c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->sizes[t], m);
270 n = c->sizes[t] / 2;
271 }
272
273 // Copy table
274 for (int i = 0; i < c->sizes[0]; ++i)
275 {
276 c->tables[0][i] = table[i];
277 }
278
279 // Make bandlimited copies
280 // Not worth going over order 8 I think, and even 8 is only marginally better than 4.
281 tButterworth_initToPool(&c->bl, 8, -1.0f, m->leaf->sampleRate * 0.25f, mp);
282 tOversampler_initToPool(&c->ds, 2, 1, mp);
283 for (int t = 1; t < c->numTables; ++t)
284 {
285 // Similar to tWavetable, doing multiple passes here helps, but not sure what number is optimal
286 for (int p = 0; p < 12; ++p)
287 {
288 for (int i = 0; i < c->sizes[t]; ++i)
289 {
290 c->dsBuffer[0] = tButterworth_tick(&c->bl, c->tables[t-1][i*2]);
291 c->dsBuffer[1] = tButterworth_tick(&c->bl, c->tables[t-1][(i*2)+1]);
292 c->tables[t][i] = tOversampler_downsample(&c->ds, c->dsBuffer);
293 }
294 }
295 }
296 tOversampler_free(&c->ds);
297 tButterworth_free(&c->bl);
298
299 c->inc = 0.0f;
300 c->phase = 0.0f;
301 c->aa = 0.5f;
302
303 tCompactWavetable_setFreq(cy, 220);
304}
305
306void tCompactWavetable_free(tCompactWavetable* const cy)
307{
308 _tCompactWavetable* c = *cy;
309
310 for (int t = 0; t < c->numTables; ++t)
311 {
312 mpool_free((char*)c->tables[t], c->mempool);
313 }
314 mpool_free((char*)c->tables, c->mempool);
315 mpool_free((char*)c->sizes, c->mempool);
316 mpool_free((char*)c, c->mempool);
317}
318
319float tCompactWavetable_tick(tCompactWavetable* const cy)
320{
321 _tCompactWavetable* c = *cy;
322
323 float temp;
324 int idx;
325 float frac;
326 float samp0;
327 float samp1;
328
329 // Phasor increment
330 c->phase += c->inc;
331 while (c->phase >= 1.0f) c->phase -= 1.0f;
332 while (c->phase < 0.0f) c->phase += 1.0f;
333
334 // Wavetable synthesis
335 temp = c->sizes[c->oct] * c->phase;
336 idx = (int)temp;
337 frac = temp - (float)idx;
338 samp0 = c->tables[c->oct][idx];
339 if (++idx >= c->sizes[c->oct]) idx = 0;
340 samp1 = c->tables[c->oct][idx];
341
342 float oct0 = (samp0 + (samp1 - samp0) * frac);
343
344 temp = c->sizes[c->oct+1] * c->phase;
345 idx = (int)temp;
346 frac = temp - (float)idx;
347 samp0 = c->tables[c->oct+1][idx];
348 if (++idx >= c->sizes[c->oct+1]) idx = 0;
349 samp1 = c->tables[c->oct+1][idx];
350
351 float oct1 = (samp0 + (samp1 - samp0) * frac);
352
353 return oct0 + (oct1 - oct0) * c->w;
354}
355
356void tCompactWavetable_setFreq(tCompactWavetable* const cy, float freq)
357{
358 _tCompactWavetable* c = *cy;
359
360 LEAF* leaf = c->mempool->leaf;
361
362 c->freq = freq;
363
364 c->inc = c->freq * leaf->invSampleRate;
365
366 // abs for negative frequencies
367 c->w = fabsf(c->freq * c->invBaseFreq);
368
369 // Probably ok to use a log2 approx here; won't effect tuning at all, just crossfading between octave tables
370 c->w = log2f_approx(c->w) + c->aa;//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
371 if (c->w < 0.0f) c->w = 0.0f; // If c->w is < 0.0f, then freq is less than our base freq
372 c->oct = (int)c->w;
373 c->w -= c->oct;
374 if (c->oct >= c->numTables - 1) c->oct = c->numTables - 2;
375}
376
377void tCompactWavetable_setAntiAliasing(tCompactWavetable* const cy, float aa)
378{
379 _tCompactWavetable* c = *cy;
380
381 c->aa = aa;
382 tCompactWavetable_setFreq(cy, c->freq);
204}383}
205 384
206#if LEAF_INCLUDE_SINE_TABLE385#if LEAF_INCLUDE_SINE_TABLE
@@ -243,9 +422,9 @@ void tCycle_setFreq(tCycle* const cy, float freq) · 36 unmodified lines
243float tCycle_tick(tCycle* const cy)422float tCycle_tick(tCycle* const cy)
244{423{
245 _tCycle* c = *cy;424 _tCycle* c = *cy;
246 float temp;;425 float temp;
247 int intPart;;426 int idx;
248 float fracPart;427 float frac;
249 float samp0;428 float samp0;
250 float samp1;429 float samp1;
251 430
@@ -257,13 +436,13 @@ float tCycle_tick(tCycle* const cy) · 5 unmodified lines
257 // Wavetable synthesis436 // Wavetable synthesis
258 437
259 temp = SINE_TABLE_SIZE * c->phase;438 temp = SINE_TABLE_SIZE * c->phase;
260 intPart = (int)temp;439 idx = (int)temp;
261 fracPart = temp - (float)intPart;440 frac = temp - (float)idx;
262 samp0 = __leaf_table_sinewave[intPart];441 samp0 = __leaf_table_sinewave[idx];
263 if (++intPart >= SINE_TABLE_SIZE) intPart = 0;442 if (++idx >= SINE_TABLE_SIZE) idx = 0;
264 samp1 = __leaf_table_sinewave[intPart];443 samp1 = __leaf_table_sinewave[idx];
265 444
266 return (samp0 + (samp1 - samp0) * fracPart);445 return (samp0 + (samp1 - samp0) * frac);
267}446}
268 447
269void tCycleSampleRateChanged (tCycle* const cy)448void tCycleSampleRateChanged (tCycle* const cy)
@@ -310,12 +489,14 @@ void tTriangle_setFreq(tTriangle* const cy, float freq) · 40 unmodified lines
310 489
311 c->inc = c->freq * leaf->invSampleRate;490 c->inc = c->freq * leaf->invSampleRate;
312 491
313 c->w = c->freq * INV_20;492 // abs for negative frequencies
314 for (c->oct = 0; c->w > 2.0f; c->oct++)493 c->w = fabsf(c->freq * (TRI_TABLE_SIZE * leaf->invSampleRate));
315 {494
316 c->w = 0.5f * c->w;495 c->w = log2f_approx(c->w);//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
317 }496 if (c->w < 0.0f) c->w = 0.0f;
318 c->w = 2.0f - c->w;497 c->oct = (int)c->w;
498 c->w -= c->oct;
499 if (c->oct >= 10) c->oct = 9;
319}500}
320 501
321 502
@@ -323,20 +504,36 @@ float tTriangle_tick(tTriangle* const cy) · 1 unmodified line
323{504{
324 _tTriangle* c = *cy;505 _tTriangle* c = *cy;
325 506
507 float temp;
508 int idx;
509 float frac;
510 float samp0;
511 float samp1;
512
326 // Phasor increment513 // Phasor increment
327 c->phase += c->inc;514 c->phase += c->inc;
328 while (c->phase >= 1.0f) c->phase -= 1.0f;515 while (c->phase >= 1.0f) c->phase -= 1.0f;
329 while (c->phase < 0.0f) c->phase += 1.0f;516 while (c->phase < 0.0f) c->phase += 1.0f;
517
518 // Wavetable synthesis
519 temp = TRI_TABLE_SIZE * c->phase;
520
521 idx = (int)temp;
522 frac = temp - (float)idx;
523 samp0 = __leaf_table_triangle[c->oct][idx];
524 if (++idx >= TRI_TABLE_SIZE) idx = 0;
525 samp1 = __leaf_table_triangle[c->oct][idx];
330 526
331 float out = 0.0f;527 float oct0 = (samp0 + (samp1 - samp0) * frac);
332 528
333 int idx = (int)(c->phase * TRI_TABLE_SIZE);529 idx = (int)temp;
530 samp0 = __leaf_table_triangle[c->oct+1][idx];
531 if (++idx >= TRI_TABLE_SIZE) idx = 0;
532 samp1 = __leaf_table_triangle[c->oct+1][idx];
334 533
335 // Wavetable synthesis534 float oct1 = (samp0 + (samp1 - samp0) * frac);
336 out = __leaf_table_triangle[c->oct+1][idx] +
337 (__leaf_table_triangle[c->oct][idx] - __leaf_table_triangle[c->oct+1][idx]) * c->w;
338 535
339 return out;536 return oct0 + (oct1 - oct0) * c->w;
340}537}
341 538
342void tTriangleSampleRateChanged (tTriangle* const cy)539void tTriangleSampleRateChanged (tTriangle* const cy)
@@ -383,32 +580,50 @@ void tSquare_setFreq(tSquare* const cy, float freq) · 40 unmodified lines
383 580
384 c->inc = c->freq * leaf->invSampleRate;581 c->inc = c->freq * leaf->invSampleRate;
385 582
386 c->w = c->freq * INV_20;583 // abs for negative frequencies
387 for (c->oct = 0; c->w > 2.0f; c->oct++)584 c->w = fabsf(c->freq * (SQR_TABLE_SIZE * leaf->invSampleRate));
388 {585
389 c->w = 0.5f * c->w;586 c->w = log2f_approx(c->w);//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
390 }587 if (c->w < 0.0f) c->w = 0.0f;
391 c->w = 2.0f - c->w;588 c->oct = (int)c->w;
589 c->w -= c->oct;
590 if (c->oct >= 10) c->oct = 9;
392}591}
393 592
394float tSquare_tick(tSquare* const cy)593float tSquare_tick(tSquare* const cy)
395{594{
396 _tSquare* c = *cy;595 _tSquare* c = *cy;
397 596
597 float temp;
598 int idx;
599 float frac;
600 float samp0;
601 float samp1;
602
398 // Phasor increment603 // Phasor increment
399 c->phase += c->inc;604 c->phase += c->inc;
400 while (c->phase >= 1.0f) c->phase -= 1.0f;605 while (c->phase >= 1.0f) c->phase -= 1.0f;
401 while (c->phase < 0.0f) c->phase += 1.0f;606 while (c->phase < 0.0f) c->phase += 1.0f;
607
608 // Wavetable synthesis
609 temp = SQR_TABLE_SIZE * c->phase;
402 610
403 float out = 0.0f;611 idx = (int)temp;
612 frac = temp - (float)idx;
613 samp0 = __leaf_table_squarewave[c->oct][idx];
614 if (++idx >= SQR_TABLE_SIZE) idx = 0;
615 samp1 = __leaf_table_squarewave[c->oct][idx];
404 616
405 int idx = (int)(c->phase * SQR_TABLE_SIZE);617 float oct0 = (samp0 + (samp1 - samp0) * frac);
406 618
407 // Wavetable synthesis619 idx = (int)temp;
408 out = __leaf_table_squarewave[c->oct+1][idx] +620 samp0 = __leaf_table_squarewave[c->oct+1][idx];
409 (__leaf_table_squarewave[c->oct][idx] - __leaf_table_squarewave[c->oct+1][idx]) * c->w;621 if (++idx >= SQR_TABLE_SIZE) idx = 0;
622 samp1 = __leaf_table_squarewave[c->oct+1][idx];
410 623
411 return out;624 float oct1 = (samp0 + (samp1 - samp0) * frac);
625
626 return oct0 + (oct1 - oct0) * c->w;
412}627}
413 628
414void tSquareSampleRateChanged (tSquare* const cy)629void tSquareSampleRateChanged (tSquare* const cy)
@@ -455,33 +670,50 @@ void tSawtooth_setFreq(tSawtooth* const cy, float freq) · 40 unmodified lines
455 670
456 c->inc = c->freq * leaf->invSampleRate;671 c->inc = c->freq * leaf->invSampleRate;
457 672
458 // base freq 20673 // abs for negative frequencies
459 c->w = c->freq * INV_20;674 c->w = fabsf(c->freq * (SAW_TABLE_SIZE * leaf->invSampleRate));
460 for (c->oct = 0; c->w > 2.0f; c->oct++)675
461 {676 c->w = log2f_approx(c->w);//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
462 c->w = 0.5f * c->w;677 if (c->w < 0.0f) c->w = 0.0f; // If c->w is < 0.0f, then freq is less than our base freq
463 }678 c->oct = (int)c->w;
464 c->w = 2.0f - c->w;679 c->w -= c->oct;
680 if (c->oct >= 10) c->oct = 9;
465}681}
466 682
467float tSawtooth_tick(tSawtooth* const cy)683float tSawtooth_tick(tSawtooth* const cy)
468{684{
469 _tSawtooth* c = *cy;685 _tSawtooth* c = *cy;
470 686
687 float temp;
688 int idx;
689 float frac;
690 float samp0;
691 float samp1;
692
471 // Phasor increment693 // Phasor increment
472 c->phase += c->inc;694 c->phase += c->inc;
473 while (c->phase >= 1.0f) c->phase -= 1.0f;695 while (c->phase >= 1.0f) c->phase -= 1.0f;
474 while (c->phase < 0.0f) c->phase += 1.0f;696 while (c->phase < 0.0f) c->phase += 1.0f;
475 697
476 float out = 0.0f;698 // Wavetable synthesis
699 temp = SAW_TABLE_SIZE * c->phase;
477 700
478 int idx = (int)(c->phase * SAW_TABLE_SIZE);701 idx = (int)temp;
702 frac = temp - (float)idx;
703 samp0 = __leaf_table_sawtooth[c->oct][idx];
704 if (++idx >= SAW_TABLE_SIZE) idx = 0;
705 samp1 = __leaf_table_sawtooth[c->oct][idx];
479 706
480 // Wavetable synthesis707 float oct0 = (samp0 + (samp1 - samp0) * frac);
481 out = __leaf_table_sawtooth[c->oct+1][idx] +
482 (__leaf_table_sawtooth[c->oct][idx] - __leaf_table_sawtooth[c->oct+1][idx]) * c->w;
483 708
484 return out;709 idx = (int)temp;
710 samp0 = __leaf_table_sawtooth[c->oct+1][idx];
711 if (++idx >= SAW_TABLE_SIZE) idx = 0;
712 samp1 = __leaf_table_sawtooth[c->oct+1][idx];
713
714 float oct1 = (samp0 + (samp1 - samp0) * frac);
715
716 return oct0 + (oct1 - oct0) * c->w;
485}717}
486 718
487void tSawtoothSampleRateChanged (tSawtooth* const cy)719void tSawtoothSampleRateChanged (tSawtooth* const cy)
leaf/leaf-config.h+1−1
@@ -18,7 +18,7 @@ · 17 unmodified lines
18 18
19//==============================================================================19//==============================================================================
20 20
21//! Include FIR tables required to use tOversampler.21//! Include FIR tables required to use tOversampler and tCompactWavetable which uses tOversampler.
22#define LEAF_INCLUDE_OVERSAMPLER_TABLES 122#define LEAF_INCLUDE_OVERSAMPLER_TABLES 1
23 23
24// Unused24// Unused

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