ASPiK SDK
Loading...
Searching...
No Matches
fxobjects.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2// ASPiK-Core File: fxobjects.h
3//
19// -----------------------------------------------------------------------------
20#pragma once
21
22#include <memory>
23#include <algorithm>
24#include <math.h>
25#include "guiconstants.h"
26#include "filters.h"
27#include <time.h> /* time */
28
29#define HAVE_FFTW 1
30
35// --- constants & enumerations
36//
37// --- by placing outside the class declaration, these will also be avaialble to anything
38// that #includes this file (sometimes needed)
39const double kSmallestPositiveFloatValue = 1.175494351e-38; /* min positive value */
40const double kSmallestNegativeFloatValue = -1.175494351e-38; /* min negative value */
41const double kSqrtTwo = pow(2.0, 0.5);
42const double kMinFilterFrequency = 20.0;
43const double kMaxFilterFrequency = 20480.0; // 10 octaves above 20 Hz
44const double ARC4RANDOMMAX = 4294967295.0; // (2^32 - 1)
45
46#define NEGATIVE 0
47#define POSITIVE 1
48
49// ------------------------------------------------------------------ //
50// --- FUNCTIONS ---------------------------------------------------- //
51// ------------------------------------------------------------------ //
52
62inline bool checkFloatUnderflow(double& value)
63{
64 bool retValue = false;
65 if (value > 0.0 && value < kSmallestPositiveFloatValue)
66 {
67 value = 0;
68 retValue = true;
69 }
70 else if (value < 0.0 && value > kSmallestNegativeFloatValue)
71 {
72 value = 0;
73 retValue = true;
74 }
75 return retValue;
76}
77
92inline double doLinearInterpolation(double x1, double x2, double y1, double y2, double x)
93{
94 double denom = x2 - x1;
95 if (denom == 0)
96 return y1; // --- should not ever happen
97
98 // --- calculate decimal position of x
99 double dx = (x - x1) / (x2 - x1);
100
101 // --- use weighted sum method of interpolating
102 return dx*y2 + (1 - dx)*y1;
103}
104
117inline double doLinearInterpolation(double y1, double y2, double fractional_X)
118{
119 // --- check invalid condition
120 if (fractional_X >= 1.0) return y2;
121
122 // --- use weighted sum method of interpolating
123 return fractional_X*y2 + (1.0 - fractional_X)*y1;
124}
125
138inline double doLagrangeInterpolation(double* x, double* y, int n, double xbar)
139{
140 int i, j;
141 double fx = 0.0;
142 double l = 1.0;
143 for (i = 0; i<n; i++)
144 {
145 l = 1.0;
146 for (j = 0; j<n; j++)
147 {
148 if (j != i)
149 l *= (xbar - x[j]) / (x[i] - x[j]);
150 }
151 fx += l*y[i];
152 }
153 return (fx);
154}
155
156
167inline void boundValue(double& value, double minValue, double maxValue)
168{
169 value = fmin(value, maxValue);
170 value = fmax(value, minValue);
171}
172
184inline double doUnipolarModulationFromMin(double unipolarModulatorValue, double minValue, double maxValue)
185{
186 // --- UNIPOLAR bound
187 boundValue(unipolarModulatorValue, 0.0, 1.0);
188
189 // --- modulate from minimum value upwards
190 return unipolarModulatorValue*(maxValue - minValue) + minValue;
191}
192
204inline double doUnipolarModulationFromMax(double unipolarModulatorValue, double minValue, double maxValue)
205{
206 // --- UNIPOLAR bound
207 boundValue(unipolarModulatorValue, 0.0, 1.0);
208
209 // --- modulate from maximum value downwards
210 return maxValue - (1.0 - unipolarModulatorValue)*(maxValue - minValue);
211}
212
224inline double doBipolarModulation(double bipolarModulatorValue, double minValue, double maxValue)
225{
226 // --- BIPOLAR bound
227 boundValue(bipolarModulatorValue, -1.0, 1.0);
228
229 // --- calculate range and midpoint
230 double halfRange = (maxValue - minValue) / 2.0;
231 double midpoint = halfRange + minValue;
232
233 return bipolarModulatorValue*(halfRange) + midpoint;
234}
235
245inline double unipolarToBipolar(double value)
246{
247 return 2.0*value - 1.0;
248}
249
259inline double bipolarToUnipolar(double value)
260{
261 return 0.5*value + 0.5;
262}
263
273inline double raw2dB(double raw)
274{
275 return 20.0*log10(raw);
276}
277
287inline double dB2Raw(double dB)
288{
289 return pow(10.0, (dB / 20.0));
290}
291
301inline double peakGainFor_Q(double Q)
302{
303 // --- no resonance at or below unity
304 if (Q <= 0.707) return 1.0;
305 return (Q*Q) / (pow((Q*Q - 0.25), 0.5));
306}
307
317inline double dBPeakGainFor_Q(double Q)
318{
319 return raw2dB(peakGainFor_Q(Q));
320}
321
329inline double doWhiteNoise()
330{
331 float noise = 0.0;
332
333#if defined _WINDOWS || defined _WINDLL
334 // fNoise is 0 -> 32767.0
335 noise = (float)rand();
336
337 // normalize and make bipolar
338 noise = 2.f*(noise / 32767.f) - 1.f;
339#else
340 // fNoise is 0 -> ARC4RANDOMMAX
341 noise = (float)arc4random();
342
343 // normalize and make bipolar
344 noise = 2.0*(noise / ARC4RANDOMMAX) - 1.0;
345#endif
346
347 return noise;
348}
349
358inline double sgn(double xn)
359{
360 return (xn > 0) - (xn < 0);
361}
362
373inline double calcWSGain(double xn, double saturation, double asymmetry)
374{
375 double g = ((xn >= 0.0 && asymmetry > 0.0) || (xn < 0.0 && asymmetry < 0.0)) ? saturation * (1.0 + 4.0*fabs(asymmetry)) : saturation;
376 return g;
377}
378
388inline double atanWaveShaper(double xn, double saturation)
389{
390 return atan(saturation*xn) / atan(saturation);
391}
392
402inline double tanhWaveShaper(double xn, double saturation)
403{
404 return tanh(saturation*xn) / tanh(saturation);
405}
406
416inline double softClipWaveShaper(double xn, double saturation)
417{
418 // --- un-normalized soft clipper from Reiss book
419 return sgn(xn)*(1.0 - exp(-fabs(saturation*xn)));
420}
421
431inline double fuzzExp1WaveShaper(double xn, double saturation, double asymmetry)
432{
433 // --- setup gain
434 double wsGain = calcWSGain(xn, saturation, asymmetry);
435 return sgn(xn)*(1.0 - exp(-fabs(wsGain*xn))) / (1.0 - exp(-wsGain));
436}
437
438
448inline double getMagResponse(double theta, double a0, double a1, double a2, double b1, double b2)
449{
450 double magSqr = 0.0;
451 double num = a1*a1 + (a0 - a2)*(a0 - a2) + 2.0*a1*(a0 + a2)*cos(theta) + 4.0*a0*a2*cos(theta)*cos(theta);
452 double denom = b1*b1 + (1.0 - b2)*(1.0 - b2) + 2.0*b1*(1.0 + b2)*cos(theta) + 4.0*b2*cos(theta)*cos(theta);
453
454 magSqr = num / denom;
455 if (magSqr < 0.0)
456 magSqr = 0.0;
457
458 double mag = pow(magSqr, 0.5);
459
460 return mag;
461}
462
474{
475 ComplexNumber() {}
476 ComplexNumber(double _real, double _imag)
477 {
478 real = _real;
479 imag = _imag;
480 }
481
482 double real = 0.0;
483 double imag = 0.0;
484};
485
495{
496 ComplexNumber complexProduct;
497
498 // --- real part
499 complexProduct.real = (c1.real*c2.real) - (c1.imag*c2.imag);
500 complexProduct.imag = (c1.real*c2.imag) + (c1.imag*c2.real);
501
502 return complexProduct;
503}
504
516inline void calcEdgeFrequencies(double fc, double Q, double& f_Low, double& f_High)
517{
518 bool arithmeticBW = true;
519 double bandwidth = fc / Q;
520
521 // --- geometric bw = sqrt[ (fLow)(fHigh) ]
522 // arithmetic bw = fHigh - fLow
523 if (arithmeticBW)
524 {
525 f_Low = fc - bandwidth / 2.0;
526 f_High = fc + bandwidth / 2.0;
527 }
528 else
529 {
530 ; // TODO --- add geometric (for homework)
531 }
532
533}
534
548enum class brickwallFilter { kBrickLPF, kBrickHPF, kBrickBPF, kBrickBSF };
549
562{
564
565 brickwallFilter filterType = brickwallFilter::kBrickLPF;
566 double* magArray = nullptr;
567 unsigned int dftArrayLen = 0;
568 double sampleRate = 44100.0;
569
570 // --- for LPF, HPF fc = corner frequency
571 // for BPF, BSF fc = center frequency
572 double fc = 1000.0;
573 double Q = 0.707;
574 double f_Low = 500.00;
575 double f_High = 1500.00;
576 unsigned int relaxationBins = 0;
577 bool mirrorMag = false;
578};
579
593enum class edgeTransition { kFallingEdge, kRisingEdge };
594
607{
609
610 edgeTransition edgeType = edgeTransition::kFallingEdge;
611 unsigned int startBin = 0;
612 unsigned int stopBin = 0;
613 double slopeIncrement = 1.0;
614};
615
616
627inline int findEdgeTargetBin(double testFreq, double bin1Freq)
628{
629 return (int)(testFreq / bin1Freq);
630}
631
644inline bool getTransitionBandData(double testFreq, double bin1Freq, unsigned int relax_Bins, TransitionBandData& transitionData)
645{
646 double targetF1 = testFreq;// -(2.0*relax_Pct / 100.0)*testFreq;
647 double targetF2 = testFreq + relax_Bins*bin1Freq;
648
649 // --- for falling edge...
650 int nF1 = findEdgeTargetBin(targetF1, bin1Freq);
651 int nF2 = findEdgeTargetBin(targetF2, bin1Freq);
652
653 nF1 = std::max(0, nF1);
654 nF2 = std::max(0, nF2);
655
656 int relaxBins = nF2 - nF1;
657 if (relaxBins < 1)
658 return false;
659
660 // --- force even to make relax band symmetrical around edge
661 //if (relaxBins % 2 != 0)
662 // relaxBins++;
663
664 // --- for double-sided relax
665 transitionData.startBin = nF1;
666 transitionData.stopBin = relaxBins + nF1;
667
668 // --- slope calc
669 double run = transitionData.stopBin - transitionData.startBin;
670 double rise = 1.0;
671 if (transitionData.edgeType == edgeTransition::kFallingEdge)
672 rise = -1.0;
673 transitionData.slopeIncrement = rise / run;
674
675 return true;
676}
677
688{
689 // --- calculate first half of array
690 double actualLength = magData.mirrorMag ? (double)magData.dftArrayLen : (double)magData.dftArrayLen * 2.0;
691 uint32_t dumpLength = magData.mirrorMag ? magData.dftArrayLen / 2 : magData.dftArrayLen;
692
693 // --- first bin in Hz
694 double bin1 = magData.sampleRate / actualLength;
695
696 // --- zero out array; if filter not supported, this will return a bank of 0's!
697 memset(&magData.magArray[0], 0, magData.dftArrayLen * sizeof(double));
698
699 // --- preprocess for transition bands
700 TransitionBandData fallingEdge;
701 fallingEdge.edgeType = edgeTransition::kFallingEdge;
702
703 TransitionBandData risingEdge;
704 risingEdge.edgeType = edgeTransition::kRisingEdge;
705
706 // --- this will populate FL and FH for BPF and BSF
707 calcEdgeFrequencies(magData.fc, magData.Q, magData.f_Low, magData.f_High);
708
709 bool relaxIt = false;
710 if (magData.relaxationBins > 0)
711 {
712 if(magData.filterType == brickwallFilter::kBrickLPF)
713 relaxIt = getTransitionBandData(magData.fc, bin1, magData.relaxationBins, fallingEdge);
714 else if (magData.filterType == brickwallFilter::kBrickHPF)
715 relaxIt = getTransitionBandData(magData.fc, bin1, magData.relaxationBins, risingEdge);
716 else if (magData.filterType == brickwallFilter::kBrickBPF)
717 {
718 if(getTransitionBandData(magData.f_Low, bin1, magData.relaxationBins, risingEdge))
719 relaxIt = getTransitionBandData(magData.f_High, bin1, magData.relaxationBins, fallingEdge);
720 }
721 else if (magData.filterType == brickwallFilter::kBrickBSF)
722 {
723 if(getTransitionBandData(magData.f_Low, bin1, magData.relaxationBins, fallingEdge))
724 relaxIt = getTransitionBandData(magData.f_High, bin1, magData.relaxationBins, risingEdge);
725 }
726 }
727
728 for (uint32_t i = 0; i < dumpLength; i++)
729 {
730 double eval_f = i*bin1;
731
732 if (magData.filterType == brickwallFilter::kBrickLPF)
733 {
734 if (!relaxIt)
735 {
736 if (eval_f <= magData.fc)
737 magData.magArray[i] = 1.0;
738 }
739 else // relax
740 {
741 if (i <= fallingEdge.startBin)
742 magData.magArray[i] = 1.0;
743 else if(i > fallingEdge.startBin && i < fallingEdge.stopBin)
744 magData.magArray[i] = 1.0 + (i - fallingEdge.startBin)*fallingEdge.slopeIncrement;
745 }
746 }
747 else if (magData.filterType == brickwallFilter::kBrickHPF)
748 {
749 if (!relaxIt)
750 {
751 if (eval_f >= magData.fc)
752 magData.magArray[i] = 1.0;
753 }
754 else // relax
755 {
756 if (i >= risingEdge.stopBin)
757 magData.magArray[i] = 1.0;
758 else if (i > risingEdge.startBin && i < risingEdge.stopBin)
759 magData.magArray[i] = 0.0 + (i - risingEdge.startBin)*risingEdge.slopeIncrement;
760 }
761 }
762 else if (magData.filterType == brickwallFilter::kBrickBPF)
763 {
764 if (!relaxIt)
765 {
766 if (eval_f >= magData.f_Low && eval_f <= magData.f_High)
767 magData.magArray[i] = 1.0;
768 }
769 else // --- frankie says relax
770 {
771 if (i >= risingEdge.stopBin && i <= fallingEdge.startBin)
772 magData.magArray[i] = 1.0;
773 else if (i > risingEdge.startBin && i < risingEdge.stopBin)
774 magData.magArray[i] = 0.0 + (i - risingEdge.startBin)*risingEdge.slopeIncrement;
775 else if (i > fallingEdge.startBin && i < fallingEdge.stopBin)
776 magData.magArray[i] = 1.0 + (i - fallingEdge.startBin)*fallingEdge.slopeIncrement;
777
778 }
779 }
780 else if (magData.filterType == brickwallFilter::kBrickBSF)
781 {
782 if (!relaxIt && eval_f >= magData.f_Low && eval_f <= magData.f_High)
783 magData.magArray[i] = 0.0;
784 else if((!relaxIt && eval_f < magData.f_Low) || eval_f > magData.f_High)
785 magData.magArray[i] = 1.0;
786 else
787 {
788 // --- TODO Fill this in...
789 }
790 }
791 }
792
793 // -- make sure have legal first half...
794 if (!magData.mirrorMag)
795 return true;
796
797 // --- now mirror the other half
798 int index = magData.dftArrayLen / 2 - 1;
799 for (unsigned int i = magData.dftArrayLen / 2; i <magData.dftArrayLen; i++)
800 {
801 magData.magArray[i] = magData.magArray[index--];
802 }
803
804 return true;
805}
806
820enum class analogFilter { kLPF1, kHPF1, kLPF2, kHPF2, kBPF2, kBSF2 };
821
834{
835 AnalogMagData() {}
836
837 analogFilter filterType = analogFilter::kLPF2;
838 double* magArray = nullptr;
839 unsigned int dftArrayLen = 0;
840 double sampleRate = 44100.0;
841
842 // --- for LPF, HPF fc = corner frequency
843 // for BPF, BSF fc = center frequency
844 double fc = 1000.0;
845 double Q = 0.707;
846 bool mirrorMag = true;
847};
848
859{
860 // --- calculate first half of array
861 double actualLength = magData.mirrorMag ? (double)magData.dftArrayLen : (double)magData.dftArrayLen * 2.0;
862 uint32_t dumpLength = magData.mirrorMag ? magData.dftArrayLen / 2 : magData.dftArrayLen;
863
864 double bin1 = magData.sampleRate / actualLength;// (double)magData.dftArrayLen;
865 double zeta = 1.0 / (2.0*magData.Q);
866 double w_c = 2.0*kPi*magData.fc;
867
868 // --- zero out array; if filter not supported, this will return a bank of 0's!
869 memset(&magData.magArray[0], 0, magData.dftArrayLen * sizeof(double));
870
871 for (uint32_t i = 0; i < dumpLength; i++)
872 {
873 double eval_w = 2.0*kPi*i*bin1;
874 double w_o = eval_w / w_c;
875
876 if (magData.filterType == analogFilter::kLPF1)
877 {
878 double denXSq = 1.0 + (w_o*w_o);
879 magData.magArray[i] = 1.0 / (pow(denXSq, 0.5));
880 }
881 else if (magData.filterType == analogFilter::kHPF1)
882 {
883 double denXSq = 1.0 + (w_o*w_o);
884 magData.magArray[i] = w_o / (pow(denXSq, 0.5));
885 }
886 else if (magData.filterType == analogFilter::kLPF2)
887 {
888 double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
889 magData.magArray[i] = 1.0 / (pow(denXSq, 0.5));
890 }
891 else if (magData.filterType == analogFilter::kHPF2)
892 {
893 double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
894 magData.magArray[i] = (w_o*w_o) / (pow(denXSq, 0.5));
895 }
896 else if (magData.filterType == analogFilter::kBPF2)
897 {
898 double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
899 magData.magArray[i] = 2.0*w_o*zeta / (pow(denXSq, 0.5));
900 }
901 else if (magData.filterType == analogFilter::kBSF2)
902 {
903 double numXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o));
904 double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
905 magData.magArray[i] = (pow(numXSq, 0.5)) / (pow(denXSq, 0.5));
906 }
907 }
908
909 // -- make sure have legal first half...
910 if (!magData.mirrorMag)
911 return true;
912
913 // --- now mirror the other half
914 int index = magData.dftArrayLen / 2 - 1;
915 for (unsigned int i = magData.dftArrayLen / 2; i <magData.dftArrayLen; i++)
916 {
917 magData.magArray[i] = magData.magArray[index--];
918 }
919
920 return true;
921}
922
935inline void freqSample(int N, double A[], double h[], int symm)
936{
937 int n, k;
938 double x, val, M;
939
940 M = (N - 1.0) / 2.0;
941 if (symm == POSITIVE)
942 {
943 if (N % 2)
944 {
945 for (n = 0; n<N; n++)
946 {
947 val = A[0];
948 x = kTwoPi * (n - M) / N;
949 for (k = 1; k <= M; k++)
950 val += 2.0 * A[k] * cos(x*k);
951 h[n] = val / N;
952 }
953 }
954 else
955 {
956 for (n = 0; n<N; n++)
957 {
958 val = A[0];
959 x = kTwoPi * (n - M) / N;
960 for (k = 1; k <= (N / 2 - 1); k++)
961 val += 2.0 * A[k] * cos(x*k);
962 h[n] = val / N;
963 }
964 }
965 }
966 else
967 {
968 if (N % 2)
969 {
970 for (n = 0; n<N; n++)
971 {
972 val = 0;
973 x = kTwoPi * (n - M) / N;
974 for (k = 1; k <= M; k++)
975 val += 2.0 * A[k] * sin(x*k);
976 h[n] = val / N;
977 }
978 }
979 else
980 {
981 for (n = 0; n<N; n++)
982 {
983 val = A[N / 2] * sin(kPi * (n - M));
984 x = kTwoPi * (n - M) / N;
985 for (k = 1; k <= (N / 2 - 1); k++)
986 val += 2.0 * A[k] * sin(x*k);
987 h[n] = val / N;
988 }
989 }
990 }
991}
992
1003inline double getMagnitude(double re, double im)
1004{
1005 return sqrt((re*re) + (im*im));
1006}
1007
1018inline double getPhase(double re, double im)
1019{
1020 return atan2(im, re);
1021}
1022
1033inline double principalArg(double phaseIn)
1034{
1035 if (phaseIn >= 0)
1036 return fmod(phaseIn + kPi, kTwoPi) - kPi;
1037 else
1038 return fmod(phaseIn + kPi, -kTwoPi) + kPi;
1039}
1040
1041enum class interpolation {kLinear, kLagrange4};
1042
1060inline bool resample(double* input, double* output, uint32_t inLength, uint32_t outLength,
1061 interpolation interpType = interpolation::kLinear,
1062 double scalar = 1.0, double* outWindow = nullptr)
1063{
1064 if (inLength <= 1 || outLength <= 1) return false;
1065 if (!input || !output) return false;
1066
1067 double x[4] = { 0.0, 0.0, 0.0, 0.0 };
1068 double y[4] = { 0.0, 0.0, 0.0, 0.0 };
1069
1070 // --- inc
1071 double inc = (double)(inLength - 1) / (double)(outLength - 1);
1072
1073 // --- first point
1074 if (outWindow)
1075 output[0] = outWindow[0] * scalar * input[0];
1076 else
1077 output[0] = scalar * input[0];
1078
1079 if (interpType == interpolation::kLagrange4)
1080 {
1081 for (unsigned int i = 1; i < outLength; i++)
1082 {
1083 // --- find interpolation location
1084 double xInterp = i*inc;
1085 uint32_t x1 = (uint32_t)xInterp; // floor?
1086
1087 if (xInterp > 1.0 && x1 < inLength - 2)
1088 {
1089 x[0] = x1 - 1;
1090 y[0] = input[(int)x[0]];
1091
1092 x[1] = x1;
1093 y[1] = input[(int)x[1]];
1094
1095 x[2] = x1 + 1;
1096 y[2] = input[(int)x[2]];
1097
1098 x[3] = x1 + 2;
1099 y[3] = input[(int)x[3]];
1100
1101 if (outWindow)
1102 output[i] = outWindow[i] * scalar * doLagrangeInterpolation(x, y, 4, xInterp);
1103 else
1104 output[i] = scalar * doLagrangeInterpolation(x, y, 4, xInterp);
1105 }
1106 else // --- linear for outer 2 end pts
1107 {
1108 uint32_t x2 = x1 + 1;
1109 if (x2 >= outLength)
1110 x2 = x1;
1111 double y1 = input[x1];
1112 double y2 = input[x2];
1113
1114 if (outWindow)
1115 output[i] = outWindow[i] * scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1116 else
1117 output[i] = scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1118 }
1119 }
1120 }
1121 else // must be linear
1122 {
1123 // --- LINEAR INTERP
1124 for (uint32_t i = 1; i < outLength; i++)
1125 {
1126 double xInterp = i*inc;
1127 uint32_t x1 = (uint32_t)xInterp; // floor?
1128 uint32_t x2 = x1 + 1;
1129 if (x2 >= outLength)
1130 x2 = x1;
1131 double y1 = input[x1];
1132 double y2 = input[x2];
1133
1134 if (outWindow)
1135 output[i] = outWindow[i] * scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1136 else
1137 output[i] = scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1138 }
1139 }
1140
1141 return true;
1142}
1143
1144// ------------------------------------------------------------------ //
1145// --- INTERFACES --------------------------------------------------- //
1146// ------------------------------------------------------------------ //
1147
1160{
1161public:
1162 // --- pure virtual, derived classes must implement or will not compile
1163 // also means this is a pure abstract base class and is incomplete,
1164 // so it can only be used as a base class
1165 //
1167 virtual bool reset(double _sampleRate) = 0;
1168
1170 virtual double processAudioSample(double xn) = 0;
1171
1173 virtual bool canProcessAudioFrame() = 0;
1174
1176 virtual void setSampleRate(double _sampleRate) {}
1177
1179 virtual void enableAuxInput(bool enableAuxInput) {}
1180
1183 virtual double processAuxInputAudioSample(double xn)
1184 {
1185 // --- do nothing
1186 return xn;
1187 }
1188
1193 virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
1194 float* outputFrame,
1195 uint32_t inputChannels,
1196 uint32_t outputChannels)
1197 {
1198 // --- do nothing
1199 return false; // NOT handled
1200 }
1201};
1202
1214// --- structure to send output data from signal gen; you can add more outputs here
1216{
1217 SignalGenData() {}
1218
1219 double normalOutput = 0.0;
1220 double invertedOutput = 0.0;
1221 double quadPhaseOutput_pos = 0.0;
1222 double quadPhaseOutput_neg = 0.0;
1223};
1224
1240{
1241public:
1242 // --- pure virtual, derived classes must implement or will not compile
1243 // also means this is a pure abstract base class and is incomplete,
1244 // so it can only be used as a base class
1245 //
1247 virtual bool reset(double _sampleRate) = 0;
1248
1251};
1252
1253
1254
1255// ------------------------------------------------------------------ //
1256// --- OBJECTS ------------------------------------------------------ //
1257// ------------------------------------------------------------------ //
1258/*
1259Class Declarations :
1260
1261class name : public IAudioSignalProcessor
1262 - IAudioSignalProcessor functions
1263 - member functions that may be called externally
1264 - mutators & accessors
1265 - helper functions(may be private / protected if needed)
1266 - protected member functions
1267*/
1268
1282enum filterCoeff { a0, a1, a2, b1, b2, c0, d0, numCoeffs };
1283
1300// --- state array index values
1301// z^-1 registers;
1302// Direct Forms: we will allow max of 2 for X (feedforward) and 2 for Y (feedback) data
1303// Transpose Forms: we will use ONLY the x_z1 and x_z2 registers for the 2 required delays
1304enum stateReg { x_z1, x_z2, y_z1, y_z2, numStates };
1305
1320// --- type of calculation (algorithm)
1321enum class biquadAlgorithm { kDirect, kCanonical, kTransposeDirect, kTransposeCanonical }; // 4 types of biquad calculations, constants (k)
1322
1323
1336{
1337 BiquadParameters () {}
1338
1341 {
1342 if (this == &params)
1343 return *this;
1344
1346 return *this;
1347 }
1348
1349 biquadAlgorithm biquadCalcType = biquadAlgorithm::kDirect;
1350};
1351
1370{
1371public:
1372 Biquad() {} /* C-TOR */
1373 ~Biquad() {} /* D-TOR */
1374
1375 // --- IAudioSignalProcessor FUNCTIONS --- //
1376 //
1378 virtual bool reset(double _sampleRate)
1379 {
1380 memset(&stateArray[0], 0, sizeof(double)*numStates);
1381 return true; // handled = true
1382 }
1383
1385 virtual bool canProcessAudioFrame() { return false; }
1386
1392 virtual double processAudioSample(double xn);
1393
1399
1404 void setParameters(const BiquadParameters& _parameters){ parameters = _parameters; }
1405
1406 // --- MUTATORS & ACCESSORS --- //
1408 void setCoefficients(double* coeffs){
1409 // --- fast block memory copy:
1410 memcpy(&coeffArray[0], &coeffs[0], sizeof(double)*numCoeffs);
1411 }
1412
1415 {
1416 // --- read/write access to the array (not used)
1417 return &coeffArray[0];
1418 }
1419
1422 {
1423 // --- read/write access to the array (used only in direct form oscillator)
1424 return &stateArray[0];
1425 }
1426
1428 double getG_value() { return coeffArray[a0]; }
1429
1431 double getS_value();// { return storageComponent; }
1432
1433protected:
1435 double coeffArray[numCoeffs] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1436
1438 double stateArray[numStates] = { 0.0, 0.0, 0.0, 0.0 };
1439
1442
1444 double storageComponent = 0.0;
1445};
1446
1447
1462 kLPF1P, kLPF1, kHPF1, kLPF2, kHPF2, kBPF2, kBSF2, kButterLPF2, kButterHPF2, kButterBPF2,
1463 kButterBSF2, kMMALPF2, kMMALPF2B, kLowShelf, kHiShelf, kNCQParaEQ, kCQParaEQ, kLWRLPF2, kLWRHPF2,
1464 kAPF1, kAPF2, kResonA, kResonB, kMatchLP2A, kMatchLP2B, kMatchBP2A, kMatchBP2B,
1465 kImpInvLP1, kImpInvLP2
1466}; // --- you will add more here...
1467
1468
1481{
1484 AudioFilterParameters& operator=(const AudioFilterParameters& params) // need this override for collections to work
1485 {
1486 if (this == &params)
1487 return *this;
1488 algorithm = params.algorithm;
1489 fc = params.fc;
1490 Q = params.Q;
1491 boostCut_dB = params.boostCut_dB;
1492
1493 return *this;
1494 }
1495
1496 // --- individual parameters
1497 filterAlgorithm algorithm = filterAlgorithm::kLPF1;
1498 double fc = 100.0;
1499 double Q = 0.707;
1500 double boostCut_dB = 0.0;
1501};
1502
1521{
1522public:
1523 AudioFilter() {} /* C-TOR */
1524 ~AudioFilter() {} /* D-TOR */
1525
1526 // --- IAudioSignalProcessor
1528 virtual bool reset(double _sampleRate)
1529 {
1531
1532 // --- you can try both forms - do you hear a difference?
1533 bqp.biquadCalcType = biquadAlgorithm::kTransposeCanonical; //<- this is the default operation
1534 // bqp.biquadCalcType = biquadAlgorithm::kDirect;
1535 biquad.setParameters(bqp);
1536
1537 sampleRate = _sampleRate;
1538 return biquad.reset(_sampleRate);
1539 }
1540
1542 virtual bool canProcessAudioFrame() { return false; }
1543
1549 virtual double processAudioSample(double xn);
1550
1552 virtual void setSampleRate(double _sampleRate)
1553 {
1554 sampleRate = _sampleRate;
1556 }
1557
1560
1562 void setParameters(const AudioFilterParameters& parameters)
1563 {
1564 if (audioFilterParameters.algorithm != parameters.algorithm ||
1566 audioFilterParameters.fc != parameters.fc ||
1567 audioFilterParameters.Q != parameters.Q)
1568 {
1569 // --- save new params
1570 audioFilterParameters = parameters;
1571 }
1572 else
1573 return;
1574
1575 // --- don't allow 0 or (-) values for Q
1576 if (audioFilterParameters.Q <= 0)
1577 audioFilterParameters.Q = 0.707;
1578
1579 // --- update coeffs
1581 }
1582
1584 double getG_value() { return biquad.getG_value(); }
1585
1587 double getS_value() { return biquad.getS_value(); }
1588
1589protected:
1590 // --- our calculator
1592
1593 // --- array to hold coeffs (we need them too)
1594 double coeffArray[numCoeffs] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1595
1596 // --- object parameters
1598 double sampleRate = 44100.0;
1599
1601 bool calculateFilterCoeffs();
1602};
1603
1604
1616// --- output for filter bank requires multiple channels (bands)
1618{
1619 FilterBankOutput() {}
1620
1621 // --- band-split filter output
1622 double LFOut = 0.0;
1623 double HFOut = 0.0;
1624
1625 // --- add more filter channels here; or use an array[]
1626};
1627
1628
1643{
1646 LRFilterBankParameters& operator=(const LRFilterBankParameters& params) // need this override for collections to work
1647 {
1648 if (this == &params)
1649 return *this;
1651 return *this;
1652 }
1653
1654 // --- individual parameters
1655 double splitFrequency = 1000.0;
1656};
1657
1658
1679{
1680public:
1681 LRFilterBank() /* C-TOR */
1682 {
1683 // --- set filters as Linkwitz-Riley 2nd order
1685 params.algorithm = filterAlgorithm::kLWRLPF2;
1686 lpFilter.setParameters(params);
1687
1688 params = hpFilter.getParameters();
1689 params.algorithm = filterAlgorithm::kLWRHPF2;
1690 hpFilter.setParameters(params);
1691 }
1692
1693 ~LRFilterBank() {} /* D-TOR */
1694
1696 virtual bool reset(double _sampleRate)
1697 {
1698 lpFilter.reset(_sampleRate);
1699 hpFilter.reset(_sampleRate);
1700 return true;
1701 }
1702
1704 virtual bool canProcessAudioFrame() { return false; }
1705
1711 virtual double processAudioSample(double xn)
1712 {
1713 return xn;
1714 }
1715
1718 {
1719 FilterBankOutput output;
1720
1721 // --- process the LPF
1722 output.LFOut = lpFilter.processAudioSample(xn);
1723
1724 // --- invert the HP filter output so that recombination will
1725 // result in the correct phase and magnitude responses
1726 output.HFOut = -hpFilter.processAudioSample(xn);
1727
1728 return output;
1729 }
1730
1736 {
1737 return parameters;
1738 }
1739
1744 void setParameters(const LRFilterBankParameters& _parameters)
1745 {
1746 // --- update structure
1747 parameters = _parameters;
1748
1749 // --- update member objects
1751 params.fc = parameters.splitFrequency;
1752 lpFilter.setParameters(params);
1753
1754 params = hpFilter.getParameters();
1755 params.fc = parameters.splitFrequency;
1756 hpFilter.setParameters(params);
1757 }
1758
1759protected:
1762
1763 // --- object parameters
1765};
1766
1767// --- constants
1768const unsigned int TLD_AUDIO_DETECT_MODE_PEAK = 0;
1769const unsigned int TLD_AUDIO_DETECT_MODE_MS = 1;
1770const unsigned int TLD_AUDIO_DETECT_MODE_RMS = 2;
1771const double TLD_AUDIO_ENVELOPE_ANALOG_TC = -0.99967234081320612357829304641019; // ln(36.7%)
1772
1790{
1793 AudioDetectorParameters& operator=(const AudioDetectorParameters& params) // need this override for collections to work
1794 {
1795 if (this == &params)
1796 return *this;
1799 detectMode = params.detectMode;
1800 detect_dB = params.detect_dB;
1802 return *this;
1803 }
1804
1805 // --- individual parameters
1806 double attackTime_mSec = 0.0;
1807 double releaseTime_mSec = 0.0;
1808 unsigned int detectMode = 0;
1809 bool detect_dB = false;
1810 bool clampToUnityMax = true;
1811};
1812
1832{
1833public:
1834 AudioDetector() {} /* C-TOR */
1835 ~AudioDetector() {} /* D-TOR */
1836
1837public:
1839 virtual bool reset(double _sampleRate)
1840 {
1841 setSampleRate(_sampleRate);
1842 lastEnvelope = 0.0;
1843 return true;
1844 }
1845
1847 virtual bool canProcessAudioFrame() { return false; }
1848
1849 // --- process audio: detect the log envelope and return it in dB
1854 virtual double processAudioSample(double xn)
1855 {
1856 // --- all modes do Full Wave Rectification
1857 double input = fabs(xn);
1858
1859 // --- square it for MS and RMS
1860 if (audioDetectorParameters.detectMode == TLD_AUDIO_DETECT_MODE_MS ||
1861 audioDetectorParameters.detectMode == TLD_AUDIO_DETECT_MODE_RMS)
1862 input *= input;
1863
1864 // --- to store current
1865 double currEnvelope = 0.0;
1866
1867 // --- do the detection with attack or release applied
1868 if (input > lastEnvelope)
1869 currEnvelope = attackTime * (lastEnvelope - input) + input;
1870 else
1871 currEnvelope = releaseTime * (lastEnvelope - input) + input;
1872
1873 // --- we are recursive so need to check underflow
1874 checkFloatUnderflow(currEnvelope);
1875
1876 // --- bound them; can happen when using pre-detector gains of more than 1.0
1878 currEnvelope = fmin(currEnvelope, 1.0);
1879
1880 // --- can not be (-)
1881 currEnvelope = fmax(currEnvelope, 0.0);
1882
1883 // --- store envelope prior to sqrt for RMS version
1884 lastEnvelope = currEnvelope;
1885
1886 // --- if RMS, do the SQRT
1887 if (audioDetectorParameters.detectMode == TLD_AUDIO_DETECT_MODE_RMS)
1888 currEnvelope = pow(currEnvelope, 0.5);
1889
1890 // --- if not dB, we are done
1892 return currEnvelope;
1893
1894 // --- setup for log( )
1895 if (currEnvelope <= 0)
1896 {
1897 return -96.0;
1898 }
1899
1900 // --- true log output in dB, can go above 0dBFS!
1901 return 20.0*log10(currEnvelope);
1902 }
1903
1909 {
1911 }
1912
1918 {
1919 audioDetectorParameters = parameters;
1920
1921 // --- update structure
1924
1925 }
1926
1928 virtual void setSampleRate(double _sampleRate)
1929 {
1930 if (sampleRate == _sampleRate)
1931 return;
1932
1933 sampleRate = _sampleRate;
1934
1935 // --- recalculate RC time-constants
1938 }
1939
1940protected:
1942 double attackTime = 0.0;
1943 double releaseTime = 0.0;
1944 double sampleRate = 44100;
1945 double lastEnvelope = 0.0;
1946
1948 void setAttackTime(double attack_in_ms, bool forceCalc = false);
1949
1951 void setReleaseTime(double release_in_ms, bool forceCalc = false);
1952};
1953
1954
1971// --- processorType
1972enum class dynamicsProcessorType { kCompressor, kDownwardExpander };
1973
1974
1987{
1990 DynamicsProcessorParameters& operator=(const DynamicsProcessorParameters& params) // need this override for collections to work
1991 {
1992 if (this == &params)
1993 return *this;
1994
1995 ratio = params.ratio;
1996 threshold_dB = params.threshold_dB;
1997 kneeWidth_dB = params.kneeWidth_dB;
1999 softKnee = params.softKnee;
2001 calculation = params.calculation;
2005 // --- NOTE: do not set outbound variables??
2008 return *this;
2009 }
2010
2011 // --- individual parameters
2012 double ratio = 50.0;
2013 double threshold_dB = -10.0;
2014 double kneeWidth_dB = 10.0;
2015 bool hardLimitGate = false;
2016 bool softKnee = true;
2017 bool enableSidechain = false;
2018 dynamicsProcessorType calculation = dynamicsProcessorType::kCompressor;
2019 double attackTime_mSec = 0.0;
2020 double releaseTime_mSec = 0.0;
2021 double outputGain_dB = 0.0;
2022
2023 // --- outbound values, for owner to use gain-reduction metering
2024 double gainReduction = 1.0;
2025 double gainReduction_dB = 0.0;
2026};
2027
2046{
2047public:
2048 DynamicsProcessor() {} /* C-TOR */
2049 ~DynamicsProcessor() {} /* D-TOR */
2050
2051public:
2053 virtual bool reset(double _sampleRate)
2054 {
2056 detector.reset(_sampleRate);
2058 detectorParams.clampToUnityMax = false;
2059 detectorParams.detect_dB = true;
2060 detector.setParameters(detectorParams);
2061 return true;
2062 }
2063
2065 virtual bool canProcessAudioFrame() { return false; }
2066
2069
2071 virtual double processAuxInputAudioSample(double xn)
2072 {
2074 return sidechainInputSample;
2075 }
2076
2082
2088 {
2089 parameters = _parameters;
2090
2094 detector.setParameters(detectorParams);
2095 }
2096
2098 /*
2099 1. detect input signal
2100 2. calculate gain
2101 3. apply to input sample
2102 */
2107 virtual double processAudioSample(double xn)
2108 {
2109 // --- detect input
2110 double detect_dB = 0.0;
2111
2112 // --- if using the sidechain, process the aux input
2115 else
2116 detect_dB = detector.processAudioSample(xn);
2117
2118 // --- compute gain
2119 double gr = computeGain(detect_dB);
2120
2121 // --- makeup gain
2122 double makeupGain = pow(10.0, parameters.outputGain_dB / 20.0);
2123
2124 // --- do DCA + makeup gain
2125 return xn * gr * makeupGain;
2126 }
2127
2128protected:
2131
2132 // --- storage for sidechain audio input (mono only)
2134
2136 inline double computeGain(double detect_dB)
2137 {
2138 double output_dB = 0.0;
2139
2140 if (parameters.calculation == dynamicsProcessorType::kCompressor)
2141 {
2142 // --- hard knee
2143 if (!parameters.softKnee)
2144 {
2145 // --- below threshold, unity
2146 if (detect_dB <= parameters.threshold_dB)
2147 output_dB = detect_dB;
2148 else// --- above threshold, compress
2149 {
2150 if (parameters.hardLimitGate) // is limiter?
2151 output_dB = parameters.threshold_dB;
2152 else
2153 output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) / parameters.ratio;
2154 }
2155 }
2156 else // --- calc gain with knee
2157 {
2158 // --- left side of knee, outside of width, unity gain zone
2159 if (2.0*(detect_dB - parameters.threshold_dB) < -parameters.kneeWidth_dB)
2160 output_dB = detect_dB;
2161 // --- else inside the knee,
2162 else if (2.0*(fabs(detect_dB - parameters.threshold_dB)) <= parameters.kneeWidth_dB)
2163 {
2164 if (parameters.hardLimitGate) // --- is limiter?
2165 output_dB = detect_dB - pow((detect_dB - parameters.threshold_dB + (parameters.kneeWidth_dB / 2.0)), 2.0) / (2.0*parameters.kneeWidth_dB);
2166 else // --- 2nd order poly
2167 output_dB = detect_dB + (((1.0 / parameters.ratio) - 1.0) * pow((detect_dB - parameters.threshold_dB + (parameters.kneeWidth_dB / 2.0)), 2.0)) / (2.0*parameters.kneeWidth_dB);
2168 }
2169 // --- right of knee, compression zone
2170 else if (2.0*(detect_dB - parameters.threshold_dB) > parameters.kneeWidth_dB)
2171 {
2172 if (parameters.hardLimitGate) // --- is limiter?
2173 output_dB = parameters.threshold_dB;
2174 else
2175 output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) / parameters.ratio;
2176 }
2177 }
2178 }
2179 else if (parameters.calculation == dynamicsProcessorType::kDownwardExpander)
2180 {
2181 // --- hard knee
2182 // --- NOTE: soft knee is not technically possible with a gate because there
2183 // is no "left side" of the knee
2185 {
2186 // --- above threshold, unity gain
2187 if (detect_dB >= parameters.threshold_dB)
2188 output_dB = detect_dB;
2189 else
2190 {
2191 if (parameters.hardLimitGate) // --- gate: -inf(dB)
2192 output_dB = -1.0e34;
2193 else
2194 output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) * parameters.ratio;
2195 }
2196 }
2197 else // --- calc gain with knee
2198 {
2199 // --- right side of knee, unity gain zone
2200 if (2.0*(detect_dB - parameters.threshold_dB) > parameters.kneeWidth_dB)
2201 output_dB = detect_dB;
2202 // --- in the knee
2203 else if (2.0*(fabs(detect_dB - parameters.threshold_dB)) > -parameters.kneeWidth_dB)
2204 output_dB = ((parameters.ratio - 1.0) * pow((detect_dB - parameters.threshold_dB - (parameters.kneeWidth_dB / 2.0)), 2.0)) / (2.0*parameters.kneeWidth_dB);
2205 // --- left side of knee, downward expander zone
2206 else if (2.0*(detect_dB - parameters.threshold_dB) <= -parameters.kneeWidth_dB)
2207 output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) * parameters.ratio;
2208 }
2209 }
2210
2211 // --- convert gain; store values for user meters
2212 parameters.gainReduction_dB = output_dB - detect_dB;
2214
2215 // --- the current gain coefficient value
2217 }
2218};
2219
2231template <typename T>
2233{
2234public:
2235 LinearBuffer() {} /* C-TOR */
2236 ~LinearBuffer() {} /* D-TOR */
2237
2239 void flushBuffer() { memset(&buffer[0], 0, bufferLength * sizeof(T)); }
2240
2243 void createLinearBuffer(unsigned int _bufferLength)
2244 {
2245 // --- find nearest power of 2 for buffer, save it as bufferLength
2246 bufferLength = _bufferLength;
2247
2248 // --- create new buffer
2249 buffer.reset(new T[bufferLength]);
2250
2251 // --- flush buffer
2252 flushBuffer();
2253 }
2254
2256 void writeBuffer(unsigned int index, T input)
2257 {
2258 if (index >= bufferLength) return;
2259
2260 // --- write and increment index counter
2261 buffer[index] = input;
2262 }
2263
2265 T readBuffer(unsigned int index)//, bool readBeforeWrite = true)
2266 {
2267 if (index >= bufferLength) return 0.0;
2268
2269 // --- read it
2270 return buffer[index];
2271 }
2272
2273private:
2274 std::unique_ptr<T[]> buffer = nullptr;
2275 unsigned int bufferLength = 1024;
2276};
2277
2278
2293template <typename T>
2295{
2296public:
2297 CircularBuffer() {} /* C-TOR */
2298 ~CircularBuffer() {} /* D-TOR */
2299
2301 void flushBuffer(){ memset(&buffer[0], 0, bufferLength * sizeof(T)); }
2302
2305 void createCircularBuffer(unsigned int _bufferLength)
2306 {
2307 // --- find nearest power of 2 for buffer, and create
2308 createCircularBufferPowerOfTwo((unsigned int)(pow(2, ceil(log(_bufferLength) / log(2)))));
2309 }
2310
2313 void createCircularBufferPowerOfTwo(unsigned int _bufferLengthPowerOfTwo)
2314 {
2315 // --- reset to top
2316 writeIndex = 0;
2317
2318 // --- find nearest power of 2 for buffer, save it as bufferLength
2319 bufferLength = _bufferLengthPowerOfTwo;
2320
2321 // --- save (bufferLength - 1) for use as wrapping mask
2322 wrapMask = bufferLength - 1;
2323
2324 // --- create new buffer
2325 buffer.reset(new T[bufferLength]);
2326
2327 // --- flush buffer
2328 flushBuffer();
2329 }
2330
2332 void writeBuffer(T input)
2333 {
2334 // --- write and increment index counter
2335 buffer[writeIndex++] = input;
2336
2337 // --- wrap if index > bufferlength - 1
2338 writeIndex &= wrapMask;
2339 }
2340
2342 T readBuffer(int delayInSamples)//, bool readBeforeWrite = true)
2343 {
2344 // --- subtract to make read index
2345 // note: -1 here is because we read-before-write,
2346 // so the *last* write location is what we use for the calculation
2347 int readIndex = (writeIndex - 1) - delayInSamples;
2348
2349 // --- autowrap index
2350 readIndex &= wrapMask;
2351
2352 // --- read it
2353 return buffer[readIndex];
2354 }
2355
2357 T readBuffer(double delayInFractionalSamples)
2358 {
2359 // --- truncate delayInFractionalSamples and read the int part
2360 T y1 = readBuffer((int)delayInFractionalSamples);
2361
2362 // --- if no interpolation, just return value
2363 if (!interpolate) return y1;
2364
2365 // --- else do interpolation
2366 //
2367 // --- read the sample at n+1 (one sample OLDER)
2368 T y2 = readBuffer((int)delayInFractionalSamples + 1);
2369
2370 // --- get fractional part
2371 double fraction = delayInFractionalSamples - (int)delayInFractionalSamples;
2372
2373 // --- do the interpolation (you could try different types here)
2374 return doLinearInterpolation(y1, y2, fraction);
2375 }
2376
2378 void setInterpolate(bool b) { interpolate = b; }
2379
2380private:
2381 std::unique_ptr<T[]> buffer = nullptr;
2382 unsigned int writeIndex = 0;
2383 unsigned int bufferLength = 1024;
2384 unsigned int wrapMask = 1023;
2385 bool interpolate = true;
2386};
2387
2388
2408{
2409public:
2411 init(512);
2412 } /* C-TOR */
2413 ~ImpulseConvolver() {} /* D-TOR */
2414
2416 virtual bool reset(double _sampleRate)
2417 {
2418 // --- flush signal buffer; IR buffer is static
2420 return true;
2421 }
2422
2428 virtual double processAudioSample(double xn)
2429 {
2430 double output = 0.0;
2431
2432 // --- write buffer; x(n) overwrites oldest value
2433 // this is the only time we do not read before write!
2435
2436 // --- do the convolution
2437 for (unsigned int i = 0; i < length; i++)
2438 {
2439 // --- y(n) += x(n)h(n)
2440 // for signalBuffer.readBuffer(0) -> x(n)
2441 // signalBuffer.readBuffer(n-D)-> x(n-D)
2442 double signal = signalBuffer.readBuffer((int)i);
2443 double irrrrr = irBuffer.readBuffer((int)i);
2444 output += signal*irrrrr;
2445
2446 //output += signalBuffer.readBuffer((int)i) * irBuffer.readBuffer((int)i);
2447 }
2448
2449 return output;
2450 }
2451
2453 virtual bool canProcessAudioFrame() { return false; }
2454
2456 void init(unsigned int lengthPowerOfTwo)
2457 {
2458 length = lengthPowerOfTwo;
2459 // --- create (and clear out) the buffers
2461 irBuffer.createLinearBuffer(lengthPowerOfTwo);
2462 }
2463
2465 void setImpulseResponse(double* irArray, unsigned int lengthPowerOfTwo)
2466 {
2467 if (lengthPowerOfTwo != length)
2468 {
2469 length = lengthPowerOfTwo;
2470 // --- create (and clear out) the buffers
2472 irBuffer.createLinearBuffer(lengthPowerOfTwo);
2473 }
2474
2475 // --- load up the IR buffer
2476 for (unsigned int i = 0; i < length; i++)
2477 {
2478 irBuffer.writeBuffer(i, irArray[i]);
2479 }
2480 }
2481
2482protected:
2483 // --- delay buffer of doubles
2486
2487 unsigned int length = 0;
2488
2489};
2490
2491const unsigned int IR_LEN = 512;
2506{
2509 AnalogFIRFilterParameters& operator=(const AnalogFIRFilterParameters& params) // need this override for collections to work
2510 {
2511 if (this == &params)
2512 return *this;
2513
2514 filterType = params.filterType;
2515 fc = params.fc;
2516 Q = params.Q;
2517
2518 return *this;
2519 }
2520
2521 // --- individual parameters
2522 analogFilter filterType = analogFilter::kLPF1;
2523 double fc = 0.0;
2524 double Q = 0.0;
2525};
2526
2547{
2548public:
2549 AnalogFIRFilter() {} /* C-TOR */
2550 ~AnalogFIRFilter() {} /* D-TOR */
2551
2552public:
2554 virtual bool reset(double _sampleRate)
2555 {
2556 sampleRate = _sampleRate;
2557 convolver.reset(_sampleRate);
2558 convolver.init(IR_LEN);
2559
2560 memset(&analogMagArray[0], 0, sizeof(double) * IR_LEN);
2561 memset(&irArray[0], 0, sizeof(double) * IR_LEN);
2562
2563 return true;
2564 }
2565
2571 virtual double processAudioSample(double xn)
2572 {
2573 // --- do the linear convolution
2574 return convolver.processAudioSample(xn);
2575 }
2576
2578 virtual bool canProcessAudioFrame() { return false; }
2579
2585
2591 {
2592 if (_parameters.fc != parameters.fc ||
2593 _parameters.Q != parameters.Q ||
2594 _parameters.filterType != parameters.filterType)
2595 {
2596 // --- set the filter IR for the convolver
2597 AnalogMagData analogFilterData;
2598 analogFilterData.sampleRate = sampleRate;
2599 analogFilterData.magArray = &analogMagArray[0];
2600 analogFilterData.dftArrayLen = IR_LEN;
2601 analogFilterData.mirrorMag = false;
2602
2603 analogFilterData.filterType = _parameters.filterType;
2604 analogFilterData.fc = _parameters.fc; // 1000.0;
2605 analogFilterData.Q = _parameters.Q;
2606
2607 // --- calculate the analog mag array
2608 calculateAnalogMagArray(analogFilterData);
2609
2610 // --- frequency sample the mag array
2611 freqSample(IR_LEN, analogMagArray, irArray, POSITIVE);
2612
2613 // --- update new frequency response
2614 convolver.setImpulseResponse(irArray, IR_LEN);
2615 }
2616
2617 parameters = _parameters;
2618 }
2619
2620private:
2621 AnalogFIRFilterParameters parameters;
2622 ImpulseConvolver convolver;
2623 double analogMagArray[IR_LEN];
2624 double irArray[IR_LEN];
2625 double sampleRate = 0.0;
2626};
2627
2641enum class delayAlgorithm { kNormal, kPingPong };
2642
2657enum class delayUpdateType { kLeftAndRight, kLeftPlusRatio };
2658
2659
2672{
2675 AudioDelayParameters& operator=(const AudioDelayParameters& params) // need this override for collections to work
2676 {
2677 if (this == &params)
2678 return *this;
2679
2680 algorithm = params.algorithm;
2681 wetLevel_dB = params.wetLevel_dB;
2682 dryLevel_dB = params.dryLevel_dB;
2683 feedback_Pct = params.feedback_Pct;
2684
2685 updateType = params.updateType;
2689
2690 return *this;
2691 }
2692
2693 // --- individual parameters
2694 delayAlgorithm algorithm = delayAlgorithm::kNormal;
2695 double wetLevel_dB = -3.0;
2696 double dryLevel_dB = -3.0;
2697 double feedback_Pct = 0.0;
2698
2699 delayUpdateType updateType = delayUpdateType::kLeftAndRight;
2700 double leftDelay_mSec = 0.0;
2701 double rightDelay_mSec = 0.0;
2702 double delayRatio_Pct = 100.0;
2703};
2704
2723{
2724public:
2725 AudioDelay() {} /* C-TOR */
2726 ~AudioDelay() {} /* D-TOR */
2727
2728public:
2730 virtual bool reset(double _sampleRate)
2731 {
2732 // --- if sample rate did not change
2733 if (sampleRate == _sampleRate)
2734 {
2735 // --- just flush buffer and return
2736 delayBuffer_L.flushBuffer();
2737 delayBuffer_R.flushBuffer();
2738 return true;
2739 }
2740
2741 // --- create new buffer, will store sample rate and length(mSec)
2742 createDelayBuffers(_sampleRate, bufferLength_mSec);
2743
2744 return true;
2745 }
2746
2752 virtual double processAudioSample(double xn)
2753 {
2754 // --- read delay
2755 double yn = delayBuffer_L.readBuffer(delayInSamples_L);
2756
2757 // --- create input for delay buffer
2758 double dn = xn + (parameters.feedback_Pct / 100.0) * yn;
2759
2760 // --- write to delay buffer
2761 delayBuffer_L.writeBuffer(dn);
2762
2763 // --- form mixture out = dry*xn + wet*yn
2764 double output = dryMix*xn + wetMix*yn;
2765
2766 return output;
2767 }
2768
2770 virtual bool canProcessAudioFrame() { return true; }
2771
2773 virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
2774 float* outputFrame,
2775 uint32_t inputChannels,
2776 uint32_t outputChannels)
2777 {
2778 // --- make sure we have input and outputs
2779 if (inputChannels == 0 || outputChannels == 0)
2780 return false;
2781
2782 // --- make sure we support this delay algorithm
2783 if (parameters.algorithm != delayAlgorithm::kNormal &&
2784 parameters.algorithm != delayAlgorithm::kPingPong)
2785 return false;
2786
2787 // --- if only one output channel, revert to mono operation
2788 if (outputChannels == 1)
2789 {
2790 // --- process left channel only
2791 outputFrame[0] = (float)processAudioSample(inputFrame[0]);
2792 return true;
2793 }
2794
2795 // --- if we get here we know we have 2 output channels
2796 //
2797 // --- pick up inputs
2798 //
2799 // --- LEFT channel
2800 double xnL = inputFrame[0];
2801
2802 // --- RIGHT channel (duplicate left input if mono-in)
2803 double xnR = inputChannels > 1 ? inputFrame[1] : xnL;
2804
2805 // --- read delay LEFT
2806 double ynL = delayBuffer_L.readBuffer(delayInSamples_L);
2807
2808 // --- read delay RIGHT
2809 double ynR = delayBuffer_R.readBuffer(delayInSamples_R);
2810
2811 // --- create input for delay buffer with LEFT channel info
2812 double dnL = xnL + (parameters.feedback_Pct / 100.0) * ynL;
2813
2814 // --- create input for delay buffer with RIGHT channel info
2815 double dnR = xnR + (parameters.feedback_Pct / 100.0) * ynR;
2816
2817 // --- decode
2818 if (parameters.algorithm == delayAlgorithm::kNormal)
2819 {
2820 // --- write to LEFT delay buffer with LEFT channel info
2821 delayBuffer_L.writeBuffer(dnL);
2822
2823 // --- write to RIGHT delay buffer with RIGHT channel info
2824 delayBuffer_R.writeBuffer(dnR);
2825 }
2826 else if (parameters.algorithm == delayAlgorithm::kPingPong)
2827 {
2828 // --- write to LEFT delay buffer with RIGHT channel info
2829 delayBuffer_L.writeBuffer(dnR);
2830
2831 // --- write to RIGHT delay buffer with LEFT channel info
2832 delayBuffer_R.writeBuffer(dnL);
2833 }
2834
2835 // --- form mixture out = dry*xn + wet*yn
2836 double outputL = dryMix*xnL + wetMix*ynL;
2837
2838 // --- form mixture out = dry*xn + wet*yn
2839 double outputR = dryMix*xnR + wetMix*ynR;
2840
2841 // --- set left channel
2842 outputFrame[0] = (float)outputL;
2843
2844 // --- set right channel
2845 outputFrame[1] = (float)outputR;
2846
2847 return true;
2848 }
2849
2854 AudioDelayParameters getParameters() { return parameters; }
2855
2861 {
2862 // --- check mix in dB for calc
2863 if (_parameters.dryLevel_dB != parameters.dryLevel_dB)
2864 dryMix = pow(10.0, _parameters.dryLevel_dB / 20.0);
2865 if (_parameters.wetLevel_dB != parameters.wetLevel_dB)
2866 wetMix = pow(10.0, _parameters.wetLevel_dB / 20.0);
2867
2868 // --- save; rest of updates are cheap on CPU
2869 parameters = _parameters;
2870
2871 // --- check update type first:
2872 if (parameters.updateType == delayUpdateType::kLeftAndRight)
2873 {
2874 // --- set left and right delay times
2875 // --- calculate total delay time in samples + fraction
2876 double newDelayInSamples_L = parameters.leftDelay_mSec*(samplesPerMSec);
2877 double newDelayInSamples_R = parameters.rightDelay_mSec*(samplesPerMSec);
2878
2879 // --- new delay time with fraction
2880 delayInSamples_L = newDelayInSamples_L;
2881 delayInSamples_R = newDelayInSamples_R;
2882 }
2883 else if (parameters.updateType == delayUpdateType::kLeftPlusRatio)
2884 {
2885 // --- get and validate ratio
2886 double delayRatio = parameters.delayRatio_Pct / 100.0;
2887 boundValue(delayRatio, 0.0, 1.0);
2888
2889 // --- calculate total delay time in samples + fraction
2890 double newDelayInSamples = parameters.leftDelay_mSec*(samplesPerMSec);
2891
2892 // --- new delay time with fraction
2893 delayInSamples_L = newDelayInSamples;
2894 delayInSamples_R = delayInSamples_L*delayRatio;
2895 }
2896 }
2897
2899 void createDelayBuffers(double _sampleRate, double _bufferLength_mSec)
2900 {
2901 // --- store for math
2902 bufferLength_mSec = _bufferLength_mSec;
2903 sampleRate = _sampleRate;
2904 samplesPerMSec = sampleRate / 1000.0;
2905
2906 // --- total buffer length including fractional part
2907 bufferLength = (unsigned int)(bufferLength_mSec*(samplesPerMSec)) + 1; // +1 for fractional part
2908
2909 // --- create new buffer
2910 delayBuffer_L.createCircularBuffer(bufferLength);
2911 delayBuffer_R.createCircularBuffer(bufferLength);
2912 }
2913
2914private:
2915 AudioDelayParameters parameters;
2916
2917 double sampleRate = 0.0;
2918 double samplesPerMSec = 0.0;
2919 double delayInSamples_L = 0.0;
2920 double delayInSamples_R = 0.0;
2921 double bufferLength_mSec = 0.0;
2922 unsigned int bufferLength = 0;
2923 double wetMix = 0.707;
2924 double dryMix = 0.707;
2925
2926 // --- delay buffer of doubles
2927 CircularBuffer<double> delayBuffer_L;
2928 CircularBuffer<double> delayBuffer_R;
2929};
2930
2931
2945enum class generatorWaveform { kTriangle, kSin, kSaw };
2946
2959{
2962 OscillatorParameters& operator=(const OscillatorParameters& params) // need this override for collections to work
2963 {
2964 if (this == &params)
2965 return *this;
2966
2967 waveform = params.waveform;
2968 frequency_Hz = params.frequency_Hz;
2969 return *this;
2970 }
2971
2972 // --- individual parameters
2973 generatorWaveform waveform = generatorWaveform::kTriangle;
2974 double frequency_Hz = 0.0;
2975};
2976
2996{
2997public:
2998 LFO() { srand((uint32_t)time(NULL)); } /* C-TOR */
2999 virtual ~LFO() {} /* D-TOR */
3000
3002 virtual bool reset(double _sampleRate)
3003 {
3004 sampleRate = _sampleRate;
3006
3007 // --- timebase variables
3008 modCounter = 0.0;
3009 modCounterQP = 0.25;
3010
3011 return true;
3012 }
3013
3019
3025 {
3027 // --- update phase inc based on osc freq and fs
3028 phaseInc = params.frequency_Hz / sampleRate;
3029
3030 lfoParameters = params;
3031 }
3032
3034 virtual const SignalGenData renderAudioOutput();
3035
3036protected:
3037 // --- parameters
3039
3040 // --- sample rate
3041 double sampleRate = 0.0;
3042
3043 // --- timebase variables
3044 double modCounter = 0.0;
3045 double phaseInc = 0.0;
3046 double modCounterQP = 0.25;
3047
3049 inline bool checkAndWrapModulo(double& moduloCounter, double phaseInc)
3050 {
3051 // --- for positive frequencies
3052 if (phaseInc > 0 && moduloCounter >= 1.0)
3053 {
3054 moduloCounter -= 1.0;
3055 return true;
3056 }
3057
3058 // --- for negative frequencies
3059 if (phaseInc < 0 && moduloCounter <= 0.0)
3060 {
3061 moduloCounter += 1.0;
3062 return true;
3063 }
3064
3065 return false;
3066 }
3067
3069 inline bool advanceAndCheckWrapModulo(double& moduloCounter, double phaseInc)
3070 {
3071 // --- advance counter
3072 moduloCounter += phaseInc;
3073
3074 // --- for positive frequencies
3075 if (phaseInc > 0 && moduloCounter >= 1.0)
3076 {
3077 moduloCounter -= 1.0;
3078 return true;
3079 }
3080
3081 // --- for negative frequencies
3082 if (phaseInc < 0 && moduloCounter <= 0.0)
3083 {
3084 moduloCounter += 1.0;
3085 return true;
3086 }
3087
3088 return false;
3089 }
3090
3092 inline void advanceModulo(double& moduloCounter, double phaseInc) { moduloCounter += phaseInc; }
3093
3094 const double B = 4.0 / kPi;
3095 const double C = -4.0 / (kPi* kPi);
3096 const double P = 0.225;
3098 inline double parabolicSine(double angle)
3099 {
3100 double y = B * angle + C * angle * fabs(angle);
3101 y = P * (y * fabs(y) - y) + y;
3102 return y;
3103 }
3104};
3105
3119enum DFOscillatorCoeffs { df_b1, df_b2, numDFOCoeffs };
3120
3134enum DFOscillatorStates { df_yz1, df_yz2, numDFOStates };
3135
3136
3156{
3157public:
3158 DFOscillator() { } /* C-TOR */
3159 virtual ~DFOscillator() {} /* D-TOR */
3160
3162 virtual bool reset(double _sampleRate)
3163 {
3164 sampleRate = _sampleRate;
3165 memset(&stateArray[0], 0, sizeof(double)*numDFOStates);
3166 updateDFO();
3167 return true;
3168 }
3169
3175 {
3176 return parameters;
3177 }
3178
3184 {
3185 if (parameters.frequency_Hz != params.frequency_Hz)
3186 {
3187 parameters = params;
3188 updateDFO();
3189 }
3190 }
3191
3194 {
3195 // --- calculates normal and inverted outputs; quadphase are not used
3196 SignalGenData output;
3197
3198 // -- do difference equation y(n) = -b1y(n-2) - b2y(n-2)
3199 output.normalOutput = (-coeffArray[df_b1]*stateArray[df_yz1] - coeffArray[df_b2]*stateArray[df_yz2]);
3200 output.invertedOutput = -output.normalOutput;
3201
3202 // --- update states
3203 stateArray[df_yz2] = stateArray[df_yz1];
3204 stateArray[df_yz1] = output.normalOutput;
3205
3206 return output;
3207 }
3208
3211 {
3212 // --- Oscillation Rate = theta = wT = w/fs
3213 double wT = (kTwoPi*parameters.frequency_Hz) / sampleRate;
3214
3215 // --- coefficients to place poles right on unit circle
3216 coeffArray[df_b1] = -2.0*cos(wT); // <--- set angle a = -2Rcod(theta)
3217 coeffArray[df_b2] = 1.0; // <--- R^2 = 1, so R = 1
3218
3219 // --- now update states to reflect the new frequency
3220 // re calculate the new initial conditions
3221 // arcsine of y(n-1) gives us wnT
3222 double wnT1 = asin(stateArray[df_yz1]);
3223
3224 // find n by dividing wnT by wT
3225 double n = wnT1 / wT;
3226
3227 // --- re calculate the new initial conditions
3228 // asin returns values from -pi/2 to +pi/2 where the sinusoid
3229 // moves from -1 to +1 -- the leading (rising) edge of the
3230 // sinewave. If we are on that leading edge (increasing)
3231 // then we use the value 1T behind.
3232 //
3233 // If we are on the falling edge, we use the value 1T ahead
3234 // because it mimics the value that would be 1T behind
3235 if (stateArray[df_yz1] > stateArray[df_yz2])
3236 n -= 1;
3237 else
3238 n += 1;
3239
3240 // --- calculate the new (old) sample
3241 stateArray[df_yz2] = sin((n)*wT);
3242 }
3243
3244
3245protected:
3246 // --- parameters
3248
3249 // --- implementation of half a biquad - this object is extremely specific
3250 double stateArray[numDFOStates] = { 0.0, 0.0 };
3251 double coeffArray[numDFOCoeffs] = { 0.0, 0.0 };
3252
3253 // --- sample rate
3254 double sampleRate = 0.0;
3255};
3256
3257
3271enum class modDelaylgorithm { kFlanger, kChorus, kVibrato };
3272
3273
3286{
3289 ModulatedDelayParameters& operator=(const ModulatedDelayParameters& params) // need this override for collections to work
3290 {
3291 if (this == &params)
3292 return *this;
3293
3294 algorithm = params.algorithm;
3295 lfoRate_Hz = params.lfoRate_Hz;
3296 lfoDepth_Pct = params.lfoDepth_Pct;
3297 feedback_Pct = params.feedback_Pct;
3298 return *this;
3299 }
3300
3301 // --- individual parameters
3302 modDelaylgorithm algorithm = modDelaylgorithm::kFlanger;
3303 double lfoRate_Hz = 0.0;
3304 double lfoDepth_Pct = 0.0;
3305 double feedback_Pct = 0.0;
3306};
3307
3326{
3327public:
3328 ModulatedDelay() {
3329 } /* C-TOR */
3330 ~ModulatedDelay() {} /* D-TOR */
3331
3332public:
3334 virtual bool reset(double _sampleRate)
3335 {
3336 // --- create new buffer, 100mSec long
3337 delay.reset(_sampleRate);
3338 delay.createDelayBuffers(_sampleRate, 100.0);
3339
3340 // --- lfo
3341 lfo.reset(_sampleRate);
3342 OscillatorParameters params = lfo.getParameters();
3343 params.waveform = generatorWaveform::kTriangle;
3344 lfo.setParameters(params);
3345
3346 return true;
3347 }
3348
3354 virtual double processAudioSample(double xn)
3355 {
3356 float input = (float)xn;
3357 float output = 0.0;
3358 processAudioFrame(&input, &output, 1, 1);
3359 return output;
3360 }
3361
3363 virtual bool canProcessAudioFrame() { return true; }
3364
3366 virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
3367 float* outputFrame,
3368 uint32_t inputChannels,
3369 uint32_t outputChannels)
3370 {
3371 // --- make sure we have input and outputs
3372 if (inputChannels == 0 || outputChannels == 0)
3373 return false;
3374
3375 // --- render LFO
3376 SignalGenData lfoOutput = lfo.renderAudioOutput();
3377
3378 // --- setup delay modulation
3379 AudioDelayParameters params = delay.getParameters();
3380 double minDelay_mSec = 0.0;
3381 double maxDepth_mSec = 0.0;
3382
3383 // --- set delay times, wet/dry and feedback
3384 if (parameters.algorithm == modDelaylgorithm::kFlanger)
3385 {
3386 minDelay_mSec = 0.1;
3387 maxDepth_mSec = 7.0;
3388 params.wetLevel_dB = -3.0;
3389 params.dryLevel_dB = -3.0;
3390 }
3391 if (parameters.algorithm == modDelaylgorithm::kChorus)
3392 {
3393 minDelay_mSec = 10.0;
3394 maxDepth_mSec = 30.0;
3395 params.wetLevel_dB = -3.0;
3396 params.dryLevel_dB = -0.0;
3397 params.feedback_Pct = 0.0;
3398 }
3399 if (parameters.algorithm == modDelaylgorithm::kVibrato)
3400 {
3401 minDelay_mSec = 0.0;
3402 maxDepth_mSec = 7.0;
3403 params.wetLevel_dB = 0.0;
3404 params.dryLevel_dB = -96.0;
3405 params.feedback_Pct = 0.0;
3406 }
3407
3408 // --- calc modulated delay times
3409 double depth = parameters.lfoDepth_Pct / 100.0;
3410 double modulationMin = minDelay_mSec;
3411 double modulationMax = minDelay_mSec + maxDepth_mSec;
3412
3413 // --- flanger - unipolar
3414 if (parameters.algorithm == modDelaylgorithm::kFlanger)
3416 modulationMin, modulationMax);
3417 else
3418 params.leftDelay_mSec = doBipolarModulation(depth * lfoOutput.normalOutput, modulationMin, modulationMax);
3419
3420
3421 // --- set right delay to match (*Hint Homework!)
3422 params.rightDelay_mSec = params.leftDelay_mSec;
3423
3424 // --- modulate the delay
3425 delay.setParameters(params);
3426
3427 // --- just call the function and pass our info in/out
3428 return delay.processAudioFrame(inputFrame, outputFrame, inputChannels, outputChannels);
3429 }
3430
3436
3442 {
3443 // --- bulk copy
3444 parameters = _parameters;
3445
3446 OscillatorParameters lfoParams = lfo.getParameters();
3447 lfoParams.frequency_Hz = parameters.lfoRate_Hz;
3448 if (parameters.algorithm == modDelaylgorithm::kVibrato)
3449 lfoParams.waveform = generatorWaveform::kSin;
3450 else
3451 lfoParams.waveform = generatorWaveform::kTriangle;
3452
3453 lfo.setParameters(lfoParams);
3454
3455 AudioDelayParameters adParams = delay.getParameters();
3456 adParams.feedback_Pct = parameters.feedback_Pct;
3457 delay.setParameters(adParams);
3458 }
3459
3460private:
3461 ModulatedDelayParameters parameters;
3462 AudioDelay delay;
3463 LFO lfo;
3464};
3465
3478{
3482 {
3483 if (this == &params)
3484 return *this;
3485
3486 lfoRate_Hz = params.lfoRate_Hz;
3487 lfoDepth_Pct = params.lfoDepth_Pct;
3489 quadPhaseLFO = params.quadPhaseLFO;
3490 return *this;
3491 }
3492
3493 // --- individual parameters
3494 double lfoRate_Hz = 0.0;
3495 double lfoDepth_Pct = 0.0;
3496 double intensity_Pct = 0.0;
3497 bool quadPhaseLFO = false;
3498};
3499
3500// --- constants for Phaser
3501const unsigned int PHASER_STAGES = 6;
3502
3503// --- these are the ideal band definitions
3504//const double apf0_minF = 16.0;
3505//const double apf0_maxF = 1600.0;
3506//
3507//const double apf1_minF = 33.0;
3508//const double apf1_maxF = 3300.0;
3509//
3510//const double apf2_minF = 48.0;
3511//const double apf2_maxF = 4800.0;
3512//
3513//const double apf3_minF = 98.0;
3514//const double apf3_maxF = 9800.0;
3515//
3516//const double apf4_minF = 160.0;
3517//const double apf4_maxF = 16000.0;
3518//
3519//const double apf5_minF = 260.0;
3520//const double apf5_maxF = 20480.0;
3521
3522// --- these are the exact values from the National Semiconductor Phaser design
3523const double apf0_minF = 32.0;
3524const double apf0_maxF = 1500.0;
3525
3526const double apf1_minF = 68.0;
3527const double apf1_maxF = 3400.0;
3528
3529const double apf2_minF = 96.0;
3530const double apf2_maxF = 4800.0;
3531
3532const double apf3_minF = 212.0;
3533const double apf3_maxF = 10000.0;
3534
3535const double apf4_minF = 320.0;
3536const double apf4_maxF = 16000.0;
3537
3538const double apf5_minF = 636.0;
3539const double apf5_maxF = 20480.0;
3540
3559{
3560public:
3561 PhaseShifter(void) {
3563 lfoparams.waveform = generatorWaveform::kTriangle; // kTriangle LFO for phaser
3564 // lfoparams.waveform = generatorWaveform::kSin; // kTriangle LFO for phaser
3565 lfo.setParameters(lfoparams);
3566
3568 params.algorithm = filterAlgorithm::kAPF1; // can also use 2nd order
3569 // params.Q = 0.001; use low Q if using 2nd order APFs
3570
3571 for (uint32_t i = 0; i < PHASER_STAGES; i++)
3572 {
3573 apf[i].setParameters(params);
3574 }
3575 } /* C-TOR */
3576
3577 ~PhaseShifter(void) {} /* D-TOR */
3578
3579public:
3581 virtual bool reset(double _sampleRate)
3582 {
3583 // --- reset LFO
3584 lfo.reset(_sampleRate);
3585
3586 // --- reset APFs
3587 for (uint32_t i = 0; i < PHASER_STAGES; i++){
3588 apf[i].reset(_sampleRate);
3589 }
3590
3591 return true;
3592 }
3593
3599 virtual double processAudioSample(double xn)
3600 {
3602
3603 // --- create the bipolar modulator value
3604 double lfoValue = lfoData.normalOutput;
3606 lfoValue = lfoData.quadPhaseOutput_pos;
3607
3608 double depth = parameters.lfoDepth_Pct / 100.0;
3609 double modulatorValue = lfoValue*depth;
3610
3611 // --- calculate modulated values for each APF; note they have different ranges
3613 params.fc = doBipolarModulation(modulatorValue, apf0_minF, apf0_maxF);
3614 apf[0].setParameters(params);
3615
3616 params = apf[1].getParameters();
3617 params.fc = doBipolarModulation(modulatorValue, apf1_minF, apf1_maxF);
3618 apf[1].setParameters(params);
3619
3620 params = apf[2].getParameters();
3621 params.fc = doBipolarModulation(modulatorValue, apf2_minF, apf2_maxF);
3622 apf[2].setParameters(params);
3623
3624 params = apf[3].getParameters();
3625 params.fc = doBipolarModulation(modulatorValue, apf3_minF, apf3_maxF);
3626 apf[3].setParameters(params);
3627
3628 params = apf[4].getParameters();
3629 params.fc = doBipolarModulation(modulatorValue, apf4_minF, apf4_maxF);
3630 apf[4].setParameters(params);
3631
3632 params = apf[5].getParameters();
3633 params.fc = doBipolarModulation(modulatorValue, apf5_minF, apf5_maxF);
3634 apf[5].setParameters(params);
3635
3636 // --- calculate gamma values
3637 double gamma1 = apf[5].getG_value();
3638 double gamma2 = apf[4].getG_value() * gamma1;
3639 double gamma3 = apf[3].getG_value() * gamma2;
3640 double gamma4 = apf[2].getG_value() * gamma3;
3641 double gamma5 = apf[1].getG_value() * gamma4;
3642 double gamma6 = apf[0].getG_value() * gamma5;
3643
3644 // --- set the alpha0 value
3645 double K = parameters.intensity_Pct / 100.0;
3646 double alpha0 = 1.0 / (1.0 + K*gamma6);
3647
3648 // --- create combined feedback
3649 double Sn = gamma5*apf[0].getS_value() + gamma4*apf[1].getS_value() + gamma3*apf[2].getS_value() + gamma2*apf[3].getS_value() + gamma1*apf[4].getS_value() + apf[5].getS_value();
3650
3651 // --- form input to first APF
3652 double u = alpha0*(xn + K*Sn);
3653
3654 // --- cascade of APFs (could also nest these in one massive line of code)
3655 double APF1 = apf[0].processAudioSample(u);
3656 double APF2 = apf[1].processAudioSample(APF1);
3657 double APF3 = apf[2].processAudioSample(APF2);
3658 double APF4 = apf[3].processAudioSample(APF3);
3659 double APF5 = apf[4].processAudioSample(APF4);
3660 double APF6 = apf[5].processAudioSample(APF5);
3661
3662 // --- sum with -3dB coefficients
3663 // double output = 0.707*xn + 0.707*APF6;
3664
3665 // --- sum with National Semiconductor design ratio:
3666 // dry = 0.5, wet = 5.0
3667 // double output = 0.5*xn + 5.0*APF6;
3668 // double output = 0.25*xn + 2.5*APF6;
3669 double output = 0.125*xn + 1.25*APF6;
3670
3671 return output;
3672 }
3673
3675 virtual bool canProcessAudioFrame() { return false; }
3676
3682
3688 {
3689 // --- update LFO rate
3690 if (params.lfoRate_Hz != parameters.lfoRate_Hz)
3691 {
3693 lfoparams.frequency_Hz = params.lfoRate_Hz;
3694 lfo.setParameters(lfoparams);
3695 }
3696
3697 // --- save new
3698 parameters = params;
3699 }
3700protected:
3702 AudioFilter apf[PHASER_STAGES];
3704};
3705
3718{
3721 SimpleLPFParameters& operator=(const SimpleLPFParameters& params) // need this override for collections to work
3722 {
3723 if (this == &params)
3724 return *this;
3725
3726 g = params.g;
3727 return *this;
3728 }
3729
3730 // --- individual parameters
3731 double g = 0.0;
3732};
3733
3752{
3753public:
3754 SimpleLPF(void) {} /* C-TOR */
3755 ~SimpleLPF(void) {} /* D-TOR */
3756
3757public:
3759 virtual bool reset(double _sampleRate)
3760 {
3761 state = 0.0;
3762 return true;
3763 }
3764
3770 {
3771 return simpleLPFParameters;
3772 }
3773
3779 {
3780 simpleLPFParameters = params;
3781 }
3782
3788 virtual double processAudioSample(double xn)
3789 {
3790 double g = simpleLPFParameters.g;
3791 double yn = (1.0 - g)*xn + g*state;
3792 state = yn;
3793 return yn;
3794 }
3795
3797 virtual bool canProcessAudioFrame() { return false; }
3798
3799private:
3800 SimpleLPFParameters simpleLPFParameters;
3801 double state = 0.0;
3802};
3803
3816{
3819 SimpleDelayParameters& operator=(const SimpleDelayParameters& params) // need this override for collections to work
3820 {
3821 if (this == &params)
3822 return *this;
3823
3825 interpolate = params.interpolate;
3827 return *this;
3828 }
3829
3830 // --- individual parameters
3831 double delayTime_mSec = 0.0;
3832 bool interpolate = false;
3833
3834 // --- outbound parameters
3835 double delay_Samples = 0.0;
3836};
3837
3856{
3857public:
3858 SimpleDelay(void) {} /* C-TOR */
3859 ~SimpleDelay(void) {} /* D-TOR */
3860
3861public:
3863 virtual bool reset(double _sampleRate)
3864 {
3865 // --- if sample rate did not change
3866 if (sampleRate == _sampleRate)
3867 {
3868 // --- just flush buffer and return
3869 delayBuffer.flushBuffer();
3870 return true;
3871 }
3872
3873 // --- create new buffer, will store sample rate and length(mSec)
3874 createDelayBuffer(_sampleRate, bufferLength_mSec);
3875
3876 return true;
3877 }
3878
3884 {
3885 return simpleDelayParameters;
3886 }
3887
3893 {
3894 simpleDelayParameters = params;
3895 simpleDelayParameters.delay_Samples = simpleDelayParameters.delayTime_mSec*(samplesPerMSec);
3896 delayBuffer.setInterpolate(simpleDelayParameters.interpolate);
3897 }
3898
3904 virtual double processAudioSample(double xn)
3905 {
3906 // --- read delay
3907 if (simpleDelayParameters.delay_Samples == 0)
3908 return xn;
3909
3910 double yn = delayBuffer.readBuffer(simpleDelayParameters.delay_Samples);
3911
3912 // --- write to delay buffer
3913 delayBuffer.writeBuffer(xn);
3914
3915 // --- done
3916 return yn;
3917 }
3918
3920 virtual bool canProcessAudioFrame() { return false; }
3921
3923 void createDelayBuffer(double _sampleRate, double _bufferLength_mSec)
3924 {
3925 // --- store for math
3926 bufferLength_mSec = _bufferLength_mSec;
3927 sampleRate = _sampleRate;
3928 samplesPerMSec = sampleRate / 1000.0;
3929
3930 // --- total buffer length including fractional part
3931 bufferLength = (unsigned int)(bufferLength_mSec*(samplesPerMSec)) + 1; // +1 for fractional part
3932
3933 // --- create new buffer
3934 delayBuffer.createCircularBuffer(bufferLength);
3935 }
3936
3938 double readDelay()
3939 {
3940 // --- simple read
3941 return delayBuffer.readBuffer(simpleDelayParameters.delay_Samples);
3942 }
3943
3945 double readDelayAtTime_mSec(double _delay_mSec)
3946 {
3947 // --- calculate total delay time in samples + fraction
3948 double _delay_Samples = _delay_mSec*(samplesPerMSec);
3949
3950 // --- simple read
3951 return delayBuffer.readBuffer(_delay_Samples);
3952 }
3953
3955 double readDelayAtPercentage(double delayPercent)
3956 {
3957 // --- simple read
3958 return delayBuffer.readBuffer((delayPercent / 100.0)*simpleDelayParameters.delay_Samples);
3959 }
3960
3962 void writeDelay(double xn)
3963 {
3964 // --- simple write
3965 delayBuffer.writeBuffer(xn);
3966 }
3967
3968private:
3969 SimpleDelayParameters simpleDelayParameters;
3970
3971 double sampleRate = 0.0;
3972 double samplesPerMSec = 0.0;
3973 double bufferLength_mSec = 0.0;
3974 unsigned int bufferLength = 0;
3975
3976 // --- delay buffer of doubles
3977 CircularBuffer<double> delayBuffer;
3978};
3979
3980
3993{
3996 CombFilterParameters& operator=(const CombFilterParameters& params) // need this override for collections to work
3997 {
3998 if (this == &params)
3999 return *this;
4000
4003 enableLPF = params.enableLPF;
4004 lpf_g = params.lpf_g;
4005 interpolate = params.interpolate;
4006 return *this;
4007 }
4008
4009 // --- individual parameters
4010 double delayTime_mSec = 0.0;
4011 double RT60Time_mSec = 0.0;
4012 bool enableLPF = false;
4013 double lpf_g = 0.0;
4014 bool interpolate = false;
4015};
4016
4017
4036{
4037public:
4038 CombFilter(void) {} /* C-TOR */
4039 ~CombFilter(void) {} /* D-TOR */
4040
4041public:
4043 virtual bool reset(double _sampleRate)
4044 {
4045 // --- flush
4046 lpf_state = 0.0;
4047
4048 // --- create new buffer, will store sample rate and length(mSec)
4049 createDelayBuffer(sampleRate, bufferLength_mSec);
4050
4051 return true;
4052 }
4053
4059 virtual double processAudioSample(double xn)
4060 {
4061 double yn = delay.readDelay();
4062 double input = 0.0;
4063
4064 // --- form input & write
4065 if (combFilterParameters.enableLPF)
4066 {
4067 // --- apply simple 1st order pole LPF
4068 double g2 = lpf_g*(1.0 - comb_g); // see book for equation 11.27 (old book)
4069 double filteredSignal = yn + g2*lpf_state;
4070 input = xn + comb_g*(filteredSignal);
4071 lpf_state = filteredSignal;
4072 }
4073 else
4074 {
4075 input = xn + comb_g*yn;
4076 }
4077
4078 delay.writeDelay(input);
4079
4080 // --- done
4081 return yn;
4082 }
4083
4085 virtual bool canProcessAudioFrame() { return false; }
4086
4092 {
4093 return combFilterParameters;
4094 }
4095
4101 {
4102 combFilterParameters = params;
4103
4104 // --- update the delay line parameters first
4105 SimpleDelayParameters delayParams = delay.getParameters();
4106 delayParams.delayTime_mSec = combFilterParameters.delayTime_mSec;
4107 delayParams.interpolate = combFilterParameters.interpolate;
4108 delay.setParameters(delayParams); // this will set the delay time in samples
4109
4110 // --- calculate g with RT60 time (requires updated delay above^^)
4111 double exponent = -3.0*delayParams.delay_Samples*(1.0 / sampleRate);
4112 double rt60_mSec = combFilterParameters.RT60Time_mSec / 1000.0; // RT is in mSec!
4113 comb_g = pow(10.0, exponent / rt60_mSec);
4114
4115 // --- set LPF g
4116 lpf_g = combFilterParameters.lpf_g;
4117 }
4118
4120 void createDelayBuffer(double _sampleRate, double delay_mSec)
4121 {
4122 sampleRate = _sampleRate;
4123 bufferLength_mSec = delay_mSec;
4124
4125 // --- create new buffer, will store sample rate and length(mSec)
4126 delay.createDelayBuffer(_sampleRate, delay_mSec);
4127 }
4128
4129private:
4130 CombFilterParameters combFilterParameters;
4131 double sampleRate = 0.0;
4132 double comb_g = 0.0;
4133 double bufferLength_mSec = 0.0;
4134
4135 // --- LPF support
4136 double lpf_g = 0.0;
4137 double lpf_state = 0.0;
4138
4139 // --- delay buffer of doubles
4140 SimpleDelay delay;
4141};
4142
4155{
4158 DelayAPFParameters& operator=(const DelayAPFParameters& params) // need this override for collections to work
4159 {
4160 if (this == &params)
4161 return *this;
4162
4164 apf_g = params.apf_g;
4165 enableLPF = params.enableLPF;
4166 lpf_g = params.lpf_g;
4167 interpolate = params.interpolate;
4168 enableLFO = params.enableLFO;
4169 lfoRate_Hz = params.lfoRate_Hz;
4170 lfoDepth = params.lfoDepth;
4172 return *this;
4173 }
4174
4175 // --- individual parameters
4176 double delayTime_mSec = 0.0;
4177 double apf_g = 0.0;
4178 bool enableLPF = false;
4179 double lpf_g = 0.0;
4180 bool interpolate = false;
4181 bool enableLFO = false;
4182 double lfoRate_Hz = 0.0;
4183 double lfoDepth = 0.0;
4185
4186};
4187
4206{
4207public:
4208 DelayAPF(void) {} /* C-TOR */
4209 ~DelayAPF(void) {} /* D-TOR */
4210
4211public:
4213 virtual bool reset(double _sampleRate)
4214 {
4215 // --- reset children
4216 modLFO.reset(_sampleRate);
4217
4218 // --- flush
4219 lpf_state = 0.0;
4220
4221 // --- create new buffer, will store sample rate and length(mSec)
4223
4224 return true;
4225 }
4226
4232 virtual double processAudioSample(double xn)
4233 {
4235 if (delayParams.delay_Samples == 0)
4236 return xn;
4237
4238 // --- delay line output
4239 double wnD = 0.0;
4240 double apf_g = delayAPFParameters.apf_g;
4241 double lpf_g = delayAPFParameters.lpf_g;
4242 double lfoDepth = delayAPFParameters.lfoDepth;
4243
4244 // --- for modulated APFs
4246 {
4248 double maxDelay = delayParams.delayTime_mSec;
4249 double minDelay = maxDelay - delayAPFParameters.lfoMaxModulation_mSec;
4250 minDelay = fmax(0.0, minDelay); // bound minDelay to 0 as minimum
4251
4252 // --- calc max-down modulated value with unipolar converted LFO output
4253 // NOTE: LFO output is scaled by lfoDepth
4254 double modDelay_mSec = doUnipolarModulationFromMax(bipolarToUnipolar(lfoDepth*lfoOutput.normalOutput),
4255 minDelay, maxDelay);
4256
4257 // --- read modulated value to get w(n-D);
4258 wnD = delay.readDelayAtTime_mSec(modDelay_mSec);
4259 }
4260 else
4261 // --- read the delay line to get w(n-D)
4262 wnD = delay.readDelay();
4263
4265 {
4266 // --- apply simple 1st order pole LPF, overwrite wnD
4267 wnD = wnD*(1.0 - lpf_g) + lpf_g*lpf_state;
4268 lpf_state = wnD;
4269 }
4270
4271 // form w(n) = x(n) + gw(n-D)
4272 double wn = xn + apf_g*wnD;
4273
4274 // form y(n) = -gw(n) + w(n-D)
4275 double yn = -apf_g*wn + wnD;
4276
4277 // underflow check
4279
4280 // write delay line
4281 delay.writeDelay(wn);
4282
4283 return yn;
4284 }
4285
4287 virtual bool canProcessAudioFrame() { return false; }
4288
4294 {
4295 return delayAPFParameters;
4296 }
4297
4303 {
4304 delayAPFParameters = params;
4305
4306 // --- update delay line
4309 delay.setParameters(delayParams);
4310 }
4311
4313 void createDelayBuffer(double _sampleRate, double delay_mSec)
4314 {
4315 sampleRate = _sampleRate;
4316 bufferLength_mSec = delay_mSec;
4317
4318 // --- create new buffer, will store sample rate and length(mSec)
4319 delay.createDelayBuffer(_sampleRate, delay_mSec);
4320 }
4321
4322protected:
4323 // --- component parameters
4325 double sampleRate = 0.0;
4326 double bufferLength_mSec = 0.0;
4327
4328 // --- delay buffer of doubles
4330
4331 // --- optional LFO
4333
4334 // --- LPF support
4335 double lpf_state = 0.0;
4336};
4337
4338
4351{
4354 NestedDelayAPFParameters& operator=(const NestedDelayAPFParameters& params) // need this override for collections to work
4355 {
4356 if (this == &params)
4357 return *this;
4358
4361 outerAPF_g = params.outerAPF_g;
4362 innerAPF_g = params.innerAPF_g;
4363
4364 // --- outer LFO
4365 enableLFO = params.enableLFO;
4366 lfoRate_Hz = params.lfoRate_Hz;
4367 lfoDepth = params.lfoDepth;
4369
4370 return *this;
4371 }
4372
4373 // --- individual parameters
4376 double outerAPF_g = 0.0;
4377 double innerAPF_g = 0.0;
4378
4379 // --- this LFO belongs to the outer APF only
4380 bool enableLFO = false;
4381 double lfoRate_Hz = 0.0;
4382 double lfoDepth = 1.0;
4384
4385};
4386
4407{
4408public:
4409 NestedDelayAPF(void) { } /* C-TOR */
4410 ~NestedDelayAPF(void) { } /* D-TOR */
4411
4412public:
4414 virtual bool reset(double _sampleRate)
4415 {
4416 // --- call base class reset first
4417 DelayAPF::reset(_sampleRate);
4418
4419 // --- then do our stuff
4420 nestedAPF.reset(_sampleRate);
4421
4422 return true;
4423 }
4424
4430 virtual double processAudioSample(double xn)
4431 {
4432 // --- delay line output
4433 double wnD = 0.0;
4434
4436 if (delayParams.delay_Samples == 0)
4437 return xn;
4438
4439 double apf_g = delayAPFParameters.apf_g;
4440 double lpf_g = delayAPFParameters.lpf_g;
4441
4442 // --- for modulated APFs
4444 {
4446 double maxDelay = delayParams.delayTime_mSec;
4447 double minDelay = maxDelay - delayAPFParameters.lfoMaxModulation_mSec;
4448 minDelay = fmax(0.0, minDelay); // bound minDelay to 0 as minimum
4449 double lfoDepth = delayAPFParameters.lfoDepth;
4450
4451 // --- calc max-down modulated value with unipolar converted LFO output
4452 // NOTE: LFO output is scaled by lfoDepth
4453 double modDelay_mSec = doUnipolarModulationFromMax(bipolarToUnipolar(lfoDepth*lfoOutput.normalOutput),
4454 minDelay, maxDelay);
4455
4456 // --- read modulated value to get w(n-D);
4457 wnD = delay.readDelayAtTime_mSec(modDelay_mSec);
4458 }
4459 else
4460 // --- read the delay line to get w(n-D)
4461 wnD = delay.readDelay();
4462
4464 {
4465 // --- apply simple 1st order pole LPF, overwrite wnD
4466 wnD = wnD*(1.0 - lpf_g) + lpf_g*lpf_state;
4467 lpf_state = wnD;
4468 }
4469
4470 // --- form w(n) = x(n) + gw(n-D)
4471 double wn = xn + apf_g*wnD;
4472
4473 // --- process wn through inner APF
4474 double ynInner = nestedAPF.processAudioSample(wn);
4475
4476 // --- form y(n) = -gw(n) + w(n-D)
4477 double yn = -apf_g*wn + wnD;
4478
4479 // --- underflow check
4481
4482 // --- write delay line
4483 delay.writeDelay(ynInner);
4484
4485 return yn;
4486 }
4487
4492 NestedDelayAPFParameters getParameters() { return nestedAPFParameters; }
4493
4499 {
4500 nestedAPFParameters = params;
4501
4502 DelayAPFParameters outerAPFParameters = DelayAPF::getParameters();
4503 DelayAPFParameters innerAPFParameters = nestedAPF.getParameters();
4504
4505 // --- outer APF
4506 outerAPFParameters.apf_g = nestedAPFParameters.outerAPF_g;
4507 outerAPFParameters.delayTime_mSec = nestedAPFParameters.outerAPFdelayTime_mSec;
4508
4509 // --- LFO support
4510 outerAPFParameters.enableLFO = nestedAPFParameters.enableLFO;
4511 outerAPFParameters.lfoDepth = nestedAPFParameters.lfoDepth;
4512 outerAPFParameters.lfoRate_Hz = nestedAPFParameters.lfoRate_Hz;
4513 outerAPFParameters.lfoMaxModulation_mSec = nestedAPFParameters.lfoMaxModulation_mSec;
4514
4515 // --- inner APF
4516 innerAPFParameters.apf_g = nestedAPFParameters.innerAPF_g;
4517 innerAPFParameters.delayTime_mSec = nestedAPFParameters.innerAPFdelayTime_mSec;
4518
4519 DelayAPF::setParameters(outerAPFParameters);
4520 nestedAPF.setParameters(innerAPFParameters);
4521 }
4522
4524 void createDelayBuffers(double _sampleRate, double delay_mSec, double nestedAPFDelay_mSec)
4525 {
4526 // --- base class
4527 DelayAPF::createDelayBuffer(_sampleRate, delay_mSec);
4528
4529 // --- then our stuff
4530 nestedAPF.createDelayBuffer(_sampleRate, nestedAPFDelay_mSec);
4531 }
4532
4533private:
4534 NestedDelayAPFParameters nestedAPFParameters;
4535 DelayAPF nestedAPF;
4536};
4537
4550{
4553 TwoBandShelvingFilterParameters& operator=(const TwoBandShelvingFilterParameters& params) // need this override for collections to work
4554 {
4555 if (this == &params)
4556 return *this;
4557
4558 lowShelf_fc = params.lowShelf_fc;
4560 highShelf_fc = params.highShelf_fc;
4562 return *this;
4563 }
4564
4565 // --- individual parameters
4566 double lowShelf_fc = 0.0;
4567 double lowShelfBoostCut_dB = 0.0;
4568 double highShelf_fc = 0.0;
4570};
4571
4590{
4591public:
4593 {
4594 AudioFilterParameters params = lowShelfFilter.getParameters();
4595 params.algorithm = filterAlgorithm::kLowShelf;
4596 lowShelfFilter.setParameters(params);
4597
4598 params = highShelfFilter.getParameters();
4599 params.algorithm = filterAlgorithm::kHiShelf;
4600 highShelfFilter.setParameters(params);
4601 } /* C-TOR */
4602
4603 ~TwoBandShelvingFilter() {} /* D-TOR */
4604
4606 virtual bool reset(double _sampleRate)
4607 {
4608 lowShelfFilter.reset(_sampleRate);
4609 highShelfFilter.reset(_sampleRate);
4610 return true;
4611 }
4612
4614 virtual bool canProcessAudioFrame() { return false; }
4615
4621 virtual double processAudioSample(double xn)
4622 {
4623 // --- all modes do Full Wave Rectification
4624 double filteredSignal = lowShelfFilter.processAudioSample(xn);
4625 filteredSignal = highShelfFilter.processAudioSample(filteredSignal);
4626
4627 return filteredSignal;
4628 }
4629
4635 {
4636 return parameters;
4637 }
4638
4644 {
4645 parameters = params;
4646 AudioFilterParameters filterParams = lowShelfFilter.getParameters();
4647 filterParams.fc = parameters.lowShelf_fc;
4648 filterParams.boostCut_dB = parameters.lowShelfBoostCut_dB;
4649 lowShelfFilter.setParameters(filterParams);
4650
4651 filterParams = highShelfFilter.getParameters();
4652 filterParams.fc = parameters.highShelf_fc;
4653 filterParams.boostCut_dB = parameters.highShelfBoostCut_dB;
4654 highShelfFilter.setParameters(filterParams);
4655 }
4656
4657private:
4659 AudioFilter lowShelfFilter;
4660 AudioFilter highShelfFilter;
4661};
4662
4676enum class reverbDensity { kThick, kSparse };
4677
4690{
4693 ReverbTankParameters& operator=(const ReverbTankParameters& params) // need this override for collections to work
4694 {
4695 if (this == &params)
4696 return *this;
4697
4698 density = params.density;
4699
4700 // --- tweaker variables
4706
4707 lpf_g = params.lpf_g;
4708 kRT = params.kRT;
4709
4710 lowShelf_fc = params.lowShelf_fc;
4712 highShelf_fc = params.highShelf_fc;
4714
4715 wetLevel_dB = params.wetLevel_dB;
4716 dryLevel_dB = params.dryLevel_dB;
4717 return *this;
4718 }
4719
4720 // --- individual parameters
4721 reverbDensity density = reverbDensity::kThick;
4722
4723 // --- tweaking parameters - you may not want to expose these
4724 // in the final plugin!
4725 // --- See the book for all the details on how these tweakers work!!
4726 double apfDelayMax_mSec = 5.0;
4727 double apfDelayWeight_Pct = 100.0;
4728 double fixeDelayMax_mSec = 50.0;
4729 double fixeDelayWeight_Pct = 100.0;
4730
4731 // --- direct control parameters
4732 double preDelayTime_mSec = 0.0;
4733 double lpf_g = 0.0;
4734 double kRT = 0.0;
4735
4736 double lowShelf_fc = 0.0;
4737 double lowShelfBoostCut_dB = 0.0;
4738 double highShelf_fc = 0.0;
4740
4741 double wetLevel_dB = -3.0;
4742 double dryLevel_dB = -3.0;
4743};
4744
4745// --- constants for reverb tank
4746const unsigned int NUM_BRANCHES = 4;
4747const unsigned int NUM_CHANNELS = 2; // stereo
4748
4767{
4768public:
4769 ReverbTank() {} /* C-TOR */
4770 ~ReverbTank() {} /* D-TOR */
4771
4773 virtual bool reset(double _sampleRate)
4774 {
4775 // ---store
4776 sampleRate = _sampleRate;
4777
4778 // ---set up preDelay
4779 preDelay.reset(_sampleRate);
4780 preDelay.createDelayBuffer(_sampleRate, 100.0);
4781
4782 for (uint32_t i = 0; i < NUM_BRANCHES; i++)
4783 {
4784 branchDelays[i].reset(_sampleRate);
4785 branchDelays[i].createDelayBuffer(_sampleRate, 100.0);
4786
4787 branchNestedAPFs[i].reset(_sampleRate);
4788 branchNestedAPFs[i].createDelayBuffers(_sampleRate, 100.0, 100.0);
4789
4790 branchLPFs[i].reset(_sampleRate);
4791 }
4792 for (uint32_t i = 0; i < NUM_CHANNELS; i++)
4793 {
4794 shelvingFilters[i].reset(_sampleRate);
4795 }
4796
4797 return true;
4798 }
4799
4801 virtual bool canProcessAudioFrame() { return true; }
4802
4808 virtual double processAudioSample(double xn)
4809 {
4810 float inputs[2] = { 0.0, 0.0 };
4811 float outputs[2] = { 0.0, 0.0 };
4812 processAudioFrame(inputs, outputs, 1, 1);
4813 return outputs[0];
4814 }
4815
4817 virtual bool processAudioFrame(const float* inputFrame,
4818 float* outputFrame,
4819 uint32_t inputChannels,
4820 uint32_t outputChannels)
4821 {
4822 // --- global feedback from delay in last branch
4823 double globFB = branchDelays[NUM_BRANCHES-1].readDelay();
4824
4825 // --- feedback value
4826 double fb = parameters.kRT*(globFB);
4827
4828 // --- mono-ized input signal
4829 double xnL = inputFrame[0];
4830 double xnR = inputChannels > 1 ? inputFrame[1] : 0.0;
4831 double monoXn = double(1.0 / inputChannels)*xnL + double(1.0 / inputChannels)*xnR;
4832
4833 // --- pre delay output
4834 double preDelayOut = preDelay.processAudioSample(monoXn);
4835
4836 // --- input to first branch = preDalay + globFB
4837 double input = preDelayOut + fb;
4838 for (uint32_t i = 0; i < NUM_BRANCHES; i++)
4839 {
4840 double apfOut = branchNestedAPFs[i].processAudioSample(input);
4841 double lpfOut = branchLPFs[i].processAudioSample(apfOut);
4842 double delayOut = parameters.kRT*branchDelays[i].processAudioSample(lpfOut);
4843 input = delayOut + preDelayOut;
4844 }
4845 // --- gather outputs
4846 /*
4847 There are 25 prime numbers between 1 and 100.
4848 They are 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
4849 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, and 97
4850
4851 we want 16 of them: 23, 29, 31, 37, 41,
4852 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, and 97
4853 */
4854
4855 double weight = 0.707;
4856
4857 double outL= 0.0;
4858 outL += weight*branchDelays[0].readDelayAtPercentage(23.0);
4859 outL -= weight*branchDelays[1].readDelayAtPercentage(41.0);
4860 outL += weight*branchDelays[2].readDelayAtPercentage(59.0);
4861 outL -= weight*branchDelays[3].readDelayAtPercentage(73.0);
4862
4863 double outR = 0.0;
4864 outR -= weight*branchDelays[0].readDelayAtPercentage(29.0);
4865 outR += weight*branchDelays[1].readDelayAtPercentage(43.0);
4866 outR -= weight*branchDelays[2].readDelayAtPercentage(61.0);
4867 outR += weight*branchDelays[3].readDelayAtPercentage(79.0);
4868
4869 if (parameters.density == reverbDensity::kThick)
4870 {
4871 outL += weight*branchDelays[0].readDelayAtPercentage(31.0);
4872 outL -= weight*branchDelays[1].readDelayAtPercentage(47.0);
4873 outL += weight*branchDelays[2].readDelayAtPercentage(67.0);
4874 outL -= weight*branchDelays[3].readDelayAtPercentage(83.0);
4875
4876 outR -= weight*branchDelays[0].readDelayAtPercentage(37.0);
4877 outR += weight*branchDelays[1].readDelayAtPercentage(53.0);
4878 outR -= weight*branchDelays[2].readDelayAtPercentage(71.0);
4879 outR += weight*branchDelays[3].readDelayAtPercentage(89.0);
4880 }
4881
4882 // --- filter
4883 double tankOutL = shelvingFilters[0].processAudioSample(outL);
4884 double tankOutR = shelvingFilters[1].processAudioSample(outR);
4885
4886 // --- sum with dry
4887 double dry = pow(10.0, parameters.dryLevel_dB / 20.0);
4888 double wet = pow(10.0, parameters.wetLevel_dB / 20.0);
4889
4890 if (outputChannels == 1)
4891 outputFrame[0] = (float)(dry*xnL + wet*(0.5*tankOutL + 0.5*tankOutR));
4892 else
4893 {
4894 outputFrame[0] = (float)(dry*xnL + wet*tankOutL);
4895 outputFrame[1] = (float)(dry*xnR + wet*tankOutR);
4896 }
4897
4898 return true;
4899 }
4900
4905 ReverbTankParameters getParameters() { return parameters; }
4906
4912 {
4913 // --- do the updates here, the sub-components will only update themselves if
4914 // their parameters changed, so we let those object handle that chore
4915 TwoBandShelvingFilterParameters filterParams = shelvingFilters[0].getParameters();
4916 filterParams.highShelf_fc = params.highShelf_fc;
4917 filterParams.highShelfBoostCut_dB = params.highShelfBoostCut_dB;
4918 filterParams.lowShelf_fc = params.lowShelf_fc;
4919 filterParams.lowShelfBoostCut_dB = params.lowShelfBoostCut_dB;
4920
4921 // --- copy to both channels
4922 shelvingFilters[0].setParameters(filterParams);
4923 shelvingFilters[1].setParameters(filterParams);
4924
4925 SimpleLPFParameters lpfParams = branchLPFs[0].getParameters();
4926 lpfParams.g = params.lpf_g;
4927
4928 for (uint32_t i = 0; i < NUM_BRANCHES; i++)
4929 {
4930 branchLPFs[i].setParameters(lpfParams);
4931 }
4932
4933 // --- update pre delay
4934 SimpleDelayParameters delayParams = preDelay.getParameters();
4935 delayParams.delayTime_mSec = params.preDelayTime_mSec;
4936 preDelay.setParameters(delayParams);
4937
4938 // --- set apf and delay parameters
4939 int m = 0;
4940 NestedDelayAPFParameters apfParams = branchNestedAPFs[0].getParameters();
4941 delayParams = branchDelays[0].getParameters();
4942
4943 // --- global max Delay times
4944 double globalAPFMaxDelay = (parameters.apfDelayWeight_Pct / 100.0)*parameters.apfDelayMax_mSec;
4945 double globalFixedMaxDelay = (parameters.fixeDelayWeight_Pct / 100.0)*parameters.fixeDelayMax_mSec;
4946
4947 // --- lfo
4948 apfParams.enableLFO = true;
4949 apfParams.lfoMaxModulation_mSec = 0.3;
4950 apfParams.lfoDepth = 1.0;
4951
4952 for (uint32_t i = 0; i < NUM_BRANCHES; i++)
4953 {
4954 // --- setup APFs
4955 apfParams.outerAPFdelayTime_mSec = globalAPFMaxDelay*apfDelayWeight[m++];
4956 apfParams.innerAPFdelayTime_mSec = globalAPFMaxDelay*apfDelayWeight[m++];
4957 apfParams.innerAPF_g = -0.5;
4958 apfParams.outerAPF_g = 0.5;
4959 if (i == 0)
4960 apfParams.lfoRate_Hz = 0.15;
4961 else if (i == 1)
4962 apfParams.lfoRate_Hz = 0.33;
4963 else if (i == 2)
4964 apfParams.lfoRate_Hz = 0.57;
4965 else if (i == 3)
4966 apfParams.lfoRate_Hz = 0.73;
4967
4968 branchNestedAPFs[i].setParameters(apfParams);
4969
4970 // --- fixedDelayWeight
4971 delayParams.delayTime_mSec = globalFixedMaxDelay*fixedDelayWeight[i];
4972 branchDelays[i].setParameters(delayParams);
4973 }
4974
4975 // --- save our copy
4976 parameters = params;
4977 }
4978
4979
4980private:
4981 ReverbTankParameters parameters;
4982
4983 SimpleDelay preDelay;
4984 SimpleDelay branchDelays[NUM_BRANCHES];
4985 NestedDelayAPF branchNestedAPFs[NUM_BRANCHES];
4986 SimpleLPF branchLPFs[NUM_BRANCHES];
4987
4988 TwoBandShelvingFilter shelvingFilters[NUM_CHANNELS];
4989
4990 // --- weighting values to make various and low-correlated APF delay values easily
4991 double apfDelayWeight[NUM_BRANCHES * 2] = { 0.317, 0.873, 0.477, 0.291, 0.993, 0.757, 0.179, 0.575 };
4992 double fixedDelayWeight[NUM_BRANCHES] = { 1.0, 0.873, 0.707, 0.667 };
4993 double sampleRate = 0.0;
4994};
4995
4996
5017{
5018public:
5019 PeakLimiter() { setThreshold_dB(-3.0); }
5020 ~PeakLimiter() {}
5021
5023 virtual bool reset(double _sampleRate)
5024 {
5025 // --- init; true = analog time-constant
5026 detector.setSampleRate(_sampleRate);
5027
5029 detectorParams.detect_dB = true;
5030 detectorParams.attackTime_mSec = 5.0;
5031 detectorParams.releaseTime_mSec = 25.0;
5032 detectorParams.clampToUnityMax = false;
5033 detectorParams.detectMode = ENVELOPE_DETECT_MODE_PEAK;
5034 detector.setParameters(detectorParams);
5035
5036 return true;
5037 }
5038
5040 virtual bool canProcessAudioFrame() { return false; }
5041
5047 virtual double processAudioSample(double xn)
5048 {
5050 }
5051
5053 double computeGain(double detect_dB)
5054 {
5055 double output_dB = 0.0;
5056
5057 // --- defaults - you can change these here
5058 bool softknee = true;
5059 double kneeWidth_dB = 10.0;
5060
5061 // --- hard knee
5062 if (!softknee)
5063 {
5064 // --- below threshold, unity
5065 if (detect_dB <= threshold_dB)
5066 output_dB = detect_dB;
5067 // --- above threshold, compress
5068 else
5069 output_dB = threshold_dB;
5070 }
5071 else
5072 {
5073 // --- calc gain with knee
5074 // --- left side of knee, outside of width, unity gain zone
5075 if (2.0*(detect_dB - threshold_dB) < -kneeWidth_dB)
5076 output_dB = detect_dB;
5077 // --- inside the knee,
5078 else if (2.0*(fabs(detect_dB - threshold_dB)) <= kneeWidth_dB)
5079 output_dB = detect_dB - pow((detect_dB - threshold_dB + (kneeWidth_dB / 2.0)), 2.0) / (2.0*kneeWidth_dB);
5080 // --- right of knee, compression zone
5081 else if (2.0*(detect_dB - threshold_dB) > kneeWidth_dB)
5082 output_dB = threshold_dB;
5083 }
5084
5085 // --- convert difference between threshold and detected to raw
5086 return pow(10.0, (output_dB - detect_dB) / 20.0);
5087 }
5088
5090 void setThreshold_dB(double _threshold_dB) { threshold_dB = _threshold_dB; }
5091
5093 void setMakeUpGain_dB(double _makeUpGain_dB) { makeUpGain_dB = _makeUpGain_dB; }
5094
5095protected:
5097 double threshold_dB = 0.0;
5098 double makeUpGain_dB = 0.0;
5099};
5100
5101
5116 kLPF1, kHPF1, kAPF1, kSVF_LP, kSVF_HP, kSVF_BP, kSVF_BS
5117}; // --- you will add more here...
5118
5119
5132{
5135 ZVAFilterParameters& operator=(const ZVAFilterParameters& params) // need this override for collections to work
5136 {
5137 if (this == &params)
5138 return *this;
5139
5141 fc = params.fc;
5142 Q = params.Q;
5147 enableNLP = params.enableNLP;
5148 return *this;
5149 }
5150
5151 // --- individual parameters
5152 vaFilterAlgorithm filterAlgorithm = vaFilterAlgorithm::kSVF_LP;
5153 double fc = 1000.0;
5154 double Q = 0.707;
5155 double filterOutputGain_dB = 0.0;
5156 bool enableGainComp = false;
5158 bool selfOscillate = false;
5159 bool enableNLP = false;
5160};
5161
5162
5180{
5181public:
5182 ZVAFilter() {} /* C-TOR */
5183 ~ZVAFilter() {} /* D-TOR */
5184
5186 virtual bool reset(double _sampleRate)
5187 {
5188 sampleRate = _sampleRate;
5189 integrator_z[0] = 0.0;
5190 integrator_z[1] = 0.0;
5191
5192 return true;
5193 }
5194
5200 {
5201 return zvaFilterParameters;
5202 }
5203
5209 {
5210 if (params.fc != zvaFilterParameters.fc ||
5211 params.Q != zvaFilterParameters.Q ||
5214 {
5215 zvaFilterParameters = params;
5217 }
5218 else
5219 zvaFilterParameters = params;
5220 }
5221
5223 virtual bool canProcessAudioFrame() { return false; }
5224
5230 virtual double processAudioSample(double xn)
5231 {
5232 // --- with gain comp enabled, we reduce the input by
5233 // half the gain in dB at resonant peak
5234 // NOTE: you can change that logic here!
5236 bool matchAnalogNyquistLPF = zvaFilterParameters.matchAnalogNyquistLPF;
5237
5239 {
5240 double peak_dB = dBPeakGainFor_Q(zvaFilterParameters.Q);
5241 if (peak_dB > 0.0)
5242 {
5243 double halfPeak_dBGain = dB2Raw(-peak_dB / 2.0);
5244 xn *= halfPeak_dBGain;
5245 }
5246 }
5247
5248 // --- for 1st order filters:
5249 if (filterAlgorithm == vaFilterAlgorithm::kLPF1 ||
5250 filterAlgorithm == vaFilterAlgorithm::kHPF1 ||
5251 filterAlgorithm == vaFilterAlgorithm::kAPF1)
5252 {
5253 // --- create vn node
5254 double vn = (xn - integrator_z[0])*alpha;
5255
5256 // --- form LP output
5257 double lpf = ((xn - integrator_z[0])*alpha) + integrator_z[0];
5258
5259 // double sn = integrator_z[0];
5260
5261 // --- update memory
5262 integrator_z[0] = vn + lpf;
5263
5264 // --- form the HPF = INPUT = LPF
5265 double hpf = xn - lpf;
5266
5267 // --- form the APF = LPF - HPF
5268 double apf = lpf - hpf;
5269
5270 // --- set the outputs
5271 if (filterAlgorithm == vaFilterAlgorithm::kLPF1)
5272 {
5273 // --- this is a very close match as-is at Nyquist!
5274 if (matchAnalogNyquistLPF)
5275 return lpf + alpha*hpf;
5276 else
5277 return lpf;
5278 }
5279 else if (filterAlgorithm == vaFilterAlgorithm::kHPF1)
5280 return hpf;
5281 else if (filterAlgorithm == vaFilterAlgorithm::kAPF1)
5282 return apf;
5283
5284 // --- unknown filter
5285 return xn;
5286 }
5287
5288 // --- form the HP output first
5289 double hpf = alpha0*(xn - rho*integrator_z[0] - integrator_z[1]);
5290
5291 // --- BPF Out
5292 double bpf = alpha*hpf + integrator_z[0];
5294 bpf = softClipWaveShaper(bpf, 1.0);
5295
5296 // --- LPF Out
5297 double lpf = alpha*bpf + integrator_z[1];
5298
5299 // --- BSF Out
5300 double bsf = hpf + lpf;
5301
5302 // --- finite gain at Nyquist; slight error at VHF
5303 double sn = integrator_z[0];
5304
5305 // update memory
5306 integrator_z[0] = alpha*hpf + bpf;
5307 integrator_z[1] = alpha*bpf + lpf;
5308
5309 double filterOutputGain = pow(10.0, zvaFilterParameters.filterOutputGain_dB / 20.0);
5310
5311 // return our selected type
5312 if (filterAlgorithm == vaFilterAlgorithm::kSVF_LP)
5313 {
5314 if (matchAnalogNyquistLPF)
5315 lpf += analogMatchSigma*(sn);
5316 return filterOutputGain*lpf;
5317 }
5318 else if (filterAlgorithm == vaFilterAlgorithm::kSVF_HP)
5319 return filterOutputGain*hpf;
5320 else if (filterAlgorithm == vaFilterAlgorithm::kSVF_BP)
5321 return filterOutputGain*bpf;
5322 else if (filterAlgorithm == vaFilterAlgorithm::kSVF_BS)
5323 return filterOutputGain*bsf;
5324
5325 // --- unknown filter
5326 return filterOutputGain*lpf;
5327 }
5328
5331 {
5332 double fc = zvaFilterParameters.fc;
5333 double Q = zvaFilterParameters.Q;
5335
5336 // --- normal Zavalishin SVF calculations here
5337 // prewarp the cutoff- these are bilinear-transform filters
5338 double wd = kTwoPi*fc;
5339 double T = 1.0 / sampleRate;
5340 double wa = (2.0 / T)*tan(wd*T / 2.0);
5341 double g = wa*T / 2.0;
5342
5343 // --- for 1st order filters:
5344 if (filterAlgorithm == vaFilterAlgorithm::kLPF1 ||
5345 filterAlgorithm == vaFilterAlgorithm::kHPF1 ||
5346 filterAlgorithm == vaFilterAlgorithm::kAPF1)
5347 {
5348 // --- calculate alpha
5349 alpha = g / (1.0 + g);
5350 }
5351 else // state variable variety
5352 {
5353 // --- note R is the traditional analog damping factor zeta
5354 double R = zvaFilterParameters.selfOscillate ? 0.0 : 1.0 / (2.0*Q);
5355 alpha0 = 1.0 / (1.0 + 2.0*R*g + g*g);
5356 alpha = g;
5357 rho = 2.0*R + g;
5358
5359 // --- sigma for analog matching version
5360 double f_o = (sampleRate / 2.0) / fc;
5361 analogMatchSigma = 1.0 / (alpha*f_o*f_o);
5362 }
5363 }
5364
5366 void setBeta(double _beta) { beta = _beta; }
5367
5369 double getBeta() { return beta; }
5370
5371protected:
5373 double sampleRate = 44100.0;
5374
5375 // --- state storage
5376 double integrator_z[2];
5377
5378 // --- filter coefficients
5379 double alpha0 = 0.0;
5380 double alpha = 0.0;
5381 double rho = 0.0;
5382
5383 double beta = 0.0;
5384
5385 // --- for analog Nyquist matching
5386 double analogMatchSigma = 0.0;
5387
5388};
5389
5402{
5405 EnvelopeFollowerParameters& operator=(const EnvelopeFollowerParameters& params) // need this override for collections to work
5406 {
5407 if (this == &params)
5408 return *this;
5409
5410 fc = params.fc;
5411 Q = params.Q;
5414 threshold_dB = params.threshold_dB;
5415 sensitivity = params.sensitivity;
5416
5417 return *this;
5418 }
5419
5420 // --- individual parameters
5421 double fc = 0.0;
5422 double Q = 0.707;
5423 double attackTime_mSec = 10.0;
5424 double releaseTime_mSec = 10.0;
5425 double threshold_dB = 0.0;
5426 double sensitivity = 1.0;
5427};
5428
5448{
5449public:
5451 // --- setup the filter
5452 ZVAFilterParameters filterParams;
5453 filterParams.filterAlgorithm = vaFilterAlgorithm::kSVF_LP;
5454 filterParams.fc = 1000.0;
5455 filterParams.enableGainComp = true;
5456 filterParams.enableNLP = true;
5457 filterParams.matchAnalogNyquistLPF = true;
5458 filter.setParameters(filterParams);
5459
5460 // --- setup the detector
5461 AudioDetectorParameters adParams;
5462 adParams.attackTime_mSec = -1.0;
5463 adParams.releaseTime_mSec = -1.0;
5464 adParams.detectMode = TLD_AUDIO_DETECT_MODE_RMS;
5465 adParams.detect_dB = true;
5466 adParams.clampToUnityMax = false;
5467 detector.setParameters(adParams);
5468
5469 } /* C-TOR */
5470 ~EnvelopeFollower() {} /* D-TOR */
5471
5473 virtual bool reset(double _sampleRate)
5474 {
5475 filter.reset(_sampleRate);
5476 detector.reset(_sampleRate);
5477 return true;
5478 }
5479
5485
5491 {
5492 ZVAFilterParameters filterParams = filter.getParameters();
5494
5495 if (params.fc != parameters.fc || params.Q != parameters.Q)
5496 {
5497 filterParams.fc = params.fc;
5498 filterParams.Q = params.Q;
5499 filter.setParameters(filterParams);
5500 }
5503 {
5504 adParams.attackTime_mSec = params.attackTime_mSec;
5505 adParams.releaseTime_mSec = params.releaseTime_mSec;
5506 detector.setParameters(adParams);
5507 }
5508
5509 // --- save
5510 parameters = params;
5511 }
5512
5514 virtual bool canProcessAudioFrame() { return false; }
5515
5521 virtual double processAudioSample(double xn)
5522 {
5523 // --- calc threshold
5524 double threshValue = pow(10.0, parameters.threshold_dB / 20.0);
5525
5526 // --- detect the signal
5527 double detect_dB = detector.processAudioSample(xn);
5528 double detectValue = pow(10.0, detect_dB / 20.0);
5529 double deltaValue = detectValue - threshValue;
5530
5531 ZVAFilterParameters filterParams = filter.getParameters();
5532 filterParams.fc = parameters.fc;
5533
5534 // --- if above the threshold, modulate the filter fc
5535 if (deltaValue > 0.0)// || delta_dB > 0.0)
5536 {
5537 // --- fc Computer
5538 double modulatorValue = 0.0;
5539
5540 // --- best results are with linear values when detector is in dB mode
5541 modulatorValue = (deltaValue * parameters.sensitivity);
5542
5543 // --- calculate modulated frequency
5544 filterParams.fc = doUnipolarModulationFromMin(modulatorValue, parameters.fc, kMaxFilterFrequency);
5545 }
5546
5547 // --- update with new modulated frequency
5548 filter.setParameters(filterParams);
5549
5550 // --- perform the filtering operation
5551 return filter.processAudioSample(xn);
5552 }
5553
5554protected:
5556
5557 // --- 1 filter and 1 detector
5560};
5561
5575enum class distortionModel { kSoftClip, kArcTan, kFuzzAsym };
5576
5589{
5592 TriodeClassAParameters& operator=(const TriodeClassAParameters& params) // need this override for collections to work
5593 {
5594 if (this == &params)
5595 return *this;
5596
5597 waveshaper = params.waveshaper;
5598 saturation = params.saturation;
5599 asymmetry = params.asymmetry;
5600 outputGain = params.outputGain;
5601
5602 invertOutput = params.invertOutput;
5603 enableHPF = params.enableHPF;
5604 enableLSF = params.enableLSF;
5605
5606 hpf_Fc = params.hpf_Fc;
5607 lsf_Fshelf = params.lsf_Fshelf;
5609
5610 return *this;
5611 }
5612
5613 // --- individual parameters
5614 distortionModel waveshaper = distortionModel::kSoftClip;
5615
5616 double saturation = 1.0;
5617 double asymmetry = 0.0;
5618 double outputGain = 1.0;
5619
5620 bool invertOutput = true;
5621 bool enableHPF = true;
5622 bool enableLSF = false;
5623
5624 double hpf_Fc = 1.0;
5625 double lsf_Fshelf = 80.0;
5626 double lsf_BoostCut_dB = 0.0;
5627};
5628
5648{
5649public:
5650 TriodeClassA() {
5651 AudioFilterParameters params;
5652 params.algorithm = filterAlgorithm::kHPF1;
5653 params.fc = parameters.hpf_Fc;
5654 outputHPF.setParameters(params);
5655
5656 params.algorithm = filterAlgorithm::kLowShelf;
5657 params.fc = parameters.lsf_Fshelf;
5659 outputLSF.setParameters(params);
5660 } /* C-TOR */
5661 ~TriodeClassA() {} /* D-TOR */
5662
5664 virtual bool reset(double _sampleRate)
5665 {
5666 outputHPF.reset(_sampleRate);
5667 outputLSF.reset(_sampleRate);
5668
5669 // ---
5670 return true;
5671 }
5672
5678
5684 {
5685 parameters = params;
5686
5687 AudioFilterParameters filterParams;
5688 filterParams.algorithm = filterAlgorithm::kHPF1;
5689 filterParams.fc = parameters.hpf_Fc;
5690 outputHPF.setParameters(filterParams);
5691
5692 filterParams.algorithm = filterAlgorithm::kLowShelf;
5693 filterParams.fc = parameters.lsf_Fshelf;
5694 filterParams.boostCut_dB = parameters.lsf_BoostCut_dB;
5695 outputLSF.setParameters(filterParams);
5696 }
5697
5699 virtual bool canProcessAudioFrame() { return false; }
5700
5706 virtual double processAudioSample(double xn)
5707 {
5708 // --- perform waveshaping
5709 double output = 0.0;
5710
5711 if (parameters.waveshaper == distortionModel::kSoftClip)
5713 else if (parameters.waveshaper == distortionModel::kArcTan)
5714 output = atanWaveShaper(xn, parameters.saturation);
5715 else if (parameters.waveshaper == distortionModel::kFuzzAsym)
5717
5718 // --- inversion, normal for plate of class A triode
5720 output *= -1.0;
5721
5722 // --- Output (plate) capacitor = HPF, remove DC offset
5724 output = outputHPF.processAudioSample(output);
5725
5726 // --- if cathode resistor bypass, will create low shelf
5728 output = outputLSF.processAudioSample(output);
5729
5730 // --- final resistor divider/potentiometer
5731 output *= parameters.outputGain;
5732
5733 return output;
5734 }
5735
5736protected:
5740};
5741
5742const unsigned int NUM_TUBES = 4;
5743
5756{
5759 ClassATubePreParameters& operator=(const ClassATubePreParameters& params) // need this override for collections to work
5760 {
5761 if (this == &params)
5762 return *this;
5763
5765 saturation = params.saturation;
5766 asymmetry = params.asymmetry;
5768
5769 lowShelf_fc = params.lowShelf_fc;
5771 highShelf_fc = params.highShelf_fc;
5773
5774 return *this;
5775 }
5776
5777 // --- individual parameters
5778 double inputLevel_dB = 0.0;
5779 double saturation = 0.0;
5780 double asymmetry = 0.0;
5781 double outputLevel_dB = 0.0;
5782
5783 // --- shelving filter params
5784 double lowShelf_fc = 0.0;
5785 double lowShelfBoostCut_dB = 0.0;
5786 double highShelf_fc = 0.0;
5788
5789};
5790
5809{
5810public:
5811 ClassATubePre() {} /* C-TOR */
5812 ~ClassATubePre() {} /* D-TOR */
5813
5815 virtual bool reset(double _sampleRate)
5816 {
5818 tubeParams.invertOutput = true;
5819 tubeParams.enableHPF = true; // remove DC offsets
5820 tubeParams.outputGain = 1.0;
5821 tubeParams.saturation = 1.0;
5822 tubeParams.asymmetry = 0.0;
5823 tubeParams.enableLSF = true;
5824 tubeParams.lsf_Fshelf = 88.0;
5825 tubeParams.lsf_BoostCut_dB = -12.0;
5826 tubeParams.waveshaper = distortionModel::kFuzzAsym;
5827
5828 for (uint32_t i = 0; i < NUM_TUBES; i++)
5829 {
5830 triodes[i].reset(_sampleRate);
5831 triodes[i].setParameters(tubeParams);
5832 }
5833
5834 shelvingFilter.reset(_sampleRate);
5835
5836 return true;
5837 }
5838
5844
5850 {
5851 // --- check for re-calc
5853 inputLevel = pow(10.0, params.inputLevel_dB / 20.0);
5855 outputLevel = pow(10.0, params.outputLevel_dB / 20.0);
5856
5857 // --- store
5858 parameters = params;
5859
5860 // --- shelving filter update
5866 shelvingFilter.setParameters(sfParams);
5867
5868 // --- triode updates
5870 tubeParams.saturation = parameters.saturation;
5871 tubeParams.asymmetry = parameters.asymmetry;
5872
5873 for (uint32_t i = 0; i < NUM_TUBES; i++)
5874 triodes[i].setParameters(tubeParams);
5875 }
5876
5878 virtual bool canProcessAudioFrame() { return false; }
5879
5885 virtual double processAudioSample(double xn)
5886 {
5887 double output1 = triodes[0].processAudioSample(xn*inputLevel);
5888 double output2 = triodes[1].processAudioSample(output1);
5889 double output3 = triodes[2].processAudioSample(output2);
5890
5891 // --- filter stage is between 3 and 4
5892 double outputEQ = shelvingFilter.processAudioSample(output3);
5893 double output4 = triodes[3].processAudioSample(outputEQ);
5894
5895 return output4*outputLevel;
5896 }
5897
5898protected:
5902
5903 double inputLevel = 1.0;
5904 double outputLevel = 1.0;
5905};
5906
5907
5920{
5923 BitCrusherParameters& operator=(const BitCrusherParameters& params) // need this override for collections to work
5924 {
5925 if (this == &params)
5926 return *this;
5927
5929
5930 return *this;
5931 }
5932
5933 double quantizedBitDepth = 4.0;
5934};
5935
5954{
5955public:
5956 BitCrusher() {} /* C-TOR */
5957 ~BitCrusher() {} /* D-TOR */
5958
5960 virtual bool reset(double _sampleRate){ return true; }
5961
5967
5973 {
5974 // --- calculate and store
5976 QL = 2.0 / (pow(2.0, params.quantizedBitDepth) - 1.0);
5977
5978 parameters = params;
5979 }
5980
5982 virtual bool canProcessAudioFrame() { return false; }
5983
5989 virtual double processAudioSample(double xn)
5990 {
5991 return QL*(int(xn / QL));
5992 }
5993
5994protected:
5996 double QL = 1.0;
5997};
5998
5999
6000// ------------------------------------------------------------------ //
6001// --- WDF LIBRARY -------------------------------------------------- //
6002// ------------------------------------------------------------------ //
6003
6016{
6017public:
6019 virtual void initialize(double _R1) {}
6020
6022 virtual void initializeAdaptorChain() {}
6023
6025 virtual void setInput(double _in) {}
6026
6028 virtual double getOutput() { return 0.0; }
6029
6030 // --- for adaptors
6032 virtual void setInput1(double _in1) = 0;
6033
6035 virtual void setInput2(double _in2) = 0;
6036
6038 virtual void setInput3(double _in3) = 0;
6039
6041 virtual double getOutput1() = 0;
6042
6044 virtual double getOutput2() = 0;
6045
6047 virtual double getOutput3() = 0;
6048
6050 virtual void reset(double _sampleRate) {}
6051
6053 virtual double getComponentResistance() { return 0.0; }
6054
6056 virtual double getComponentConductance() { return 0.0; }
6057
6060
6062 virtual void setComponentValue(double _componentValue) { }
6063
6065 virtual void setComponentValue_LC(double componentValue_L, double componentValue_C) { }
6066
6068 virtual void setComponentValue_RL(double componentValue_R, double componentValue_L) { }
6069
6071 virtual void setComponentValue_RC(double componentValue_R, double componentValue_C) { }
6072
6074 virtual double getComponentValue() { return 0.0; }
6075};
6076
6077// ------------------------------------------------------------------ //
6078// --- WDF COMPONENTS & COMMBO COMPONENTS --------------------------- //
6079// ------------------------------------------------------------------ //
6093{
6094public:
6095 WdfResistor(double _componentValue) { componentValue = _componentValue; }
6096 WdfResistor() { }
6097 virtual ~WdfResistor() {}
6098
6100 void setSampleRate(double _sampleRate)
6101 {
6102 sampleRate = _sampleRate;
6104 }
6105
6107 virtual double getComponentResistance() { return componentResistance; }
6108
6110 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6111
6113 virtual double getComponentValue() { return componentValue; }
6114
6116 virtual void setComponentValue(double _componentValue)
6117 {
6118 componentValue = _componentValue;
6120 }
6121
6124
6126 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6127
6129 virtual void setInput(double in) {}
6130
6132 virtual double getOutput() { return 0.0; }
6133
6135 virtual double getOutput1() { return getOutput(); }
6136
6138 virtual double getOutput2() { return getOutput(); }
6139
6141 virtual double getOutput3() { return getOutput(); }
6142
6144 virtual void setInput1(double _in1) {}
6145
6147 virtual void setInput2(double _in2) {}
6148
6150 virtual void setInput3(double _in3) {}
6151
6152protected:
6153 double zRegister = 0.0;
6154 double componentValue = 0.0;
6156 double sampleRate = 0.0;
6157};
6158
6159
6173{
6174public:
6175 WdfCapacitor(double _componentValue) { componentValue = _componentValue; }
6176 WdfCapacitor() { }
6177 virtual ~WdfCapacitor() {}
6178
6180 void setSampleRate(double _sampleRate)
6181 {
6182 sampleRate = _sampleRate;
6184 }
6185
6187 virtual double getComponentResistance() { return componentResistance; }
6188
6190 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6191
6193 virtual double getComponentValue() { return componentValue; }
6194
6196 virtual void setComponentValue(double _componentValue)
6197 {
6198 componentValue = _componentValue;
6200 }
6201
6204 {
6206 }
6207
6209 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6210
6212 virtual void setInput(double in) { zRegister = in; }
6213
6215 virtual double getOutput() { return zRegister; } // z^-1
6216
6218 virtual double getOutput1() { return getOutput(); }
6219
6221 virtual double getOutput2() { return getOutput(); }
6222
6224 virtual double getOutput3() { return getOutput(); }
6225
6227 virtual void setInput1(double _in1) {}
6228
6230 virtual void setInput2(double _in2) {}
6231
6233 virtual void setInput3(double _in3) {}
6234
6235protected:
6236 double zRegister = 0.0;
6237 double componentValue = 0.0;
6239 double sampleRate = 0.0;
6240};
6241
6255{
6256public:
6257 WdfInductor(double _componentValue) { componentValue = _componentValue; }
6258 WdfInductor() { }
6259 virtual ~WdfInductor() {}
6260
6262 void setSampleRate(double _sampleRate)
6263 {
6264 sampleRate = _sampleRate;
6266 }
6267
6269 virtual double getComponentResistance() { return componentResistance; }
6270
6272 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6273
6275 virtual double getComponentValue() { return componentValue; }
6276
6278 virtual void setComponentValue(double _componentValue)
6279 {
6280 componentValue = _componentValue;
6282 }
6283
6286
6288 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6289
6291 virtual void setInput(double in) { zRegister = in; }
6292
6294 virtual double getOutput() { return -zRegister; } // -z^-1
6295
6297 virtual double getOutput1() { return getOutput(); }
6298
6300 virtual double getOutput2() { return getOutput(); }
6301
6303 virtual double getOutput3() { return getOutput(); }
6304
6306 virtual void setInput1(double _in1) {}
6307
6309 virtual void setInput2(double _in2) {}
6310
6312 virtual void setInput3(double _in3) {}
6313
6314protected:
6315 double zRegister = 0.0;
6316 double componentValue = 0.0;
6318 double sampleRate = 0.0;
6319};
6320
6321
6336{
6337public:
6338 WdfSeriesLC() {}
6339 WdfSeriesLC(double _componentValue_L, double _componentValue_C)
6340 {
6341 componentValue_L = _componentValue_L;
6342 componentValue_C = _componentValue_C;
6343 }
6344 virtual ~WdfSeriesLC() {}
6345
6347 void setSampleRate(double _sampleRate)
6348 {
6349 sampleRate = _sampleRate;
6351 }
6352
6354 virtual double getComponentResistance() { return componentResistance; }
6355
6357 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6358
6361 {
6363 RC = 1.0 / (2.0*componentValue_C*sampleRate);
6364 componentResistance = RL + (1.0 / RC);
6365 }
6366
6368 virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
6369 {
6370 componentValue_L = _componentValue_L;
6371 componentValue_C = _componentValue_C;
6373 }
6374
6376 virtual void setComponentValue_L(double _componentValue_L)
6377 {
6378 componentValue_L = _componentValue_L;
6380 }
6381
6383 virtual void setComponentValue_C(double _componentValue_C)
6384 {
6385 componentValue_C = _componentValue_C;
6387 }
6388
6390 virtual double getComponentValue_L() { return componentValue_L; }
6391
6393 virtual double getComponentValue_C() { return componentValue_C; }
6394
6396 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6397
6399 virtual void setInput(double in)
6400 {
6401 double YC = 1.0 / RC;
6402 double K = (1.0 - RL*YC) / (1.0 + RL*YC);
6403 double N1 = K*(in - zRegister_L);
6404 zRegister_L = N1 + zRegister_C;
6405 zRegister_C = in;
6406 }
6407
6409 virtual double getOutput(){ return zRegister_L; }
6410
6412 virtual double getOutput1() { return getOutput(); }
6413
6415 virtual double getOutput2() { return getOutput(); }
6416
6418 virtual double getOutput3() { return getOutput(); }
6419
6421 virtual void setInput1(double _in1) {}
6422
6424 virtual void setInput2(double _in2) {}
6425
6427 virtual void setInput3(double _in3) {}
6428
6429protected:
6430 double zRegister_L = 0.0;
6431 double zRegister_C = 0.0;
6432
6433 double componentValue_L = 0.0;
6434 double componentValue_C = 0.0;
6435
6436 double RL = 0.0;
6437 double RC = 0.0;
6438 double componentResistance = 0.0;
6439 double sampleRate = 0.0;
6440};
6441
6456{
6457public:
6458 WdfParallelLC() {}
6459 WdfParallelLC(double _componentValue_L, double _componentValue_C)
6460 {
6461 componentValue_L = _componentValue_L;
6462 componentValue_C = _componentValue_C;
6463 }
6464 virtual ~WdfParallelLC() {}
6465
6467 void setSampleRate(double _sampleRate)
6468 {
6469 sampleRate = _sampleRate;
6471 }
6472
6474 virtual double getComponentResistance() { return componentResistance; }
6475
6477 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6478
6481 {
6483 RC = 1.0 / (2.0*componentValue_C*sampleRate);
6484 componentResistance = (RC + 1.0 / RL);
6485 }
6486
6488 virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
6489 {
6490 componentValue_L = _componentValue_L;
6491 componentValue_C = _componentValue_C;
6493 }
6494
6496 virtual void setComponentValue_L(double _componentValue_L)
6497 {
6498 componentValue_L = _componentValue_L;
6500 }
6501
6503 virtual void setComponentValue_C(double _componentValue_C)
6504 {
6505 componentValue_C = _componentValue_C;
6507 }
6508
6510 virtual double getComponentValue_L() { return componentValue_L; }
6511
6513 virtual double getComponentValue_C() { return componentValue_C; }
6514
6516 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6517
6519 virtual void setInput(double in)
6520 {
6521 double YL = 1.0 / RL;
6522 double K = (YL*RC - 1.0) / (YL*RC + 1.0);
6523 double N1 = K*(in - zRegister_L);
6524 zRegister_L = N1 + zRegister_C;
6525 zRegister_C = in;
6526 }
6527
6529 virtual double getOutput(){ return -zRegister_L; }
6530
6532 virtual double getOutput1() { return getOutput(); }
6533
6535 virtual double getOutput2() { return getOutput(); }
6536
6538 virtual double getOutput3() { return getOutput(); }
6539
6541 virtual void setInput1(double _in1) {}
6542
6544 virtual void setInput2(double _in2) {}
6545
6547 virtual void setInput3(double _in3) {}
6548
6549protected:
6550 double zRegister_L = 0.0;
6551 double zRegister_C = 0.0;
6552
6553 double componentValue_L = 0.0;
6554 double componentValue_C = 0.0;
6555
6556 double RL = 0.0;
6557 double RC = 0.0;
6558 double componentResistance = 0.0;
6559 double sampleRate = 0.0;
6560};
6561
6562
6577{
6578public:
6579 WdfSeriesRL() {}
6580 WdfSeriesRL(double _componentValue_R, double _componentValue_L)
6581 {
6582 componentValue_L = _componentValue_L;
6583 componentValue_R = _componentValue_R;
6584 }
6585 virtual ~WdfSeriesRL() {}
6586
6588 void setSampleRate(double _sampleRate)
6589 {
6590 sampleRate = _sampleRate;
6592 }
6593
6595 virtual double getComponentResistance() { return componentResistance; }
6596
6598 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6599
6602 {
6606 K = RR / componentResistance;
6607 }
6608
6610 virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
6611 {
6612 componentValue_L = _componentValue_L;
6613 componentValue_R = _componentValue_R;
6615 }
6616
6618 virtual void setComponentValue_L(double _componentValue_L)
6619 {
6620 componentValue_L = _componentValue_L;
6622 }
6623
6625 virtual void setComponentValue_R(double _componentValue_R)
6626 {
6627 componentValue_R = _componentValue_R;
6629 }
6630
6632 virtual double getComponentValue_L() { return componentValue_L; }
6633
6635 virtual double getComponentValue_R() { return componentValue_R; }
6636
6638 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6639
6641 virtual void setInput(double in){ zRegister_L = in; }
6642
6644 virtual double getOutput()
6645 {
6646 double NL = -zRegister_L;
6647 double out = NL*(1.0 - K) - K*zRegister_C;
6648 zRegister_C = out;
6649
6650 return out;
6651 }
6652
6654 virtual double getOutput1() { return getOutput(); }
6655
6657 virtual double getOutput2() { return getOutput(); }
6658
6660 virtual double getOutput3() { return getOutput(); }
6661
6663 virtual void setInput1(double _in1) {}
6664
6666 virtual void setInput2(double _in2) {}
6667
6669 virtual void setInput3(double _in3) {}
6670
6671protected:
6672 double zRegister_L = 0.0;
6673 double zRegister_C = 0.0;
6674 double K = 0.0;
6675
6676 double componentValue_L = 0.0;
6677 double componentValue_R = 0.0;
6678
6679 double RL = 0.0;
6680 double RC = 0.0;
6681 double RR = 0.0;
6682
6683 double componentResistance = 0.0;
6684 double sampleRate = 0.0;
6685};
6686
6700{
6701public:
6702 WdfParallelRL() {}
6703 WdfParallelRL(double _componentValue_R, double _componentValue_L)
6704 {
6705 componentValue_L = _componentValue_L;
6706 componentValue_R = _componentValue_R;
6707 }
6708 virtual ~WdfParallelRL() {}
6709
6711 void setSampleRate(double _sampleRate)
6712 {
6713 sampleRate = _sampleRate;
6715 }
6716
6718 virtual double getComponentResistance() { return componentResistance; }
6719
6721 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6722
6725 {
6728 componentResistance = 1.0 / ((1.0 / RR) + (1.0 / RL));
6730 }
6731
6732
6734 virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
6735 {
6736 componentValue_L = _componentValue_L;
6737 componentValue_R = _componentValue_R;
6739 }
6740
6742 virtual void setComponentValue_L(double _componentValue_L)
6743 {
6744 componentValue_L = _componentValue_L;
6746 }
6747
6749 virtual void setComponentValue_R(double _componentValue_R)
6750 {
6751 componentValue_R = _componentValue_R;
6753 }
6754
6756 virtual double getComponentValue_L() { return componentValue_L; }
6757
6759 virtual double getComponentValue_R() { return componentValue_R; }
6760
6762 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6763
6765 virtual void setInput(double in){ zRegister_L = in; }
6766
6768 virtual double getOutput()
6769 {
6770 double NL = -zRegister_L;
6771 double out = NL*(1.0 - K) + K*zRegister_C;
6772 zRegister_C = out;
6773 return out;
6774 }
6775
6777 virtual double getOutput1() { return getOutput(); }
6778
6780 virtual double getOutput2() { return getOutput(); }
6781
6783 virtual double getOutput3() { return getOutput(); }
6784
6786 virtual void setInput1(double _in1) {}
6787
6789 virtual void setInput2(double _in2) {}
6790
6792 virtual void setInput3(double _in3) {}
6793
6794protected:
6795 double zRegister_L = 0.0;
6796 double zRegister_C = 0.0;
6797 double K = 0.0;
6798
6799 double componentValue_L = 0.0;
6800 double componentValue_R = 0.0;
6801
6802 double RL = 0.0;
6803 double RC = 0.0;
6804 double RR = 0.0;
6805
6806 double componentResistance = 0.0;
6807 double sampleRate = 0.0;
6808};
6809
6824{
6825public:
6826 WdfSeriesRC() {}
6827 WdfSeriesRC(double _componentValue_R, double _componentValue_C)
6828 {
6829 componentValue_C = _componentValue_C;
6830 componentValue_R = _componentValue_R;
6831 }
6832 virtual ~WdfSeriesRC() {}
6833
6835 void setSampleRate(double _sampleRate)
6836 {
6837 sampleRate = _sampleRate;
6839 }
6840
6842 virtual double getComponentResistance() { return componentResistance; }
6843
6845 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6846
6849 {
6851 RC = 1.0 / (2.0*componentValue_C*sampleRate);
6853 K = RR / componentResistance;
6854 }
6855
6857 virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
6858 {
6859 componentValue_R = _componentValue_R;
6860 componentValue_C = _componentValue_C;
6862 }
6863
6865 virtual void setComponentValue_R(double _componentValue_R)
6866 {
6867 componentValue_R = _componentValue_R;
6869 }
6870
6872 virtual void setComponentValue_C(double _componentValue_C)
6873 {
6874 componentValue_C = _componentValue_C;
6876 }
6877
6879 virtual double getComponentValue_R() { return componentValue_R; }
6880
6882 virtual double getComponentValue_C() { return componentValue_C; }
6883
6885 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6886
6888 virtual void setInput(double in){ zRegister_L = in; }
6889
6891 virtual double getOutput()
6892 {
6893 double NL = zRegister_L;
6894 double out = NL*(1.0 - K) + K*zRegister_C;
6895 zRegister_C = out;
6896 return out;
6897 }
6898
6900 virtual double getOutput1() { return getOutput(); }
6901
6903 virtual double getOutput2() { return getOutput(); }
6904
6906 virtual double getOutput3() { return getOutput(); }
6907
6909 virtual void setInput1(double _in1) {}
6910
6912 virtual void setInput2(double _in2) {}
6913
6915 virtual void setInput3(double _in3) {}
6916
6917protected:
6918 double zRegister_L = 0.0;
6919 double zRegister_C = 0.0;
6920 double K = 0.0;
6921
6922 double componentValue_R = 0.0;
6923 double componentValue_C = 0.0;
6924
6925 double RL = 0.0;
6926 double RC = 0.0;
6927 double RR = 0.0;
6928
6929 double componentResistance = 0.0;
6930 double sampleRate = 0.0;
6931};
6932
6947{
6948public:
6949 WdfParallelRC() {}
6950 WdfParallelRC(double _componentValue_R, double _componentValue_C)
6951 {
6952 componentValue_C = _componentValue_C;
6953 componentValue_R = _componentValue_R;
6954 }
6955 virtual ~WdfParallelRC() {}
6956
6958 void setSampleRate(double _sampleRate)
6959 {
6960 sampleRate = _sampleRate;
6962 }
6963
6965 virtual double getComponentResistance() { return componentResistance; }
6966
6968 virtual double getComponentConductance() { return 1.0 / componentResistance; }
6969
6972 {
6974 RC = 1.0 / (2.0*componentValue_C*sampleRate);
6975 componentResistance = 1.0 / ((1.0 / RR) + (1.0 / RC));
6976 K = componentResistance / RR;
6977 }
6978
6980 virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
6981 {
6982 componentValue_R = _componentValue_R;
6983 componentValue_C = _componentValue_C;
6985 }
6986
6988 virtual void setComponentValue_R(double _componentValue_R)
6989 {
6990 componentValue_R = _componentValue_R;
6992 }
6993
6995 virtual void setComponentValue_C(double _componentValue_C)
6996 {
6997 componentValue_C = _componentValue_C;
6999 }
7000
7002 virtual double getComponentValue_R() { return componentValue_R; }
7003
7005 virtual double getComponentValue_C() { return componentValue_C; }
7006
7008 virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
7009
7011 virtual void setInput(double in){ zRegister_L = in; }
7012
7014 virtual double getOutput()
7015 {
7016 double NL = zRegister_L;
7017 double out = NL*(1.0 - K) - K*zRegister_C;
7018 zRegister_C = out;
7019 return out;
7020 }
7021
7023 virtual double getOutput1() { return getOutput(); }
7024
7026 virtual double getOutput2() { return getOutput(); }
7027
7029 virtual double getOutput3() { return getOutput(); }
7030
7032 virtual void setInput1(double _in1) {}
7033
7035 virtual void setInput2(double _in2) {}
7036
7038 virtual void setInput3(double _in3) {}
7039
7040protected:
7041 double zRegister_L = 0.0;
7042 double zRegister_C = 0.0;
7043 double K = 0.0;
7044
7045 double componentValue_C = 0.0;
7046 double componentValue_R = 0.0;
7047
7048 double RL = 0.0;
7049 double RC = 0.0;
7050 double RR = 0.0;
7051
7052 double componentResistance = 0.0;
7053 double sampleRate = 0.0;
7054};
7055
7056
7057// ------------------------------------------------------------------ //
7058// --- WDF ADAPTORS ------------------------------------------------- //
7059// ------------------------------------------------------------------ //
7060
7074enum class wdfComponent { R, L, C, seriesLC, parallelLC, seriesRL, parallelRL, seriesRC, parallelRC };
7075
7088{
7089 WdfComponentInfo() { }
7090
7091 WdfComponentInfo(wdfComponent _componentType, double value1 = 0.0, double value2 = 0.0)
7092 {
7093 componentType = _componentType;
7094 if (componentType == wdfComponent::R)
7095 R = value1;
7096 else if (componentType == wdfComponent::L)
7097 L = value1;
7098 else if (componentType == wdfComponent::C)
7099 C = value1;
7100 else if (componentType == wdfComponent::seriesLC || componentType == wdfComponent::parallelLC)
7101 {
7102 L = value1;
7103 C = value2;
7104 }
7105 else if (componentType == wdfComponent::seriesRL || componentType == wdfComponent::parallelRL)
7106 {
7107 R = value1;
7108 L = value2;
7109 }
7110 else if (componentType == wdfComponent::seriesRC || componentType == wdfComponent::parallelRC)
7111 {
7112 R = value1;
7113 C = value2;
7114 }
7115 }
7116
7117 double R = 0.0;
7118 double L = 0.0;
7119 double C = 0.0;
7120 wdfComponent componentType = wdfComponent::R;
7121};
7122
7123
7137{
7138public:
7139 WdfAdaptorBase() {}
7140 virtual ~WdfAdaptorBase() {}
7141
7143 void setTerminalResistance(double _terminalResistance) { terminalResistance = _terminalResistance; }
7144
7146 void setOpenTerminalResistance(bool _openTerminalResistance = true)
7147 {
7148 // --- flag overrides value
7149 openTerminalResistance = _openTerminalResistance;
7150 terminalResistance = 1.0e+34; // avoid /0.0
7151 }
7152
7154 void setSourceResistance(double _sourceResistance) { sourceResistance = _sourceResistance; }
7155
7157 void setPort1_CompAdaptor(IComponentAdaptor* _port1CompAdaptor) { port1CompAdaptor = _port1CompAdaptor; }
7158
7160 void setPort2_CompAdaptor(IComponentAdaptor* _port2CompAdaptor) { port2CompAdaptor = _port2CompAdaptor; }
7161
7163 void setPort3_CompAdaptor(IComponentAdaptor* _port3CompAdaptor) { port3CompAdaptor = _port3CompAdaptor; }
7164
7166 virtual void reset(double _sampleRate)
7167 {
7168 if (wdfComponent)
7169 wdfComponent->reset(_sampleRate);
7170 }
7171
7173 void setComponent(wdfComponent componentType, double value1 = 0.0, double value2 = 0.0)
7174 {
7175 // --- decode and set
7176 if (componentType == wdfComponent::R)
7177 {
7181 }
7182 else if (componentType == wdfComponent::L)
7183 {
7187 }
7188 else if (componentType == wdfComponent::C)
7189 {
7193 }
7194 else if (componentType == wdfComponent::seriesLC)
7195 {
7197 wdfComponent->setComponentValue_LC(value1, value2);
7199 }
7200 else if (componentType == wdfComponent::parallelLC)
7201 {
7203 wdfComponent->setComponentValue_LC(value1, value2);
7205 }
7206 else if (componentType == wdfComponent::seriesRL)
7207 {
7209 wdfComponent->setComponentValue_RL(value1, value2);
7211 }
7212 else if (componentType == wdfComponent::parallelRL)
7213 {
7215 wdfComponent->setComponentValue_RL(value1, value2);
7217 }
7218 else if (componentType == wdfComponent::seriesRC)
7219 {
7221 wdfComponent->setComponentValue_RC(value1, value2);
7223 }
7224 else if (componentType == wdfComponent::parallelRC)
7225 {
7227 wdfComponent->setComponentValue_RC(value1, value2);
7229 }
7230 }
7231
7233 static void connectAdaptors(WdfAdaptorBase* upstreamAdaptor, WdfAdaptorBase* downstreamAdaptor)
7234 {
7235 upstreamAdaptor->setPort2_CompAdaptor(downstreamAdaptor);
7236 downstreamAdaptor->setPort1_CompAdaptor(upstreamAdaptor);
7237 }
7238
7241 {
7243 }
7244
7246 virtual void setComponentValue(double _componentValue)
7247 {
7248 if (wdfComponent)
7249 wdfComponent->setComponentValue(_componentValue);
7250 }
7251
7253 virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
7254 {
7255 if (wdfComponent)
7256 wdfComponent->setComponentValue_LC(componentValue_L, componentValue_C);
7257 }
7258
7260 virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
7261 {
7262 if (wdfComponent)
7263 wdfComponent->setComponentValue_RL(componentValue_R, componentValue_L);
7264 }
7265
7267 virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
7268 {
7269 if (wdfComponent)
7270 wdfComponent->setComponentValue_RC(componentValue_R, componentValue_C);
7271 }
7272
7275
7278
7281
7282protected:
7283 // --- can in theory connect any port to a component OR adaptor;
7284 // though this library is setup with a convention R3 = component
7289
7290 // --- These hold the input (R1), component (R3) and output (R2) resistances
7291 double R1 = 0.0;
7292 double R2 = 0.0;
7293 double R3 = 0.0;
7294
7295 // --- these are input variables that are stored;
7296 // not used in this implementation but may be required for extended versions
7297 double in1 = 0.0;
7298 double in2 = 0.0;
7299 double in3 = 0.0;
7300
7301 // --- these are output variables that are stored;
7302 // currently out2 is the only one used as it is y(n) for this library
7303 // out1 and out2 are stored; not used in this implementation but may be required for extended versions
7304 double out1 = 0.0;
7305 double out2 = 0.0;
7306 double out3 = 0.0;
7307
7308 // --- terminal impedance
7309 double terminalResistance = 600.0;
7311
7312 // --- source impedance, OK for this to be set to 0.0 for Rs = 0
7313 double sourceResistance = 600.0;
7314};
7315
7328{
7329public:
7330 WdfSeriesAdaptor() {}
7331 virtual ~WdfSeriesAdaptor() {}
7332
7334 virtual double getR2()
7335 {
7336 double componentResistance = 0.0;
7338 componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7339
7340 R2 = R1 + componentResistance;
7341 return R2;
7342 }
7343
7345 virtual void initialize(double _R1)
7346 {
7347 // --- R1 is source resistance for this adaptor
7348 R1 = _R1;
7349
7350 double componentResistance = 0.0;
7352 componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7353
7354 // --- calculate B coeff
7355 B = R1 / (R1 + componentResistance);
7356
7357 // --- init downstream adaptor
7360
7361 // --- not used in this implementation but saving for extended use
7362 R3 = componentResistance;
7363 }
7364
7366 virtual void setInput1(double _in1)
7367 {
7368 // --- save
7369 in1 = _in1;
7370
7371 // --- read component value
7372 N2 = 0.0;
7375
7376 // --- form output
7377 out2 = -(in1 + N2);
7378
7379 // --- deliver downstream
7382 }
7383
7385 virtual void setInput2(double _in2)
7386 {
7387 // --- save
7388 in2 = _in2;
7389
7390 // --- calc N1
7391 N1 = -(in1 - B*(in1 + N2 + in2) + in2);
7392
7393 // --- calc out1
7394 out1 = in1 - B*(N2 + in2);
7395
7396 // --- deliver upstream
7399
7400 // --- set component state
7403 }
7404
7406 virtual void setInput3(double _in3){ }
7407
7409 virtual double getOutput1() { return out1; }
7410
7412 virtual double getOutput2() { return out2; }
7413
7415 virtual double getOutput3() { return out3; }
7416
7417private:
7418 double N1 = 0.0;
7419 double N2 = 0.0;
7420 double B = 0.0;
7421};
7422
7434// --- Series terminated adaptor
7436{
7437public:
7439 virtual ~WdfSeriesTerminatedAdaptor() {}
7440
7442 virtual double getR2()
7443 {
7444 double componentResistance = 0.0;
7446 componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7447
7448 R2 = R1 + componentResistance;
7449 return R2;
7450 }
7451
7453 virtual void initialize(double _R1)
7454 {
7455 // --- source impedance
7456 R1 = _R1;
7457
7458 double componentResistance = 0.0;
7460 componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7461
7462 B1 = (2.0*R1) / (R1 + componentResistance + terminalResistance);
7463 B3 = (2.0*terminalResistance) / (R1 + componentResistance + terminalResistance);
7464
7465 // --- init downstream
7468
7469 // --- not used in this implementation but saving for extended use
7470 R3 = componentResistance;
7471 }
7472
7474 virtual void setInput1(double _in1)
7475 {
7476 // --- save
7477 in1 = _in1;
7478
7479 N2 = 0.0;
7482
7483 double N3 = in1 + N2;
7484
7485 // --- calc out2 y(n)
7486 out2 = -B3*N3;
7487
7488 // --- form output1
7489 out1 = in1 - B1*N3;
7490
7491 // --- form N1
7492 N1 = -(out1 + out2 + N3);
7493
7494 // --- deliver upstream to input2
7497
7498 // --- set component state
7501 }
7502
7505 virtual void setInput2(double _in2) { in2 = _in2;}
7506
7508 virtual void setInput3(double _in3) { in3 = _in3;}
7509
7511 virtual double getOutput1() { return out1; }
7512
7514 virtual double getOutput2() { return out2; }
7515
7517 virtual double getOutput3() { return out3; }
7518
7519private:
7520 double N1 = 0.0;
7521 double N2 = 0.0;
7522 double B1 = 0.0;
7523 double B3 = 0.0;
7524};
7525
7538{
7539public:
7541 virtual ~WdfParallelAdaptor() {}
7542
7544 virtual double getR2()
7545 {
7546 double componentConductance = 0.0;
7548 componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7549
7550 // --- 1 / (sum of admittances)
7551 R2 = 1.0 / ((1.0 / R1) + componentConductance);
7552 return R2;
7553 }
7554
7556 virtual void initialize(double _R1)
7557 {
7558 // --- save R1
7559 R1 = _R1;
7560
7561 double G1 = 1.0 / R1;
7562 double componentConductance = 0.0;
7564 componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7565
7566 // --- calculate B coeff
7567 A = G1 / (G1 + componentConductance);
7568
7569 // --- now, do we init our downstream??
7572
7573 // --- not used in this implementation but saving for extended use
7574 R3 = 1.0/ componentConductance;
7575 }
7576
7578 virtual void setInput1(double _in1)
7579 {
7580 // --- save
7581 in1 = _in1;
7582
7583 // --- read component
7584 N2 = 0.0;
7587
7588 // --- form output
7589 out2 = N2 - A*(-in1 + N2);
7590
7591 // --- deliver downstream
7594 }
7595
7597 virtual void setInput2(double _in2)
7598 {
7599 // --- save
7600 in2 = _in2;
7601
7602 // --- calc N1
7603 N1 = in2 - A*(-in1 + N2);
7604
7605 // --- calc out1
7606 out1 = -in1 + N2 + N1;
7607
7608 // --- deliver upstream
7611
7612 // --- set component state
7615 }
7616
7618 virtual void setInput3(double _in3) { }
7619
7621 virtual double getOutput1() { return out1; }
7622
7624 virtual double getOutput2() { return out2; }
7625
7627 virtual double getOutput3() { return out3; }
7628
7629private:
7630 double N1 = 0.0;
7631 double N2 = 0.0;
7632 double A = 0.0;
7633};
7634
7635
7648{
7649public:
7652
7654 virtual double getR2()
7655 {
7656 double componentConductance = 0.0;
7658 componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7659
7660 // --- 1 / (sum of admittances)
7661 R2 = 1.0 / ((1.0 / R1) + componentConductance);
7662 return R2;
7663 }
7664
7666 virtual void initialize(double _R1)
7667 {
7668 // --- save R1
7669 R1 = _R1;
7670
7671 double G1 = 1.0 / R1;
7672 if (terminalResistance <= 0.0)
7673 terminalResistance = 1e-15;
7674
7675 double G2 = 1.0 / terminalResistance;
7676 double componentConductance = 0.0;
7678 componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7679
7680 A1 = 2.0*G1 / (G1 + componentConductance + G2);
7681 A3 = openTerminalResistance ? 0.0 : 2.0*G2 / (G1 + componentConductance + G2);
7682
7683 // --- init downstream
7686
7687 // --- not used in this implementation but saving for extended use
7688 R3 = 1.0 / componentConductance;
7689 }
7690
7692 virtual void setInput1(double _in1)
7693 {
7694 // --- save
7695 in1 = _in1;
7696
7697 N2 = 0.0;
7700
7701 // --- form N1
7702 N1 = -A1*(-in1 + N2) + N2 - A3*N2;
7703
7704 // --- form output1
7705 out1 = -in1 + N2 + N1;
7706
7707 // --- deliver upstream to input2
7710
7711 // --- calc out2 y(n)
7712 out2 = N2 + N1;
7713
7714 // --- set component state
7717 }
7718
7720 virtual void setInput2(double _in2){ in2 = _in2;}
7721
7723 virtual void setInput3(double _in3) { }
7724
7726 virtual double getOutput1() { return out1; }
7727
7729 virtual double getOutput2() { return out2; }
7730
7732 virtual double getOutput3() { return out3; }
7733
7734private:
7735 double N1 = 0.0;
7736 double N2 = 0.0;
7737 double A1 = 0.0;
7738 double A3 = 0.0;
7739};
7740
7741// ------------------------------------------------------------------------------ //
7742// --- WDF Ladder Filter Design Examples --------------------------------------- //
7743// ------------------------------------------------------------------------------ //
7744//
7745// --- 3rd order Butterworth LPF designed with Elsie www.TonneSoftware.comm
7746//
7747/*
7748 3rd Order Inductor-Leading LPF
7749
7750 Rs = Rload = 600 ohms
7751
7752 Series(L1) -> Parallel(C1) -> Series(L2)
7753
7754 --L1-- | --L2--
7755 C1
7756 |
7757
7758 fc = 1kHz
7759 L1 = 95.49e-3;
7760 C1 = 0.5305e-6;
7761 L2 = 95.49e-3;
7762
7763 fc = 10kHz
7764 L1 = 9.549e-3;
7765 C1 = 0.05305e-6;
7766 L2 = 9.549e-3;
7767*/
7768
7788{
7789public:
7790 WDFButterLPF3(void) { createWDF(); } /* C-TOR */
7791 ~WDFButterLPF3(void) {} /* D-TOR */
7792
7794 virtual bool reset(double _sampleRate)
7795 {
7796 // --- rest WDF components (flush state registers)
7797 seriesAdaptor_L1.reset(_sampleRate);
7798 parallelAdaptor_C1.reset(_sampleRate);
7799 seriesTerminatedAdaptor_L2.reset(_sampleRate);
7800
7801 // --- intialize the chain of adapters
7803 return true;
7804 }
7805
7807 virtual bool canProcessAudioFrame() { return false; }
7808
7814 virtual double processAudioSample(double xn)
7815 {
7816 // --- push audio sample into series L1
7818
7819 // --- output is at terminated L2's output2
7821 }
7822
7825 {
7826 // --- actual component values fc = 1kHz
7827 double L1_value = 95.49e-3; // 95.5 mH
7828 double C1_value = 0.5305e-6; // 0.53 uF
7829 double L2_value = 95.49e-3; // 95.5 mH
7830
7831 // --- set adapter components
7832 seriesAdaptor_L1.setComponent(wdfComponent::L, L1_value);
7833 parallelAdaptor_C1.setComponent(wdfComponent::C, C1_value);
7834 seriesTerminatedAdaptor_L2.setComponent(wdfComponent::L, L2_value);
7835
7836 // --- connect adapters
7839
7840 // --- set source resistance
7841 seriesAdaptor_L1.setSourceResistance(600.0); // --- Rs = 600
7842
7843 // --- set terminal resistance
7844 seriesTerminatedAdaptor_L2.setTerminalResistance(600.0); // --- Rload = 600
7845 }
7846
7847protected:
7848 // --- three adapters
7852};
7853
7874{
7875public:
7876 WDFTunableButterLPF3(void) { createWDF(); } /* C-TOR */
7877 ~WDFTunableButterLPF3(void) {} /* D-TOR */
7878
7880 virtual bool reset(double _sampleRate)
7881 {
7882 sampleRate = _sampleRate;
7883 // --- rest WDF components (flush state registers)
7884 seriesAdaptor_L1.reset(_sampleRate);
7885 parallelAdaptor_C1.reset(_sampleRate);
7886 seriesTerminatedAdaptor_L2.reset(_sampleRate);
7887
7888 // --- intialize the chain of adapters
7890 return true;
7891 }
7892
7894 virtual bool canProcessAudioFrame() { return false; }
7895
7901 virtual double processAudioSample(double xn)
7902 {
7903 // --- push audio sample into series L1
7905
7906 // --- output is at terminated L2's output2
7908 }
7909
7912 {
7913 // --- create components, init to noramlized values fc = 1Hz
7914 seriesAdaptor_L1.setComponent(wdfComponent::L, L1_norm);
7915 parallelAdaptor_C1.setComponent(wdfComponent::C, C1_norm);
7916 seriesTerminatedAdaptor_L2.setComponent(wdfComponent::L, L2_norm);
7917
7918 // --- connect adapters
7921
7922 // --- set source resistance
7923 seriesAdaptor_L1.setSourceResistance(600.0); // --- Rs = 600
7924
7925 // --- set terminal resistance
7926 seriesTerminatedAdaptor_L2.setTerminalResistance(600.0); // --- Rload = 600
7927 }
7928
7931
7933 void setFilterFc(double fc_Hz)
7934 {
7936 {
7937 double arg = (kPi*fc_Hz) / sampleRate;
7938 fc_Hz = fc_Hz*(tan(arg) / arg);
7939 }
7940
7941 seriesAdaptor_L1.setComponentValue(L1_norm / fc_Hz);
7942 parallelAdaptor_C1.setComponentValue(C1_norm / fc_Hz);
7944 }
7945
7946protected:
7947 // --- three adapters
7951
7952 double L1_norm = 95.493; // 95.5 mH
7953 double C1_norm = 530.516e-6; // 0.53 uF
7954 double L2_norm = 95.493; // 95.5 mH
7955
7956 bool useFrequencyWarping = false;
7957 double sampleRate = 1.0;
7958};
7959
7979{
7980public:
7981 WDFBesselBSF3(void) { createWDF(); } /* C-TOR */
7982 ~WDFBesselBSF3(void) {} /* D-TOR */
7983
7985 virtual bool reset(double _sampleRate)
7986 {
7987 // --- rest WDF components (flush state registers)
7988 seriesAdaptor_L1C1.reset(_sampleRate);
7989 parallelAdaptor_L2C2.reset(_sampleRate);
7991
7992 // --- intialize the chain of adapters
7994
7995 return true;
7996 }
7997
7999 virtual bool canProcessAudioFrame() { return false; }
8000
8006 virtual double processAudioSample(double xn)
8007 {
8008 // --- push audio sample into series L1
8010
8011 // --- output is at terminated L2's output2
8013 }
8014
8017 {
8018 // --- set component values
8019 // --- fo = 5kHz
8020 // BW = 2kHz or Q = 2.5
8021 seriesAdaptor_L1C1.setComponent(wdfComponent::parallelLC, 16.8327e-3, 0.060193e-6); /* L, C */
8022 parallelAdaptor_L2C2.setComponent(wdfComponent::seriesLC, 49.1978e-3, 0.02059e-6); /* L, C */
8023 seriesTerminatedAdaptor_L3C3.setComponent(wdfComponent::parallelLC, 2.57755e-3, 0.393092e-6); /* L, C */
8024
8025 // --- connect adapters
8028
8029 // --- set source resistance
8030 seriesAdaptor_L1C1.setSourceResistance(600.0); // Ro = 600
8031
8032 // --- set terminal resistance
8034 }
8035
8036protected:
8037 // --- three adapters
8041};
8042
8043
8063{
8064public:
8065 WDFConstKBPF6(void) { createWDF(); } /* C-TOR */
8066 ~WDFConstKBPF6(void) {} /* D-TOR */
8067
8069 virtual bool reset(double _sampleRate)
8070 {
8071 // --- rest WDF components (flush state registers)
8072 seriesAdaptor_L1C1.reset(_sampleRate);
8073 parallelAdaptor_L2C2.reset(_sampleRate);
8074
8075 seriesAdaptor_L3C3.reset(_sampleRate);
8076 parallelAdaptor_L4C4.reset(_sampleRate);
8077
8078 seriesAdaptor_L5C5.reset(_sampleRate);
8080
8081 // --- intialize the chain of adapters
8083 return true;
8084 }
8085
8087 virtual bool canProcessAudioFrame() { return false; }
8088
8094 virtual double processAudioSample(double xn)
8095 {
8096 // --- push audio sample into series L1
8098
8099 // --- output is at terminated L6C6 output2
8101
8102 return output;
8103 }
8104
8107 {
8108 // --- fo = 5kHz
8109 // BW = 2kHz or Q = 2.5
8110 seriesAdaptor_L1C1.setComponent(wdfComponent::seriesLC, 47.7465e-3, 0.02122e-6);
8111 parallelAdaptor_L2C2.setComponent(wdfComponent::parallelLC, 3.81972e-3, 0.265258e-6);
8112
8113 seriesAdaptor_L3C3.setComponent(wdfComponent::seriesLC, 95.493e-3, 0.01061e-6);
8114 parallelAdaptor_L4C4.setComponent(wdfComponent::parallelLC, 3.81972e-3, 0.265258e-6);
8115
8116 seriesAdaptor_L5C5.setComponent(wdfComponent::seriesLC, 95.493e-3, 0.01061e-6);
8117 parallelTerminatedAdaptor_L6C6.setComponent(wdfComponent::parallelLC, 7.63944e-3, 0.132629e-6);
8118
8119 // --- connect adapters
8125
8126 // --- set source resistance
8127 seriesAdaptor_L1C1.setSourceResistance(600.0); // Ro = 600
8128
8129 // --- set terminal resistance
8131 }
8132
8133protected:
8134 // --- six adapters
8137
8140
8143};
8144
8145
8158{
8159 WDFParameters() {}
8162 {
8163 if (this == &params)
8164 return *this;
8165
8166 fc = params.fc;
8167 Q = params.Q;
8168 boostCut_dB = params.boostCut_dB;
8170 return *this;
8171 }
8172
8173 // --- individual parameters
8174 double fc = 100.0;
8175 double Q = 0.707;
8176 double boostCut_dB = 0.0;
8177 bool frequencyWarping = true;
8178};
8179
8198{
8199public:
8200 WDFIdealRLCLPF(void) { createWDF(); } /* C-TOR */
8201 ~WDFIdealRLCLPF(void) {} /* D-TOR */
8202
8204 virtual bool reset(double _sampleRate)
8205 {
8206 sampleRate = _sampleRate;
8207
8208 // --- rest WDF components (flush state registers)
8209 seriesAdaptor_RL.reset(_sampleRate);
8211
8212 // --- intialize the chain of adapters
8214 return true;
8215 }
8216
8218 virtual bool canProcessAudioFrame() { return false; }
8219
8225 virtual double processAudioSample(double xn)
8226 {
8227 // --- push audio sample into series L1
8229
8230 // --- output is at terminated L2's output2
8231 // note compensation scaling by -6dB = 0.5
8232 // because of WDF assumption about Rs and Rload
8234 }
8235
8238 {
8239 // --- create components, init to noramlized values fc =
8240 // initial values for fc = 1kHz Q = 0.707
8241 // Holding C Constant at 1e-6
8242 // L = 2.533e-2
8243 // R = 2.251131 e2
8244 seriesAdaptor_RL.setComponent(wdfComponent::seriesRL, 2.251131e2, 2.533e-2);
8245 parallelTerminatedAdaptor_C.setComponent(wdfComponent::C, 1.0e-6);
8246
8247 // --- connect adapters
8249
8250 // --- set source resistance
8251 seriesAdaptor_RL.setSourceResistance(0.0); // --- Rs = 600
8252
8253 // --- set open ckt termination
8255 }
8256
8262
8267 void setParameters(const WDFParameters& _wdfParameters)
8268 {
8269 if (_wdfParameters.fc != wdfParameters.fc ||
8270 _wdfParameters.Q != wdfParameters.Q ||
8271 _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8273 {
8274 wdfParameters = _wdfParameters;
8275 double fc_Hz = wdfParameters.fc;
8276
8278 {
8279 double arg = (kPi*fc_Hz) / sampleRate;
8280 fc_Hz = fc_Hz*(tan(arg) / arg);
8281 }
8282
8283 double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8284 double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8285
8286 seriesAdaptor_RL.setComponentValue_RL(resistorValue, inductorValue);
8288 }
8289 }
8290
8291protected:
8293
8294 // --- adapters
8297
8298 double sampleRate = 1.0;
8299
8300};
8301
8320{
8321public:
8322 WDFIdealRLCHPF(void) { createWDF(); } /* C-TOR */
8323 ~WDFIdealRLCHPF(void) {} /* D-TOR */
8324
8326 virtual bool reset(double _sampleRate)
8327 {
8328 sampleRate = _sampleRate;
8329 // --- rest WDF components (flush state registers)
8330 seriesAdaptor_RC.reset(_sampleRate);
8332
8333 // --- intialize the chain of adapters
8335 return true;
8336 }
8337
8339 virtual bool canProcessAudioFrame() { return false; }
8340
8346 virtual double processAudioSample(double xn)
8347 {
8348 // --- push audio sample into series L1
8350
8351 // --- output is at terminated L2's output2
8352 // note compensation scaling by -6dB = 0.5
8353 // because of WDF assumption about Rs and Rload
8355 }
8356
8359 {
8360 // --- create components, init to noramlized values fc =
8361 // initial values for fc = 1kHz Q = 0.707
8362 // Holding C Constant at 1e-6
8363 // L = 2.533e-2
8364 // R = 2.251131 e2
8365 seriesAdaptor_RC.setComponent(wdfComponent::seriesRC, 2.251131e2, 1.0e-6);
8366 parallelTerminatedAdaptor_L.setComponent(wdfComponent::L, 2.533e-2);
8367
8368 // --- connect adapters
8370
8371 // --- set source resistance
8372 seriesAdaptor_RC.setSourceResistance(0.0); // --- Rs = 600
8373
8374 // --- set open ckt termination
8376 }
8377
8383
8388 void setParameters(const WDFParameters& _wdfParameters)
8389 {
8390 if (_wdfParameters.fc != wdfParameters.fc ||
8391 _wdfParameters.Q != wdfParameters.Q ||
8392 _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8394 {
8395 wdfParameters = _wdfParameters;
8396 double fc_Hz = wdfParameters.fc;
8397
8399 {
8400 double arg = (kPi*fc_Hz) / sampleRate;
8401 fc_Hz = fc_Hz*(tan(arg) / arg);
8402 }
8403
8404 double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8405 double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8406
8407 seriesAdaptor_RC.setComponentValue_RC(resistorValue, 1.0e-6);
8410 }
8411 }
8412
8413
8414protected:
8416
8417 // --- three
8420
8421 double sampleRate = 1.0;
8422};
8423
8442{
8443public:
8444 WDFIdealRLCBPF(void) { createWDF(); } /* C-TOR */
8445 ~WDFIdealRLCBPF(void) {} /* D-TOR */
8446
8448 virtual bool reset(double _sampleRate)
8449 {
8450 sampleRate = _sampleRate;
8451 // --- rest WDF components (flush state registers)
8452 seriesAdaptor_LC.reset(_sampleRate);
8454
8455 // --- intialize the chain of adapters
8457 return true;
8458 }
8459
8461 virtual bool canProcessAudioFrame() { return false; }
8462
8468 virtual double processAudioSample(double xn)
8469 {
8470 // --- push audio sample into series L1
8472
8473 // --- output is at terminated L2's output2
8474 // note compensation scaling by -6dB = 0.5
8475 // because of WDF assumption about Rs and Rload
8477 }
8478
8481 {
8482 // --- create components, init to noramlized values fc =
8483 // initial values for fc = 1kHz Q = 0.707
8484 // Holding C Constant at 1e-6
8485 // L = 2.533e-2
8486 // R = 2.251131 e2
8487 seriesAdaptor_LC.setComponent(wdfComponent::seriesLC, 2.533e-2, 1.0e-6);
8488 parallelTerminatedAdaptor_R.setComponent(wdfComponent::R, 2.251131e2);
8489
8490 // --- connect adapters
8492
8493 // --- set source resistance
8494 seriesAdaptor_LC.setSourceResistance(0.0); // --- Rs = 600
8495
8496 // --- set open ckt termination
8498 }
8499
8505
8510 void setParameters(const WDFParameters& _wdfParameters)
8511 {
8512 if (_wdfParameters.fc != wdfParameters.fc ||
8513 _wdfParameters.Q != wdfParameters.Q ||
8514 _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8516 {
8517 wdfParameters = _wdfParameters;
8518 double fc_Hz = wdfParameters.fc;
8519
8521 {
8522 double arg = (kPi*fc_Hz) / sampleRate;
8523 fc_Hz = fc_Hz*(tan(arg) / arg);
8524 }
8525
8526 double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8527 double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8528
8529 seriesAdaptor_LC.setComponentValue_LC(inductorValue, 1.0e-6);
8532 }
8533 }
8534
8535protected:
8537
8538 // --- adapters
8541
8542 double sampleRate = 1.0;
8543};
8544
8545
8564{
8565public:
8566 WDFIdealRLCBSF(void) { createWDF(); } /* C-TOR */
8567 ~WDFIdealRLCBSF(void) {} /* D-TOR */
8568
8570 virtual bool reset(double _sampleRate)
8571 {
8572 sampleRate = _sampleRate;
8573 // --- rest WDF components (flush state registers)
8574 seriesAdaptor_R.reset(_sampleRate);
8576
8577 // --- intialize the chain of adapters
8579 return true;
8580 }
8581
8583 virtual bool canProcessAudioFrame() { return false; }
8584
8590 virtual double processAudioSample(double xn)
8591 {
8592 // --- push audio sample into series L1
8594
8595 // --- output is at terminated L2's output2
8596 // note compensation scaling by -6dB = 0.5
8597 // because of WDF assumption about Rs and Rload
8599 }
8600
8603 {
8604 // --- create components, init to noramlized values fc =
8605 // initial values for fc = 1kHz Q = 0.707
8606 // Holding C Constant at 1e-6
8607 // L = 2.533e-2
8608 // R = 2.251131 e2
8609 seriesAdaptor_R.setComponent(wdfComponent::R, 2.533e-2);
8610 parallelTerminatedAdaptor_LC.setComponent(wdfComponent::seriesLC, 2.533e-2, 1.0e-6);
8611
8612 // --- connect adapters
8614
8615 // --- set source resistance
8616 seriesAdaptor_R.setSourceResistance(0.0); // --- Rs = 600
8617
8618 // --- set open ckt termination
8620 }
8621
8627
8632 void setParameters(const WDFParameters& _wdfParameters)
8633 {
8634 if (_wdfParameters.fc != wdfParameters.fc ||
8635 _wdfParameters.Q != wdfParameters.Q ||
8636 _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8638 {
8639 wdfParameters = _wdfParameters;
8640 double fc_Hz = wdfParameters.fc;
8641
8643 {
8644 double arg = (kPi*fc_Hz) / sampleRate;
8645 fc_Hz = fc_Hz*(tan(arg) / arg);
8646 }
8647
8648 double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8649 double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8650
8651 seriesAdaptor_R.setComponentValue(resistorValue);
8654 }
8655 }
8656
8657protected:
8659
8660 // --- adapters
8663
8664 double sampleRate = 1.0;
8665};
8666
8667
8668// ------------------------------------------------------------------ //
8669// --- OBJECTS REQUIRING FFTW --------------------------------------- //
8670// ------------------------------------------------------------------ //
8671
8685enum class windowType {kNoWindow, kRectWindow, kHannWindow, kBlackmanHarrisWindow, kHammingWindow };
8686
8697inline std::unique_ptr<double[]> makeWindow(unsigned int windowLength, unsigned int hopSize, windowType window, double& gainCorrectionValue)
8698{
8699 std::unique_ptr<double[]> windowBuffer;
8700 windowBuffer.reset(new double[windowLength]);
8701
8702 if (!windowBuffer) return nullptr;
8703
8704 double overlap = hopSize > 0.0 ? 1.0 - (double)hopSize / (double)windowLength : 0.0;
8705 gainCorrectionValue = 0.0;
8706
8707 for (uint32_t n = 0; n < windowLength; n++)
8708 {
8709 if (window == windowType::kRectWindow)
8710 {
8711 if (n >= 1 && n <= windowLength - 1)
8712 windowBuffer[n] = 1.0;
8713 }
8714 else if (window == windowType::kHammingWindow)
8715 {
8716 windowBuffer[n] = 0.54 - 0.46*cos((n*2.0*kPi) / (windowLength));
8717 }
8718 else if (window == windowType::kHannWindow)
8719 {
8720 windowBuffer[n] = 0.5 * (1 - cos((n*2.0*kPi) / (windowLength)));
8721 }
8722 else if (window == windowType::kBlackmanHarrisWindow)
8723 {
8724 windowBuffer[n] = (0.42323 - (0.49755*cos((n*2.0*kPi) / (windowLength))) + 0.07922*cos((2 * n*2.0*kPi) / (windowLength)));
8725 }
8726 else if (window == windowType::kNoWindow)
8727 {
8728 windowBuffer[n] = 1.0;
8729 }
8730
8731 gainCorrectionValue += windowBuffer[n];
8732 }
8733
8734 // --- calculate gain correction factor
8735 if (window != windowType::kNoWindow)
8736 gainCorrectionValue = (1.0 - overlap) / gainCorrectionValue;
8737 else
8738 gainCorrectionValue = 1.0 / gainCorrectionValue;
8739
8740 return windowBuffer;
8741}
8742
8743// --- FFTW --- to enable, add the statement #define HAVE_FFTW 1 to the top of the file
8744#ifdef HAVE_FFTW
8745#include "fftw3.h"
8746
8765{
8766public:
8767 FastFFT() {} /* C-TOR */
8768 ~FastFFT() {
8769 if (windowBuffer) delete[] windowBuffer;
8770 destroyFFTW();
8771 } /* D-TOR */
8772
8774 void initialize(unsigned int _frameLength, windowType _window);
8775
8777 void destroyFFTW();
8778
8780 fftw_complex* doFFT(double* inputReal, double* inputImag = nullptr);
8781
8783 fftw_complex* doInverseFFT(double* inputReal, double* inputImag);
8784
8786 unsigned int getFrameLength() { return frameLength; }
8787
8788protected:
8789 // --- setup FFTW
8790 fftw_complex* fft_input = nullptr;
8791 fftw_complex* fft_result = nullptr;
8792 fftw_complex* ifft_input = nullptr;
8793 fftw_complex* ifft_result = nullptr;
8794 fftw_plan plan_forward = nullptr;
8795 fftw_plan plan_backward = nullptr;
8796
8797 double* windowBuffer = nullptr;
8799 windowType window = windowType::kHannWindow;
8800 unsigned int frameLength = 0;
8801};
8802
8803
8824{
8825public:
8826 PhaseVocoder() {} /* C-TOR */
8827 ~PhaseVocoder() {
8828 if (inputBuffer) delete[] inputBuffer;
8829 if (outputBuffer) delete[] outputBuffer;
8830 if (windowBuffer) delete[] windowBuffer;
8831 destroyFFTW();
8832 } /* D-TOR */
8833
8835 void initialize(unsigned int _frameLength, unsigned int _hopSize, windowType _window);
8836
8838 void destroyFFTW();
8839
8841 double processAudioSample(double input, bool& fftReady);
8842
8844 bool addZeroPad(unsigned int count);
8845
8847 bool advanceAndCheckFFT();
8848
8850 fftw_complex* getFFTData() { return fft_result; }
8851
8853 fftw_complex* getIFFTData() { return ifft_result; }
8854
8856 void doInverseFFT();
8857
8859 void doOverlapAdd(double* outputData = nullptr, int length = 0);
8860
8862 unsigned int getFrameLength() { return frameLength; }
8863
8865 unsigned int getHopSize() { return hopSize; }
8866
8868 double getOverlap() { return overlap; }
8869
8871 // --- for fast convolution and other overlap-add algorithms
8872 // that are not hop-size dependent
8873 void setOverlapAddOnly(bool b){ bool overlapAddOnly = b; }
8874
8875protected:
8876 // --- setup FFTW
8877 fftw_complex* fft_input = nullptr;
8878 fftw_complex* fft_result = nullptr;
8879 fftw_complex* ifft_result = nullptr;
8880 fftw_plan plan_forward = nullptr;
8881 fftw_plan plan_backward = nullptr;
8882
8883 // --- linear buffer for window
8884 double* windowBuffer = nullptr;
8885
8886 // --- circular buffers for input and output
8887 double* inputBuffer = nullptr;
8888 double* outputBuffer = nullptr;
8889
8890 // --- index and wrap masks for input and output buffers
8891 unsigned int inputWriteIndex = 0;
8892 unsigned int outputWriteIndex = 0;
8893 unsigned int inputReadIndex = 0;
8894 unsigned int outputReadIndex = 0;
8895 unsigned int wrapMask = 0;
8896 unsigned int wrapMaskOut = 0;
8897
8898 // --- amplitude correction factor, aking into account both hopsize (overlap)
8899 // and the window power itself
8900 double windowHopCorrection = 1.0;
8901
8902 // --- these allow a more robust combination of user interaction
8903 bool needInverseFFT = false;
8904 bool needOverlapAdd = false;
8905
8906 // --- our window type; you can add more windows if you like
8907 windowType window = windowType::kHannWindow;
8908
8909 // --- counters
8910 unsigned int frameLength = 0;
8911 unsigned int fftCounter = 0;
8912
8913 // --- hop-size and overlap (mathematically related)
8914 unsigned int hopSize = 0;
8915 double overlap = 1.0;
8916
8917 // --- flag for overlap-add algorithms that do not involve hop-size, other
8918 // than setting the overlap
8919 bool overlapAddOnly = false;
8920
8921};
8922
8943{
8944public:
8945 FastConvolver() {
8947 } /* C-TOR */
8948 ~FastConvolver() {
8949 if (filterIR)
8950 delete[] filterIR;
8951
8952 if (filterFFT)
8953 fftw_free(filterFFT);
8954 } /* D-TOR */
8955
8960 void initialize(unsigned int _filterImpulseLength)
8961 {
8962 if (filterImpulseLength == _filterImpulseLength)
8963 return;
8964
8965 // --- setup a specialized vocoder with 50% hop size
8966 filterImpulseLength = _filterImpulseLength;
8967 vocoder.initialize(filterImpulseLength * 2, filterImpulseLength, windowType::kNoWindow);
8968
8969 // --- initialize the FFT object for capturing the filter FFT
8970 filterFastFFT.initialize(filterImpulseLength * 2, windowType::kNoWindow);
8971
8972 // --- array to hold the filter IR; this could be localized to the particular function that uses it
8973 if (filterIR)
8974 delete [] filterIR;
8975 filterIR = new double[filterImpulseLength * 2];
8976 memset(&filterIR[0], 0, filterImpulseLength * 2 * sizeof(double));
8977
8978 // --- allocate the filter FFT arrays
8979 if(filterFFT)
8980 fftw_free(filterFFT);
8981
8982 filterFFT = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * filterImpulseLength * 2);
8983
8984 // --- reset
8985 inputCount = 0;
8986 }
8987
8989 void setFilterIR(double* irBuffer)
8990 {
8991 if (!irBuffer) return;
8992
8993 memset(&filterIR[0], 0, filterImpulseLength * 2 * sizeof(double));
8994
8995 // --- copy over first half; filterIR len = filterImpulseLength * 2
8996 int m = 0;
8997 for (unsigned int i = 0; i < filterImpulseLength; i++)
8998 {
8999 filterIR[i] = irBuffer[i];
9000 }
9001
9002 // --- take FFT of the h(n)
9003 fftw_complex* fftOfFilter = filterFastFFT.doFFT(&filterIR[0]);
9004
9005 // --- copy the FFT into our local buffer for storage; also
9006 // we never want to hold a pointer to a FFT output
9007 // for more than one local function's worth
9008 // could replace with memcpy( )
9009 for (uint32_t i = 0; i < 2; i++)
9010 {
9011 for (unsigned int j = 0; j < filterImpulseLength * 2; j++)
9012 {
9013 filterFFT[j][i] = fftOfFilter[j][i];
9014 }
9015 }
9016 }
9017
9019 double processAudioSample(double input)
9020 {
9021 bool fftReady = false;
9022 double output = 0.0;
9023
9025 {
9027
9028 if (fftReady) // should happen on time
9029 {
9030 // --- multiply our filter IR with the vocoder FFT
9031 fftw_complex* signalFFT = vocoder.getFFTData();
9032 if (signalFFT)
9033 {
9034 unsigned int fff = vocoder.getFrameLength();
9035
9036 // --- complex multiply with FFT of IR
9037 for (unsigned int i = 0; i < filterImpulseLength * 2; i++)
9038 {
9039 // --- get real/imag parts of each FFT
9040 ComplexNumber signal(signalFFT[i][0], signalFFT[i][1]);
9041 ComplexNumber filter(filterFFT[i][0], filterFFT[i][1]);
9042
9043 // --- use complex multiply function; this convolves in the time domain
9044 ComplexNumber product = complexMultiply(signal, filter);
9045
9046 // --- overwrite the FFT bins
9047 signalFFT[i][0] = product.real;
9048 signalFFT[i][1] = product.imag;
9049 }
9050 }
9051 }
9052
9053 // --- reset counter
9054 inputCount = 0;
9055 }
9056
9057 // --- process next sample
9058 output = vocoder.processAudioSample(input, fftReady);
9059 inputCount++;
9060
9061 return output;
9062 }
9063
9065 unsigned int getFrameLength() { return vocoder.getFrameLength(); }
9066
9068 unsigned int getFilterIRLength() { return filterImpulseLength; }
9069
9070protected:
9073 fftw_complex* filterFFT = nullptr;
9074 double* filterIR = nullptr;
9075 unsigned int inputCount = 0;
9076 unsigned int filterImpulseLength = 0;
9077};
9078
9079// --- PSM Vocoder
9080const unsigned int PSM_FFT_LEN = 4096;
9081
9096{
9097 BinData() {}
9099 BinData& operator=(const BinData& params) // need this override for collections to work
9100 {
9101 if (this == &params)
9102 return *this;
9103
9104 isPeak = params.isPeak;
9105 magnitude = params.magnitude;
9106 phi = params.phi;
9107
9108 psi = params.psi;
9109 localPeakBin = params.localPeakBin;
9111 updatedPhase = params.updatedPhase;
9112
9113 return *this;
9114 }
9115
9117 void reset()
9118 {
9119 isPeak = false;
9120 magnitude = 0.0;
9121 phi = 0.0;
9122
9123 psi = 0.0;
9124 localPeakBin = 0;
9125 previousPeakBin = -1; // -1 is flag
9126 updatedPhase = 0.0;
9127 }
9128
9129 bool isPeak = false;
9130 double magnitude = 0.0;
9131 double phi = 0.0;
9132 double psi = 0.0;
9133 unsigned int localPeakBin = 0;
9135 double updatedPhase = 0.0;
9136};
9137
9150{
9153 PSMVocoderParameters& operator=(const PSMVocoderParameters& params) // need this override for collections to work
9154 {
9155 if (this == &params)
9156 return *this;
9157
9161
9162 return *this;
9163 }
9164
9165 // --- params
9166 double pitchShiftSemitones = 0.0;
9168 bool enablePeakTracking = false;
9169};
9170
9190{
9191public:
9192 PSMVocoder() {
9193 vocoder.initialize(PSM_FFT_LEN, PSM_FFT_LEN/4, windowType::kHannWindow); // 75% overlap
9194 } /* C-TOR */
9195 ~PSMVocoder() {
9196 if (windowBuff) delete[] windowBuff;
9197 if (outputBuff) delete[] outputBuff;
9198
9199 } /* D-TOR */
9200
9202 virtual bool reset(double _sampleRate)
9203 {
9204 memset(&phi[0], 0, sizeof(double)*PSM_FFT_LEN);
9205 memset(&psi[0], 0, sizeof(double)* PSM_FFT_LEN);
9206 if(outputBuff)
9207 memset(outputBuff, 0, sizeof(double)*outputBufferLength);
9208
9209 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9210 {
9211 binData[i].reset();
9213
9214 peakBins[i] = -1;
9215 peakBinsPrevious[i] = -1;
9216 }
9217
9218 return true;
9219 }
9220
9222 virtual bool canProcessAudioFrame() { return false; }
9223
9225 void setPitchShift(double semitones)
9226 {
9227 // --- this is costly so only update when things changed
9228 double newAlpha = pow(2.0, semitones / 12.0);
9229 double newOutputBufferLength = round((1.0/newAlpha)*(double)PSM_FFT_LEN);
9230
9231 // --- check for change
9232 if (newOutputBufferLength == outputBufferLength)
9233 return;
9234
9235 // --- new stuff
9236 alphaStretchRatio = newAlpha;
9238
9239 // --- set output resample buffer
9240 outputBufferLength = newOutputBufferLength;
9241
9242 // --- create Hann window
9243 if (windowBuff) delete[] windowBuff;
9244 windowBuff = new double[outputBufferLength];
9245 windowCorrection = 0.0;
9246 for (unsigned int i = 0; i < outputBufferLength; i++)
9247 {
9248 windowBuff[i] = 0.5 * (1.0 - cos((i*2.0*kPi) / (outputBufferLength)));
9250 }
9252
9253 // --- create output buffer
9254 if (outputBuff) delete[] outputBuff;
9255 outputBuff = new double[outputBufferLength];
9256 memset(outputBuff, 0, sizeof(double)*outputBufferLength);
9257 }
9258
9260 int findPreviousNearestPeak(int peakIndex)
9261 {
9262 if (peakBinsPrevious[0] == -1) // first run, there is no peak
9263 return -1;
9264
9265 int delta = -1;
9266 int previousPeak = -1;
9267 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9268 {
9269 if (peakBinsPrevious[i] < 0)
9270 break;
9271
9272 int dist = abs(peakIndex - peakBinsPrevious[i]);
9273 if (dist > PSM_FFT_LEN/4)
9274 break;
9275
9276 if (i == 0)
9277 {
9278 previousPeak = i;
9279 delta = dist;
9280 }
9281 else if (dist < delta)
9282 {
9283 previousPeak = i;
9284 delta = dist;
9285 }
9286 }
9287
9288 return previousPeak;
9289 }
9290
9293 {
9294 // --- FIND PEAKS --- //
9295 //
9296 // --- find local maxima in 4-sample window
9297 double localWindow[4] = { 0.0, 0.0, 0.0, 0.0 };
9298 int m = 0;
9299 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9300 {
9301 if (i == 0)
9302 {
9303 localWindow[0] = 0.0;
9304 localWindow[1] = 0.0;
9305 localWindow[2] = binData[i + 1].magnitude;
9306 localWindow[3] = binData[i + 2].magnitude;
9307 }
9308 else if (i == 1)
9309 {
9310 localWindow[0] = 0.0;
9311 localWindow[1] = binData[i - 1].magnitude;
9312 localWindow[2] = binData[i + 1].magnitude;
9313 localWindow[3] = binData[i + 2].magnitude;
9314 }
9315 else if (i == PSM_FFT_LEN - 1)
9316 {
9317 localWindow[0] = binData[i - 2].magnitude;
9318 localWindow[1] = binData[i - 1].magnitude;
9319 localWindow[2] = 0.0;
9320 localWindow[3] = 0.0;
9321 }
9322 else if (i == PSM_FFT_LEN - 2)
9323 {
9324 localWindow[0] = binData[i - 2].magnitude;
9325 localWindow[1] = binData[i - 1].magnitude;
9326 localWindow[2] = binData[i + 1].magnitude;
9327 localWindow[3] = 0.0;
9328 }
9329 else
9330 {
9331 localWindow[0] = binData[i - 2].magnitude;
9332 localWindow[1] = binData[i - 1].magnitude;
9333 localWindow[2] = binData[i + 1].magnitude;
9334 localWindow[3] = binData[i + 2].magnitude;
9335 }
9336
9337 // --- found peak bin!
9338 if (binData[i].magnitude > 0.00001 &&
9339 binData[i].magnitude > localWindow[0]
9340 && binData[i].magnitude > localWindow[1]
9341 && binData[i].magnitude > localWindow[2]
9342 && binData[i].magnitude > localWindow[3])
9343 {
9344 binData[i].isPeak = true;
9345 peakBins[m++] = i;
9346
9347 // --- for peak bins, assume that it is part of a previous, moving peak
9350 else
9351 binData[i].previousPeakBin = -1;
9352 }
9353 }
9354
9355 // --- assign peak bosses
9356 if (m > 0)
9357 {
9358 int n = 0;
9359 int bossPeakBin = peakBins[n];
9360 double nextPeak = peakBins[++n];
9361 int midBoundary = (nextPeak - (double)bossPeakBin) / 2.0 + bossPeakBin;
9362
9363 if (nextPeak >= 0)
9364 {
9365 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9366 {
9367 if (i <= bossPeakBin)
9368 {
9369 binData[i].localPeakBin = bossPeakBin;
9370 }
9371 else if (i < midBoundary)
9372 {
9373 binData[i].localPeakBin = bossPeakBin;
9374 }
9375 else // > boundary, calc next set
9376 {
9377 bossPeakBin = nextPeak;
9378 nextPeak = peakBins[++n];
9379 if (nextPeak > bossPeakBin)
9380 midBoundary = (nextPeak - (double)bossPeakBin) / 2.0 + bossPeakBin;
9381 else // nextPeak == -1
9382 midBoundary = PSM_FFT_LEN;
9383
9384 binData[i].localPeakBin = bossPeakBin;
9385 }
9386 }
9387 }
9388 }
9389 }
9390
9396 virtual double processAudioSample(double input)
9397 {
9398 bool fftReady = false;
9399 double output = 0.0;
9400
9401 // --- normal processing
9402 output = vocoder.processAudioSample(input, fftReady);
9403
9404 // --- if FFT is here, GO!
9405 if (fftReady)
9406 {
9407 // --- get the FFT data
9408 fftw_complex* fftData = vocoder.getFFTData();
9409
9411 {
9412 // --- get the magnitudes for searching
9413 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9414 {
9415 binData[i].reset();
9416 peakBins[i] = -1;
9417
9418 // --- store mag and phase
9419 binData[i].magnitude = getMagnitude(fftData[i][0], fftData[i][1]);
9420 binData[i].phi = getPhase(fftData[i][0], fftData[i][1]);
9421 }
9422
9424
9425 // --- each bin data should now know its local boss-peak
9426 //
9427 // --- now propagate phases accordingly
9428 //
9429 // FIRST: set PSI angles of bosses
9430 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9431 {
9432 double mag_k = binData[i].magnitude;
9433 double phi_k = binData[i].phi;
9434
9435 // --- horizontal phase propagation
9436 //
9437 // --- omega_k = bin frequency(k)
9438 double omega_k = kTwoPi*i / PSM_FFT_LEN;
9439
9440 // --- phase deviation is actual - expected phase
9441 // = phi_k -(phi(last frame) + wk*ha
9442 double phaseDev = phi_k - phi[i] - omega_k*ha;
9443
9444 // --- unwrapped phase increment
9445 double deltaPhi = omega_k*ha + principalArg(phaseDev);
9446
9447 // --- save for next frame
9448 phi[i] = phi_k;
9449
9450 // --- if peak, assume it could have hopped from a different bin
9451 if (binData[i].isPeak)
9452 {
9453 // --- calculate new phase based on stretch factor; save phase for next time
9454 if(binData[i].previousPeakBin < 0)
9455 psi[i] = principalArg(psi[i] + deltaPhi * alphaStretchRatio);
9456 else
9457 psi[i] = principalArg(psi[binDataPrevious[i].previousPeakBin] + deltaPhi * alphaStretchRatio);
9458 }
9459
9460 // --- save peak PSI (new angle)
9461 binData[i].psi = psi[i];
9462
9463 // --- for IFFT
9465 }
9466
9467 // --- now set non-peaks
9468 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9469 {
9470 if (!binData[i].isPeak)
9471 {
9472 int myPeakBin = binData[i].localPeakBin;
9473
9474 double PSI_kp = binData[myPeakBin].psi;
9475 double phi_kp = binData[myPeakBin].phi;
9476
9477 // --- save for next frame
9478 // phi[i] = binData[myPeakBin].phi;
9479
9480 // --- calculate new phase, locked to boss peak
9481 psi[i] = principalArg(PSI_kp - phi_kp - binData[i].phi);
9482 binData[i].updatedPhase = psi[i];// principalArg(PSI_kp - phi_kp - binData[i].phi);
9483 }
9484 }
9485
9486 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9487 {
9488 double mag_k = binData[i].magnitude;
9489
9490 // --- convert back
9491 fftData[i][0] = mag_k*cos(binData[i].updatedPhase);
9492 fftData[i][1] = mag_k*sin(binData[i].updatedPhase);
9493
9494 // --- save for next frame
9495 binDataPrevious[i] = binData[i];
9496 peakBinsPrevious[i] = peakBins[i];
9497
9498 }
9499 }// end if peak locking
9500
9501 else // ---> old school
9502 {
9503 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9504 {
9505 double mag_k = getMagnitude(fftData[i][0], fftData[i][1]);
9506 double phi_k = getPhase(fftData[i][0], fftData[i][1]);
9507
9508 // --- horizontal phase propagation
9509 //
9510 // --- omega_k = bin frequency(k)
9511 double omega_k = kTwoPi*i / PSM_FFT_LEN;
9512
9513 // --- phase deviation is actual - expected phase
9514 // = phi_k -(phi(last frame) + wk*ha
9515 double phaseDev = phi_k - phi[i] - omega_k*ha;
9516
9517 // --- unwrapped phase increment
9518 double deltaPhi = omega_k*ha + principalArg(phaseDev);
9519
9520 // --- save for next frame
9521 phi[i] = phi_k;
9522
9523 // --- calculate new phase based on stretch factor; save phase for next time
9524 psi[i] = principalArg(psi[i] + deltaPhi * alphaStretchRatio);
9525
9526 // --- convert back
9527 fftData[i][0] = mag_k*cos(psi[i]);
9528 fftData[i][1] = mag_k*sin(psi[i]);
9529 }
9530 }
9531
9532
9533 // --- manually so the IFFT (OPTIONAL)
9535
9536 // --- can get the iFFT buffers
9537 fftw_complex* inv_fftData = vocoder.getIFFTData();
9538
9539 // --- make copy (can speed this up)
9540 double ifft[PSM_FFT_LEN] = { 0.0 };
9541 for (uint32_t i = 0; i < PSM_FFT_LEN; i++)
9542 ifft[i] = inv_fftData[i][0];
9543
9544 // --- resample the audio as if it were stretched
9545 resample(&ifft[0], outputBuff, PSM_FFT_LEN, outputBufferLength, interpolation::kLinear, windowCorrection, windowBuff);
9546
9547 // --- overlap-add the interpolated buffer to complete the operation
9549 }
9550
9551 return output;
9552 }
9553
9559 {
9560 return parameters;
9561 }
9562
9568 {
9570 {
9572 }
9573
9574 // --- save
9575 parameters = params;
9576 }
9577
9578protected:
9581 double alphaStretchRatio = 1.0;
9582
9583 // --- FFT is 4096 with 75% overlap
9584 const double hs = PSM_FFT_LEN / 4;
9585 double ha = PSM_FFT_LEN / 4;
9586 double phi[PSM_FFT_LEN] = { 0.0 };
9587 double psi[PSM_FFT_LEN] = { 0.0 };
9588
9589 // --- for peak-locking
9590 BinData binData[PSM_FFT_LEN];
9592
9593 int peakBins[PSM_FFT_LEN] = { -1 };
9594 int peakBinsPrevious[PSM_FFT_LEN] = { -1 };
9595
9596 double* windowBuff = nullptr;
9597 double* outputBuff = nullptr;
9598 double windowCorrection = 0.0;
9599 unsigned int outputBufferLength = 0;
9600};
9601
9602// --- sample rate conversion
9603//
9604// --- supported conversion ratios - you can EASILY add more to this
9618enum class rateConversionRatio { k2x, k4x };
9619const unsigned int maxSamplingRatio = 4;
9620
9630inline unsigned int countForRatio(rateConversionRatio ratio)
9631{
9632 if (ratio == rateConversionRatio::k2x)
9633 return 2;
9634 else if (ratio == rateConversionRatio::k4x || ratio == rateConversionRatio::k4x)
9635 return 4;
9636
9637 return 0;
9638}
9639
9640// --- get table pointer for built-in anti-aliasing LPFs
9652inline double* getFilterIRTable(unsigned int FIRLength, rateConversionRatio ratio, unsigned int sampleRate)
9653{
9654 // --- we only have built in filters for 44.1 and 48 kHz
9655 if (sampleRate != 44100 && sampleRate != 48000) return nullptr;
9656
9657 // --- choose 2xtable
9658 if (ratio == rateConversionRatio::k2x)
9659 {
9660 if (sampleRate == 44100)
9661 {
9662 if (FIRLength == 128)
9663 return &LPF128_882[0];
9664 else if (FIRLength == 256)
9665 return &LPF256_882[0];
9666 else if (FIRLength == 512)
9667 return &LPF512_882[0];
9668 else if (FIRLength == 1024)
9669 return &LPF1024_882[0];
9670 }
9671 if (sampleRate == 48000)
9672 {
9673 if (FIRLength == 128)
9674 return &LPF128_96[0];
9675 else if (FIRLength == 256)
9676 return &LPF256_96[0];
9677 else if (FIRLength == 512)
9678 return &LPF512_96[0];
9679 else if (FIRLength == 1024)
9680 return &LPF1024_96[0];
9681 }
9682 }
9683
9684 // --- choose 4xtable
9685 if (ratio == rateConversionRatio::k4x)
9686 {
9687 if (sampleRate == 44100)
9688 {
9689 if (FIRLength == 128)
9690 return &LPF128_1764[0];
9691 else if (FIRLength == 256)
9692 return &LPF256_1764[0];
9693 else if (FIRLength == 512)
9694 return &LPF512_1764[0];
9695 else if (FIRLength == 1024)
9696 return &LPF1024_1764[0];
9697 }
9698 if (sampleRate == 48000)
9699 {
9700 if (FIRLength == 128)
9701 return &LPF128_192[0];
9702 else if (FIRLength == 256)
9703 return &LPF256_192[0];
9704 else if (FIRLength == 512)
9705 return &LPF512_192[0];
9706 else if (FIRLength == 1024)
9707 return &LPF1024_192[0];
9708 }
9709 }
9710 return nullptr;
9711}
9712
9713// --- get table pointer for built-in anti-aliasing LPFs
9725inline double** decomposeFilter(double* filterIR, unsigned int FIRLength, unsigned int ratio)
9726{
9727 unsigned int subBandLength = FIRLength / ratio;
9728 double ** polyFilterSet = new double*[ratio];
9729 for (unsigned int i = 0; i < ratio; i++)
9730 {
9731 double* polyFilter = new double[subBandLength];
9732 polyFilterSet[i] = polyFilter;
9733 }
9734
9735 int m = 0;
9736 for (uint32_t i = 0; i < subBandLength; i++)
9737 {
9738 for (int j = ratio - 1; j >= 0; j--)
9739 {
9740 double* polyFilter = polyFilterSet[j];
9741 polyFilter[i] = filterIR[m++];
9742 }
9743 }
9744
9745 return polyFilterSet;
9746}
9747
9760{
9762 double audioData[maxSamplingRatio] = { 0.0, 0.0, 0.0, 0.0 };
9763 unsigned int count = maxSamplingRatio;
9764};
9765
9766
9785{
9786public:
9787 Interpolator() { } /* C-TOR */
9788 ~Interpolator() { } /* D-TOR */
9789
9797 inline void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase = true)
9798 {
9799 polyphase = _polyphase;
9800 sampleRate = _sampleRate;
9801 FIRLength = _FIRLength;
9802 ratio = _ratio;
9803 unsigned int count = countForRatio(ratio);
9804 unsigned int subBandLength = FIRLength / count;
9805
9806 // --- straight SRC, no polyphase
9808
9809 // --- set filterIR from built-in set - user can always override this!
9810 double* filterTable = getFilterIRTable(FIRLength, ratio, sampleRate);
9811 if (!filterTable) return;
9812 convolver.setFilterIR(filterTable);
9813
9814 if (!polyphase) return;
9815
9816 // --- decompose filter
9817 double** polyPhaseFilters = decomposeFilter(filterTable, FIRLength, count);
9818 if (!polyPhaseFilters)
9819 {
9820 polyphase = false;
9821 return;
9822 }
9823
9824 // --- set the individual polyphase filter IRs on the convolvers
9825 for (unsigned int i = 0; i < count; i++)
9826 {
9827 polyPhaseConvolvers[i].initialize(subBandLength);
9828 polyPhaseConvolvers[i].setFilterIR(polyPhaseFilters[i]);
9829 delete[] polyPhaseFilters[i];
9830 }
9831
9832 delete[] polyPhaseFilters;
9833 }
9834
9837 {
9838 unsigned int count = countForRatio(ratio);
9839
9840 // --- setup output
9841 InterpolatorOutput output;
9842 output.count = count;
9843
9844 // --- interpolators need the amp correction
9845 double ampCorrection = double(count);
9846
9847 // --- polyphase uses "backwards" indexing for interpolator; see book
9848 int m = count-1;
9849 for (unsigned int i = 0; i < count; i++)
9850 {
9851 if (!polyphase)
9852 output.audioData[i] = i == 0 ? ampCorrection*convolver.processAudioSample(xn) : ampCorrection*convolver.processAudioSample(0.0);
9853 else
9854 output.audioData[i] = ampCorrection*polyPhaseConvolvers[m--].processAudioSample(xn);
9855 }
9856 return output;
9857 }
9858
9859protected:
9860 // --- for straight, non-polyphase
9862
9863 // --- we save these for future expansion, currently only sparsely used
9864 unsigned int sampleRate = 44100;
9865 unsigned int FIRLength = 256;
9866 rateConversionRatio ratio = rateConversionRatio::k2x;
9867
9868 // --- polyphase: 4x is max right now
9869 bool polyphase = true;
9871};
9872
9885{
9886 DecimatorInput() {}
9887 double audioData[maxSamplingRatio] = { 0.0, 0.0, 0.0, 0.0 };
9888 unsigned int count = maxSamplingRatio;
9889};
9890
9910{
9911public:
9912 Decimator() { } /* C-TOR */
9913 ~Decimator() { } /* D-TOR */
9914
9922 inline void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase = true)
9923 {
9924 polyphase = _polyphase;
9925 sampleRate = _sampleRate;
9926 FIRLength = _FIRLength;
9927 ratio = _ratio;
9928 unsigned int count = countForRatio(ratio);
9929 unsigned int subBandLength = FIRLength / count;
9930
9931 // --- straight SRC, no polyphase
9933
9934 // --- set filterIR from built-in set - user can always override this!
9935 double* filterTable = getFilterIRTable(FIRLength, ratio, sampleRate);
9936 if (!filterTable) return;
9937 convolver.setFilterIR(filterTable);
9938
9939 if (!polyphase) return;
9940
9941 // --- decompose filter
9942 double** polyPhaseFilters = decomposeFilter(filterTable, FIRLength, count);
9943 if (!polyPhaseFilters)
9944 {
9945 polyphase = false;
9946 return;
9947 }
9948
9949 // --- set the individual polyphase filter IRs on the convolvers
9950 for (unsigned int i = 0; i < count; i++)
9951 {
9952 polyPhaseConvolvers[i].initialize(subBandLength);
9953 polyPhaseConvolvers[i].setFilterIR(polyPhaseFilters[i]);
9954 delete[] polyPhaseFilters[i];
9955 }
9956
9957 delete[] polyPhaseFilters;
9958 }
9959
9961 inline double decimateAudio(DecimatorInput data)
9962 {
9963 unsigned int count = countForRatio(ratio);
9964
9965 // --- setup output
9966 double output = 0.0;
9967
9968 // --- polyphase uses "forwards" indexing for decimator; see book
9969 for (unsigned int i = 0; i < count; i++)
9970 {
9971 if (!polyphase) // overwrites output; only the last output is saved
9972 output = convolver.processAudioSample(data.audioData[i]);
9973 else
9974 output += polyPhaseConvolvers[i].processAudioSample(data.audioData[i]);
9975 }
9976 return output;
9977 }
9978
9979protected:
9980 // --- for straight, non-polyphase
9982
9983 // --- we save these for future expansion, currently only sparsely used
9984 unsigned int sampleRate = 44100;
9985 unsigned int FIRLength = 256;
9986 rateConversionRatio ratio = rateConversionRatio::k2x;
9987
9988 // --- polyphase: 4x is max right now
9989 bool polyphase = true;
9991};
9992
9993#endif
The AnalogFIRFilter object implements a somewhat silly algorithm that implaments an analog magnitude ...
Definition: fxobjects.h:2547
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2571
AnalogFIRFilterParameters getParameters()
Definition: fxobjects.h:2584
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2578
void setParameters(AnalogFIRFilterParameters _parameters)
Definition: fxobjects.h:2590
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2554
The AudioDelay object implements a stereo audio delay with multiple delay algorithms.
Definition: fxobjects.h:2723
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2752
void createDelayBuffers(double _sampleRate, double _bufferLength_mSec)
Definition: fxobjects.h:2899
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:2773
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2770
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2730
AudioDelayParameters getParameters()
Definition: fxobjects.h:2854
void setParameters(AudioDelayParameters _parameters)
Definition: fxobjects.h:2860
The AudioDetector object implements the audio detector defined in the book source below....
Definition: fxobjects.h:1832
AudioDetectorParameters audioDetectorParameters
parameters for object
Definition: fxobjects.h:1941
double sampleRate
stored sample rate
Definition: fxobjects.h:1944
double releaseTime
release time coefficient
Definition: fxobjects.h:1943
void setParameters(const AudioDetectorParameters &parameters)
Definition: fxobjects.h:1917
void setAttackTime(double attack_in_ms, bool forceCalc=false)
sets the new attack time and re-calculates the time constant
Definition: fxobjects.cpp:958
double lastEnvelope
output register
Definition: fxobjects.h:1945
double attackTime
attack time coefficient
Definition: fxobjects.h:1942
virtual double processAudioSample(double xn)
Definition: fxobjects.h:1854
AudioDetectorParameters getParameters()
Definition: fxobjects.h:1908
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1847
void setReleaseTime(double release_in_ms, bool forceCalc=false)
sets the new release time and re-calculates the time constant
Definition: fxobjects.cpp:974
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1839
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1928
The AudioFilter object implements all filters in Designing Audio Effects Plugins in C++ 2nd Ed....
Definition: fxobjects.h:1521
double getG_value()
Definition: fxobjects.h:1584
double coeffArray[numCoeffs]
our local copy of biquad coeffs
Definition: fxobjects.h:1594
double sampleRate
current sample rate
Definition: fxobjects.h:1598
virtual double processAudioSample(double xn)
process one sample through the audio filter
Definition: fxobjects.cpp:944
AudioFilterParameters audioFilterParameters
parameters
Definition: fxobjects.h:1597
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1528
AudioFilterParameters getParameters()
Definition: fxobjects.h:1559
double getS_value()
Definition: fxobjects.h:1587
void setParameters(const AudioFilterParameters &parameters)
Definition: fxobjects.h:1562
bool calculateFilterCoeffs()
Definition: fxobjects.cpp:153
Biquad biquad
the biquad object
Definition: fxobjects.h:1591
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1552
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1542
The Biquad object implements a first or second order H(z) transfer function using one of four standar...
Definition: fxobjects.h:1370
void setCoefficients(double *coeffs)
Definition: fxobjects.h:1408
void setParameters(const BiquadParameters &_parameters)
Definition: fxobjects.h:1404
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1378
double * getCoefficients()
Definition: fxobjects.h:1414
BiquadParameters getParameters()
Definition: fxobjects.h:1398
BiquadParameters parameters
Definition: fxobjects.h:1441
double getG_value()
Definition: fxobjects.h:1428
double * getStateArray()
Definition: fxobjects.h:1421
double getS_value()
returns the storage component S(n) for delay-free loop solutions
Definition: fxobjects.cpp:32
virtual double processAudioSample(double xn)
process one sample through the biquad
Definition: fxobjects.cpp:67
double storageComponent
Definition: fxobjects.h:1444
double coeffArray[numCoeffs]
Definition: fxobjects.h:1435
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1385
double stateArray[numStates]
Definition: fxobjects.h:1438
The BitCrusher object implements a quantizing bitcrusher algorithm.
Definition: fxobjects.h:5954
double QL
the quantization level
Definition: fxobjects.h:5996
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5982
BitCrusherParameters getParameters()
Definition: fxobjects.h:5966
BitCrusherParameters parameters
object parameters
Definition: fxobjects.h:5995
void setParameters(const BitCrusherParameters &params)
Definition: fxobjects.h:5972
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5989
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5960
The CircularBuffer object implements a simple circular buffer. It uses a wrap mask to wrap the read o...
Definition: fxobjects.h:2295
void flushBuffer()
Definition: fxobjects.h:2301
T readBuffer(int delayInSamples)
Definition: fxobjects.h:2342
void writeBuffer(T input)
Definition: fxobjects.h:2332
void createCircularBufferPowerOfTwo(unsigned int _bufferLengthPowerOfTwo)
Definition: fxobjects.h:2313
void createCircularBuffer(unsigned int _bufferLength)
Definition: fxobjects.h:2305
T readBuffer(double delayInFractionalSamples)
Definition: fxobjects.h:2357
void setInterpolate(bool b)
Definition: fxobjects.h:2378
The ClassATubePre object implements a simple cascade of four (4) triode tube models.
Definition: fxobjects.h:5809
ClassATubePreParameters parameters
object parameters
Definition: fxobjects.h:5899
double outputLevel
output level (not in dB)
Definition: fxobjects.h:5904
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5885
ClassATubePreParameters getParameters()
Definition: fxobjects.h:5843
void setParameters(const ClassATubePreParameters &params)
Definition: fxobjects.h:5849
TwoBandShelvingFilter shelvingFilter
shelving filters
Definition: fxobjects.h:5901
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5878
TriodeClassA triodes[NUM_TUBES]
array of triode tube objects
Definition: fxobjects.h:5900
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5815
double inputLevel
input level (not in dB)
Definition: fxobjects.h:5903
The CombFilter object implements a comb filter with optional LPF in feedback loop....
Definition: fxobjects.h:4036
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4085
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4059
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4043
CombFilterParameters getParameters()
Definition: fxobjects.h:4091
void setParameters(const CombFilterParameters &params)
Definition: fxobjects.h:4100
void createDelayBuffer(double _sampleRate, double delay_mSec)
Definition: fxobjects.h:4120
The DFOscillator object implements generates a very pure sinusoidal oscillator by placing poles direc...
Definition: fxobjects.h:3156
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3162
OscillatorParameters parameters
object parameters
Definition: fxobjects.h:3247
OscillatorParameters getParameters()
Definition: fxobjects.h:3174
double stateArray[numDFOStates]
array of state registers
Definition: fxobjects.h:3250
double coeffArray[numDFOCoeffs]
array of coefficients
Definition: fxobjects.h:3251
virtual const SignalGenData renderAudioOutput()
Definition: fxobjects.h:3193
void updateDFO()
Definition: fxobjects.h:3210
void setParameters(const OscillatorParameters &params)
Definition: fxobjects.h:3183
double sampleRate
sample rate
Definition: fxobjects.h:3254
The Decimator object implements a sample rate decimator. Ana array of M input samples is decimated to...
Definition: fxobjects.h:9910
unsigned int FIRLength
FIR length.
Definition: fxobjects.h:9985
FastConvolver convolver
fast convolver
Definition: fxobjects.h:9981
bool polyphase
enable polyphase decomposition
Definition: fxobjects.h:9989
rateConversionRatio ratio
conversion ration
Definition: fxobjects.h:9986
FastConvolver polyPhaseConvolvers[maxSamplingRatio]
a set of sub-band convolvers for polyphase operation
Definition: fxobjects.h:9990
unsigned int sampleRate
sample rate
Definition: fxobjects.h:9984
void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase=true)
Definition: fxobjects.h:9922
double decimateAudio(DecimatorInput data)
Definition: fxobjects.h:9961
The DelayAPF object implements a delaying APF with optional LPF and optional modulated delay time wit...
Definition: fxobjects.h:4206
double lpf_state
LPF state register (z^-1)
Definition: fxobjects.h:4335
DelayAPFParameters delayAPFParameters
obeject parameters
Definition: fxobjects.h:4324
DelayAPFParameters getParameters()
Definition: fxobjects.h:4293
SimpleDelay delay
delay
Definition: fxobjects.h:4329
LFO modLFO
LFO.
Definition: fxobjects.h:4332
double sampleRate
current sample rate
Definition: fxobjects.h:4325
void createDelayBuffer(double _sampleRate, double delay_mSec)
Definition: fxobjects.h:4313
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4232
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4213
double bufferLength_mSec
total buffer length in mSec
Definition: fxobjects.h:4326
void setParameters(const DelayAPFParameters &params)
Definition: fxobjects.h:4302
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4287
The DynamicsProcessor object implements a dynamics processor suite: compressor, limiter,...
Definition: fxobjects.h:2046
virtual void enableAuxInput(bool enableAuxInput)
Definition: fxobjects.h:2068
DynamicsProcessorParameters getParameters()
Definition: fxobjects.h:2081
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2065
double computeGain(double detect_dB)
Definition: fxobjects.h:2136
double sidechainInputSample
storage for sidechain sample
Definition: fxobjects.h:2133
AudioDetector detector
the sidechain audio detector
Definition: fxobjects.h:2130
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2107
DynamicsProcessorParameters parameters
object parameters
Definition: fxobjects.h:2129
virtual double processAuxInputAudioSample(double xn)
Definition: fxobjects.h:2071
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2053
void setParameters(const DynamicsProcessorParameters &_parameters)
Definition: fxobjects.h:2087
The EnvelopeFollower object implements a traditional envelope follower effect modulating a LPR fc val...
Definition: fxobjects.h:5448
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5473
EnvelopeFollowerParameters parameters
object parameters
Definition: fxobjects.h:5555
void setParameters(const EnvelopeFollowerParameters &params)
Definition: fxobjects.h:5490
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5521
EnvelopeFollowerParameters getParameters()
Definition: fxobjects.h:5484
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5514
AudioDetector detector
detector to track input signal
Definition: fxobjects.h:5559
ZVAFilter filter
filter to modulate
Definition: fxobjects.h:5558
The FastConvolver provides a fast convolver - the user supplies the filter IR and the object snapshot...
Definition: fxobjects.h:8943
FastFFT filterFastFFT
FastFFT object.
Definition: fxobjects.h:9072
unsigned int getFilterIRLength()
Definition: fxobjects.h:9068
unsigned int inputCount
input sample counter
Definition: fxobjects.h:9075
void setFilterIR(double *irBuffer)
Definition: fxobjects.h:8989
unsigned int filterImpulseLength
IR length.
Definition: fxobjects.h:9076
void initialize(unsigned int _filterImpulseLength)
Definition: fxobjects.h:8960
double * filterIR
filter IR
Definition: fxobjects.h:9074
double processAudioSample(double input)
Definition: fxobjects.h:9019
unsigned int getFrameLength()
Definition: fxobjects.h:9065
PhaseVocoder vocoder
vocoder object
Definition: fxobjects.h:9071
fftw_complex * filterFFT
filterFFT output arrays
Definition: fxobjects.h:9073
The FastFFT provides a simple wrapper for the FFTW FFT operation - it is ultra-thin and simple to use...
Definition: fxobjects.h:8765
fftw_complex * fft_input
array for FFT input
Definition: fxobjects.h:8790
void initialize(unsigned int _frameLength, windowType _window)
initialize the Fast FFT object for operation
Definition: fxobjects.cpp:1082
fftw_plan plan_forward
FFTW plan for FFT.
Definition: fxobjects.h:8794
fftw_complex * ifft_input
array for IFFT input
Definition: fxobjects.h:8792
unsigned int getFrameLength()
Definition: fxobjects.h:8786
windowType window
window type
Definition: fxobjects.h:8799
double * windowBuffer
buffer for window (naked)
Definition: fxobjects.h:8797
double windowGainCorrection
window gain correction
Definition: fxobjects.h:8798
fftw_complex * ifft_result
array for IFFT output
Definition: fxobjects.h:8793
void destroyFFTW()
destroys the FFTW arrays and plans.
Definition: fxobjects.cpp:1051
fftw_complex * fft_result
array for FFT output
Definition: fxobjects.h:8791
fftw_complex * doInverseFFT(double *inputReal, double *inputImag)
perform the IFFT operation
Definition: fxobjects.cpp:1204
unsigned int frameLength
current FFT length
Definition: fxobjects.h:8800
fftw_complex * doFFT(double *inputReal, double *inputImag=nullptr)
perform the FFT operation
Definition: fxobjects.cpp:1176
fftw_plan plan_backward
FFTW plan for IFFT.
Definition: fxobjects.h:8795
Use this interface for objects that render an output without an input, such as oscillators....
Definition: fxobjects.h:1240
virtual bool reset(double _sampleRate)=0
virtual const SignalGenData renderAudioOutput()=0
Use this interface for objects that process audio input samples to produce audio output samples....
Definition: fxobjects.h:1160
virtual bool reset(double _sampleRate)=0
virtual void enableAuxInput(bool enableAuxInput)
Definition: fxobjects.h:1179
virtual double processAudioSample(double xn)=0
virtual double processAuxInputAudioSample(double xn)
Definition: fxobjects.h:1183
virtual bool canProcessAudioFrame()=0
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:1193
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1176
Use this interface for objects in the WDF Ladder Filter library; see book for more information.
Definition: fxobjects.h:6016
virtual void updateComponentResistance()
Definition: fxobjects.h:6059
virtual void setInput3(double _in3)=0
virtual void setInput(double _in)
Definition: fxobjects.h:6025
virtual double getOutput()
Definition: fxobjects.h:6028
virtual void setInput2(double _in2)=0
virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
Definition: fxobjects.h:6065
virtual double getOutput2()=0
virtual void initializeAdaptorChain()
Definition: fxobjects.h:6022
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6062
virtual double getComponentValue()
Definition: fxobjects.h:6074
virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
Definition: fxobjects.h:6068
virtual double getOutput3()=0
virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
Definition: fxobjects.h:6071
virtual double getComponentResistance()
Definition: fxobjects.h:6053
virtual void initialize(double _R1)
Definition: fxobjects.h:6019
virtual double getOutput1()=0
virtual void setInput1(double _in1)=0
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6050
virtual double getComponentConductance()
Definition: fxobjects.h:6056
The ImpulseConvolver object implements a linear conovlver. NOTE: compile in Release mode or you may e...
Definition: fxobjects.h:2408
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2416
void init(unsigned int lengthPowerOfTwo)
Definition: fxobjects.h:2456
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2428
LinearBuffer< double > irBuffer
linear buffer for the IR
Definition: fxobjects.h:2485
void setImpulseResponse(double *irArray, unsigned int lengthPowerOfTwo)
Definition: fxobjects.h:2465
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2453
unsigned int length
length of convolution (buffer)
Definition: fxobjects.h:2487
CircularBuffer< double > signalBuffer
circulat buffer for the signal
Definition: fxobjects.h:2484
The Interpolator object implements a sample rate interpolator. One input sample yields N output sampl...
Definition: fxobjects.h:9785
rateConversionRatio ratio
conversion ration
Definition: fxobjects.h:9866
InterpolatorOutput interpolateAudio(double xn)
Definition: fxobjects.h:9836
unsigned int sampleRate
sample rate
Definition: fxobjects.h:9864
void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase=true)
Definition: fxobjects.h:9797
bool polyphase
enable polyphase decomposition
Definition: fxobjects.h:9869
unsigned int FIRLength
FIR length.
Definition: fxobjects.h:9865
FastConvolver convolver
the convolver
Definition: fxobjects.h:9861
FastConvolver polyPhaseConvolvers[maxSamplingRatio]
a set of sub-band convolvers for polyphase operation
Definition: fxobjects.h:9870
The LFO object implements a mathematically perfect LFO generator for modulation uses only....
Definition: fxobjects.h:2996
virtual const SignalGenData renderAudioOutput()
generates the oscillator output for one sample interval; note that there are multiple outputs.
Definition: fxobjects.cpp:986
double phaseInc
phase inc = fo/fs
Definition: fxobjects.h:3045
bool checkAndWrapModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3049
OscillatorParameters lfoParameters
obejcgt parameters
Definition: fxobjects.h:3038
double sampleRate
sample rate
Definition: fxobjects.h:3041
double parabolicSine(double angle)
Definition: fxobjects.h:3098
OscillatorParameters getParameters()
Definition: fxobjects.h:3018
void setParameters(const OscillatorParameters &params)
Definition: fxobjects.h:3024
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3002
double modCounter
modulo counter [0.0, +1.0]
Definition: fxobjects.h:3044
void advanceModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3092
bool advanceAndCheckWrapModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3069
double modCounterQP
Quad Phase modulo counter [0.0, +1.0].
Definition: fxobjects.h:3046
The LRFilterBank object implements 2 Linkwitz-Riley Filters in a parallel filter bank to split the si...
Definition: fxobjects.h:1679
FilterBankOutput processFilterBank(double xn)
Definition: fxobjects.h:1717
LRFilterBankParameters parameters
parameters for the object
Definition: fxobjects.h:1764
virtual double processAudioSample(double xn)
Definition: fxobjects.h:1711
LRFilterBankParameters getParameters()
Definition: fxobjects.h:1735
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1696
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1704
AudioFilter hpFilter
high-band filter
Definition: fxobjects.h:1761
AudioFilter lpFilter
low-band filter
Definition: fxobjects.h:1760
void setParameters(const LRFilterBankParameters &_parameters)
Definition: fxobjects.h:1744
The LinearBuffer object implements a linear buffer of type T. It allows easy wrapping of a smart poin...
Definition: fxobjects.h:2233
void createLinearBuffer(unsigned int _bufferLength)
Definition: fxobjects.h:2243
void writeBuffer(unsigned int index, T input)
Definition: fxobjects.h:2256
void flushBuffer()
Definition: fxobjects.h:2239
T readBuffer(unsigned int index)
Definition: fxobjects.h:2265
The ModulatedDelay object implements the three basic algorithms: flanger, chorus, vibrato.
Definition: fxobjects.h:3326
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3363
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3334
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:3366
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3354
void setParameters(ModulatedDelayParameters _parameters)
Definition: fxobjects.h:3441
ModulatedDelayParameters getParameters()
Definition: fxobjects.h:3435
The NestedDelayAPF object implements a pair of nested Delaying APF structures. These are labled the o...
Definition: fxobjects.h:4407
NestedDelayAPFParameters getParameters()
Definition: fxobjects.h:4492
void setParameters(const NestedDelayAPFParameters &params)
Definition: fxobjects.h:4498
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4430
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4414
void createDelayBuffers(double _sampleRate, double delay_mSec, double nestedAPFDelay_mSec)
Definition: fxobjects.h:4524
The PSMVocoder object implements a phase vocoder pitch shifter. Phase locking and peak tracking are o...
Definition: fxobjects.h:9190
int findPreviousNearestPeak(int peakIndex)
Definition: fxobjects.h:9260
unsigned int outputBufferLength
lenght of resampled output array
Definition: fxobjects.h:9599
double ha
ha = N/4 — 75% overlap
Definition: fxobjects.h:9585
int peakBinsPrevious[PSM_FFT_LEN]
array of previous peak bin index values (-1 = not peak)
Definition: fxobjects.h:9594
const double hs
hs = N/4 — 75% overlap
Definition: fxobjects.h:9584
void findPeaksAndRegionsOfInfluence()
Definition: fxobjects.h:9292
BinData binDataPrevious[PSM_FFT_LEN]
array of BinData structures for previous FFT frame
Definition: fxobjects.h:9591
double alphaStretchRatio
alpha stretch ratio = hs/ha
Definition: fxobjects.h:9581
double windowCorrection
window correction value
Definition: fxobjects.h:9598
void setPitchShift(double semitones)
Definition: fxobjects.h:9225
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:9202
double * windowBuff
buffer for window
Definition: fxobjects.h:9596
double * outputBuff
buffer for resampled output
Definition: fxobjects.h:9597
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:9222
int peakBins[PSM_FFT_LEN]
array of current peak bin index values (-1 = not peak)
Definition: fxobjects.h:9593
PhaseVocoder vocoder
vocoder to perform PSM
Definition: fxobjects.h:9580
double phi[PSM_FFT_LEN]
array of phase values for classic algorithm
Definition: fxobjects.h:9586
void setParameters(const PSMVocoderParameters &params)
Definition: fxobjects.h:9567
BinData binData[PSM_FFT_LEN]
array of BinData structures for current FFT frame
Definition: fxobjects.h:9590
PSMVocoderParameters getParameters()
Definition: fxobjects.h:9558
double psi[PSM_FFT_LEN]
array of phase correction values for classic algorithm
Definition: fxobjects.h:9587
PSMVocoderParameters parameters
object parameters
Definition: fxobjects.h:9579
virtual double processAudioSample(double input)
Definition: fxobjects.h:9396
The PeakLimiter object implements a simple peak limiter; it is really a simplified and hard-wired ver...
Definition: fxobjects.h:5017
void setMakeUpGain_dB(double _makeUpGain_dB)
Definition: fxobjects.h:5093
void setThreshold_dB(double _threshold_dB)
Definition: fxobjects.h:5090
double computeGain(double detect_dB)
Definition: fxobjects.h:5053
AudioDetector detector
the detector object
Definition: fxobjects.h:5096
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5040
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5047
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5023
double makeUpGain_dB
stored makeup gain (dB)
Definition: fxobjects.h:5098
double threshold_dB
stored threshold (dB)
Definition: fxobjects.h:5097
The PhaseShifter object implements a six-stage phaser.
Definition: fxobjects.h:3559
AudioFilter apf[PHASER_STAGES]
six APF objects
Definition: fxobjects.h:3702
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3599
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3675
LFO lfo
the one and only LFO
Definition: fxobjects.h:3703
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3581
PhaseShifterParameters getParameters()
Definition: fxobjects.h:3681
PhaseShifterParameters parameters
the object parameters
Definition: fxobjects.h:3701
void setParameters(const PhaseShifterParameters &params)
Definition: fxobjects.h:3687
The PhaseVocoder provides a basic phase vocoder that is initialized to N = 4096 and 75% overlap; the ...
Definition: fxobjects.h:8824
double overlap
overlap as raw value (75% = 0.75)
Definition: fxobjects.h:8915
unsigned int hopSize
hop: ha = hs
Definition: fxobjects.h:8914
unsigned int outputReadIndex
circular buffer index: output read
Definition: fxobjects.h:8894
double windowHopCorrection
window correction including hop/overlap
Definition: fxobjects.h:8900
double getOverlap()
Definition: fxobjects.h:8868
unsigned int getFrameLength()
Definition: fxobjects.h:8862
unsigned int outputWriteIndex
circular buffer index: output write
Definition: fxobjects.h:8892
bool advanceAndCheckFFT()
advance the sample counter and check to see if we need to do the FFT.
Definition: fxobjects.cpp:1422
bool addZeroPad(unsigned int count)
zero pad the input timeline
Definition: fxobjects.cpp:1392
fftw_plan plan_forward
FFTW plan for FFT.
Definition: fxobjects.h:8880
double * inputBuffer
input timeline (x)
Definition: fxobjects.h:8887
bool needOverlapAdd
internal flag to signal overlap/add required
Definition: fxobjects.h:8904
fftw_complex * getFFTData()
Definition: fxobjects.h:8850
void setOverlapAddOnly(bool b)
Definition: fxobjects.h:8873
double * windowBuffer
array for window
Definition: fxobjects.h:8884
unsigned int fftCounter
FFT sample counter.
Definition: fxobjects.h:8911
unsigned int frameLength
current FFT length
Definition: fxobjects.h:8910
fftw_complex * fft_result
array for FFT output
Definition: fxobjects.h:8878
bool needInverseFFT
internal flag to signal IFFT required
Definition: fxobjects.h:8903
bool overlapAddOnly
flag for overlap-add-only algorithms
Definition: fxobjects.h:8919
double * outputBuffer
output timeline (y)
Definition: fxobjects.h:8888
windowType window
window type
Definition: fxobjects.h:8907
void doInverseFFT()
perform the inverse FFT on the processed data
Definition: fxobjects.cpp:1516
unsigned int wrapMask
input wrap mask
Definition: fxobjects.h:8895
fftw_complex * fft_input
array for FFT input
Definition: fxobjects.h:8877
unsigned int inputReadIndex
circular buffer index: input read
Definition: fxobjects.h:8893
fftw_complex * getIFFTData()
Definition: fxobjects.h:8853
unsigned int inputWriteIndex
circular buffer index: input write
Definition: fxobjects.h:8891
unsigned int wrapMaskOut
output wrap mask
Definition: fxobjects.h:8896
fftw_plan plan_backward
FFTW plan for IFFT.
Definition: fxobjects.h:8881
void destroyFFTW()
destroys the FFTW arrays and plans.
Definition: fxobjects.cpp:1225
fftw_complex * ifft_result
array for IFFT output
Definition: fxobjects.h:8879
void initialize(unsigned int _frameLength, unsigned int _hopSize, windowType _window)
initialize the Fast FFT object for operation
Definition: fxobjects.cpp:1251
void doOverlapAdd(double *outputData=nullptr, int length=0)
perform the overlap/add on the IFFT data
Definition: fxobjects.cpp:1535
double processAudioSample(double input, bool &fftReady)
process one input sample throug the vocoder to produce one output sample
Definition: fxobjects.cpp:1476
unsigned int getHopSize()
Definition: fxobjects.h:8865
The ReverbTank object implements the cyclic reverb tank in the FX book listed below.
Definition: fxobjects.h:4767
ReverbTankParameters getParameters()
Definition: fxobjects.h:4905
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4808
void setParameters(const ReverbTankParameters &params)
Definition: fxobjects.h:4911
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4801
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:4817
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4773
The SimpleDelay object implements a basic delay line without feedback.
Definition: fxobjects.h:3856
void createDelayBuffer(double _sampleRate, double _bufferLength_mSec)
Definition: fxobjects.h:3923
SimpleDelayParameters getParameters()
Definition: fxobjects.h:3883
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3863
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3920
double readDelayAtPercentage(double delayPercent)
Definition: fxobjects.h:3955
double readDelayAtTime_mSec(double _delay_mSec)
Definition: fxobjects.h:3945
void setParameters(const SimpleDelayParameters &params)
Definition: fxobjects.h:3892
void writeDelay(double xn)
Definition: fxobjects.h:3962
double readDelay()
Definition: fxobjects.h:3938
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3904
The SimpleLPF object implements a first order one-pole LPF using one coefficient "g" value.
Definition: fxobjects.h:3752
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3788
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3759
SimpleLPFParameters getParameters()
Definition: fxobjects.h:3769
void setParameters(const SimpleLPFParameters &params)
Definition: fxobjects.h:3778
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3797
The TriodeClassA object simulates a triode in class A configuration. This is a very simple and basic ...
Definition: fxobjects.h:5648
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5699
TriodeClassAParameters parameters
object parameters
Definition: fxobjects.h:5737
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5664
AudioFilter outputLSF
LSF to simulate shelf caused by cathode self-biasing cap.
Definition: fxobjects.h:5739
AudioFilter outputHPF
HPF to simulate output DC blocking cap.
Definition: fxobjects.h:5738
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5706
void setParameters(const TriodeClassAParameters &params)
Definition: fxobjects.h:5683
TriodeClassAParameters getParameters()
Definition: fxobjects.h:5677
The TwoBandShelvingFilter object implements two shelving filters in series in the standard "Bass and ...
Definition: fxobjects.h:4590
void setParameters(const TwoBandShelvingFilterParameters &params)
Definition: fxobjects.h:4643
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4606
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4614
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4621
TwoBandShelvingFilterParameters getParameters()
Definition: fxobjects.h:4634
The WDFBesselBSF3 object implements a 3rd order Bessel BSF NOTE: designed with Elsie www....
Definition: fxobjects.h:7979
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L3C3
adaptor for L3 and C3
Definition: fxobjects.h:8040
WdfParallelAdaptor parallelAdaptor_L2C2
adaptor for L2 and C2
Definition: fxobjects.h:8039
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8006
WdfSeriesAdaptor seriesAdaptor_L1C1
adaptor for L1 and C1
Definition: fxobjects.h:8038
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7999
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7985
void createWDF()
Definition: fxobjects.h:8016
The WDFButterLPF3 object implements a 3rd order Butterworth ladder filter. NOTE: designed with Elsie ...
Definition: fxobjects.h:7788
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7807
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7794
WdfSeriesAdaptor seriesAdaptor_L1
adaptor for L1
Definition: fxobjects.h:7849
void createWDF()
Definition: fxobjects.h:7824
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7814
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L2
adaptor for L2
Definition: fxobjects.h:7851
WdfParallelAdaptor parallelAdaptor_C1
adaptor for C1
Definition: fxobjects.h:7850
The WDFConstKBPF6 object implements a 6th order constant K BPF NOTE: designed with Elsie www....
Definition: fxobjects.h:8063
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_L6C6
adaptor for L6 and C6
Definition: fxobjects.h:8142
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8094
WdfSeriesAdaptor seriesAdaptor_L5C5
adaptor for L5 and C5
Definition: fxobjects.h:8141
WdfSeriesAdaptor seriesAdaptor_L3C3
adaptor for L3 and C3
Definition: fxobjects.h:8138
void createWDF()
Definition: fxobjects.h:8106
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8069
WdfParallelAdaptor parallelAdaptor_L2C2
adaptor for L2 and C2
Definition: fxobjects.h:8136
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8087
WdfSeriesAdaptor seriesAdaptor_L1C1
adaptor for L1 and C1
Definition: fxobjects.h:8135
WdfParallelAdaptor parallelAdaptor_L4C4
adaptor for L4 and C4
Definition: fxobjects.h:8139
The WDFIdealRLCBPF object implements an ideal RLC BPF using the WDF library.
Definition: fxobjects.h:8442
WdfSeriesAdaptor seriesAdaptor_LC
adaptor for LC
Definition: fxobjects.h:8539
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8468
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8448
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8510
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8461
WDFParameters getParameters()
Definition: fxobjects.h:8504
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_R
adaptor for R
Definition: fxobjects.h:8540
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8536
void createWDF()
Definition: fxobjects.h:8480
The WDFIdealRLCBSF object implements an ideal RLC BSF using the WDF library.
Definition: fxobjects.h:8564
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8583
WdfSeriesAdaptor seriesAdaptor_R
adaptor for series R
Definition: fxobjects.h:8661
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8590
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8658
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_LC
adaptor for parallel LC
Definition: fxobjects.h:8662
WDFParameters getParameters()
Definition: fxobjects.h:8626
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8632
void createWDF()
Definition: fxobjects.h:8602
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8570
double sampleRate
sample rate storage
Definition: fxobjects.h:8664
The WDFIdealRLCHPF object implements an ideal RLC HPF using the WDF library.
Definition: fxobjects.h:8320
void createWDF()
Definition: fxobjects.h:8358
WDFParameters getParameters()
Definition: fxobjects.h:8382
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8339
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8415
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8346
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8326
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_L
adaptor for L
Definition: fxobjects.h:8419
double sampleRate
sample rate storage
Definition: fxobjects.h:8421
WdfSeriesAdaptor seriesAdaptor_RC
adaptor for RC
Definition: fxobjects.h:8418
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8388
The WDFIdealRLCLPF object implements an ideal RLC LPF using the WDF library.
Definition: fxobjects.h:8198
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8292
WDFParameters getParameters()
Definition: fxobjects.h:8261
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8267
WdfSeriesAdaptor seriesAdaptor_RL
adaptor for series RL
Definition: fxobjects.h:8295
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8225
void createWDF()
Definition: fxobjects.h:8237
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_C
adaptopr for parallel C
Definition: fxobjects.h:8296
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8218
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8204
The WDFTunableButterLPF3 object implements a tunable 3rd order Butterworth ladder filter....
Definition: fxobjects.h:7874
bool useFrequencyWarping
flag for freq warping
Definition: fxobjects.h:7956
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L2
adaptor for L2
Definition: fxobjects.h:7950
void setFilterFc(double fc_Hz)
Definition: fxobjects.h:7933
double sampleRate
stored sample rate
Definition: fxobjects.h:7957
WdfSeriesAdaptor seriesAdaptor_L1
adaptor for L1
Definition: fxobjects.h:7948
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7894
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7901
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7880
WdfParallelAdaptor parallelAdaptor_C1
adaptor for C1
Definition: fxobjects.h:7949
void setUsePostWarping(bool b)
Definition: fxobjects.h:7930
void createWDF()
Definition: fxobjects.h:7911
The WdfAdaptorBase object acts as the base class for all WDF Adaptors; the static members allow for s...
Definition: fxobjects.h:7137
double terminalResistance
value of terminal (load) resistance
Definition: fxobjects.h:7309
double R1
input port resistance
Definition: fxobjects.h:7291
virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
Definition: fxobjects.h:7253
virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
Definition: fxobjects.h:7260
void setOpenTerminalResistance(bool _openTerminalResistance=true)
Definition: fxobjects.h:7146
virtual void reset(double _sampleRate)
Definition: fxobjects.h:7166
virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
Definition: fxobjects.h:7267
bool openTerminalResistance
flag for open circuit load
Definition: fxobjects.h:7310
IComponentAdaptor * port2CompAdaptor
componant or adaptor connected to port 2
Definition: fxobjects.h:7286
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:7246
IComponentAdaptor * getPort1_CompAdaptor()
Definition: fxobjects.h:7274
void setPort1_CompAdaptor(IComponentAdaptor *_port1CompAdaptor)
Definition: fxobjects.h:7157
double out1
stored port 1 output; not used in this implementation but may be required for extended versions
Definition: fxobjects.h:7304
double R3
component resistance
Definition: fxobjects.h:7293
IComponentAdaptor * getPort3_CompAdaptor()
Definition: fxobjects.h:7280
void setComponent(wdfComponent componentType, double value1=0.0, double value2=0.0)
Definition: fxobjects.h:7173
void setPort3_CompAdaptor(IComponentAdaptor *_port3CompAdaptor)
Definition: fxobjects.h:7163
double out2
stored port 2 output; it is y(n) for this library
Definition: fxobjects.h:7305
IComponentAdaptor * wdfComponent
WDF componant connected to port 3 (default operation)
Definition: fxobjects.h:7288
double in1
stored port 1 input; not used in this implementation but may be required for extended versions
Definition: fxobjects.h:7297
double in2
stored port 2 input; not used in this implementation but may be required for extended versions
Definition: fxobjects.h:7298
double sourceResistance
source impedance; OK for this to be set to 0.0 for Rs = 0
Definition: fxobjects.h:7313
void setSourceResistance(double _sourceResistance)
Definition: fxobjects.h:7154
double out3
stored port 3 output; not used in this implementation but may be required for extended versions
Definition: fxobjects.h:7306
static void connectAdaptors(WdfAdaptorBase *upstreamAdaptor, WdfAdaptorBase *downstreamAdaptor)
Definition: fxobjects.h:7233
IComponentAdaptor * port1CompAdaptor
componant or adaptor connected to port 1
Definition: fxobjects.h:7285
IComponentAdaptor * getPort2_CompAdaptor()
Definition: fxobjects.h:7277
void setPort2_CompAdaptor(IComponentAdaptor *_port2CompAdaptor)
Definition: fxobjects.h:7160
IComponentAdaptor * port3CompAdaptor
componant or adaptor connected to port 3
Definition: fxobjects.h:7287
double R2
output port resistance
Definition: fxobjects.h:7292
double in3
stored port 3 input; not used in this implementation but may be required for extended versions
Definition: fxobjects.h:7299
void setTerminalResistance(double _terminalResistance)
Definition: fxobjects.h:7143
virtual void initializeAdaptorChain()
Definition: fxobjects.h:7240
The WdfCapacitor object implements the reflection coefficient and signal flow through a WDF simulated...
Definition: fxobjects.h:6173
virtual double getComponentResistance()
Definition: fxobjects.h:6187
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6196
virtual double getOutput3()
Definition: fxobjects.h:6224
virtual void setInput1(double _in1)
Definition: fxobjects.h:6227
virtual void setInput(double in)
Definition: fxobjects.h:6212
virtual void setInput2(double _in2)
Definition: fxobjects.h:6230
virtual double getOutput()
Definition: fxobjects.h:6215
double componentResistance
simulated resistance
Definition: fxobjects.h:6238
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6237
double sampleRate
sample rate
Definition: fxobjects.h:6239
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6236
virtual double getOutput1()
Definition: fxobjects.h:6218
virtual double getComponentValue()
Definition: fxobjects.h:6193
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6209
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6180
virtual void updateComponentResistance()
Definition: fxobjects.h:6203
virtual double getComponentConductance()
Definition: fxobjects.h:6190
virtual void setInput3(double _in3)
Definition: fxobjects.h:6233
virtual double getOutput2()
Definition: fxobjects.h:6221
The WdfInductor object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6255
double sampleRate
sample rate
Definition: fxobjects.h:6318
virtual double getOutput1()
Definition: fxobjects.h:6297
virtual double getOutput()
Definition: fxobjects.h:6294
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6278
virtual double getComponentResistance()
Definition: fxobjects.h:6269
double componentResistance
simulated resistance
Definition: fxobjects.h:6317
virtual double getComponentValue()
Definition: fxobjects.h:6275
virtual void setInput2(double _in2)
Definition: fxobjects.h:6309
virtual void setInput3(double _in3)
Definition: fxobjects.h:6312
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6316
virtual double getOutput2()
Definition: fxobjects.h:6300
virtual double getComponentConductance()
Definition: fxobjects.h:6272
virtual void setInput(double in)
Definition: fxobjects.h:6291
virtual double getOutput3()
Definition: fxobjects.h:6303
virtual void setInput1(double _in1)
Definition: fxobjects.h:6306
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6262
virtual void updateComponentResistance()
Definition: fxobjects.h:6285
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6288
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6315
The WdfParallelAdaptor object implements the parallel reflection-free (non-terminated) adaptor.
Definition: fxobjects.h:7538
virtual double getOutput2()
Definition: fxobjects.h:7624
virtual double getOutput1()
Definition: fxobjects.h:7621
virtual double getOutput3()
Definition: fxobjects.h:7627
virtual double getR2()
Definition: fxobjects.h:7544
virtual void setInput1(double _in1)
Definition: fxobjects.h:7578
virtual void setInput2(double _in2)
Definition: fxobjects.h:7597
virtual void initialize(double _R1)
Definition: fxobjects.h:7556
virtual void setInput3(double _in3)
Definition: fxobjects.h:7618
The WdfParallelLC object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6456
virtual double getOutput1()
Definition: fxobjects.h:6532
double zRegister_L
storage register for L
Definition: fxobjects.h:6550
double componentValue_C
component value C
Definition: fxobjects.h:6554
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6558
virtual double getComponentValue_L()
Definition: fxobjects.h:6510
virtual void setInput3(double _in3)
Definition: fxobjects.h:6547
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6503
double RL
RL value.
Definition: fxobjects.h:6556
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6496
virtual void setInput1(double _in1)
Definition: fxobjects.h:6541
virtual void setInput(double in)
Definition: fxobjects.h:6519
double componentValue_L
component value L
Definition: fxobjects.h:6553
virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
Definition: fxobjects.h:6488
virtual double getOutput3()
Definition: fxobjects.h:6538
virtual double getOutput()
Definition: fxobjects.h:6529
double zRegister_C
storage register for C
Definition: fxobjects.h:6551
virtual void updateComponentResistance()
Definition: fxobjects.h:6480
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6467
virtual void setInput2(double _in2)
Definition: fxobjects.h:6544
virtual double getComponentConductance()
Definition: fxobjects.h:6477
double RC
RC value.
Definition: fxobjects.h:6557
virtual double getComponentValue_C()
Definition: fxobjects.h:6513
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6516
virtual double getComponentResistance()
Definition: fxobjects.h:6474
double sampleRate
sample rate
Definition: fxobjects.h:6559
virtual double getOutput2()
Definition: fxobjects.h:6535
The WdfParallelRC object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6947
virtual double getComponentValue_R()
Definition: fxobjects.h:7002
double componentValue_C
component value C
Definition: fxobjects.h:7045
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6995
virtual double getOutput()
Definition: fxobjects.h:7014
virtual double getComponentConductance()
Definition: fxobjects.h:6968
double zRegister_C
storage register for C
Definition: fxobjects.h:7042
double zRegister_L
storage register for L
Definition: fxobjects.h:7041
virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
Definition: fxobjects.h:6980
double RL
RL value.
Definition: fxobjects.h:7048
double RC
RC value.
Definition: fxobjects.h:7049
virtual void setInput2(double _in2)
Definition: fxobjects.h:7035
virtual double getOutput1()
Definition: fxobjects.h:7023
virtual double getOutput3()
Definition: fxobjects.h:7029
virtual void setInput1(double _in1)
Definition: fxobjects.h:7032
virtual double getComponentResistance()
Definition: fxobjects.h:6965
virtual void setInput3(double _in3)
Definition: fxobjects.h:7038
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6988
double componentValue_R
component value R
Definition: fxobjects.h:7046
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:7052
double RR
RR value.
Definition: fxobjects.h:7050
double sampleRate
sample rate
Definition: fxobjects.h:7053
virtual void updateComponentResistance()
Definition: fxobjects.h:6971
virtual void setInput(double in)
Definition: fxobjects.h:7011
virtual void reset(double _sampleRate)
Definition: fxobjects.h:7008
virtual double getComponentValue_C()
Definition: fxobjects.h:7005
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6958
virtual double getOutput2()
Definition: fxobjects.h:7026
The WdfParallelRL object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6700
virtual double getOutput3()
Definition: fxobjects.h:6783
virtual void updateComponentResistance()
Definition: fxobjects.h:6724
virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
Definition: fxobjects.h:6734
virtual double getOutput2()
Definition: fxobjects.h:6780
virtual double getComponentConductance()
Definition: fxobjects.h:6721
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6742
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6711
virtual double getComponentValue_L()
Definition: fxobjects.h:6756
double zRegister_L
storage register for L
Definition: fxobjects.h:6795
virtual void setInput1(double _in1)
Definition: fxobjects.h:6786
double RR
RR value.
Definition: fxobjects.h:6804
virtual void setInput2(double _in2)
Definition: fxobjects.h:6789
double RL
RL value.
Definition: fxobjects.h:6802
virtual double getOutput()
Definition: fxobjects.h:6768
virtual double getOutput1()
Definition: fxobjects.h:6777
double componentValue_L
component value L
Definition: fxobjects.h:6799
double K
K value.
Definition: fxobjects.h:6797
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6806
double componentValue_R
component value R
Definition: fxobjects.h:6800
virtual void setInput(double in)
Definition: fxobjects.h:6765
double RC
RC value.
Definition: fxobjects.h:6803
virtual void setInput3(double _in3)
Definition: fxobjects.h:6792
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6749
virtual double getComponentValue_R()
Definition: fxobjects.h:6759
double sampleRate
sample rate
Definition: fxobjects.h:6807
virtual double getComponentResistance()
Definition: fxobjects.h:6718
double zRegister_C
storage register for L
Definition: fxobjects.h:6796
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6762
The WdfParallelTerminatedAdaptor object implements the parallel terminated (non-reflection-free) adap...
Definition: fxobjects.h:7648
virtual void setInput3(double _in3)
Definition: fxobjects.h:7723
virtual double getOutput2()
Definition: fxobjects.h:7729
virtual double getR2()
Definition: fxobjects.h:7654
virtual void initialize(double _R1)
Definition: fxobjects.h:7666
virtual double getOutput1()
Definition: fxobjects.h:7726
virtual double getOutput3()
Definition: fxobjects.h:7732
virtual void setInput1(double _in1)
Definition: fxobjects.h:7692
virtual void setInput2(double _in2)
Definition: fxobjects.h:7720
The WdfResistor object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6093
virtual double getComponentResistance()
Definition: fxobjects.h:6107
virtual double getOutput2()
Definition: fxobjects.h:6138
double componentResistance
simulated resistance
Definition: fxobjects.h:6155
virtual void updateComponentResistance()
Definition: fxobjects.h:6123
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6154
virtual void setInput2(double _in2)
Definition: fxobjects.h:6147
virtual void setInput3(double _in3)
Definition: fxobjects.h:6150
virtual double getComponentConductance()
Definition: fxobjects.h:6110
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6100
virtual void setInput1(double _in1)
Definition: fxobjects.h:6144
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6116
virtual double getOutput3()
Definition: fxobjects.h:6141
double sampleRate
sample rate
Definition: fxobjects.h:6156
virtual double getOutput1()
Definition: fxobjects.h:6135
virtual void setInput(double in)
Definition: fxobjects.h:6129
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6126
virtual double getOutput()
Definition: fxobjects.h:6132
virtual double getComponentValue()
Definition: fxobjects.h:6113
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6153
The WdfSeriesAdaptor object implements the series reflection-free (non-terminated) adaptor.
Definition: fxobjects.h:7328
virtual double getR2()
Definition: fxobjects.h:7334
virtual void setInput1(double _in1)
Definition: fxobjects.h:7366
virtual double getOutput3()
Definition: fxobjects.h:7415
virtual double getOutput1()
Definition: fxobjects.h:7409
virtual double getOutput2()
Definition: fxobjects.h:7412
virtual void initialize(double _R1)
Definition: fxobjects.h:7345
virtual void setInput3(double _in3)
Definition: fxobjects.h:7406
virtual void setInput2(double _in2)
Definition: fxobjects.h:7385
The WdfSeriesLC object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6336
virtual void setInput3(double _in3)
Definition: fxobjects.h:6427
virtual double getComponentResistance()
Definition: fxobjects.h:6354
virtual void setInput1(double _in1)
Definition: fxobjects.h:6421
virtual double getOutput3()
Definition: fxobjects.h:6418
virtual double getOutput()
Definition: fxobjects.h:6409
virtual double getOutput1()
Definition: fxobjects.h:6412
double sampleRate
sample rate
Definition: fxobjects.h:6439
double componentValue_L
component value L
Definition: fxobjects.h:6433
virtual void setInput2(double _in2)
Definition: fxobjects.h:6424
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6396
virtual double getOutput2()
Definition: fxobjects.h:6415
double zRegister_C
storage register for C
Definition: fxobjects.h:6431
double RC
RC value.
Definition: fxobjects.h:6437
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6347
virtual double getComponentValue_C()
Definition: fxobjects.h:6393
double RL
RL value.
Definition: fxobjects.h:6436
double zRegister_L
storage register for L
Definition: fxobjects.h:6430
virtual void updateComponentResistance()
Definition: fxobjects.h:6360
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6438
virtual double getComponentValue_L()
Definition: fxobjects.h:6390
virtual double getComponentConductance()
Definition: fxobjects.h:6357
double componentValue_C
component value C
Definition: fxobjects.h:6434
virtual void setInput(double in)
Definition: fxobjects.h:6399
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6376
virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
Definition: fxobjects.h:6368
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6383
The WdfSeriesRC object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6824
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6872
virtual void setInput(double in)
Definition: fxobjects.h:6888
virtual void updateComponentResistance()
Definition: fxobjects.h:6848
double RC
RC value.
Definition: fxobjects.h:6926
virtual double getComponentValue_R()
Definition: fxobjects.h:6879
virtual double getOutput3()
Definition: fxobjects.h:6906
double RR
RR value.
Definition: fxobjects.h:6927
virtual void setInput1(double _in1)
Definition: fxobjects.h:6909
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6929
double RL
RL value.
Definition: fxobjects.h:6925
virtual void setInput2(double _in2)
Definition: fxobjects.h:6912
virtual double getComponentValue_C()
Definition: fxobjects.h:6882
virtual double getOutput1()
Definition: fxobjects.h:6900
double zRegister_L
storage register for L
Definition: fxobjects.h:6918
virtual void setInput3(double _in3)
Definition: fxobjects.h:6915
virtual double getOutput()
Definition: fxobjects.h:6891
virtual double getComponentConductance()
Definition: fxobjects.h:6845
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6865
virtual double getComponentResistance()
Definition: fxobjects.h:6842
double zRegister_C
storage register for C
Definition: fxobjects.h:6919
virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
Definition: fxobjects.h:6857
double componentValue_R
component value R
Definition: fxobjects.h:6922
virtual double getOutput2()
Definition: fxobjects.h:6903
double sampleRate
sample rate
Definition: fxobjects.h:6930
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6835
double componentValue_C
component value C
Definition: fxobjects.h:6923
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6885
The WdfSeriesRL object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6577
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6588
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6638
virtual double getOutput2()
Definition: fxobjects.h:6657
virtual double getOutput()
Definition: fxobjects.h:6644
virtual void setInput1(double _in1)
Definition: fxobjects.h:6663
virtual void setInput2(double _in2)
Definition: fxobjects.h:6666
virtual void setInput3(double _in3)
Definition: fxobjects.h:6669
virtual double getComponentResistance()
Definition: fxobjects.h:6595
virtual void updateComponentResistance()
Definition: fxobjects.h:6601
double RC
RC value.
Definition: fxobjects.h:6680
virtual double getComponentValue_R()
Definition: fxobjects.h:6635
virtual double getOutput1()
Definition: fxobjects.h:6654
virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
Definition: fxobjects.h:6610
virtual double getComponentValue_L()
Definition: fxobjects.h:6632
double RL
RL value.
Definition: fxobjects.h:6679
double zRegister_L
storage register for L
Definition: fxobjects.h:6672
virtual void setInput(double in)
Definition: fxobjects.h:6641
double RR
RR value.
Definition: fxobjects.h:6681
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6625
double componentValue_R
component value R
Definition: fxobjects.h:6677
double zRegister_C
storage register for C (not used)
Definition: fxobjects.h:6673
double sampleRate
sample rate
Definition: fxobjects.h:6684
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6618
double componentResistance
equivalent resistance of pair of componen
Definition: fxobjects.h:6683
double componentValue_L
component value L
Definition: fxobjects.h:6676
virtual double getOutput3()
Definition: fxobjects.h:6660
virtual double getComponentConductance()
Definition: fxobjects.h:6598
The WdfSeriesTerminatedAdaptor object implements the series terminated (non-reflection-free) adaptor.
Definition: fxobjects.h:7436
virtual double getOutput3()
Definition: fxobjects.h:7517
virtual double getOutput1()
Definition: fxobjects.h:7511
virtual void initialize(double _R1)
Definition: fxobjects.h:7453
virtual void setInput2(double _in2)
Definition: fxobjects.h:7505
virtual void setInput3(double _in3)
Definition: fxobjects.h:7508
virtual double getOutput2()
Definition: fxobjects.h:7514
virtual void setInput1(double _in1)
Definition: fxobjects.h:7474
virtual double getR2()
Definition: fxobjects.h:7442
The ZVAFilter object implements multpile Zavalishin VA Filters. Audio I/O:
Definition: fxobjects.h:5180
ZVAFilterParameters zvaFilterParameters
object parameters
Definition: fxobjects.h:5372
double analogMatchSigma
analog matching Sigma value (see book)
Definition: fxobjects.h:5386
ZVAFilterParameters getParameters()
Definition: fxobjects.h:5199
void setBeta(double _beta)
Definition: fxobjects.h:5366
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5230
double alpha0
input scalar, correct delay-free loop
Definition: fxobjects.h:5379
double sampleRate
current sample rate
Definition: fxobjects.h:5373
void setParameters(const ZVAFilterParameters &params)
Definition: fxobjects.h:5208
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5186
double integrator_z[2]
state variables
Definition: fxobjects.h:5376
void calculateFilterCoeffs()
Definition: fxobjects.h:5330
double alpha
alpha is (wcT/2)
Definition: fxobjects.h:5380
double getBeta()
Definition: fxobjects.h:5369
double rho
p = 2R + g (feedback)
Definition: fxobjects.h:5381
double beta
beta value, not used
Definition: fxobjects.h:5383
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5223
hard-coded arrays of FIR filter coefficients for the sample rate conversion objects (Interpolator and...
filterCoeff
Use this enum to easily access coefficents inside of arrays.
Definition: fxobjects.h:1282
analogFilter
Use this strongy typed enum to set the analog filter type for the AnalogMagData structure.
Definition: fxobjects.h:820
edgeTransition
Use this strongly typed enum to easily set the edge direction (rising or falling) of a transition ban...
Definition: fxobjects.h:593
modDelaylgorithm
Use this strongly typed enum to easily set modulated delay algorithm.
Definition: fxobjects.h:3271
filterAlgorithm
Use this strongly typed enum to easily set the filter algorithm for the AudioFilter object or any oth...
Definition: fxobjects.h:1461
wdfComponent
Use this strongly typed enum to easily set the wdfComponent type.
Definition: fxobjects.h:7074
delayAlgorithm
Use this strongly typed enum to easily set the delay algorithm.
Definition: fxobjects.h:2641
windowType
Use this strongly typed enum to easily set the windowing type for FFT algorithms that use it.
Definition: fxobjects.h:8685
generatorWaveform
Use this strongly typed enum to easily set the oscillator waveform.
Definition: fxobjects.h:2945
const double kTwoPi
2pi to 80 decimal places
Definition: guiconstants.h:191
DFOscillatorCoeffs
Use this non-typed enum to easily access the direct form oscillator coefficients.
Definition: fxobjects.h:3119
delayUpdateType
Use this strongly typed enum to easily set the delay update type; this varies depending on the design...
Definition: fxobjects.h:2657
dynamicsProcessorType
Use this strongly typed enum to set the dynamics processor type.
Definition: fxobjects.h:1972
vaFilterAlgorithm
Use this strongly typed enum to easily set the virtual analog filter algorithm.
Definition: fxobjects.h:5115
DFOscillatorStates
Use this non-typed enum to easily access the direct form oscillator state registers.
Definition: fxobjects.h:3134
const uint32_t ENVELOPE_DETECT_MODE_PEAK
|x|
Definition: guiconstants.h:199
stateReg
Use this enum to easily access z^-1 state values inside of arrays. For some structures,...
Definition: fxobjects.h:1304
biquadAlgorithm
Use this strongly typed enum to easily set the biquad calculation type.
Definition: fxobjects.h:1321
reverbDensity
Use this strongly typed enum to easily set the density in the reverb object.
Definition: fxobjects.h:4676
brickwallFilter
Use this strongly typed enum to easily set brickwall filter type for functions that need it.
Definition: fxobjects.h:548
rateConversionRatio
Use this strongly typed enum to easily set up or down sampling ratios.
Definition: fxobjects.h:9618
distortionModel
Use this strongly typed enum to easily set the waveshaper model for the Triode objects.
Definition: fxobjects.h:5575
const double kPi
pi to 80 decimal places
Definition: guiconstants.h:184
double tanhWaveShaper(double xn, double saturation)
calculates hyptan waveshaper
Definition: fxobjects.h:402
double dBPeakGainFor_Q(double Q)
calculates the peak magnitude in dB for a given Q
Definition: fxobjects.h:317
double principalArg(double phaseIn)
calculates proncipal argument of a phase value; this is the wrapped value on the range of [-pi,...
Definition: fxobjects.h:1033
void boundValue(double &value, double minValue, double maxValue)
Bound a value to min and max limits.
Definition: fxobjects.h:167
double peakGainFor_Q(double Q)
calculates the peak magnitude for a given Q
Definition: fxobjects.h:301
bool calculateBrickwallMagArray(BrickwallMagData &magData)
calculate an arra of magnitude points from brickwall specifications
Definition: fxobjects.h:687
double doLagrangeInterpolation(double *x, double *y, int n, double xbar)
implements n-order Lagrange Interpolation
Definition: fxobjects.h:138
void freqSample(int N, double A[], double h[], int symm)
calcuate the IR for an array of magnitude points using the frequency sampling method....
Definition: fxobjects.h:935
double doUnipolarModulationFromMax(double unipolarModulatorValue, double minValue, double maxValue)
Perform unipolar modulation from a max value down to a min value using a unipolar modulator value.
Definition: fxobjects.h:204
bool resample(double *input, double *output, uint32_t inLength, uint32_t outLength, interpolation interpType=interpolation::kLinear, double scalar=1.0, double *outWindow=nullptr)
function that resamples an input array of length N into an output array of length M....
Definition: fxobjects.h:1060
void calcEdgeFrequencies(double fc, double Q, double &f_Low, double &f_High)
calculagte low and high edge frequencies of BPF or BSF
Definition: fxobjects.h:516
double getMagResponse(double theta, double a0, double a1, double a2, double b1, double b2)
returns the magnitude resonse of a 2nd order H(z) transfer function
Definition: fxobjects.h:448
double softClipWaveShaper(double xn, double saturation)
calculates hyptan waveshaper
Definition: fxobjects.h:416
double getPhase(double re, double im)
calculates phase of a complex numb er
Definition: fxobjects.h:1018
double getMagnitude(double re, double im)
calculates magnitude of a complex numb er
Definition: fxobjects.h:1003
double dB2Raw(double dB)
converts dB to raw value
Definition: fxobjects.h:287
int findEdgeTargetBin(double testFreq, double bin1Freq)
find bin for target frequency
Definition: fxobjects.h:627
double doBipolarModulation(double bipolarModulatorValue, double minValue, double maxValue)
Perform bipolar modulation about a center that his halfway between the min and max values.
Definition: fxobjects.h:224
bool calculateAnalogMagArray(AnalogMagData &magData)
calculate an arra of magnitude points from analog filter specifications
Definition: fxobjects.h:858
double calcWSGain(double xn, double saturation, double asymmetry)
calculates gain of a waveshaper
Definition: fxobjects.h:373
double unipolarToBipolar(double value)
calculates the bipolar [-1.0, +1.0] value FROM a unipolar [0.0, +1.0] value
Definition: fxobjects.h:245
unsigned int countForRatio(rateConversionRatio ratio)
returns the up or downsample ratio as a numeric value
Definition: fxobjects.h:9630
double doLinearInterpolation(double x1, double x2, double y1, double y2, double x)
performs linear interpolation of x distance between two (x,y) points; returns interpolated value
Definition: fxobjects.h:92
double bipolarToUnipolar(double value)
calculates the unipolar [0.0, +1.0] value FROM a bipolar [-1.0, +1.0] value
Definition: fxobjects.h:259
double doUnipolarModulationFromMin(double unipolarModulatorValue, double minValue, double maxValue)
Perform unipolar modulation from a min value up to a max value using a unipolar modulator value.
Definition: fxobjects.h:184
double atanWaveShaper(double xn, double saturation)
calculates arctangent waveshaper
Definition: fxobjects.h:388
double ** decomposeFilter(double *filterIR, unsigned int FIRLength, unsigned int ratio)
performs a polyphase decomposition on a big FIR into a set of sub-band FIRs
Definition: fxobjects.h:9725
double doWhiteNoise()
calculates a random value between -1.0 and +1.0
Definition: fxobjects.h:329
bool checkFloatUnderflow(double &value)
Perform underflow check; returns true if we did underflow (user may not care)
Definition: fxobjects.h:62
double sgn(double xn)
calculates sgn( ) of input
Definition: fxobjects.h:358
ComplexNumber complexMultiply(ComplexNumber c1, ComplexNumber c2)
returns the complex product of two complex numbers
Definition: fxobjects.h:494
std::unique_ptr< double[]> makeWindow(unsigned int windowLength, unsigned int hopSize, windowType window, double &gainCorrectionValue)
creates a new std::unique_ptr<double[]> array for a given window lenght and type.
Definition: fxobjects.h:8697
double raw2dB(double raw)
calculates dB for given input
Definition: fxobjects.h:273
double * getFilterIRTable(unsigned int FIRLength, rateConversionRatio ratio, unsigned int sampleRate)
returns the up or downsample ratio as a numeric value
Definition: fxobjects.h:9652
bool getTransitionBandData(double testFreq, double bin1Freq, unsigned int relax_Bins, TransitionBandData &transitionData)
get bin data for a filter's transitino band (see FX book for details)
Definition: fxobjects.h:644
double fuzzExp1WaveShaper(double xn, double saturation, double asymmetry)
calculates fuzz exp1 waveshaper
Definition: fxobjects.h:431
globally utilized constants and enumerations
Custom parameter structure for the AnalogFIRFilter object. This is a somewhat silly object that impla...
Definition: fxobjects.h:2506
AnalogFIRFilterParameters & operator=(const AnalogFIRFilterParameters &params)
Definition: fxobjects.h:2509
analogFilter filterType
filter type
Definition: fxobjects.h:2522
double Q
filter Q
Definition: fxobjects.h:2524
double fc
filter fc
Definition: fxobjects.h:2523
Custom parameter structure calculating analog magnitude response arrays with calculateAnalogMagArray(...
Definition: fxobjects.h:834
Custom parameter structure for the AudioDelay object.
Definition: fxobjects.h:2672
double wetLevel_dB
wet output level in dB
Definition: fxobjects.h:2695
AudioDelayParameters & operator=(const AudioDelayParameters &params)
Definition: fxobjects.h:2675
double delayRatio_Pct
dela ratio: right length = (delayRatio)*(left length)
Definition: fxobjects.h:2702
double rightDelay_mSec
right delay time
Definition: fxobjects.h:2701
double dryLevel_dB
dry output level in dB
Definition: fxobjects.h:2696
double feedback_Pct
feedback as a % value
Definition: fxobjects.h:2697
delayAlgorithm algorithm
delay algorithm
Definition: fxobjects.h:2694
double leftDelay_mSec
left delay time
Definition: fxobjects.h:2700
delayUpdateType updateType
update algorithm
Definition: fxobjects.h:2699
Custom parameter structure for the AudioDetector object. NOTE: this object uses constant defintions:
Definition: fxobjects.h:1790
double attackTime_mSec
attack time in milliseconds
Definition: fxobjects.h:1806
unsigned int detectMode
detect mode, see TLD_ constants above
Definition: fxobjects.h:1808
bool detect_dB
detect in dB DEFAULT = false (linear NOT log)
Definition: fxobjects.h:1809
bool clampToUnityMax
clamp output to 1.0 (set false for true log detectors)
Definition: fxobjects.h:1810
AudioDetectorParameters & operator=(const AudioDetectorParameters &params)
Definition: fxobjects.h:1793
double releaseTime_mSec
release time in milliseconds
Definition: fxobjects.h:1807
Custom parameter structure for the AudioFilter object.
Definition: fxobjects.h:1481
AudioFilterParameters & operator=(const AudioFilterParameters &params)
Definition: fxobjects.h:1484
double fc
filter cutoff or center frequency (Hz)
Definition: fxobjects.h:1498
filterAlgorithm algorithm
filter algorithm
Definition: fxobjects.h:1497
double boostCut_dB
filter gain; note not used in all types
Definition: fxobjects.h:1500
double Q
filter Q
Definition: fxobjects.h:1499
Custom structure that holds information about each FFT bin. This includes all information needed to p...
Definition: fxobjects.h:9096
bool isPeak
flag for peak bins
Definition: fxobjects.h:9129
unsigned int localPeakBin
index of peak-boss
Definition: fxobjects.h:9133
double updatedPhase
phase update value
Definition: fxobjects.h:9135
double phi
bin phase angle
Definition: fxobjects.h:9131
BinData & operator=(const BinData &params)
Definition: fxobjects.h:9099
int previousPeakBin
index of peak bin in previous FFT
Definition: fxobjects.h:9134
double magnitude
bin magnitude angle
Definition: fxobjects.h:9130
double psi
bin phase correction
Definition: fxobjects.h:9132
void reset()
Definition: fxobjects.h:9117
Custom parameter structure for the Biquad object. Default version defines the biquad structure used i...
Definition: fxobjects.h:1336
BiquadParameters & operator=(const BiquadParameters &params)
Definition: fxobjects.h:1340
biquadAlgorithm biquadCalcType
biquad structure to use
Definition: fxobjects.h:1349
Custom parameter structure for the BitCrusher object.
Definition: fxobjects.h:5920
BitCrusherParameters & operator=(const BitCrusherParameters &params)
Definition: fxobjects.h:5923
double quantizedBitDepth
bid depth of quantizer
Definition: fxobjects.h:5933
Custom structure that holds magnitude information about a brickwall filter.
Definition: fxobjects.h:562
double fc
brickwall fc
Definition: fxobjects.h:572
double Q
brickwall Q
Definition: fxobjects.h:573
double f_High
brickwall f_high
Definition: fxobjects.h:575
bool mirrorMag
optionally mirror the output array
Definition: fxobjects.h:577
double f_Low
brickwall f_low
Definition: fxobjects.h:574
unsigned int relaxationBins
relaxation bins for FIR specification
Definition: fxobjects.h:576
Custom parameter structure for the ClassATubePre object.
Definition: fxobjects.h:5756
double outputLevel_dB
input level in dB
Definition: fxobjects.h:5781
double asymmetry
input level in dB
Definition: fxobjects.h:5780
double lowShelfBoostCut_dB
LSF shelf gain/cut.
Definition: fxobjects.h:5785
double highShelfBoostCut_dB
HSF shelf frequency.
Definition: fxobjects.h:5787
ClassATubePreParameters & operator=(const ClassATubePreParameters &params)
Definition: fxobjects.h:5759
double saturation
input level in dB
Definition: fxobjects.h:5779
double lowShelf_fc
LSF shelf frequency.
Definition: fxobjects.h:5784
double inputLevel_dB
input level in dB
Definition: fxobjects.h:5778
double highShelf_fc
HSF shelf frequency.
Definition: fxobjects.h:5786
Custom parameter structure for the CombFilter object. Used for reverb algorithms in book.
Definition: fxobjects.h:3993
CombFilterParameters & operator=(const CombFilterParameters &params)
Definition: fxobjects.h:3996
double RT60Time_mSec
RT 60 time ini mSec.
Definition: fxobjects.h:4011
double lpf_g
gain value for LPF (if enabled)
Definition: fxobjects.h:4013
bool enableLPF
enable LPF flag
Definition: fxobjects.h:4012
bool interpolate
interpolation flag (diagnostics)
Definition: fxobjects.h:4014
double delayTime_mSec
delay time in mSec
Definition: fxobjects.h:4010
Structure to hold a complex value.
Definition: fxobjects.h:474
double imag
imaginary part
Definition: fxobjects.h:483
double real
real part
Definition: fxobjects.h:482
Custom input structure for DecimatorInput; it holds an arry of input samples that will be decimated d...
Definition: fxobjects.h:9885
double audioData[maxSamplingRatio]
input array of samples to be decimated
Definition: fxobjects.h:9887
unsigned int count
count of samples in input array
Definition: fxobjects.h:9888
Custom parameter structure for the DelayAPF object. Used for reverb algorithms in book.
Definition: fxobjects.h:4155
DelayAPFParameters & operator=(const DelayAPFParameters &params)
Definition: fxobjects.h:4158
bool interpolate
interpolate flag (diagnostics)
Definition: fxobjects.h:4180
double lfoDepth
LFO deoth (not in %) if enabled.
Definition: fxobjects.h:4183
double delayTime_mSec
APF delay time.
Definition: fxobjects.h:4176
bool enableLFO
flag to enable LFO
Definition: fxobjects.h:4181
double apf_g
APF g coefficient.
Definition: fxobjects.h:4177
double lfoMaxModulation_mSec
LFO maximum modulation time in mSec.
Definition: fxobjects.h:4184
bool enableLPF
flag to enable LPF in structure
Definition: fxobjects.h:4178
double lfoRate_Hz
LFO rate in Hz, if enabled.
Definition: fxobjects.h:4182
double lpf_g
LPF g coefficient (if enabled)
Definition: fxobjects.h:4179
Custom parameter structure for the DynamicsProcessor object. Ths struct includes all information need...
Definition: fxobjects.h:1987
bool softKnee
soft knee flag
Definition: fxobjects.h:2016
DynamicsProcessorParameters & operator=(const DynamicsProcessorParameters &params)
Definition: fxobjects.h:1990
double outputGain_dB
make up gain
Definition: fxobjects.h:2021
double gainReduction
output value for gain reduction that occurred
Definition: fxobjects.h:2024
bool hardLimitGate
threshold in dB
Definition: fxobjects.h:2015
double gainReduction_dB
output value for gain reduction that occurred in dB
Definition: fxobjects.h:2025
dynamicsProcessorType calculation
processor calculation type
Definition: fxobjects.h:2018
double releaseTime_mSec
release mSec
Definition: fxobjects.h:2020
double threshold_dB
threshold in dB
Definition: fxobjects.h:2013
bool enableSidechain
enable external sidechain input to object
Definition: fxobjects.h:2017
double ratio
processor I/O gain ratio
Definition: fxobjects.h:2012
double kneeWidth_dB
knee width in dB for soft-knee operation
Definition: fxobjects.h:2014
double attackTime_mSec
attack mSec
Definition: fxobjects.h:2019
Custom parameter structure for the EnvelopeFollower object.
Definition: fxobjects.h:5402
double fc
filter fc
Definition: fxobjects.h:5421
double sensitivity
detector sensitivity
Definition: fxobjects.h:5426
double attackTime_mSec
detector attack time
Definition: fxobjects.h:5423
double Q
filter Q
Definition: fxobjects.h:5422
double threshold_dB
detector threshold in dB
Definition: fxobjects.h:5425
double releaseTime_mSec
detector release time
Definition: fxobjects.h:5424
EnvelopeFollowerParameters & operator=(const EnvelopeFollowerParameters &params)
Definition: fxobjects.h:5405
Custom output structure for filter bank objects that split the inptu into multiple frequency channels...
Definition: fxobjects.h:1618
double HFOut
high frequency output sample
Definition: fxobjects.h:1623
double LFOut
low frequency output sample
Definition: fxobjects.h:1622
Custom output structure for interpolator; it holds an arry of interpolated output samples.
Definition: fxobjects.h:9760
unsigned int count
number of samples in output array
Definition: fxobjects.h:9763
double audioData[maxSamplingRatio]
array of interpolated output samples
Definition: fxobjects.h:9762
Custom parameter structure for the LRFilterBank object which splits the input signal into multiple ba...
Definition: fxobjects.h:1643
double splitFrequency
LF/HF split frequency.
Definition: fxobjects.h:1655
LRFilterBankParameters & operator=(const LRFilterBankParameters &params)
Definition: fxobjects.h:1646
Custom parameter structure for the ModulatedDelay object.
Definition: fxobjects.h:3286
double feedback_Pct
feedback in %
Definition: fxobjects.h:3305
double lfoDepth_Pct
mod delay LFO depth in %
Definition: fxobjects.h:3304
modDelaylgorithm algorithm
mod delay algorithm
Definition: fxobjects.h:3302
ModulatedDelayParameters & operator=(const ModulatedDelayParameters &params)
Definition: fxobjects.h:3289
double lfoRate_Hz
mod delay LFO rate in Hz
Definition: fxobjects.h:3303
Custom parameter structure for the NestedDelayAPF object. Used for reverb algorithms in book.
Definition: fxobjects.h:4351
double innerAPFdelayTime_mSec
delay time for inner APF
Definition: fxobjects.h:4375
double outerAPF_g
g coefficient for outer APF
Definition: fxobjects.h:4376
double lfoMaxModulation_mSec
max modulation time if LFO is enabled
Definition: fxobjects.h:4383
double outerAPFdelayTime_mSec
delay time for outer APF
Definition: fxobjects.h:4374
double innerAPF_g
g coefficient for inner APF
Definition: fxobjects.h:4377
NestedDelayAPFParameters & operator=(const NestedDelayAPFParameters &params)
Definition: fxobjects.h:4354
double lfoDepth
LFO depth (not in %) (if enabled)
Definition: fxobjects.h:4382
bool enableLFO
flag to enable the modulated delay
Definition: fxobjects.h:4380
double lfoRate_Hz
LFO rate in Hz (if enabled)
Definition: fxobjects.h:4381
Custom parameter structure for the LFO and DFOscillator objects.
Definition: fxobjects.h:2959
OscillatorParameters & operator=(const OscillatorParameters &params)
Definition: fxobjects.h:2962
double frequency_Hz
oscillator frequency
Definition: fxobjects.h:2974
generatorWaveform waveform
the current waveform
Definition: fxobjects.h:2973
Custom parameter structure for the Biquad object. Default version defines the biquad structure used i...
Definition: fxobjects.h:9150
PSMVocoderParameters & operator=(const PSMVocoderParameters &params)
Definition: fxobjects.h:9153
bool enablePeakTracking
flag to enable peak tracking
Definition: fxobjects.h:9168
double pitchShiftSemitones
pitch shift in half-steps
Definition: fxobjects.h:9166
bool enablePeakPhaseLocking
flag to enable phase lock
Definition: fxobjects.h:9167
Custom parameter structure for the PhaseShifter object.
Definition: fxobjects.h:3478
double intensity_Pct
phaser feedback in %
Definition: fxobjects.h:3496
double lfoDepth_Pct
phaser LFO depth in %
Definition: fxobjects.h:3495
PhaseShifterParameters & operator=(const PhaseShifterParameters &params)
Definition: fxobjects.h:3481
double lfoRate_Hz
phaser LFO rate in Hz
Definition: fxobjects.h:3494
bool quadPhaseLFO
quad phase LFO flag
Definition: fxobjects.h:3497
Custom parameter structure for the ReverbTank object.
Definition: fxobjects.h:4690
double lowShelfBoostCut_dB
low shelf gain
Definition: fxobjects.h:4737
double wetLevel_dB
wet output level in dB
Definition: fxobjects.h:4741
double preDelayTime_mSec
pre-delay time in mSec
Definition: fxobjects.h:4732
double apfDelayMax_mSec
APF max delay time.
Definition: fxobjects.h:4726
double fixeDelayMax_mSec
fixed delay max time
Definition: fxobjects.h:4728
reverbDensity density
density setting thick or thin
Definition: fxobjects.h:4721
double kRT
reverb time, 0 to 1
Definition: fxobjects.h:4734
double apfDelayWeight_Pct
APF max delay weighying.
Definition: fxobjects.h:4727
double fixeDelayWeight_Pct
fixed delay max weighying
Definition: fxobjects.h:4729
double highShelfBoostCut_dB
high shelf gain
Definition: fxobjects.h:4739
double highShelf_fc
high shelf fc
Definition: fxobjects.h:4738
double lowShelf_fc
low shelf fc
Definition: fxobjects.h:4736
ReverbTankParameters & operator=(const ReverbTankParameters &params)
Definition: fxobjects.h:4693
double lpf_g
LPF g coefficient.
Definition: fxobjects.h:4733
double dryLevel_dB
dry output level in dB
Definition: fxobjects.h:4742
This is the output structure for audio generator objects that can render up to four outputs.
Definition: fxobjects.h:1216
double quadPhaseOutput_neg
-90 degrees out
Definition: fxobjects.h:1222
double normalOutput
normal
Definition: fxobjects.h:1219
double invertedOutput
inverted
Definition: fxobjects.h:1220
double quadPhaseOutput_pos
90 degrees out
Definition: fxobjects.h:1221
Custom parameter structure for the SimpleDelay object. Used for reverb algorithms in book.
Definition: fxobjects.h:3816
double delay_Samples
current delay in samples; other objects may need to access this information
Definition: fxobjects.h:3835
bool interpolate
interpolation flag (diagnostics usually)
Definition: fxobjects.h:3832
double delayTime_mSec
delay tine in mSec
Definition: fxobjects.h:3831
SimpleDelayParameters & operator=(const SimpleDelayParameters &params)
Definition: fxobjects.h:3819
Custom parameter structure for the SimpleLPFP object. Used for reverb algorithms in book.
Definition: fxobjects.h:3718
SimpleLPFParameters & operator=(const SimpleLPFParameters &params)
Definition: fxobjects.h:3721
double g
simple LPF g value
Definition: fxobjects.h:3731
Custom structure that holds transition band information for FIR filter calculations.
Definition: fxobjects.h:607
edgeTransition edgeType
edge type
Definition: fxobjects.h:610
unsigned int startBin
starting bin for transition band
Definition: fxobjects.h:611
double slopeIncrement
transition slope
Definition: fxobjects.h:613
unsigned int stopBin
ending bin for transition band
Definition: fxobjects.h:612
Custom parameter structure for the TriodeClassA object.
Definition: fxobjects.h:5589
bool enableHPF
HPF simulates DC blocking cap on output.
Definition: fxobjects.h:5621
TriodeClassAParameters & operator=(const TriodeClassAParameters &params)
Definition: fxobjects.h:5592
bool enableLSF
LSF simulates shelf due to cathode self biasing.
Definition: fxobjects.h:5622
double lsf_BoostCut_dB
boost/cut due to cathode self biasing
Definition: fxobjects.h:5626
double outputGain
outputGain level
Definition: fxobjects.h:5618
double saturation
saturation level
Definition: fxobjects.h:5616
bool invertOutput
invertOutput - triodes invert output
Definition: fxobjects.h:5620
double lsf_Fshelf
shelf fc from self bias cap
Definition: fxobjects.h:5625
double asymmetry
asymmetry level
Definition: fxobjects.h:5617
distortionModel waveshaper
waveshaper
Definition: fxobjects.h:5614
double hpf_Fc
fc of DC blocking cap
Definition: fxobjects.h:5624
Custom parameter structure for the TwoBandShelvingFilter object. Used for reverb algorithms in book.
Definition: fxobjects.h:4550
double lowShelf_fc
fc for low shelf
Definition: fxobjects.h:4566
double highShelf_fc
fc for high shelf
Definition: fxobjects.h:4568
TwoBandShelvingFilterParameters & operator=(const TwoBandShelvingFilterParameters &params)
Definition: fxobjects.h:4553
double highShelfBoostCut_dB
high shelf gain
Definition: fxobjects.h:4569
double lowShelfBoostCut_dB
low shelf gain
Definition: fxobjects.h:4567
Custom parameter structure for the WDF filter examples.
Definition: fxobjects.h:8158
double fc
filter fc
Definition: fxobjects.h:8174
double boostCut_dB
filter boost or cut in dB
Definition: fxobjects.h:8176
bool frequencyWarping
enable frequency warping
Definition: fxobjects.h:8177
WDFParameters & operator=(const WDFParameters &params)
Definition: fxobjects.h:8161
double Q
filter Q
Definition: fxobjects.h:8175
Custom structure to hold component information.
Definition: fxobjects.h:7088
wdfComponent componentType
selected component type
Definition: fxobjects.h:7120
double R
value of R component
Definition: fxobjects.h:7117
double L
value of L component
Definition: fxobjects.h:7118
double C
value of C component
Definition: fxobjects.h:7119
Custom parameter structure for the ZVAFilter object.
Definition: fxobjects.h:5132
ZVAFilterParameters & operator=(const ZVAFilterParameters &params)
Definition: fxobjects.h:5135
bool enableNLP
enable non linear processing (use oversampling for best results)
Definition: fxobjects.h:5159
bool selfOscillate
enable selfOscillation
Definition: fxobjects.h:5158
double Q
va filter Q
Definition: fxobjects.h:5154
bool enableGainComp
enable gain compensation (see book)
Definition: fxobjects.h:5156
double fc
va filter fc
Definition: fxobjects.h:5153
bool matchAnalogNyquistLPF
match analog gain at Nyquist
Definition: fxobjects.h:5157
vaFilterAlgorithm filterAlgorithm
va filter algorithm
Definition: fxobjects.h:5152
double filterOutputGain_dB
va filter gain (normally unused)
Definition: fxobjects.h:5155