arduino-audio-tools
Loading...
Searching...
No Matches
AudioEffectsSuite.h
Go to the documentation of this file.
1#pragma once
2
20#include <cmath>
21#include <cstdint>
22#include <iostream>
26
27#ifndef PI
28# define PI 3.141592653589793f
29#endif
30
31namespace audio_tools {
32
33// soft_float_t: integer mantissa/exponent under the hood, so the whole
34// suite's per-sample delay/filter/modulation arithmetic (the vast bulk of
35// this file's float use) avoids the FPU on FPU-less MCUs. It keeps float's
36// wide dynamic range (unlike q1_14_t's bounded +-2.0), which this file
37// needs: delay-buffer indices run up to sampleRate, filter coefficients
38// vary widely with cutoff. Setup-time-only transcendental calls (sin/cos/
39// pow/sqrt/...) still go through soft_float_t's implicit float conversion,
40// which is fine since they aren't in the per-sample hot path -- except
41// EnvelopeFilter::processFloat(), which recomputes a full Chebyshev filter
42// (multiple sin/cos/sqrt/log/pow calls) every sample; that's expensive on
43// any platform and isn't something this typedef swap can fix.
44//
45// Every class below is templated on the numeric type it uses internally --
46// named `effectsuite_t` (shadowing this default alias) so the class bodies
47// below don't need renaming. This lets both SimpleLPF<float> and
48// SimpleLPF<soft_float_t> (etc.) be instantiated side by side in the same
49// program, e.g. to compare their output directly, rather than requiring two
50// separate builds gated by PREFER_FIXEDPOINT. The macro only picks the
51// *default* -- what you get when you don't specify a type explicitly.
52#if PREFER_FIXEDPOINT
53using effectsuite_t_default = soft_float_t;
54#else
56#endif
57
62template <typename effectsuite_t = effectsuite_t_default>
69 virtual effectsuite_t processFloat(effectsuite_t inputSample) = 0;
70
76 virtual effect_t process(effect_t inputSample) override {
77 return this->active_flag ? (effect_t)(32767.0f * processFloat(static_cast<effectsuite_t>(inputSample)/32767.0f)) : inputSample;
78 }
79
80};
81
82
92template <typename effectsuite_t = effectsuite_t_default>
94public:
96 ModulationBaseClass() { srand(static_cast<unsigned>(time(0))); }
97
98 // deep-copies waveTable (owned) -- the compiler-generated (shallow) copy
99 // this replaces would leave clone and original pointing at the *same*
100 // waveTable, which breaks AudioEffectStreamT's per-channel cloning for
101 // stereo: each channel's clone must own independent state.
103 sampleRate = copy.sampleRate;
104 timeStep = copy.timeStep;
105 tableIndex = copy.tableIndex;
106 is_noise = copy.is_noise;
107 memcpy(interpTable, copy.interpTable, sizeof(interpTable));
108 if (copy.waveTable != nullptr) {
109 waveTable = new effectsuite_t[sampleRate];
110 std::copy(copy.waveTable, copy.waveTable + sampleRate, waveTable);
111 }
112 }
113
114 ModulationBaseClass(effectsuite_t extSampRate) {
115 this->sampleRate = extSampRate;
116 timeStep = 1. / extSampRate;
118 // setInterpTable();
119 srand(static_cast<unsigned>(time(0)));
120 }
123
129 void setupModulationBaseClass(effectsuite_t extSampRate) {
130 if (waveTable != nullptr) {
131 delete[] waveTable;
132 }
133 sampleRate = extSampRate;
134 timeStep = 1. / extSampRate;
136 }
137
141 void setTriangle() {
142 std::fill(waveTable, waveTable + sampleRate, 0);
143 const effectsuite_t radPerSec = 2 * 3.1415926536f * timeStep;
144 for (int i = 0; i < sampleRate; i++) {
145 for (int j = 0; j < 35; j += 1)
146 waveTable[i] += pow(-1., j) *
147 (sin((2. * effectsuite_t(j) + 1) * i * radPerSec)) /
148 (2. * effectsuite_t(j) + 1);
149 }
150 }
154 void setSquare() {
155 std::fill(waveTable, waveTable + sampleRate, 0);
156 const effectsuite_t radPerSec = 2 * 3.1415926536f * timeStep;
157 for (int i = 0; i < sampleRate; i++) {
158 for (int j = 0; j < 35; j += 1)
159 waveTable[i] += (sin((2 * j + 1) * i * radPerSec)) / (2 * j + 1);
160 }
161 }
165 void setSawtooth() {
166 std::fill(waveTable, waveTable + sampleRate, 0);
167 const effectsuite_t radPerSec = 2 * 3.1415926536f * timeStep;
168 for (int i = 0; i < sampleRate; i++) {
169 for (int j = 1; j < 11; j += 1)
170 waveTable[i] += pow(-1, j) * sin(j * radPerSec * i) / effectsuite_t(j);
171 }
172 }
176 void setSine() {
177 const effectsuite_t radPerSec = 2 * 3.1415926536f * timeStep;
178 for (int i = 0; i < sampleRate; i++)
179 waveTable[i] = sin(i * radPerSec);
180 }
184 void setOffSine() {
185 const effectsuite_t radPerSec = 2 * 3.1415926536f * timeStep;
186 for (int i = 0; i < sampleRate; i++)
187 waveTable[i] = (sin(i * radPerSec) + 1) * .5f;
188 }
189
190 void setNoise() {
191 is_noise = true;
192 }
193
194 bool isNoise() {
195 return is_noise;
196 }
197
201 void setDC() {
202 for (int i = 0; i < sampleRate; i++)
203 waveTable[i] = 1.0;
204 }
206 void setRamp() {
207 for (int i = 0; i < sampleRate; i++)
208 waveTable[i] = i / effectsuite_t(sampleRate);
209 }
214 effectsuite_t readNoise() {
215 const effectsuite_t lo = -1.;
216 const effectsuite_t hi = 1.;
217 return lo + static_cast<effectsuite_t>(rand()) /
218 (static_cast<effectsuite_t>(RAND_MAX / (hi - lo)));
219 }
226 void clipWave(effectsuite_t amp) {
227 if (amp < .01) {
228 amp = .01;
229 }
230
231 for (int i = 0; i < sampleRate; i++)
232 waveTable[i] = tanh(amp * waveTable[i]) / tanh(amp);
233 }
234
241 effectsuite_t readTable(effectsuite_t freq) {
242 if (freq > 0) {
243 // const effectsuite_t out = getInterpOut(tableIndex);
244 const effectsuite_t out = getSplineOut(tableIndex, int(freq));
245 tableIndex += freq;
246 if (tableIndex - sampleRate > 0)
248
249 return out;
250 } else {
251 return 0.;
252 }
253 }
255 for (int j = 0; j < res; j++) {
256 for (int i = 0; i < order; i++) {
257 std::cout << interpTable[i][j] << '\t';
258 }
259 std::cout << '\n';
260 }
261 }
267 effectsuite_t *polynomial_normaliser = new effectsuite_t[order];
268 if (!polynomial_normaliser) {
269 return false;
270 }
271 std::fill(polynomial_normaliser, polynomial_normaliser + order, 1);
272 effectsuite_t *alphas = new effectsuite_t[res];
273 if (!alphas) {
274 return false;
275 }
276
277 for (int i = 0; i < res; i++) {
278 alphas[i] = (i / float(res)) - 0.5;
279 }
280
281 effectsuite_t *anchors = new effectsuite_t[order];
282
283 if ((order % 2) == 0) {
284 for (int i = 0; i < order; i++) {
285 anchors[i] = -(effectsuite_t(order) - 1) * 0.5 + effectsuite_t(i);
286 std::fill(interpTable[i], interpTable[i] + res, 1);
287 }
288 } else {
289 for (int i = 0; i < order; i++) {
290 anchors[i] = (-(effectsuite_t(order)) * 0.5) + effectsuite_t(i);
291 }
292 }
293
294 // loop for every value of alpha
295 for (int q = 0; q < res; q++) {
296 // loop for sub polynomial
297 for (int j = 0; j < order; j++) {
298 // loop for each point in subpoly
299 for (int m = 0; m < order; m++) {
300 if (m != j) {
301 if (q == 0) {
302 polynomial_normaliser[j] =
303 polynomial_normaliser[j] * (anchors[j] - anchors[m]);
304 }
305 interpTable[j][q] *= (alphas[q] - anchors[m]);
306 }
307 }
308 interpTable[j][q] /= polynomial_normaliser[j];
309 }
310 }
311
312 delete[] polynomial_normaliser;
313 delete[] alphas;
314 delete[] anchors;
315 return true;
316 }
317
318protected:
324 waveTable = new effectsuite_t[sampleRate];
325 assert(waveTable!=nullptr);
326 if (!waveTable) {
327 return false;
328 }
329 std::fill(waveTable, waveTable + sampleRate, 0);
330 return true;
331 }
338 effectsuite_t getInterpOut(effectsuite_t bufferIndex) {
339 const int order = 4;
340 const int orderHalf = order * .5;
341 const int res = 100;
342 effectsuite_t interpOut = 0;
343 int intBufferIndex = floor(bufferIndex);
344 int alphaIndex = int(floor((bufferIndex - intBufferIndex) * res));
345
346 for (int i = 0; i < order; i++) {
347 int interpIndex =
348 (((i + 1 - orderHalf) + intBufferIndex) + sampleRate) % sampleRate;
349 interpOut += (interpTable[i][alphaIndex]) * (waveTable[interpIndex]);
350 }
351 return interpOut;
352 }
353
365 effectsuite_t getSplineOut(effectsuite_t bufferIndex, int freq) {
366 if (freq < 1) {
367 freq = 1;
368 }
369 const int n0 = floor(bufferIndex);
370 const int n1 = (n0 + freq) % sampleRate;
371 const int n2 = (n0 + (2 * freq)) % sampleRate;
372 const effectsuite_t alpha = bufferIndex - n0;
373 const effectsuite_t a = waveTable[n1];
374 const effectsuite_t c = ((3 * (waveTable[n2] - waveTable[n1])) -
375 (3 * (waveTable[n1] - waveTable[n0]))) *
376 .25;
377 const effectsuite_t b = (waveTable[n2] - waveTable[n1]) - ((2 * c)) / 3;
378 const effectsuite_t d = (-c) / 3;
379 return a + (b * alpha) + (c * alpha * alpha) + (d * alpha * alpha * alpha);
380 }
381
382public:
384 effectsuite_t tableIndex = 0;
388 effectsuite_t timeStep;
390 // was uninitialized in the default (no-arg) constructor -- the new
391 // destructor's delete[] would then free indeterminate memory
392 effectsuite_t *waveTable = nullptr;
393
394protected:
395 static const int order = 4;
396 static const int res = 100;
397 effectsuite_t interpTable[order][res];// = {1};
398 bool is_noise = false;
399};
400
407 template <class T, typename effectsuite_t = effectsuite_t_default>
409 public:
411 p_mod = &mod;
412 this->freq = freq;
413 }
414 bool begin(AudioInfo info) override{
415 max_value = pow(2, info.bits_per_sample)/2-1;
417 }
418 virtual T readSample() override {
419 return p_mod->isNoise() ? max_value * p_mod->readNoise() : max_value * p_mod->readTable(freq);
420 }
421
422 protected:
424 int freq;
425 float max_value=32767;
426};
427
428
438template <typename effectsuite_t = effectsuite_t_default>
440public:
442 DelayEffectBase() = default;
443
444 // deep-copies delayBuffer (owned) -- the compiler-generated (shallow) copy
445 // this replaces would leave clone and original pointing at the *same*
446 // delayBuffer, which breaks AudioEffectStreamT's per-channel cloning for
447 // stereo (and would double-free delayBuffer when both are destroyed,
448 // since ~DelayEffectBase() below does free it). interpolationTable is a
449 // shared *static* lookup table -- one per DelayEffectBase<effectsuite_t>
450 // instantiation, not per-instance state -- so it's correctly left alone
451 // here.
463
464 DelayEffectBase(int bufferSizeSamples) {
465 error = setDelayBuffer(bufferSizeSamples);
466 delayTimeSamples = bufferSizeSamples;
467 if (interpolationTable == nullptr) {
469 }
470 }
471
474 if (delayBuffer != nullptr)
475 delete[] delayBuffer;
476 }
477
482 void setupDelayEffectBase(const int bufferSizeSamples) {
483 error = setDelayBuffer(bufferSizeSamples);
484 delayTimeSamples = bufferSizeSamples;
485 }
486
487protected:
495 static effectsuite_t **setInterpolationTable() {
496 const int order = interpOrder;
497 const int res = interpResolution;
498 effectsuite_t **interpTable = new effectsuite_t *[order];
499 if (!interpTable) {
500 return NULL;
501 }
502
503 for (int i = 0; i < order; i++) {
504 interpTable[i] = new effectsuite_t[res + 1];
505 if (!interpTable[i]) {
506 return NULL;
507 }
508 std::fill(interpTable[i], interpTable[i] + res, 1);
509 }
510
511 effectsuite_t *polynomial_normaliser = new effectsuite_t[order];
512 if (!polynomial_normaliser) {
513 return NULL;
514 }
515 std::fill(polynomial_normaliser, polynomial_normaliser + order, 1);
516 effectsuite_t *alphas = new effectsuite_t[res];
517 if (!alphas) {
518 return NULL;
519 }
520
521 for (int i = 0; i < res; i++) {
522 alphas[i] = (i / float(res)) - 0.5;
523 }
524
525 effectsuite_t *anchors = new effectsuite_t[order];
526
527 if ((order % 2) == 0) {
528 for (int i = 0; i < order; i++) {
529 anchors[i] = -(effectsuite_t(order) - 1) * 0.5 + effectsuite_t(i);
530 }
531 } else {
532 for (int i = 0; i < order; i++) {
533 anchors[i] = (-(effectsuite_t(order)) * 0.5) + effectsuite_t(i);
534 }
535 }
536
537 // loop for every value of alpha
538 for (int q = 0; q < res; q++) {
539 // loop for sub polynomial
540 for (int j = 0; j < order; j++) {
541 // loop for each point in subpoly
542 for (int m = 0; m < order; m++) {
543 if (m != j) {
544 if (q == 0) {
545 polynomial_normaliser[j] =
546 polynomial_normaliser[j] * (anchors[j] - anchors[m]);
547 }
548 interpTable[j][q] *= (alphas[q] - anchors[m]);
549 }
550 }
551 interpTable[j][q] /= polynomial_normaliser[j];
552 }
553 }
554 delete[] polynomial_normaliser;
555 delete[] alphas;
556 delete[] anchors;
557 return interpTable;
558 }
559
560 // void printInterpTable() {
561 // for (int j = 0; j < interpResolution; j++) {
562 // for (int i = 0; i < interpOrder; i++) {
563 // printf("index %d: %.2f \t", i, interpolationTable[i][j]);
564 // }
565 // printf("\n");
566 // }
567 // }
568
569protected:
576 bool setDelayBuffer(int bufferSizeSamples) {
577 maxDelayBufferSize = bufferSizeSamples;
578 delayBuffer = new effectsuite_t[maxDelayBufferSize];
579 if (!delayBuffer) {
580 return false;
581 }
583 return true;
584 }
585
590 void storeSample(effectsuite_t inputSample) {
591 delayBuffer[currentDelayWriteIndex] = inputSample;
592 }
593
601
606 void incDelayBuffReadIndex(effectsuite_t indexInc) {
607 currentDelayReadIndex += indexInc;
608 if (currentDelayReadIndex >= effectsuite_t(delayTimeSamples)) {
610 }
611 if (currentDelayReadIndex < 0) {
613 }
614 }
615
620 void setDelayBuffReadIndex(effectsuite_t index) {
621 currentDelayReadIndex = index;
622 if (currentDelayReadIndex >= effectsuite_t(delayTimeSamples)) {
624 }
625 if (currentDelayReadIndex < 0) {
627 }
628 }
629
635 void delaySample(effectsuite_t inputSample) {
636 storeSample(inputSample);
638 }
644 effectsuite_t getInterpolatedOut(effectsuite_t bufferIndex) {
645 const int order = interpOrder;
646 const int orderHalf = order * .5;
647 const int res = interpResolution;
648 effectsuite_t interpOut = 0;
649 int intBufferIndex = floor(bufferIndex);
650 int alphaIndex = int(floor((bufferIndex - intBufferIndex) * res));
651
652 for (int i = 0; i < order; i++) {
653 int interpIndex = (i + 1 - orderHalf) + intBufferIndex;
654 if (interpIndex < 0 || (interpIndex >= maxDelayBufferSize)) {
655 if (interpIndex < 0) {
656 interpIndex = maxDelayBufferSize + interpIndex;
657 } else {
658 interpIndex = interpIndex - maxDelayBufferSize;
659 }
660 }
661
662 interpOut +=
663 (interpolationTable[i][alphaIndex]) * (delayBuffer[interpIndex]);
664 }
665 return interpOut;
666 }
667
668protected: // member variables
670 effectsuite_t *delayBuffer = 0;
672 int maxDelayBufferSize = 441000;
674 int delayTimeSamples = 44100;
676 effectsuite_t currentDelayReadIndex = 0;
677 static const int interpOrder = 4;
678 static const int interpResolution = 1000;
686 static effectsuite_t **interpolationTable;
687
689 bool error;
690};
691
692template <typename effectsuite_t>
694
703template <typename effectsuite_t = effectsuite_t_default>
704class FilterEffectBase : public EffectSuiteBase<effectsuite_t> {
705public:
708
709 // deep-copies the owned filter/rms buffers -- the compiler-generated
710 // (shallow) copy this replaces would leave clone and original pointing
711 // at the *same* buffers, which breaks AudioEffectStreamT's per-channel
712 // cloning for stereo (each channel's IIR filter state must be
713 // independent, or one channel's audio corrupts the other's).
719
720 // firCoefficients/iirCoefficients/firBuffer/iirBuffer may be allocated
721 // wider than filterOrder (allocateBufferMemory() allocates coefficient
722 // arrays at a fixed 22), but applyFilter() and everything downstream of
723 // setup only ever reads indices [0, filterOrder), so copying exactly
724 // filterOrder elements is always enough to preserve behavior.
725 if (filterOrder > 0 && copy.firCoefficients != nullptr) {
726 firCoefficients = new float[filterOrder];
728 }
729 if (filterOrder > 0 && copy.iirCoefficients != nullptr) {
730 iirCoefficients = new float[filterOrder];
732 }
733 if (filterOrder > 0 && copy.firBuffer != nullptr) {
734 firBuffer = new float[filterOrder];
735 std::copy(copy.firBuffer, copy.firBuffer + filterOrder, firBuffer);
736 }
737 if (filterOrder > 0 && copy.iirBuffer != nullptr) {
738 iirBuffer = new float[filterOrder];
739 std::copy(copy.iirBuffer, copy.iirBuffer + filterOrder, iirBuffer);
740 }
741 // firTemp/iirTemp are pure scratch space used only transiently inside
742 // setChebyICoefficients() (overwritten from firCoefficients/
743 // iirCoefficients at the start of every use there), so the clone just
744 // needs its own 22-element scratch buffers, not copies of the old
745 // contents.
746 if (copy.firTemp != nullptr) {
747 firTemp = new float[22];
748 std::fill(firTemp, firTemp + 22, 0);
749 }
750 if (copy.iirTemp != nullptr) {
751 iirTemp = new float[22];
752 std::fill(iirTemp, iirTemp + 22, 0);
753 }
754
755 rmsBuffer = new effectsuite_t[rmsWindowSize];
756 std::copy(copy.rmsBuffer, copy.rmsBuffer + rmsWindowSize, rmsBuffer);
757 }
758
761 delete[] firCoefficients;
762 delete[] iirCoefficients;
763 delete[] firTemp;
764 delete[] iirTemp;
765 delete[] firBuffer;
766 delete[] iirBuffer;
767 delete[] rmsBuffer;
768 }
769
776 virtual effectsuite_t applyFilter(effectsuite_t sampVal) {
777 // native float in/out at this boundary; see the member declarations
778 // below for why the IIR recursion itself stays float
779 float outSample = 0;
780 firBuffer[bufferIndex] = (float)sampVal;
781
782 for (int j = 0; j < filterOrder; j++) {
783 int i = ((bufferIndex - j) + filterOrder) % filterOrder;
784 outSample +=
786 }
787
788 iirBuffer[bufferIndex] = outSample;
790
791 return outSample;
792 }
793
794 virtual effectsuite_t processFloat(effectsuite_t inputSample) override {
795 return applyFilter(inputSample);
796 }
797
799 virtual effect_t process(effect_t inputSample) override {
800 return this->active_flag ? (effect_t)(32767.0 * processFloat(static_cast<effectsuite_t>(inputSample)/32767.0)) : inputSample;
801 }
802
808 effectsuite_t envelope(effectsuite_t sample) { return applyFilter(rms(sample)); }
809
810 // void printBuffers() {
811 // printf("FIRb\t\tIIRb\n");
812 // for (int i = 0; i < filterOrder; i++) {
813 // printf("%.4e\t%.4e\n", firBuffer[i], iirBuffer[i]);
814 // }
815 // printf("\n");
816 // }
817
818 // void printCoefs() {
819 // printf("FIR\t\tIIR\n");
820 // for (int i = 0; i < filterOrder; i++) {
821 // printf("%.4e\t%.4e\n", firCoefficients[i], iirCoefficients[i]);
822 // }
823 // printf("\n");
824 // }
825
837 // Coefficient derivation chains dozens of transcendental calls and
838 // differences of near-equal quantities -- but it only runs at
839 // setup/reconfiguration time, never per-sample (EnvelopeFilter is the
840 // one exception, and it's already documented as a separate, unresolved
841 // hotspot), so it costs nothing to keep it in native float, matching
842 // firCoefficients/iirCoefficients' own type (see their declarations for
843 // why applyFilter()'s IIR recursion needs float precision).
844 bool setChebyICoefficients(effectsuite_t cutFreqIn, bool shelfType, effectsuite_t rippleIn) {
845 const float cutFreq = (float)cutFreqIn;
846 const float ripple = (float)rippleIn;
847
848 // NOTE: coefficient buffers must be cleared as are additive in the
849 // following code
850 std::fill(firCoefficients, firCoefficients + 22, 0);
851 std::fill(iirCoefficients, iirCoefficients + 22, 0);
852
853 float poles = (float)filterOrder - 1;
854 int order = (int)poles;
855
856 firCoefficients[2] = 1;
857 iirCoefficients[2] = 1;
858
859 float Es, Vx, Kx;
860 if (ripple != 0) {
861 Es = sqrt(pow(1 / (1 - ripple), 2) - 1);
862 Vx = (1 / poles) * log(1 / Es + sqrt(1 / (pow(Es, 2)) + 1));
863 Kx = (1 / poles) * log(1 / Es + sqrt(1 / (pow(Es, 2)) - 1));
864 Kx = cosh(Kx);
865 } else {
866 Vx = 1;
867 Kx = 1;
868 }
869
870 const float T = 2.0f * tan(.5f);
871 const float W = 2.0f * (float)PI * cutFreq;
872
873 float K;
874
875 if (shelfType == 0)
876 {
877 K = sin(.5f - W / 2) / sin(.5f + W / 2);
878 } else
879 {
880
881 K = -cos(.5f + W / 2) / cos(W / 2 - .5f);
882 }
883
885 for (int i = 0; i < (order / 2); i++) {
887 const float alpha = (float)PI / (2 * poles) + (i - 1) * ((float)PI / poles);
888
889 float Rp, Ip;
890 if (ripple != 0) {
891 Rp = -cos(alpha) * sinh(Vx) / Kx;
892 Ip = sin(alpha) * cosh(Vx) / Kx;
893 } else {
894 Rp = -cos(alpha);
895 Ip = sin(alpha);
896 }
897
898 const float M = pow(Rp, 2) + pow(Ip, 2);
899 const float D = 4 - 4 * Rp * T + M * T;
900
901 const float X0 = (pow(T, 2)) / D;
902 const float X1 = (2 * pow(T, 2)) / D;
903 const float X2 = X0;
904
905 const float Y1 = (8 - (2 * M * pow(T, 2))) / D;
906 const float Y2 = (-4 - 4 * Rp * T - M * T) / D;
907
908 // renamed and inverted from original algorithm
909 const float _D1 = 1 / (1 + Y1 * K - Y2 * pow(K, 2));
910
911 const float _A0 = (X0 - X1 * K + X2 * pow(K, 2)) * _D1;
912 float _A1 = (-2 * X0 * K + X1 + X1 * pow(K, 2) - 2 * X2 * K) * _D1;
913 const float _A2 = (X0 * pow(K, 2) - X1 * K + X2) * _D1;
914
915 float _B1 = (2 * K + Y1 + Y1 * pow(K, 2) - 2 * Y2 * K) * _D1;
916 const float B2 = (-(pow(K, 2)) - Y1 * K + Y2) * _D1;
917
918 if (shelfType == 1) {
919 _A1 = -_A1;
920 _B1 = -_B1;
921 }
922
923 for (int j = 0; j < 22; j++) {
924 firTemp[j] = firCoefficients[j];
925 iirTemp[j] = iirCoefficients[j];
926 }
927 for (int j = 2; j < 22; j++) {
928 firCoefficients[j] =
929 _A0 * firTemp[j] + _A1 * firTemp[j - 1] + _A2 * firTemp[j - 2];
930 iirCoefficients[j] =
931 iirTemp[j] - _B1 * iirTemp[j - 1] - B2 * iirTemp[j - 2];
932 }
933 }
934
935 iirCoefficients[2] = 0;
936 for (int j = 0; j < filterOrder; j++) {
938 iirCoefficients[j] = -iirCoefficients[j + 2];
939 }
941 float SA = 0;
942 float SB = 0;
943 if (shelfType == 0) {
944 for (int j = 0; j < filterOrder; j++) {
945 SA += firCoefficients[j];
946 SB += iirCoefficients[j];
947 }
948 } else {
949 for (int j = 0; j < order; j++) {
950 SA += firCoefficients[j] * pow(-1, j);
951 SB += iirCoefficients[j] * pow(-1, j);
952 }
953 }
954
955 const float gain = SA / (1 - SB);
956 for (int j = 0; j < filterOrder; j++) {
957 firCoefficients[j] /= gain;
958 }
959
960 return true;
961 }
962
963protected:
974 bool changeChebyICoefficients(effectsuite_t cutFreq, bool shelfType, effectsuite_t ripple,
975 int poles) {
976 filterOrder = poles + 1;
977 clearMemory();
979 setChebyICoefficients(cutFreq, shelfType, ripple);
980
981 return true;
982 }
983
988 bool setSimpleLpf(int order) {
989 filterOrder = order;
990 clearMemory();
992 firCoefficients = new float[filterOrder];
993 iirCoefficients = new float[filterOrder];
995 int coef = 1;
996 float gain = 0;
997 for (int j = 0; j < filterOrder; j++) {
998 if (j == 0) {
999 coef = 1;
1000 } else {
1001 coef = coef * (filterOrder - j) / j;
1002 }
1003
1004 firCoefficients[j] = (float)coef;
1005 gain += firCoefficients[j];
1006 }
1007
1008 // was `<=`: an off-by-one that wrote one element past the
1009 // filterOrder-sized array (pre-existing, unrelated to the float type
1010 // change on this line)
1011 for (int j = 0; j < filterOrder; j++) {
1012 firCoefficients[j] /= gain;
1013 }
1014
1015 return true;
1016 }
1017
1018protected:
1021 bufferIndex++;
1023 }
1024
1030 if (firCoefficients) {
1031 delete[] firCoefficients;
1032 }
1033
1034 if (iirCoefficients) {
1035 delete[] iirCoefficients;
1036 }
1037 }
1038
1044 if (firBuffer) {
1045 delete[] firBuffer;
1046 }
1047
1048 if (iirBuffer) {
1049 delete[] iirBuffer;
1050 }
1051 firBuffer = new float[filterOrder];
1052 iirBuffer = new float[filterOrder];
1053 std::fill(firBuffer, firBuffer + filterOrder, 0);
1054 std::fill(iirBuffer, iirBuffer + filterOrder, 0);
1055
1056 if (firCoefficients) {
1057 delete[] firCoefficients;
1058 }
1059
1060 if (iirCoefficients) {
1061 delete[] iirCoefficients;
1062 }
1063
1064 if (firTemp) {
1065 delete[] firTemp;
1066 }
1067
1068 if (iirTemp) {
1069 delete[] iirTemp;
1070 }
1071
1072 firCoefficients = new float[22];
1073 iirCoefficients = new float[22];
1074 firTemp = new float[22];
1075 iirTemp = new float[22];
1076 std::fill(firCoefficients, firCoefficients + 22, 0);
1077 std::fill(iirCoefficients, iirCoefficients + 22, 0);
1078 std::fill(firTemp, firTemp + 22, 0);
1079 std::fill(iirTemp, iirTemp + 22, 0);
1080 }
1081
1083 effectsuite_t rms(effectsuite_t sample) {
1084 rmsBuffer[rmsBufferIndex] = sample;
1085 effectsuite_t rmsValue = 0;
1086 for (int j = 0; j < rmsBufferIndex; j++) {
1087 int i = ((rmsBufferIndex - j) + rmsWindowSize) % rmsWindowSize;
1088 rmsValue += rmsBuffer[i] * rmsBuffer[i];
1089 }
1090
1091 // printf("samp: %e\tsum: %e\n", sample, rmsValue);
1092 rmsValue /= rmsWindowSize;
1093 rmsValue = sqrt(rmsValue);
1094
1097
1098 return rmsValue;
1099 }
1100
1101protected:
1102 // These stay native float regardless of PREFER_FIXEDPOINT, unlike the
1103 // rest of this file: applyFilter()'s IIR recursion feeds firBuffer/
1104 // iirBuffer back into itself every sample, and soft_float_t's ~15-bit
1105 // mantissa (vs float's ~24-bit) lets that feedback state slowly diverge
1106 // from a real-FPU reference -- measured ~11% peak drift, growing over
1107 // the run, for a Chebyshev filter's feedback state. Filter *design*
1108 // (setChebyICoefficients(), setSimpleLpf()) only runs at
1109 // setup/reconfiguration time, never per-sample, so there's no per-sample
1110 // FPU cost being traded away by keeping these float either.
1111
1122 float *firTemp = 0;
1124 float *iirTemp = 0;
1127 float *firBuffer = 0;
1130 float *iirBuffer = 0;
1135 /***/
1138 const int rmsWindowSize = 128;
1142 effectsuite_t *rmsBuffer = new effectsuite_t[rmsWindowSize];
1143
1144};
1145
1152template <typename effectsuite_t = effectsuite_t_default>
1153class SimpleLPF : public FilterEffectBase<effectsuite_t> {
1154public:
1161 SimpleLPF(effectsuite_t cutoff, int order) {
1162 this->changeChebyICoefficients(cutoff, false, .1, order);
1163 };
1164
1165 SimpleLPF(SimpleLPF &copy) = default;
1166
1168 ~SimpleLPF() = default;
1169
1171 return new SimpleLPF(*this);
1172 }
1173
1174};
1175
1184template <typename effectsuite_t = effectsuite_t_default>
1185class SimpleChorus : public DelayEffectBase<effectsuite_t>,
1186 public ModulationBaseClass<effectsuite_t>,
1187 public SimpleLPF<effectsuite_t>{
1188public:
1194// SimpleChorus() : SimpleLPF(0.0001, 4) {}
1195 SimpleChorus(int extSampleRate=44100) :
1196 DelayEffectBase<effectsuite_t>(static_cast<int>(0.031 * extSampleRate)),
1197 ModulationBaseClass<effectsuite_t>(extSampleRate),
1198 SimpleLPF<effectsuite_t>(0.0001, 4) {
1199 swing = 0.005 * this->sampleRate;
1200 base = 0.015 * this->sampleRate;
1201 if (this->sampleRate != 0)
1202 setRandLfo();
1203 }
1204
1206
1207 ~SimpleChorus() = default;
1208
1214 virtual effectsuite_t processFloat(effectsuite_t inputSample) override {
1215 this->delaySample(inputSample);
1216 const effectsuite_t waveDelay = getModSignal();
1217 const effectsuite_t delayAmount =
1218 ((int(this->currentDelayWriteIndex - waveDelay) + this->delayTimeSamples) %
1219 this->delayTimeSamples) +
1220 ((this->currentDelayWriteIndex - waveDelay) -
1221 trunc(this->currentDelayWriteIndex - waveDelay));
1222 const effectsuite_t out = .0 * inputSample + 1. * this->getInterpolatedOut(delayAmount);
1223 return out;
1224 }
1225
1230 void setupChorus(effectsuite_t extSampleRate) {
1231 this->setupModulationBaseClass(extSampleRate);
1232 this->setupDelayEffectBase(effectsuite_t(extSampleRate) * .1);
1233 // SimpleLPF(0.0004,4)
1234 this->setChebyICoefficients(0.00005, false, 0);
1235
1236 swing = readSpeed * extSampleRate * 5;
1237 base = readSpeed * extSampleRate * 20;
1238 setRandLfo();
1239 }
1240
1246 void setSwing(effectsuite_t swingAmount) { swing = swingAmount * this->sampleRate; }
1247
1252 void setBase(effectsuite_t baseAmount) { base = baseAmount * this->sampleRate; }
1253
1254 SimpleChorus* clone() override {
1255 return new SimpleChorus(*this);
1256 }
1257
1258protected:
1262 effectsuite_t swing;
1264 effectsuite_t base;
1266 effectsuite_t modMin = .5;
1268 effectsuite_t modMax = .5;
1270 effectsuite_t modNorm = 1 / (modMax - modMin);
1271 const effectsuite_t readSpeed = ((this->readNoise() + 1) * .5) * .0005;
1272
1278 effectsuite_t getModSignal() { return (this->readTable(readSpeed) * swing) + base; }
1279
1280 void setRandLfo() {
1281 std::fill(this->iirBuffer, this->iirBuffer + this->filterOrder, .5);
1282 for (int i = 0; i < this->sampleRate; i++) {
1283 this->waveTable[i] = (this->readNoise() + 1) * .5;
1284 // waveTable[i] = applyFilter((readNoise()+1)*.5);
1285 if (this->waveTable[i] < modMin)
1286 modMin = this->waveTable[i];
1287 if (this->waveTable[i] > modMax) {
1288 modMax = this->waveTable[i];
1289 }
1290 }
1291
1292 modNorm = 1 / (modMax - modMin);
1293
1294 // normalises the delay signal
1295 for (int i = 0; i < this->sampleRate; i++) {
1296 this->waveTable[i] -= modMin;
1297 this->waveTable[i] *= modNorm;
1298 }
1299
1300 // setOffSine();
1301
1302 // this code fades out at the end and fades in at the start
1303 // to avoid any discontinuities int the signal.
1304 // const int fadeSize = 10000;
1305 // const effectsuite_t fadeSpeed = 2*M_PI/fadeSize;
1306 // for (int i = 0; i < fadeSize; i++)
1307 // {
1308 // const int fadeIndex = ((sampleRate-fadeSize/2)+i)%sampleRate;
1309 // waveTable[fadeIndex] *= (1+cos(fadeSpeed*i))*.5;
1310 // }
1311 }
1312};
1313
1320template <typename effectsuite_t = effectsuite_t_default>
1321class FilteredDelay : public DelayEffectBase<effectsuite_t>, public FilterEffectBase<effectsuite_t> {
1322public:
1324 FilteredDelay(int delayInSamples, int sample_rate=44100) : DelayEffectBase<effectsuite_t>(sample_rate) {
1325 this->delayTimeSamples = delayInSamples;
1326 this->changeChebyICoefficients(.05, true, .1, 4);
1327 };
1328
1330
1332 ~FilteredDelay() = default;
1333
1340 void setDelayGain(effectsuite_t gain) {
1341 capGain(gain);
1342 delayGain = gain;
1343 }
1344
1352 void setFeedbackGain(effectsuite_t gain) {
1353 capGain(gain);
1354 feedbackGain = gain;
1355 }
1356
1358 effectsuite_t processFloat(effectsuite_t inputSample) override {
1359 this->delaySample(
1360 this->applyFilter((inputSample * delayGain) +
1362 const effectsuite_t out = this->getInterpolatedOut(this->currentDelayWriteIndex) + inputSample;
1363 return out;
1364 }
1365
1366 effect_t process(effect_t inputSample) override {
1367 return this->active_flag ? (effect_t)(32767.0 * processFloat(static_cast<effectsuite_t>(inputSample)/32767.0)) : inputSample;
1368 }
1369
1370 FilteredDelay *clone() override {
1371 return new FilteredDelay(*this);
1372 }
1373
1374protected:
1379 void capGain(effectsuite_t &gain) {
1380 if (gain > 1.) {
1381 gain = 1.;
1382 } else if (gain < -1.) {
1383 gain = -1.;
1384 }
1385 return;
1386 }
1387
1388protected:
1389 effectsuite_t delayGain = .707, feedbackGain = 0.0;
1390};
1391
1401template <typename effectsuite_t = effectsuite_t_default>
1402class SimpleDelay : public DelayEffectBase<effectsuite_t>, public EffectSuiteBase<effectsuite_t> {
1403public:
1409 // was missing the DelayEffectBase(maxDelayInSamples) base-constructor
1410 // call entirely -- delayBuffer stayed null and processFloat() below
1411 // dereferenced it immediately (pre-existing bug, fixed here since this
1412 // constructor needed touching for the template conversion anyway)
1413 SimpleDelay(int maxDelayInSamples=8810, int samplingRate=44100)
1414 : DelayEffectBase<effectsuite_t>(maxDelayInSamples) {
1415 writeHeadIndex = 0;
1416 readHeadIndex = 1;
1417 currentDelaySamples = maxDelayInSamples;
1418 targetDelaySamples = maxDelayInSamples;
1420 }
1421
1422 SimpleDelay(SimpleDelay &copy) = default;
1423
1425 ~SimpleDelay() = default;
1426
1434 void setDelayGain(effectsuite_t gain) {
1435 capGain(gain);
1436 delayGain = gain;
1437 }
1438
1446 void setFeedbackGain(effectsuite_t gain) {
1447 capGain(gain);
1448 feedbackGain = gain;
1449 }
1450
1456 effectsuite_t processFloat(effectsuite_t inputSample) override {
1457 // write sample
1458 this->delayBuffer[writeHeadIndex] = inputSample;
1461
1462 // read sample
1463 effectsuite_t outSample = getSplineOut(readHeadIndex) + (inputSample * 1);
1464 if (delayTimeChanged) {
1465 count++;
1466 const effectsuite_t difference = (currentDelaySamples - targetDelaySamples);
1467 const effectsuite_t increment = delayIncrement * (difference / fabs(difference));
1468 currentDelaySamples -= increment;
1469 readHeadIndex += 1 + increment;
1471 if (count > floor(delayTransitionTimeInSamples)) {
1474 delayTimeChanged = false;
1475 }
1476 } else {
1477 // soft_float_t doesn't implement operator++ (no other call site in
1478 // the codebase needs it, so the class doesn't carry the extra API)
1481 }
1482 return outSample;
1483 }
1484
1485 effect_t process(effect_t inputSample) override {
1486 return this->active_flag ? (effect_t)(32767.0 * processFloat(static_cast<effectsuite_t>(inputSample)/32767.0)) : inputSample;
1487 }
1488
1493 void setupSimpleDelay(int delayInSamples) {
1494 this->setupDelayEffectBase(delayInSamples);
1495 }
1500 void setDelayTime(effectsuite_t delayInSamples) {
1501 delayTimeChanged = true;
1502 targetDelaySamples = delayInSamples;
1503 const effectsuite_t delayTimeDifference = currentDelaySamples - targetDelaySamples;
1504 delayIncrement = delayTimeDifference / delayTransitionTimeInSamples;
1505 count = 0;
1506 }
1511 void setDelayTransitionTime(effectsuite_t seconds) {
1512 delayTransitionTime = seconds;
1514 }
1515
1516 SimpleDelay* clone() override {
1517 return new SimpleDelay(*this);
1518 }
1519
1520protected:
1525 void capGain(effectsuite_t &gain) {
1526 if (gain > 1.) {
1527 gain = 1.;
1528 } else if (gain < -1.) {
1529 gain = -1.;
1530 }
1531 return;
1532 }
1541 effectsuite_t getSplineOut(effectsuite_t bufferIndex) {
1542 const int n0 = floor(bufferIndex);
1543 const int n1 = (n0 + 1) % this->maxDelayBufferSize;
1544 const int n2 = (n0 + 2) % this->maxDelayBufferSize;
1545 const effectsuite_t alpha = bufferIndex - n0;
1546
1547 const effectsuite_t a = this->delayBuffer[n1];
1548 const effectsuite_t c = ((3 * (this->delayBuffer[n2] - this->delayBuffer[n1])) -
1549 (3 * (this->delayBuffer[n1] - this->delayBuffer[n0]))) *
1550 0.25;
1551 const effectsuite_t b = (this->delayBuffer[n2] - this->delayBuffer[n1]) - (2 * c * 0.33333);
1552 const effectsuite_t d = (-c) * 0.33333;
1553 return a + (b * alpha) + (c * alpha * alpha) + (d * alpha * alpha * alpha);
1554 }
1555
1556protected: // member vairables
1557 effectsuite_t delayGain = .707;
1558 effectsuite_t feedbackGain = 0.;
1559 effectsuite_t readHeadIndex;
1560 unsigned int writeHeadIndex;
1561 effectsuite_t currentDelaySamples;
1562 effectsuite_t targetDelaySamples;
1565 effectsuite_t delayIncrement;
1568 effectsuite_t invDelayIncrement;
1570 effectsuite_t delayTransitionTime;
1573 int count = 0;
1574 bool delayTimeChanged = false;
1575};
1576
1587template <typename effectsuite_t = effectsuite_t_default>
1588class SimpleFlanger : public DelayEffectBase<effectsuite_t>, public EffectSuiteBase<effectsuite_t> {
1589public:
1594 SimpleFlanger() = default;
1596 SimpleFlanger(effectsuite_t extSampleRate=44100)
1597 : DelayEffectBase<effectsuite_t>(static_cast<int>(extSampleRate * 0.02)) {}
1598
1600 ~SimpleFlanger() = default;
1601
1608 void setEffectGain(effectsuite_t gain) { effectGain = capGain(gain); }
1609
1614 void setDepth(const effectsuite_t depth) {
1615 if (depth > effectsuite_t(this->delayTimeSamples))
1616 modulationDepth = effectsuite_t(this->delayTimeSamples) - 1;
1617 else
1618 modulationDepth = depth;
1619 }
1620
1625 void setRate(const effectsuite_t rate) {
1626 modulationRate = rate;
1627 setAngleDelta();
1628 }
1629
1636 void setEffectParams(effectsuite_t gain, effectsuite_t depth, effectsuite_t rate) {
1637 setEffectGain(gain);
1638 setDepth(depth);
1639 setRate(rate);
1640 }
1641
1643 effectsuite_t processFloat(effectsuite_t inputSample) override {
1644 this->delaySample(inputSample);
1645 const effectsuite_t out = ((1 - fabs(effectGain * .2)) * (inputSample) +
1648 return out;
1649 }
1650
1651 void setupSimpleFlanger(effectsuite_t extSampleRate) {
1652 this->setupDelayEffectBase(extSampleRate * .02);
1653 timeStep = 1. / extSampleRate;
1654 setEffectParams(.707, extSampleRate * .02, .1);
1655 }
1656
1657 SimpleFlanger* clone() override {
1658 return new SimpleFlanger(*this);
1659 }
1660
1661protected:
1666 effectsuite_t capGain(effectsuite_t gain) {
1667 if (gain > 1.) {
1668 gain = 1.;
1669 } else if (gain < -1.) {
1670 gain = -1.;
1671 }
1672 return gain;
1673 }
1674
1679 const effectsuite_t cyclesPerSample = modulationRate * timeStep;
1680 angleDelta = cyclesPerSample * 2.0f * PI;
1681 }
1682
1689 (modulationDepth * (1 + (sin(modulationAngle))))) -
1690 12;
1692 ((int(modulationIndex) + this->delayTimeSamples) % this->delayTimeSamples) +
1694 }
1695
1696protected:
1697
1698 effectsuite_t modulationDepth = 1000, modulationRate = 0, effectGain = .01;
1699
1700 effectsuite_t modulationIndex = 0;
1701
1703 effectsuite_t timeStep = 1. / 44100.;
1704
1707
1708 // const effectsuite_t cyclesPerSample = modulationRate * timeStep;
1710 effectsuite_t angleDelta = 2.0f * PI * timeStep;
1711};
1712
1719template <typename effectsuite_t = effectsuite_t_default>
1720class EnvelopeFilter : public FilterEffectBase<effectsuite_t> {
1721public:
1724 // NOTE: Initialising chebyshev coeffcients allocates memory, perhaps alter
1725 // so that memory is already pre allocated
1726 this->changeChebyICoefficients(.01, false, .1, 4);
1727 envelopeFollower.setChebyICoefficients(.00006, false, 0);
1728 };
1729
1731 ~EnvelopeFilter() = default;
1738 effectsuite_t processFloat(effectsuite_t sample) {
1739 this->setChebyICoefficients(0.001 + envelopeFollower.envelope(2 * sample), false,
1740 .1); // Offset avoids zero cutoff value
1741 return this->applyFilter(sample);
1742 }
1743
1744 EnvelopeFilter* clone() override {
1745 return new EnvelopeFilter(*this);
1746 }
1747
1748protected:
1754};
1755
1756} // namespace effectsuite_tools
1757
#define PI
Definition AudioEffectsSuite.h:28
#define assert(T)
Definition avr.h:10
Abstract Base class for Sound Effects.
Definition AudioEffect.h:24
bool active_flag
Definition AudioEffect.h:47
A Base class for delay based digital effects. Provides the basic methods that are shared amongst Flan...
Definition AudioEffectsSuite.h:439
void setDelayBuffReadIndex(effectsuite_t index)
Definition AudioEffectsSuite.h:620
~DelayEffectBase()
Definition AudioEffectsSuite.h:473
void storeSample(effectsuite_t inputSample)
Definition AudioEffectsSuite.h:590
static effectsuite_t ** setInterpolationTable()
Definition AudioEffectsSuite.h:495
int currentDelayWriteIndex
Definition AudioEffectsSuite.h:675
static const int interpResolution
Definition AudioEffectsSuite.h:678
DelayEffectBase(int bufferSizeSamples)
Definition AudioEffectsSuite.h:464
static const int interpOrder
Definition AudioEffectsSuite.h:677
DelayEffectBase(DelayEffectBase &copy)
Definition AudioEffectsSuite.h:452
effectsuite_t currentDelayReadIndex
Definition AudioEffectsSuite.h:676
void incDelayBuffWriteIndex()
Definition AudioEffectsSuite.h:597
bool error
Definition AudioEffectsSuite.h:689
void setupDelayEffectBase(const int bufferSizeSamples)
Definition AudioEffectsSuite.h:482
int delayTimeSamples
Definition AudioEffectsSuite.h:674
int maxDelayBufferSize
Definition AudioEffectsSuite.h:672
bool setDelayBuffer(int bufferSizeSamples)
Definition AudioEffectsSuite.h:576
effectsuite_t * delayBuffer
Definition AudioEffectsSuite.h:670
effectsuite_t getInterpolatedOut(effectsuite_t bufferIndex)
Definition AudioEffectsSuite.h:644
void delaySample(effectsuite_t inputSample)
Definition AudioEffectsSuite.h:635
void incDelayBuffReadIndex(effectsuite_t indexInc)
Definition AudioEffectsSuite.h:606
static effectsuite_t ** interpolationTable
Table of interpolation values as a 2D array indexed by interpolationTable[pointIndex][alphaIndex]....
Definition AudioEffectsSuite.h:686
Base Class for Effects.
Definition AudioEffectsSuite.h:63
EnvelopeFilter.
Definition AudioEffectsSuite.h:1720
SimpleLPF< effectsuite_t > envelopeFollower
Definition AudioEffectsSuite.h:1753
EnvelopeFilter()
Definition AudioEffectsSuite.h:1723
effectsuite_t processFloat(effectsuite_t sample)
Definition AudioEffectsSuite.h:1738
EnvelopeFilter * clone() override
Definition AudioEffectsSuite.h:1744
A Base class for filter based effects including methods for simple high, low and band pass filtering.
Definition AudioEffectsSuite.h:704
virtual effectsuite_t processFloat(effectsuite_t inputSample) override
Main process block for applying audio effect.
Definition AudioEffectsSuite.h:794
int samplingRate
Definition AudioEffectsSuite.h:1136
float * iirCoefficients
Definition AudioEffectsSuite.h:1120
float * firCoefficients
Definition AudioEffectsSuite.h:1116
~FilterEffectBase()
Definition AudioEffectsSuite.h:760
bool setSimpleLpf(int order)
Definition AudioEffectsSuite.h:988
virtual effectsuite_t applyFilter(effectsuite_t sampVal)
Definition AudioEffectsSuite.h:776
float * iirTemp
Definition AudioEffectsSuite.h:1124
float * iirBuffer
Definition AudioEffectsSuite.h:1130
int bufferIndex
Definition AudioEffectsSuite.h:1132
bool changeChebyICoefficients(effectsuite_t cutFreq, bool shelfType, effectsuite_t ripple, int poles)
Definition AudioEffectsSuite.h:974
effectsuite_t envelope(effectsuite_t sample)
Definition AudioEffectsSuite.h:808
float * firBuffer
Definition AudioEffectsSuite.h:1127
bool setChebyICoefficients(effectsuite_t cutFreqIn, bool shelfType, effectsuite_t rippleIn)
Definition AudioEffectsSuite.h:844
virtual effect_t process(effect_t inputSample) override
see applyFilter
Definition AudioEffectsSuite.h:799
int filterOrder
Definition AudioEffectsSuite.h:1134
FilterEffectBase()
Definition AudioEffectsSuite.h:707
FilterEffectBase(FilterEffectBase &copy)
Definition AudioEffectsSuite.h:714
int rmsBufferIndex
Definition AudioEffectsSuite.h:1140
const int rmsWindowSize
Definition AudioEffectsSuite.h:1138
void allocateBufferMemory()
Definition AudioEffectsSuite.h:1043
void clearMemory()
Definition AudioEffectsSuite.h:1029
effectsuite_t rms(effectsuite_t sample)
Definition AudioEffectsSuite.h:1083
void incBufferIndex()
Definition AudioEffectsSuite.h:1020
float * firTemp
Definition AudioEffectsSuite.h:1122
effectsuite_t * rmsBuffer
Definition AudioEffectsSuite.h:1142
Delay effect that filters the repeat delay.
Definition AudioEffectsSuite.h:1321
effectsuite_t feedbackGain
Definition AudioEffectsSuite.h:1389
FilteredDelay(FilteredDelay &copy)=default
FilteredDelay(int delayInSamples, int sample_rate=44100)
Definition AudioEffectsSuite.h:1324
effectsuite_t processFloat(effectsuite_t inputSample) override
Definition AudioEffectsSuite.h:1358
effect_t process(effect_t inputSample) override
see applyFilter
Definition AudioEffectsSuite.h:1366
FilteredDelay * clone() override
Definition AudioEffectsSuite.h:1370
effectsuite_t delayGain
Definition AudioEffectsSuite.h:1389
void capGain(effectsuite_t &gain)
Definition AudioEffectsSuite.h:1379
void setDelayGain(effectsuite_t gain)
Definition AudioEffectsSuite.h:1340
void setFeedbackGain(effectsuite_t gain)
Definition AudioEffectsSuite.h:1352
Class provides a wave table that can be populated with a number of preallocated waveforms....
Definition AudioEffectsSuite.h:93
static const int order
Definition AudioEffectsSuite.h:395
effectsuite_t readNoise()
Definition AudioEffectsSuite.h:214
void clipWave(effectsuite_t amp)
Definition AudioEffectsSuite.h:226
ModulationBaseClass(ModulationBaseClass &copy)
Definition AudioEffectsSuite.h:102
effectsuite_t tableIndex
Definition AudioEffectsSuite.h:384
void setRamp()
Definition AudioEffectsSuite.h:206
bool is_noise
Definition AudioEffectsSuite.h:398
effectsuite_t getInterpOut(effectsuite_t bufferIndex)
Definition AudioEffectsSuite.h:338
void setupModulationBaseClass(effectsuite_t extSampRate)
setup the class with a given sample rate. Basically reperforming the constructor
Definition AudioEffectsSuite.h:129
ModulationBaseClass(effectsuite_t extSampRate)
Definition AudioEffectsSuite.h:114
static const int res
Definition AudioEffectsSuite.h:396
void setSine()
Definition AudioEffectsSuite.h:176
void setSawtooth()
Definition AudioEffectsSuite.h:165
~ModulationBaseClass()
Definition AudioEffectsSuite.h:122
bool setInterpTable()
Definition AudioEffectsSuite.h:266
effectsuite_t interpTable[order][res]
Definition AudioEffectsSuite.h:397
bool isNoise()
Definition AudioEffectsSuite.h:194
void setDC()
Definition AudioEffectsSuite.h:201
void setSquare()
Definition AudioEffectsSuite.h:154
effectsuite_t getSplineOut(effectsuite_t bufferIndex, int freq)
Definition AudioEffectsSuite.h:365
void setNoise()
Definition AudioEffectsSuite.h:190
effectsuite_t * waveTable
Definition AudioEffectsSuite.h:392
effectsuite_t timeStep
Definition AudioEffectsSuite.h:388
bool allocateMemory()
Definition AudioEffectsSuite.h:323
int sampleRate
Definition AudioEffectsSuite.h:386
effectsuite_t readTable(effectsuite_t freq)
Definition AudioEffectsSuite.h:241
void setOffSine()
Definition AudioEffectsSuite.h:184
ModulationBaseClass()
Definition AudioEffectsSuite.h:96
void printInterpTable()
Definition AudioEffectsSuite.h:254
void setTriangle()
Definition AudioEffectsSuite.h:141
Simple Chorus effect with a single delay voice and mono output Chorus is effective between 15 and 20 ...
Definition AudioEffectsSuite.h:1187
virtual effectsuite_t processFloat(effectsuite_t inputSample) override
Definition AudioEffectsSuite.h:1214
SimpleChorus * clone() override
Definition AudioEffectsSuite.h:1254
SimpleChorus(SimpleChorus &copy)=default
const effectsuite_t readSpeed
Definition AudioEffectsSuite.h:1271
effectsuite_t base
Definition AudioEffectsSuite.h:1264
void setBase(effectsuite_t baseAmount)
Definition AudioEffectsSuite.h:1252
void setupChorus(effectsuite_t extSampleRate)
Definition AudioEffectsSuite.h:1230
void setSwing(effectsuite_t swingAmount)
Definition AudioEffectsSuite.h:1246
effectsuite_t modMax
Definition AudioEffectsSuite.h:1268
effectsuite_t swing
Definition AudioEffectsSuite.h:1262
void setRandLfo()
Definition AudioEffectsSuite.h:1280
effectsuite_t getModSignal()
Definition AudioEffectsSuite.h:1278
SimpleChorus(int extSampleRate=44100)
Definition AudioEffectsSuite.h:1195
effectsuite_t modNorm
Definition AudioEffectsSuite.h:1270
effectsuite_t modMin
Definition AudioEffectsSuite.h:1266
Simple Delay effect consiting of a single tap delay with Effect Gain and feed back controls Construct...
Definition AudioEffectsSuite.h:1402
effectsuite_t getSplineOut(effectsuite_t bufferIndex)
Definition AudioEffectsSuite.h:1541
effectsuite_t feedbackGain
Definition AudioEffectsSuite.h:1558
void setDelayTransitionTime(effectsuite_t seconds)
Definition AudioEffectsSuite.h:1511
void setDelayTime(effectsuite_t delayInSamples)
Definition AudioEffectsSuite.h:1500
void setupSimpleDelay(int delayInSamples)
Definition AudioEffectsSuite.h:1493
effectsuite_t processFloat(effectsuite_t inputSample) override
Definition AudioEffectsSuite.h:1456
effectsuite_t delayIncrement
Definition AudioEffectsSuite.h:1565
SimpleDelay * clone() override
Definition AudioEffectsSuite.h:1516
SimpleDelay(SimpleDelay &copy)=default
SimpleDelay(int maxDelayInSamples=8810, int samplingRate=44100)
Definition AudioEffectsSuite.h:1413
effect_t process(effect_t inputSample) override
Definition AudioEffectsSuite.h:1485
effectsuite_t currentDelaySamples
Definition AudioEffectsSuite.h:1561
effectsuite_t targetDelaySamples
Definition AudioEffectsSuite.h:1562
unsigned int writeHeadIndex
Definition AudioEffectsSuite.h:1560
effectsuite_t delayTransitionTimeInSamples
Definition AudioEffectsSuite.h:1571
bool delayTimeChanged
Definition AudioEffectsSuite.h:1574
effectsuite_t delayTransitionTime
Definition AudioEffectsSuite.h:1570
effectsuite_t delayGain
Definition AudioEffectsSuite.h:1557
effectsuite_t readHeadIndex
Definition AudioEffectsSuite.h:1559
void capGain(effectsuite_t &gain)
Definition AudioEffectsSuite.h:1525
void setDelayGain(effectsuite_t gain)
Definition AudioEffectsSuite.h:1434
int sampleRate
Definition AudioEffectsSuite.h:1572
int count
Definition AudioEffectsSuite.h:1573
void setFeedbackGain(effectsuite_t gain)
Definition AudioEffectsSuite.h:1446
effectsuite_t invDelayIncrement
Definition AudioEffectsSuite.h:1568
Simple Flanger Effect Consistig of a single voice flanger The flanger has an effective range between ...
Definition AudioEffectsSuite.h:1588
void updateModulation()
Definition AudioEffectsSuite.h:1686
effectsuite_t processFloat(effectsuite_t inputSample) override
Definition AudioEffectsSuite.h:1643
effectsuite_t modulationIndex
Definition AudioEffectsSuite.h:1700
effectsuite_t modulationAngle
Definition AudioEffectsSuite.h:1706
effectsuite_t modulationRate
Definition AudioEffectsSuite.h:1698
effectsuite_t modulationConstant
Definition AudioEffectsSuite.h:1706
void setRate(const effectsuite_t rate)
Definition AudioEffectsSuite.h:1625
void setEffectGain(effectsuite_t gain)
Definition AudioEffectsSuite.h:1608
SimpleFlanger(effectsuite_t extSampleRate=44100)
Definition AudioEffectsSuite.h:1596
effectsuite_t capGain(effectsuite_t gain)
Definition AudioEffectsSuite.h:1666
SimpleFlanger(SimpleFlanger &copy)=default
void setEffectParams(effectsuite_t gain, effectsuite_t depth, effectsuite_t rate)
Definition AudioEffectsSuite.h:1636
void setDepth(const effectsuite_t depth)
Definition AudioEffectsSuite.h:1614
effectsuite_t modulationDepth
Definition AudioEffectsSuite.h:1698
void setupSimpleFlanger(effectsuite_t extSampleRate)
Definition AudioEffectsSuite.h:1651
effectsuite_t angleDelta
Definition AudioEffectsSuite.h:1710
effectsuite_t timeStep
Definition AudioEffectsSuite.h:1703
void setAngleDelta()
Definition AudioEffectsSuite.h:1678
SimpleFlanger * clone() override
Definition AudioEffectsSuite.h:1657
effectsuite_t effectGain
Definition AudioEffectsSuite.h:1698
SimpleLPF.
Definition AudioEffectsSuite.h:1153
SimpleLPF(effectsuite_t cutoff, int order)
Definition AudioEffectsSuite.h:1161
SimpleLPF(SimpleLPF &copy)=default
SimpleLPF * clone()
Definition AudioEffectsSuite.h:1170
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:28
AudioInfo info
Definition SoundGenerator.h:116
virtual bool begin()
Starts the processing.
Definition SoundGenerator.h:41
SoundGenerator using the ModulationBaseClass to generate the samples.
Definition AudioEffectsSuite.h:408
virtual T readSample() override
Provides a single sample.
Definition AudioEffectsSuite.h:418
SoundGeneratorModulation(ModulationBaseClass< effectsuite_t > &mod, int freq)
Definition AudioEffectsSuite.h:410
ModulationBaseClass< effectsuite_t > * p_mod
Definition AudioEffectsSuite.h:423
float max_value
Definition AudioEffectsSuite.h:425
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition AudioEffectsSuite.h:414
int freq
Definition AudioEffectsSuite.h:424
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
int16_t effect_t
Definition AudioEffect.h:15
float effectsuite_t_default
Definition AudioEffectsSuite.h:55
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57