ASPiK SDK
fxobjects.h
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 // ASPiK-Core File: fxobjects.h
3 //
17 // -----------------------------------------------------------------------------
18 #pragma once
19 
20 #include <memory>
21 #include <math.h>
22 #include "guiconstants.h"
23 #include "filters.h"
24 #include <time.h> /* time */
25 
30 // --- constants & enumerations
31 //
32 // --- by placing outside the class declaration, these will also be avaialble to anything
33 // that #includes this file (sometimes needed)
34 const double kSmallestPositiveFloatValue = 1.175494351e-38; /* min positive value */
35 const double kSmallestNegativeFloatValue = -1.175494351e-38; /* min negative value */
36 const double kSqrtTwo = pow(2.0, 0.5);
37 const double kMinFilterFrequency = 20.0;
38 const double kMaxFilterFrequency = 20480.0; // 10 octaves above 20 Hz
39 const double ARC4RANDOMMAX = 4294967295.0; // (2^32 - 1)
40 
41 #define NEGATIVE 0
42 #define POSITIVE 1
43 
44 // ------------------------------------------------------------------ //
45 // --- FUNCTIONS ---------------------------------------------------- //
46 // ------------------------------------------------------------------ //
47 
57 inline bool checkFloatUnderflow(double& value)
58 {
59  bool retValue = false;
60  if (value > 0.0 && value < kSmallestPositiveFloatValue)
61  {
62  value = 0;
63  retValue = true;
64  }
65  else if (value < 0.0 && value > kSmallestNegativeFloatValue)
66  {
67  value = 0;
68  retValue = true;
69  }
70  return retValue;
71 }
72 
87 inline double doLinearInterpolation(double x1, double x2, double y1, double y2, double x)
88 {
89  double denom = x2 - x1;
90  if (denom == 0)
91  return y1; // --- should not ever happen
92 
93  // --- calculate decimal position of x
94  double dx = (x - x1) / (x2 - x1);
95 
96  // --- use weighted sum method of interpolating
97  return dx*y2 + (1 - dx)*y1;
98 }
99 
112 inline double doLinearInterpolation(double y1, double y2, double fractional_X)
113 {
114  // --- check invalid condition
115  if (fractional_X >= 1.0) return y2;
116 
117  // --- use weighted sum method of interpolating
118  return fractional_X*y2 + (1.0 - fractional_X)*y1;
119 }
120 
133 inline double doLagrangeInterpolation(double* x, double* y, int n, double xbar)
134 {
135  int i, j;
136  double fx = 0.0;
137  double l = 1.0;
138  for (i = 0; i<n; i++)
139  {
140  l = 1.0;
141  for (j = 0; j<n; j++)
142  {
143  if (j != i)
144  l *= (xbar - x[j]) / (x[i] - x[j]);
145  }
146  fx += l*y[i];
147  }
148  return (fx);
149 }
150 
151 
162 inline void boundValue(double& value, double minValue, double maxValue)
163 {
164  value = fmin(value, maxValue);
165  value = fmax(value, minValue);
166 }
167 
179 inline double doUnipolarModulationFromMin(double unipolarModulatorValue, double minValue, double maxValue)
180 {
181  // --- UNIPOLAR bound
182  boundValue(unipolarModulatorValue, 0.0, 1.0);
183 
184  // --- modulate from minimum value upwards
185  return unipolarModulatorValue*(maxValue - minValue) + minValue;
186 }
187 
199 inline double doUnipolarModulationFromMax(double unipolarModulatorValue, double minValue, double maxValue)
200 {
201  // --- UNIPOLAR bound
202  boundValue(unipolarModulatorValue, 0.0, 1.0);
203 
204  // --- modulate from maximum value downwards
205  return maxValue - (1.0 - unipolarModulatorValue)*(maxValue - minValue);
206 }
207 
219 inline double doBipolarModulation(double bipolarModulatorValue, double minValue, double maxValue)
220 {
221  // --- BIPOLAR bound
222  boundValue(bipolarModulatorValue, -1.0, 1.0);
223 
224  // --- calculate range and midpoint
225  double halfRange = (maxValue - minValue) / 2.0;
226  double midpoint = halfRange + minValue;
227 
228  return bipolarModulatorValue*(halfRange) + midpoint;
229 }
230 
240 inline double unipolarToBipolar(double value)
241 {
242  return 2.0*value - 1.0;
243 }
244 
254 inline double bipolarToUnipolar(double value)
255 {
256  return 0.5*value + 0.5;
257 }
258 
268 inline double raw2dB(double raw)
269 {
270  return 20.0*log10(raw);
271 }
272 
282 inline double dB2Raw(double dB)
283 {
284  return pow(10.0, (dB / 20.0));
285 }
286 
296 inline double peakGainFor_Q(double Q)
297 {
298  // --- no resonance at or below unity
299  if (Q <= 0.707) return 1.0;
300  return (Q*Q) / (pow((Q*Q - 0.25), 0.5));
301 }
302 
312 inline double dBPeakGainFor_Q(double Q)
313 {
314  return raw2dB(peakGainFor_Q(Q));
315 }
316 
324 inline double doWhiteNoise()
325 {
326  float noise = 0.0;
327 
328 #if defined _WINDOWS || defined _WINDLL
329  // fNoise is 0 -> 32767.0
330  noise = (float)rand();
331 
332  // normalize and make bipolar
333  noise = 2.0*(noise / 32767.0) - 1.0;
334 #else
335  // fNoise is 0 -> ARC4RANDOMMAX
336  noise = (float)arc4random();
337 
338  // normalize and make bipolar
339  noise = 2.0*(noise / ARC4RANDOMMAX) - 1.0;
340 #endif
341 
342  return noise;
343 }
344 
353 inline double sgn(double xn)
354 {
355  return (xn > 0) - (xn < 0);
356 }
357 
368 inline double calcWSGain(double xn, double saturation, double asymmetry)
369 {
370  double g = ((xn >= 0.0 && asymmetry > 0.0) || (xn < 0.0 && asymmetry < 0.0)) ? saturation * (1.0 + 4.0*fabs(asymmetry)) : saturation;
371  return g;
372 }
373 
383 inline double atanWaveShaper(double xn, double saturation)
384 {
385  return atan(saturation*xn) / atan(saturation);
386 }
387 
397 inline double tanhWaveShaper(double xn, double saturation)
398 {
399  return tanh(saturation*xn) / tanh(saturation);
400 }
401 
411 inline double softClipWaveShaper(double xn, double saturation)
412 {
413  // --- un-normalized soft clipper from Reiss book
414  double d = sgn(xn);
415  return sgn(xn)*(1.0 - exp(-fabs(saturation*xn)));
416 }
417 
427 inline double fuzzExp1WaveShaper(double xn, double saturation, double asymmetry)
428 {
429  // --- setup gain
430  double wsGain = calcWSGain(xn, saturation, asymmetry);
431  return sgn(xn)*(1.0 - exp(-fabs(wsGain*xn))) / (1.0 - exp(-wsGain));
432 }
433 
434 
444 inline double getMagResponse(double theta, double a0, double a1, double a2, double b1, double b2)
445 {
446  double magSqr = 0.0;
447  double num = a1*a1 + (a0 - a2)*(a0 - a2) + 2.0*a1*(a0 + a2)*cos(theta) + 4.0*a0*a2*cos(theta)*cos(theta);
448  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);
449 
450  magSqr = num / denom;
451  if (magSqr < 0.0)
452  magSqr = 0.0;
453 
454  double mag = pow(magSqr, 0.5);
455 
456  return mag;
457 }
458 
470 {
471  ComplexNumber() {}
472  ComplexNumber(double _real, double _imag)
473  {
474  real = _real;
475  imag = _imag;
476  }
477 
478  double real = 0.0;
479  double imag = 0.0;
480 };
481 
491 {
492  ComplexNumber complexProduct;
493 
494  // --- real part
495  complexProduct.real = (c1.real*c2.real) - (c1.imag*c2.imag);
496  complexProduct.imag = (c1.real*c2.imag) + (c1.imag*c2.real);
497 
498  return complexProduct;
499 }
500 
512 inline void calcEdgeFrequencies(double fc, double Q, double& f_Low, double& f_High)
513 {
514  bool arithmeticBW = true;
515  double bandwidth = fc / Q;
516 
517  // --- geometric bw = sqrt[ (fLow)(fHigh) ]
518  // arithmetic bw = fHigh - fLow
519  if (arithmeticBW)
520  {
521  f_Low = fc - bandwidth / 2.0;
522  f_High = fc + bandwidth / 2.0;
523  }
524  else
525  {
526  ; // TODO --- add geometric (for homework)
527  }
528 
529 }
530 
544 enum class brickwallFilter { kBrickLPF, kBrickHPF, kBrickBPF, kBrickBSF };
545 
558 {
559  BrickwallMagData() {}
560 
561  brickwallFilter filterType = brickwallFilter::kBrickLPF;
562  double* magArray = nullptr;
563  unsigned int dftArrayLen = 0;
564  double sampleRate = 44100.0;
565 
566  // --- for LPF, HPF fc = corner frequency
567  // for BPF, BSF fc = center frequency
568  double fc = 1000.0;
569  double Q = 0.707;
570  double f_Low = 500.00;
571  double f_High = 1500.00;
572  unsigned int relaxationBins = 0;
573  bool mirrorMag = false;
574 };
575 
589 enum class edgeTransition { kFallingEdge, kRisingEdge };
590 
603 {
604  TransitionBandData() {}
605 
606  edgeTransition edgeType = edgeTransition::kFallingEdge;
607  unsigned int startBin = 0;
608  unsigned int stopBin = 0;
609  double slopeIncrement = 1.0;
610 };
611 
612 
623 inline int findEdgeTargetBin(double testFreq, double bin1Freq)
624 {
625  return (int)(testFreq / bin1Freq);
626 }
627 
640 inline bool getTransitionBandData(double testFreq, double bin1Freq, unsigned int relax_Bins, TransitionBandData& transitionData)
641 {
642  double targetF1 = testFreq;// -(2.0*relax_Pct / 100.0)*testFreq;
643  double targetF2 = testFreq + relax_Bins*bin1Freq;
644 
645  // --- for falling edge...
646  int nF1 = findEdgeTargetBin(targetF1, bin1Freq);
647  int nF2 = findEdgeTargetBin(targetF2, bin1Freq);
648  int relaxBinsAbsDiff = nF2 - nF1;
649 
650  nF1 = fmax(0, nF1);
651  nF2 = fmax(0, nF2);
652 
653  //if (relaxBinsAbsDiff < 0 || nF1 == 0)
654  // nF2 = nF1 + relaxBinsAbsDiff;
655 
656  int relaxBins = nF2 - nF1;
657 
658  if (relaxBins < 1)
659  return false;
660 
661  // --- force even to make relax band symmetrical around edge
662  //if (relaxBins % 2 != 0)
663  // relaxBins++;
664 
665  // --- for double-sided relax
666  transitionData.startBin = nF1;
667  transitionData.stopBin = relaxBins + nF1;
668 
669  // --- slope calc
670  double run = transitionData.stopBin - transitionData.startBin;
671  double rise = 1.0;
672  if (transitionData.edgeType == edgeTransition::kFallingEdge)
673  rise = -1.0;
674  transitionData.slopeIncrement = rise / run;
675 
676  return true;
677 }
678 
689 {
690  // --- calculate first half of array
691  double actualLength = magData.mirrorMag ? (double)magData.dftArrayLen : (double)magData.dftArrayLen * 2.0;
692  int dumpLength = magData.mirrorMag ? magData.dftArrayLen / 2 : magData.dftArrayLen;
693 
694  // --- first bin in Hz
695  double bin1 = magData.sampleRate / actualLength;
696 
697  // --- zero out array; if filter not supported, this will return a bank of 0's!
698  memset(&magData.magArray[0], 0, magData.dftArrayLen * sizeof(double));
699 
700  // --- preprocess for transition bands
701  TransitionBandData fallingEdge;
702  fallingEdge.edgeType = edgeTransition::kFallingEdge;
703 
704  TransitionBandData risingEdge;
705  risingEdge.edgeType = edgeTransition::kRisingEdge;
706 
707  // --- this will populate FL and FH for BPF and BSF
708  calcEdgeFrequencies(magData.fc, magData.Q, magData.f_Low, magData.f_High);
709 
710  bool relaxIt = false;
711  if (magData.relaxationBins > 0)
712  {
713  if(magData.filterType == brickwallFilter::kBrickLPF)
714  relaxIt = getTransitionBandData(magData.fc, bin1, magData.relaxationBins, fallingEdge);
715  else if (magData.filterType == brickwallFilter::kBrickHPF)
716  relaxIt = getTransitionBandData(magData.fc, bin1, magData.relaxationBins, risingEdge);
717  else if (magData.filterType == brickwallFilter::kBrickBPF)
718  {
719  if(getTransitionBandData(magData.f_Low, bin1, magData.relaxationBins, risingEdge))
720  relaxIt = getTransitionBandData(magData.f_High, bin1, magData.relaxationBins, fallingEdge);
721  }
722  else if (magData.filterType == brickwallFilter::kBrickBSF)
723  {
724  if(getTransitionBandData(magData.f_Low, bin1, magData.relaxationBins, fallingEdge))
725  relaxIt = getTransitionBandData(magData.f_High, bin1, magData.relaxationBins, risingEdge);
726  }
727  }
728 
729  for (int i = 0; i < dumpLength; i++)
730  {
731  double eval_f = i*bin1;
732 
733  if (magData.filterType == brickwallFilter::kBrickLPF)
734  {
735  if (!relaxIt)
736  {
737  if (eval_f <= magData.fc)
738  magData.magArray[i] = 1.0;
739  }
740  else // relax
741  {
742  if (i <= fallingEdge.startBin)
743  magData.magArray[i] = 1.0;
744  else if(i > fallingEdge.startBin && i < fallingEdge.stopBin)
745  magData.magArray[i] = 1.0 + (i - fallingEdge.startBin)*fallingEdge.slopeIncrement;
746  }
747  }
748  else if (magData.filterType == brickwallFilter::kBrickHPF)
749  {
750  if (!relaxIt)
751  {
752  if (eval_f >= magData.fc)
753  magData.magArray[i] = 1.0;
754  }
755  else // relax
756  {
757  if (i >= risingEdge.stopBin)
758  magData.magArray[i] = 1.0;
759  else if (i > risingEdge.startBin && i < risingEdge.stopBin)
760  magData.magArray[i] = 0.0 + (i - risingEdge.startBin)*risingEdge.slopeIncrement;
761  }
762  }
763  else if (magData.filterType == brickwallFilter::kBrickBPF)
764  {
765  if (!relaxIt)
766  {
767  if (eval_f >= magData.f_Low && eval_f <= magData.f_High)
768  magData.magArray[i] = 1.0;
769  }
770  else // --- frankie says relax
771  {
772  if (i >= risingEdge.stopBin && i <= fallingEdge.startBin)
773  magData.magArray[i] = 1.0;
774  else if (i > risingEdge.startBin && i < risingEdge.stopBin)
775  magData.magArray[i] = 0.0 + (i - risingEdge.startBin)*risingEdge.slopeIncrement;
776  else if (i > fallingEdge.startBin && i < fallingEdge.stopBin)
777  magData.magArray[i] = 1.0 + (i - fallingEdge.startBin)*fallingEdge.slopeIncrement;
778 
779  }
780  }
781  else if (magData.filterType == brickwallFilter::kBrickBSF)
782  {
783  if (!relaxIt && eval_f >= magData.f_Low && eval_f <= magData.f_High)
784  magData.magArray[i] = 0.0;
785  else if(!relaxIt && eval_f < magData.f_Low || eval_f > magData.f_High)
786  magData.magArray[i] = 1.0;
787  else
788  {
789  // --- TODO Fill this in...
790  }
791  }
792  }
793 
794  // -- make sure have legal first half...
795  if (!magData.mirrorMag)
796  return true;
797 
798  // --- now mirror the other half
799  int index = magData.dftArrayLen / 2 - 1;
800  for (unsigned int i = magData.dftArrayLen / 2; i <magData.dftArrayLen; i++)
801  {
802  magData.magArray[i] = magData.magArray[index--];
803  }
804 
805  return true;
806 }
807 
821 enum class analogFilter { kLPF1, kHPF1, kLPF2, kHPF2, kBPF2, kBSF2 };
822 
835 {
836  AnalogMagData() {}
837 
838  analogFilter filterType = analogFilter::kLPF2;
839  double* magArray = nullptr;
840  unsigned int dftArrayLen = 0;
841  double sampleRate = 44100.0;
842 
843  // --- for LPF, HPF fc = corner frequency
844  // for BPF, BSF fc = center frequency
845  double fc = 1000.0;
846  double Q = 0.707;
847  bool mirrorMag = true;
848 };
849 
860 {
861  // --- calculate first half of array
862  double actualLength = magData.mirrorMag ? (double)magData.dftArrayLen : (double)magData.dftArrayLen * 2.0;
863  int dumpLength = magData.mirrorMag ? magData.dftArrayLen / 2 : magData.dftArrayLen;
864 
865  double bin1 = magData.sampleRate / actualLength;// (double)magData.dftArrayLen;
866  double zeta = 1.0 / (2.0*magData.Q);
867  double w_c = 2.0*kPi*magData.fc;
868 
869  // --- zero out array; if filter not supported, this will return a bank of 0's!
870  memset(&magData.magArray[0], 0, magData.dftArrayLen * sizeof(double));
871 
872  for (int i = 0; i < dumpLength; i++)
873  {
874  double eval_w = 2.0*kPi*i*bin1;
875  double w_o = eval_w / w_c;
876 
877  if (magData.filterType == analogFilter::kLPF1)
878  {
879  double denXSq = 1.0 + (w_o*w_o);
880  magData.magArray[i] = 1.0 / (pow(denXSq, 0.5));
881  }
882  else if (magData.filterType == analogFilter::kHPF1)
883  {
884  double denXSq = 1.0 + (w_o*w_o);
885  magData.magArray[i] = w_o / (pow(denXSq, 0.5));
886  }
887  else if (magData.filterType == analogFilter::kLPF2)
888  {
889  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
890  magData.magArray[i] = 1.0 / (pow(denXSq, 0.5));
891  }
892  else if (magData.filterType == analogFilter::kHPF2)
893  {
894  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
895  magData.magArray[i] = (w_o*w_o) / (pow(denXSq, 0.5));
896  }
897  else if (magData.filterType == analogFilter::kBPF2)
898  {
899  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
900  magData.magArray[i] = 2.0*w_o*zeta / (pow(denXSq, 0.5));
901  }
902  else if (magData.filterType == analogFilter::kBSF2)
903  {
904  double numXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o));
905  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
906  magData.magArray[i] = (pow(numXSq, 0.5)) / (pow(denXSq, 0.5));
907  }
908  }
909 
910  // -- make sure have legal first half...
911  if (!magData.mirrorMag)
912  return true;
913 
914  // --- now mirror the other half
915  int index = magData.dftArrayLen / 2 - 1;
916  for (unsigned int i = magData.dftArrayLen / 2; i <magData.dftArrayLen; i++)
917  {
918  magData.magArray[i] = magData.magArray[index--];
919  }
920 
921  return true;
922 }
923 
936 inline void freqSample(int N, double A[], double h[], int symm)
937 {
938  int n, k;
939  double x, val, M;
940 
941  M = (N - 1.0) / 2.0;
942  if (symm == POSITIVE)
943  {
944  if (N % 2)
945  {
946  for (n = 0; n<N; n++)
947  {
948  val = A[0];
949  x = kTwoPi * (n - M) / N;
950  for (k = 1; k <= M; k++)
951  val += 2.0 * A[k] * cos(x*k);
952  h[n] = val / N;
953  }
954  }
955  else
956  {
957  for (n = 0; n<N; n++)
958  {
959  val = A[0];
960  x = kTwoPi * (n - M) / N;
961  for (k = 1; k <= (N / 2 - 1); k++)
962  val += 2.0 * A[k] * cos(x*k);
963  h[n] = val / N;
964  }
965  }
966  }
967  else
968  {
969  if (N % 2)
970  {
971  for (n = 0; n<N; n++)
972  {
973  val = 0;
974  x = kTwoPi * (n - M) / N;
975  for (k = 1; k <= M; k++)
976  val += 2.0 * A[k] * sin(x*k);
977  h[n] = val / N;
978  }
979  }
980  else
981  {
982  for (n = 0; n<N; n++)
983  {
984  val = A[N / 2] * sin(kPi * (n - M));
985  x = kTwoPi * (n - M) / N;
986  for (k = 1; k <= (N / 2 - 1); k++)
987  val += 2.0 * A[k] * sin(x*k);
988  h[n] = val / N;
989  }
990  }
991  }
992 }
993 
1004 inline double getMagnitude(double re, double im)
1005 {
1006  return sqrt((re*re) + (im*im));
1007 }
1008 
1019 inline double getPhase(double re, double im)
1020 {
1021  return atan2(im, re);
1022 }
1023 
1034 inline double principalArg(double phaseIn)
1035 {
1036  if (phaseIn >= 0)
1037  return fmod(phaseIn + kPi, kTwoPi) - kPi;
1038  else
1039  return fmod(phaseIn + kPi, -kTwoPi) + kPi;
1040 }
1041 
1042 enum class interpolation {kLinear, kLagrange4};
1043 
1061 inline bool resample(double* input, double* output, uint32_t inLength, uint32_t outLength,
1062  interpolation interpType = interpolation::kLinear,
1063  double scalar = 1.0, double* outWindow = nullptr)
1064 {
1065  if (inLength == 0 || outLength == 0) return false;
1066  if (!input || !output) return false;
1067 
1068  double x[4] = { 0.0 };
1069  double y[4] = { 0.0 };
1070 
1071  // --- inc
1072  double inc = (double)inLength / (double)(outLength);
1073 
1074  // --- first point
1075  if (outWindow)
1076  output[0] = outWindow[0] * scalar * input[0];
1077  else
1078  output[0] = scalar * input[0];
1079 
1080  if (interpType == interpolation::kLagrange4)
1081  {
1082  for (unsigned int i = 1; i < outLength; i++)
1083  {
1084  // --- find interpolation location
1085  double xInterp = i*inc;
1086  int x1 = (int)xInterp; // floor?
1087  double xbar = xInterp - x1;
1088 
1089  if (xInterp > 1 && x1 < outLength-2)
1090  {
1091  x[0] = x1 - 1;
1092  y[0] = input[(int)x[0]];
1093 
1094  x[1] = x1;
1095  y[1] = input[(int)x[1]];
1096 
1097  x[2] = x1 + 1;
1098  y[2] = input[(int)x[2]];
1099 
1100  x[3] = x1 + 2;
1101  y[3] = input[(int)x[3]];
1102 
1103  if (outWindow)
1104  output[i] = outWindow[i] * scalar * doLagrangeInterpolation(x, y, 4, xInterp);
1105  else
1106  output[i] = scalar * doLagrangeInterpolation(x, y, 4, xInterp);
1107  }
1108  else // --- linear for outer 2 end pts
1109  {
1110  int x2 = x1 + 1;
1111  if (x2 >= outLength)
1112  x2 = x1;
1113  double y1 = input[x1];
1114  double y2 = input[x2];
1115 
1116  if (outWindow)
1117  output[i] = outWindow[i] * scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1118  else
1119  output[i] = scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1120  }
1121  }
1122  }
1123  else // must be linear
1124  {
1125  // --- LINEAR INTERP
1126  for (unsigned int i = 1; i < outLength; i++)
1127  {
1128  double xInterp = i*inc;
1129  int x1 = (int)xInterp; // floor?
1130  int x2 = x1 + 1;
1131  if (x2 >= outLength)
1132  x2 = x1;
1133  double y1 = input[x1];
1134  double y2 = input[x2];
1135 
1136  if (outWindow)
1137  output[i] = outWindow[i] * scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1138  else
1139  output[i] = scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1140  }
1141  }
1142 
1143  return true;
1144 }
1145 
1146 // ------------------------------------------------------------------ //
1147 // --- INTERFACES --------------------------------------------------- //
1148 // ------------------------------------------------------------------ //
1149 
1162 {
1163 public:
1164  // --- pure virtual, derived classes must implement or will not compile
1165  // also means this is a pure abstract base class and is incomplete,
1166  // so it can only be used as a base class
1167  //
1169  virtual bool reset(double _sampleRate) = 0;
1170 
1172  virtual double processAudioSample(double xn) = 0;
1173 
1175  virtual bool canProcessAudioFrame() = 0;
1176 
1178  virtual void setSampleRate(double _sampleRate) {}
1179 
1181  virtual void enableAuxInput(bool enableAuxInput) {}
1182 
1185  virtual double processAuxInputAudioSample(double xn)
1186  {
1187  // --- do nothing
1188  return xn;
1189  }
1190 
1195  virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
1196  float* outputFrame,
1197  uint32_t inputChannels,
1198  uint32_t outputChannels)
1199  {
1200  // --- do nothing
1201  return false; // NOT handled
1202  }
1203 };
1204 
1216 // --- structure to send output data from signal gen; you can add more outputs here
1218 {
1219  SignalGenData() {}
1220 
1221  double normalOutput = 0.0;
1222  double invertedOutput = 0.0;
1223  double quadPhaseOutput_pos = 0.0;
1224  double quadPhaseOutput_neg = 0.0;
1225 };
1226 
1242 {
1243 public:
1244  // --- pure virtual, derived classes must implement or will not compile
1245  // also means this is a pure abstract base class and is incomplete,
1246  // so it can only be used as a base class
1247  //
1249  virtual bool reset(double _sampleRate) = 0;
1250 
1252  virtual const SignalGenData renderAudioOutput() = 0;
1253 };
1254 
1255 
1256 
1257 // ------------------------------------------------------------------ //
1258 // --- OBJECTS ------------------------------------------------------ //
1259 // ------------------------------------------------------------------ //
1260 /*
1261 Class Declarations :
1262 
1263 class name : public IAudioSignalProcessor
1264  - IAudioSignalProcessor functions
1265  - member functions that may be called externally
1266  - mutators & accessors
1267  - helper functions(may be private / protected if needed)
1268  - protected member functions
1269 */
1270 
1285 // a0 = 0, a1 = 1, a2 = 2, b1 = 3, b2 = 4, numCoeffs = 5
1286 enum filterCoeff { a0, a1, a2, b1, b2, c0, d0, numCoeffs };
1287 
1304 // --- state array index values
1305 // z^-1 registers;
1306 // Direct Forms: we will allow max of 2 for X (feedforward) and 2 for Y (feedback) data
1307 // Transpose Forms: we will use ONLY the x_z1 and x_z2 registers for the 2 required delays
1308 enum stateReg { x_z1, x_z2, y_z1, y_z2, numStates };
1309 
1324 // --- type of calculation (algorithm)
1325 enum class biquadAlgorithm { kDirect, kCanonical, kTransposeDirect, kTransposeCanonical }; // 4 types of biquad calculations, constants (k)
1326 
1327 
1340 {
1341  BiquadParameters () {}
1342 
1345  {
1346  if (this == &params)
1347  return *this;
1348 
1349  biquadCalcType = params.biquadCalcType;
1350  return *this;
1351  }
1352 
1353  biquadAlgorithm biquadCalcType = biquadAlgorithm::kDirect;
1354 };
1355 
1374 {
1375 public:
1376  Biquad() {} /* C-TOR */
1377  ~Biquad() {} /* D-TOR */
1378 
1379  // --- IAudioSignalProcessor FUNCTIONS --- //
1380  //
1382  virtual bool reset(double _sampleRate)
1383  {
1384  memset(&stateArray[0], 0, sizeof(double)*numStates);
1385  return true; // handled = true
1386  }
1387 
1389  virtual bool canProcessAudioFrame() { return false; }
1390 
1396  virtual double processAudioSample(double xn);
1397 
1403 
1408  void setParameters(const BiquadParameters& _parameters){ parameters = _parameters; }
1409 
1410  // --- MUTATORS & ACCESSORS --- //
1412  void setCoefficients(double* coeffs){
1413  // --- fast block memory copy:
1414  memcpy(&coeffArray[0], &coeffs[0], sizeof(double)*numCoeffs);
1415  }
1416 
1419  {
1420  // --- read/write access to the array (not used)
1421  return &coeffArray[0];
1422  }
1423 
1425  double* getStateArray()
1426  {
1427  // --- read/write access to the array (used only in direct form oscillator)
1428  return &stateArray[0];
1429  }
1430 
1432  double getG_value() { return coeffArray[a0]; }
1433 
1435  double getS_value() { return storageComponent; }
1436 
1437 protected:
1439  double coeffArray[numCoeffs] = { 0.0 };
1440 
1442  double stateArray[numStates] = { 0.0 };
1443 
1446 
1448  double storageComponent = 0.0;
1449 };
1450 
1451 
1465 enum class filterAlgorithm {
1466  kLPF1P, kLPF1, kHPF1, kLPF2, kHPF2, kBPF2, kBSF2, kButterLPF2, kButterHPF2, kButterBPF2,
1467  kButterBSF2, kMMALPF2, kMMALPF2B, kLowShelf, kHiShelf, kNCQParaEQ, kCQParaEQ, kLWRLPF2, kLWRHPF2,
1468  kAPF1, kAPF2, kResonA, kResonB, kMatchLP2A, kMatchLP2B, kMatchBP2A, kMatchBP2B,
1469  kImpInvLP1, kImpInvLP2
1470 }; // --- you will add more here...
1471 
1472 
1485 {
1488  AudioFilterParameters& operator=(const AudioFilterParameters& params) // need this override for collections to work
1489  {
1490  if (this == &params)
1491  return *this;
1492  algorithm = params.algorithm;
1493  fc = params.fc;
1494  Q = params.Q;
1495  boostCut_dB = params.boostCut_dB;
1496 
1497  return *this;
1498  }
1499 
1500  // --- individual parameters
1501  filterAlgorithm algorithm = filterAlgorithm::kLPF1;
1502  double fc = 100.0;
1503  double Q = 0.707;
1504  double boostCut_dB = 0.0;
1505 };
1506 
1525 {
1526 public:
1527  AudioFilter() {} /* C-TOR */
1528  ~AudioFilter() {} /* D-TOR */
1529 
1530  // --- IAudioSignalProcessor
1532  virtual bool reset(double _sampleRate)
1533  {
1535  bqp.biquadCalcType = biquadAlgorithm::kTransposeCanonical;
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 
1589 protected:
1590  // --- our calculator
1592 
1593  // --- array to hold coeffs (we need them too)
1594  double coeffArray[numCoeffs] = { 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;
1650  splitFrequency = params.splitFrequency;
1651  return *this;
1652  }
1653 
1654  // --- individual parameters
1655  double splitFrequency = 1000.0;
1656 };
1657 
1658 
1679 {
1680 public:
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 
1759 protected:
1762 
1763  // --- object parameters
1765 };
1766 
1767 // --- constants
1768 const unsigned int TLD_AUDIO_DETECT_MODE_PEAK = 0;
1769 const unsigned int TLD_AUDIO_DETECT_MODE_MS = 1;
1770 const unsigned int TLD_AUDIO_DETECT_MODE_RMS = 2;
1771 const 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 {
1833 public:
1834  AudioDetector() {} /* C-TOR */
1835  ~AudioDetector() {} /* D-TOR */
1836 
1837 public:
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  {
1910  return audioDetectorParameters;
1911  }
1912 
1917  void setParameters(const AudioDetectorParameters& parameters)
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 
1940 protected:
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
1972 enum 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;
1998  hardLimitGate = params.hardLimitGate;
1999  softKnee = params.softKnee;
2001  calculation = params.calculation;
2004  outputGain_dB = params.outputGain_dB;
2005  // --- NOTE: do not set outbound variables??
2006  gainReduction = params.gainReduction;
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 {
2047 public:
2048  DynamicsProcessor() {} /* C-TOR */
2049  ~DynamicsProcessor() {} /* D-TOR */
2050 
2051 public:
2053  virtual bool reset(double _sampleRate)
2054  {
2055  sidechainInputSample = 0.0;
2056  detector.reset(_sampleRate);
2057  AudioDetectorParameters detectorParams = detector.getParameters();
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  {
2073  sidechainInputSample = xn;
2074  return sidechainInputSample;
2075  }
2076 
2082 
2088  {
2089  parameters = _parameters;
2090 
2091  AudioDetectorParameters detectorParams = detector.getParameters();
2092  detectorParams.attackTime_mSec = parameters.attackTime_mSec;
2093  detectorParams.releaseTime_mSec = parameters.releaseTime_mSec;
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 
2128 protected:
2131 
2132  // --- storage for sidechain audio input (mono only)
2133  double sidechainInputSample = 0.0;
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;
2213  parameters.gainReduction = pow(10.0, (parameters.gainReduction_dB) / 20.0);
2214 
2215  // --- the current gain coefficient value
2216  return parameters.gainReduction;
2217  }
2218 };
2219 
2231 template <typename T>
2233 {
2234 public:
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 
2273 private:
2274  std::unique_ptr<T[]> buffer = nullptr;
2275  unsigned int bufferLength = 1024;
2276 };
2277 
2278 
2293 template <typename T>
2295 {
2296 public:
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 
2380 private:
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 {
2409 public:
2410  ImpulseConvolver() {
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
2460  signalBuffer.createCircularBufferPowerOfTwo(lengthPowerOfTwo);
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
2471  signalBuffer.createCircularBufferPowerOfTwo(lengthPowerOfTwo);
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 
2482 protected:
2483  // --- delay buffer of doubles
2486 
2487  unsigned int length = 0;
2488 
2489 };
2490 
2491 const 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 {
2548 public:
2549  AnalogFIRFilter() {} /* C-TOR */
2550  ~AnalogFIRFilter() {} /* D-TOR */
2551 
2552 public:
2554  virtual bool reset(double _sampleRate)
2555  {
2556  sampleRate = _sampleRate;
2557  convolver.reset(_sampleRate);
2558  convolver.init(IR_LEN);
2559  return true;
2560  }
2561 
2567  virtual double processAudioSample(double xn)
2568  {
2569  // --- do the linear convolution
2570  return convolver.processAudioSample(xn);
2571  }
2572 
2574  virtual bool canProcessAudioFrame() { return false; }
2575 
2580  AnalogFIRFilterParameters getParameters() { return parameters; }
2581 
2587  {
2588  if (_parameters.fc != parameters.fc ||
2589  _parameters.Q != parameters.Q ||
2590  _parameters.filterType != parameters.filterType)
2591  {
2592  // --- set the filter IR for the convolver
2593  AnalogMagData analogFilterData;
2594  analogFilterData.sampleRate = sampleRate;
2595  analogFilterData.magArray = &analogMagArray[0];
2596  analogFilterData.dftArrayLen = IR_LEN;
2597  analogFilterData.mirrorMag = false;
2598 
2599  analogFilterData.filterType = _parameters.filterType;
2600  analogFilterData.fc = _parameters.fc; // 1000.0;
2601  analogFilterData.Q = _parameters.Q;
2602 
2603  // --- calculate the analog mag array
2604  calculateAnalogMagArray(analogFilterData);
2605 
2606  // --- frequency sample the mag array
2607  freqSample(IR_LEN, analogMagArray, irArray, POSITIVE);
2608 
2609  // --- update new frequency response
2610  convolver.setImpulseResponse(irArray, IR_LEN);
2611  }
2612 
2613  parameters = _parameters;
2614  }
2615 
2616 private:
2617  AnalogFIRFilterParameters parameters;
2618  ImpulseConvolver convolver;
2619  double analogMagArray[IR_LEN] = { 0.0 };
2620  double irArray[IR_LEN] = { 0.0 };
2621  double sampleRate = 0.0;
2622 };
2623 
2637 enum class delayAlgorithm { kNormal, kPingPong };
2638 
2653 enum class delayUpdateType { kLeftAndRight, kLeftPlusRatio };
2654 
2655 
2668 {
2671  AudioDelayParameters& operator=(const AudioDelayParameters& params) // need this override for collections to work
2672  {
2673  if (this == &params)
2674  return *this;
2675 
2676  algorithm = params.algorithm;
2677  wetLevel_dB = params.wetLevel_dB;
2678  dryLevel_dB = params.dryLevel_dB;
2679  feedback_Pct = params.feedback_Pct;
2680 
2681  updateType = params.updateType;
2682  leftDelay_mSec = params.leftDelay_mSec;
2684  delayRatio_Pct = params.delayRatio_Pct;
2685 
2686  return *this;
2687  }
2688 
2689  // --- individual parameters
2690  delayAlgorithm algorithm = delayAlgorithm::kNormal;
2691  double wetLevel_dB = -3.0;
2692  double dryLevel_dB = -3.0;
2693  double feedback_Pct = 0.0;
2694 
2695  delayUpdateType updateType = delayUpdateType::kLeftAndRight;
2696  double leftDelay_mSec = 0.0;
2697  double rightDelay_mSec = 0.0;
2698  double delayRatio_Pct = 100.0;
2699 };
2700 
2719 {
2720 public:
2721  AudioDelay() {} /* C-TOR */
2722  ~AudioDelay() {} /* D-TOR */
2723 
2724 public:
2726  virtual bool reset(double _sampleRate)
2727  {
2728  // --- if sample rate did not change
2729  if (sampleRate == _sampleRate)
2730  {
2731  // --- just flush buffer and return
2732  delayBuffer_L.flushBuffer();
2733  delayBuffer_R.flushBuffer();
2734  return true;
2735  }
2736 
2737  // --- create new buffer, will store sample rate and length(mSec)
2738  createDelayBuffers(_sampleRate, bufferLength_mSec);
2739 
2740  return true;
2741  }
2742 
2748  virtual double processAudioSample(double xn)
2749  {
2750  // --- read delay
2751  double yn = delayBuffer_L.readBuffer(delayInSamples_L);
2752 
2753  // --- create input for delay buffer
2754  double dn = xn + (parameters.feedback_Pct / 100.0) * yn;
2755 
2756  // --- write to delay buffer
2757  delayBuffer_L.writeBuffer(dn);
2758 
2759  // --- form mixture out = dry*xn + wet*yn
2760  double output = dryMix*xn + wetMix*yn;
2761 
2762  return output;
2763  }
2764 
2766  virtual bool canProcessAudioFrame() { return true; }
2767 
2769  virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
2770  float* outputFrame,
2771  uint32_t inputChannels,
2772  uint32_t outputChannels)
2773  {
2774  // --- make sure we have input and outputs
2775  if (inputChannels == 0 || outputChannels == 0)
2776  return false;
2777 
2778  // --- make sure we support this delay algorithm
2779  if (parameters.algorithm != delayAlgorithm::kNormal &&
2780  parameters.algorithm != delayAlgorithm::kPingPong)
2781  return false;
2782 
2783  // --- if only one output channel, revert to mono operation
2784  if (outputChannels == 1)
2785  {
2786  // --- process left channel only
2787  outputFrame[0] = processAudioSample(inputFrame[0]);
2788  return true;
2789  }
2790 
2791  // --- if we get here we know we have 2 output channels
2792  //
2793  // --- pick up inputs
2794  //
2795  // --- LEFT channel
2796  double xnL = inputFrame[0];
2797 
2798  // --- RIGHT channel (duplicate left input if mono-in)
2799  double xnR = inputChannels > 1 ? inputFrame[1] : xnL;
2800 
2801  // --- read delay LEFT
2802  double ynL = delayBuffer_L.readBuffer(delayInSamples_L);
2803 
2804  // --- read delay RIGHT
2805  double ynR = delayBuffer_R.readBuffer(delayInSamples_R);
2806 
2807  // --- create input for delay buffer with LEFT channel info
2808  double dnL = xnL + (parameters.feedback_Pct / 100.0) * ynL;
2809 
2810  // --- create input for delay buffer with RIGHT channel info
2811  double dnR = xnR + (parameters.feedback_Pct / 100.0) * ynR;
2812 
2813  // --- decode
2814  if (parameters.algorithm == delayAlgorithm::kNormal)
2815  {
2816  // --- write to LEFT delay buffer with LEFT channel info
2817  delayBuffer_L.writeBuffer(dnL);
2818 
2819  // --- write to RIGHT delay buffer with RIGHT channel info
2820  delayBuffer_R.writeBuffer(dnR);
2821  }
2822  else if (parameters.algorithm == delayAlgorithm::kPingPong)
2823  {
2824  // --- write to LEFT delay buffer with RIGHT channel info
2825  delayBuffer_L.writeBuffer(dnR);
2826 
2827  // --- write to RIGHT delay buffer with LEFT channel info
2828  delayBuffer_R.writeBuffer(dnL);
2829  }
2830 
2831  // --- form mixture out = dry*xn + wet*yn
2832  double outputL = dryMix*xnL + wetMix*ynL;
2833 
2834  // --- form mixture out = dry*xn + wet*yn
2835  double outputR = dryMix*xnR + wetMix*ynR;
2836 
2837  // --- set left channel
2838  outputFrame[0] = outputL;
2839 
2840  // --- set right channel
2841  outputFrame[1] = outputR;
2842 
2843  return true;
2844  }
2845 
2850  AudioDelayParameters getParameters() { return parameters; }
2851 
2857  {
2858  // --- check mix in dB for calc
2859  if (_parameters.dryLevel_dB != parameters.dryLevel_dB)
2860  dryMix = pow(10.0, _parameters.dryLevel_dB / 20.0);
2861  if (_parameters.wetLevel_dB != parameters.wetLevel_dB)
2862  wetMix = pow(10.0, _parameters.wetLevel_dB / 20.0);
2863 
2864  // --- save; rest of updates are cheap on CPU
2865  parameters = _parameters;
2866 
2867  // --- check update type first:
2868  if (parameters.updateType == delayUpdateType::kLeftAndRight)
2869  {
2870  // --- set left and right delay times
2871  // --- calculate total delay time in samples + fraction
2872  double newDelayInSamples_L = parameters.leftDelay_mSec*(samplesPerMSec);
2873  double newDelayInSamples_R = parameters.rightDelay_mSec*(samplesPerMSec);
2874 
2875  // --- new delay time with fraction
2876  delayInSamples_L = newDelayInSamples_L;
2877  delayInSamples_R = newDelayInSamples_R;
2878  }
2879  else if (parameters.updateType == delayUpdateType::kLeftPlusRatio)
2880  {
2881  // --- get and validate ratio
2882  double delayRatio = parameters.delayRatio_Pct / 100.0;
2883  boundValue(delayRatio, 0.0, 1.0);
2884 
2885  // --- calculate total delay time in samples + fraction
2886  double newDelayInSamples = parameters.leftDelay_mSec*(samplesPerMSec);
2887 
2888  // --- new delay time with fraction
2889  delayInSamples_L = newDelayInSamples;
2890  delayInSamples_R = delayInSamples_L*delayRatio;
2891  }
2892  }
2893 
2895  void createDelayBuffers(double _sampleRate, double _bufferLength_mSec)
2896  {
2897  // --- store for math
2898  bufferLength_mSec = _bufferLength_mSec;
2899  sampleRate = _sampleRate;
2900  samplesPerMSec = sampleRate / 1000.0;
2901 
2902  // --- total buffer length including fractional part
2903  bufferLength = (unsigned int)(bufferLength_mSec*(samplesPerMSec)) + 1; // +1 for fractional part
2904 
2905  // --- create new buffer
2906  delayBuffer_L.createCircularBuffer(bufferLength);
2907  delayBuffer_R.createCircularBuffer(bufferLength);
2908  }
2909 
2910 private:
2911  AudioDelayParameters parameters;
2912 
2913  double sampleRate = 0.0;
2914  double samplesPerMSec = 0.0;
2915  double delayInSamples_L = 0.0;
2916  double delayInSamples_R = 0.0;
2917  double bufferLength_mSec = 0.0;
2918  unsigned int bufferLength = 0;
2919  double wetMix = 0.707;
2920  double dryMix = 0.707;
2921 
2922  // --- delay buffer of doubles
2923  CircularBuffer<double> delayBuffer_L;
2924  CircularBuffer<double> delayBuffer_R;
2925 };
2926 
2927 
2941 enum class generatorWaveform { kTriangle, kSin, kSaw };
2942 
2955 {
2958  OscillatorParameters& operator=(const OscillatorParameters& params) // need this override for collections to work
2959  {
2960  if (this == &params)
2961  return *this;
2962 
2963  waveform = params.waveform;
2964  frequency_Hz = params.frequency_Hz;
2965  return *this;
2966  }
2967 
2968  // --- individual parameters
2969  generatorWaveform waveform = generatorWaveform::kTriangle;
2970  double frequency_Hz = 0.0;
2971 };
2972 
2992 {
2993 public:
2994  LFO() { srand(time(NULL)); } /* C-TOR */
2995  virtual ~LFO() {} /* D-TOR */
2996 
2998  virtual bool reset(double _sampleRate)
2999  {
3000  sampleRate = _sampleRate;
3002 
3003  // --- timebase variables
3004  modCounter = 0.0;
3005  modCounterQP = 0.25;
3006 
3007  return true;
3008  }
3009 
3015 
3021  {
3023  // --- update phase inc based on osc freq and fs
3024  phaseInc = params.frequency_Hz / sampleRate;
3025 
3026  lfoParameters = params;
3027  }
3028 
3030  virtual const SignalGenData renderAudioOutput();
3031 
3032 protected:
3033  // --- parameters
3035 
3036  // --- sample rate
3037  double sampleRate = 0.0;
3038 
3039  // --- timebase variables
3040  double modCounter = 0.0;
3041  double phaseInc = 0.0;
3042  double modCounterQP = 0.25;
3043 
3045  inline bool checkAndWrapModulo(double& moduloCounter, double phaseInc)
3046  {
3047  // --- for positive frequencies
3048  if (phaseInc > 0 && moduloCounter >= 1.0)
3049  {
3050  moduloCounter -= 1.0;
3051  return true;
3052  }
3053 
3054  // --- for negative frequencies
3055  if (phaseInc < 0 && moduloCounter <= 0.0)
3056  {
3057  moduloCounter += 1.0;
3058  return true;
3059  }
3060 
3061  return false;
3062  }
3063 
3065  inline bool advanceAndCheckWrapModulo(double& moduloCounter, double phaseInc)
3066  {
3067  // --- advance counter
3068  moduloCounter += phaseInc;
3069 
3070  // --- for positive frequencies
3071  if (phaseInc > 0 && moduloCounter >= 1.0)
3072  {
3073  moduloCounter -= 1.0;
3074  return true;
3075  }
3076 
3077  // --- for negative frequencies
3078  if (phaseInc < 0 && moduloCounter <= 0.0)
3079  {
3080  moduloCounter += 1.0;
3081  return true;
3082  }
3083 
3084  return false;
3085  }
3086 
3088  inline void advanceModulo(double& moduloCounter, double phaseInc) { moduloCounter += phaseInc; }
3089 
3090  const double B = 4.0 / kPi;
3091  const double C = -4.0 / (kPi* kPi);
3092  const double P = 0.225;
3094  inline double parabolicSine(double angle)
3095  {
3096  double y = B * angle + C * angle * fabs(angle);
3097  y = P * (y * fabs(y) - y) + y;
3098  return y;
3099  }
3100 };
3101 
3115 enum DFOscillatorCoeffs { df_b1, df_b2, numDFOCoeffs };
3116 
3130 enum DFOscillatorStates { df_yz1, df_yz2, numDFOStates };
3131 
3132 
3152 {
3153 public:
3154  DFOscillator() { } /* C-TOR */
3155  virtual ~DFOscillator() {} /* D-TOR */
3156 
3158  virtual bool reset(double _sampleRate)
3159  {
3160  sampleRate = _sampleRate;
3161  memset(&stateArray[0], 0, sizeof(double)*numDFOStates);
3162  updateDFO();
3163  return true;
3164  }
3165 
3171  {
3172  return parameters;
3173  }
3174 
3180  {
3181  if (parameters.frequency_Hz != params.frequency_Hz)
3182  {
3183  parameters = params;
3184  updateDFO();
3185  }
3186  }
3187 
3190  {
3191  // --- calculates normal and inverted outputs; quadphase are not used
3192  SignalGenData output;
3193 
3194  // -- do difference equation y(n) = -b1y(n-2) - b2y(n-2)
3195  output.normalOutput = (-coeffArray[df_b1]*stateArray[df_yz1] - coeffArray[df_b2]*stateArray[df_yz2]);
3196  output.invertedOutput = -output.normalOutput;
3197 
3198  // --- update states
3199  stateArray[df_yz2] = stateArray[df_yz1];
3200  stateArray[df_yz1] = output.normalOutput;
3201 
3202  return output;
3203  }
3204 
3206  void updateDFO()
3207  {
3208  // --- Oscillation Rate = theta = wT = w/fs
3209  double wT = (kTwoPi*parameters.frequency_Hz) / sampleRate;
3210 
3211  // --- coefficients to place poles right on unit circle
3212  coeffArray[df_b1] = -2.0*cos(wT); // <--- set angle a = -2Rcod(theta)
3213  coeffArray[df_b2] = 1.0; // <--- R^2 = 1, so R = 1
3214 
3215  // --- now update states to reflect the new frequency
3216  // re calculate the new initial conditions
3217  // arcsine of y(n-1) gives us wnT
3218  double wnT1 = asin(stateArray[df_yz1]);
3219 
3220  // find n by dividing wnT by wT
3221  double n = wnT1 / wT;
3222 
3223  // --- re calculate the new initial conditions
3224  // asin returns values from -pi/2 to +pi/2 where the sinusoid
3225  // moves from -1 to +1 -- the leading (rising) edge of the
3226  // sinewave. If we are on that leading edge (increasing)
3227  // then we use the value 1T behind.
3228  //
3229  // If we are on the falling edge, we use the value 1T ahead
3230  // because it mimics the value that would be 1T behind
3231  if (stateArray[df_yz1] > stateArray[df_yz2])
3232  n -= 1;
3233  else
3234  n += 1;
3235 
3236  // --- calculate the new (old) sample
3237  stateArray[df_yz2] = sin((n)*wT);
3238  }
3239 
3240 
3241 protected:
3242  // --- parameters
3244 
3245  // --- implementation of half a biquad - this object is extremely specific
3246  double stateArray[numDFOStates] = { 0.0 };
3247  double coeffArray[numDFOCoeffs] = { 0.0 };
3248 
3249  // --- sample rate
3250  double sampleRate = 0.0;
3251 };
3252 
3253 
3267 enum class modDelaylgorithm { kFlanger, kChorus, kVibrato };
3268 
3269 
3282 {
3285  ModulatedDelayParameters& operator=(const ModulatedDelayParameters& params) // need this override for collections to work
3286  {
3287  if (this == &params)
3288  return *this;
3289 
3290  algorithm = params.algorithm;
3291  lfoRate_Hz = params.lfoRate_Hz;
3292  lfoDepth_Pct = params.lfoDepth_Pct;
3293  feedback_Pct = params.feedback_Pct;
3294  return *this;
3295  }
3296 
3297  // --- individual parameters
3298  modDelaylgorithm algorithm = modDelaylgorithm::kFlanger;
3299  double lfoRate_Hz = 0.0;
3300  double lfoDepth_Pct = 0.0;
3301  double feedback_Pct = 0.0;
3302 };
3303 
3322 {
3323 public:
3324  ModulatedDelay() {
3325  } /* C-TOR */
3326  ~ModulatedDelay() {} /* D-TOR */
3327 
3328 public:
3330  virtual bool reset(double _sampleRate)
3331  {
3332  // --- create new buffer, 100mSec long
3333  delay.reset(_sampleRate);
3334  delay.createDelayBuffers(_sampleRate, 100.0);
3335 
3336  // --- lfo
3337  lfo.reset(_sampleRate);
3338  OscillatorParameters params = lfo.getParameters();
3339  params.waveform = generatorWaveform::kTriangle;
3340  lfo.setParameters(params);
3341 
3342  return true;
3343  }
3344 
3350  virtual double processAudioSample(double xn)
3351  {
3352  float input = xn;
3353  float output = 0.0;
3354  processAudioFrame(&input, &output, 1, 1);
3355  return output;
3356  }
3357 
3359  virtual bool canProcessAudioFrame() { return true; }
3360 
3362  virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
3363  float* outputFrame,
3364  uint32_t inputChannels,
3365  uint32_t outputChannels)
3366  {
3367  // --- make sure we have input and outputs
3368  if (inputChannels == 0 || outputChannels == 0)
3369  return false;
3370 
3371  // --- render LFO
3372  SignalGenData lfoOutput = lfo.renderAudioOutput();
3373 
3374  // --- setup delay modulation
3375  AudioDelayParameters params = delay.getParameters();
3376  double minDelay_mSec = 0.0;
3377  double maxDepth_mSec = 0.0;
3378 
3379  // --- set delay times, wet/dry and feedback
3380  if (parameters.algorithm == modDelaylgorithm::kFlanger)
3381  {
3382  minDelay_mSec = 0.1;
3383  maxDepth_mSec = 7.0;
3384  params.wetLevel_dB = -3.0;
3385  params.dryLevel_dB = -3.0;
3386  }
3387  if (parameters.algorithm == modDelaylgorithm::kChorus)
3388  {
3389  minDelay_mSec = 10.0;
3390  maxDepth_mSec = 30.0;
3391  params.wetLevel_dB = -3.0;
3392  params.dryLevel_dB = -0.0;
3393  params.feedback_Pct = 0.0;
3394  }
3395  if (parameters.algorithm == modDelaylgorithm::kVibrato)
3396  {
3397  minDelay_mSec = 0.0;
3398  maxDepth_mSec = 7.0;
3399  params.wetLevel_dB = 0.0;
3400  params.dryLevel_dB = -96.0;
3401  params.feedback_Pct = 0.0;
3402  }
3403 
3404  // --- calc modulated delay times
3405  double depth = parameters.lfoDepth_Pct / 100.0;
3406  double modulationMin = minDelay_mSec;
3407  double modulationMax = minDelay_mSec + maxDepth_mSec;
3408 
3409  // --- flanger - unipolar
3410  if (parameters.algorithm == modDelaylgorithm::kFlanger)
3412  modulationMin, modulationMax);
3413  else
3414  params.leftDelay_mSec = doBipolarModulation(depth * lfoOutput.normalOutput, modulationMin, modulationMax);
3415 
3416 
3417  // --- set right delay to match (*Hint Homework!)
3418  params.rightDelay_mSec = params.leftDelay_mSec;
3419 
3420  // --- modulate the delay
3421  delay.setParameters(params);
3422 
3423  // --- just call the function and pass our info in/out
3424  return delay.processAudioFrame(inputFrame, outputFrame, inputChannels, outputChannels);
3425  }
3426 
3431  ModulatedDelayParameters getParameters() { return parameters; }
3432 
3438  {
3439  // --- bulk copy
3440  parameters = _parameters;
3441 
3442  OscillatorParameters lfoParams = lfo.getParameters();
3443  lfoParams.frequency_Hz = parameters.lfoRate_Hz;
3444  if (parameters.algorithm == modDelaylgorithm::kVibrato)
3445  lfoParams.waveform = generatorWaveform::kSin;
3446  else
3447  lfoParams.waveform = generatorWaveform::kTriangle;
3448 
3449  lfo.setParameters(lfoParams);
3450 
3451  AudioDelayParameters adParams = delay.getParameters();
3452  adParams.feedback_Pct = parameters.feedback_Pct;
3453  delay.setParameters(adParams);
3454  }
3455 
3456 private:
3457  ModulatedDelayParameters parameters;
3458  AudioDelay delay;
3459  LFO lfo;
3460 };
3461 
3474 {
3478  {
3479  if (this == &params)
3480  return *this;
3481 
3482  lfoRate_Hz = params.lfoRate_Hz;
3483  lfoDepth_Pct = params.lfoDepth_Pct;
3484  intensity_Pct = params.intensity_Pct;
3485  quadPhaseLFO = params.quadPhaseLFO;
3486  return *this;
3487  }
3488 
3489  // --- individual parameters
3490  double lfoRate_Hz = 0.0;
3491  double lfoDepth_Pct = 0.0;
3492  double intensity_Pct = 0.0;
3493  bool quadPhaseLFO = false;
3494 };
3495 
3496 // --- constants for Phaser
3497 const unsigned int PHASER_STAGES = 6;
3498 const double apf0_minF = 16.0;
3499 const double apf0_maxF = 1600.0;
3500 
3501 const double apf1_minF = 33.0;
3502 const double apf1_maxF = 3300.0;
3503 
3504 const double apf2_minF = 48.0;
3505 const double apf2_maxF = 4800.0;
3506 
3507 const double apf3_minF = 98.0;
3508 const double apf3_maxF = 9800.0;
3509 
3510 const double apf4_minF = 160.0;
3511 const double apf4_maxF = 16000.0;
3512 
3513 const double apf5_minF = 260.0;
3514 const double apf5_maxF = 20480.0;
3515 
3534 {
3535 public:
3536  PhaseShifter(void) {
3537  OscillatorParameters lfoparams = lfo.getParameters();
3538  lfoparams.waveform = generatorWaveform::kSin;// sine LFO for phaser
3539  lfo.setParameters(lfoparams);
3540 
3541  AudioFilterParameters params = apf[0].getParameters();
3542  params.algorithm = filterAlgorithm::kAPF1;
3543 
3544  for (int i = 0; i < PHASER_STAGES; i++)
3545  {
3546  apf[i].setParameters(params);
3547  }
3548  } /* C-TOR */
3549 
3550  ~PhaseShifter(void) {} /* D-TOR */
3551 
3552 public:
3554  virtual bool reset(double _sampleRate)
3555  {
3556  // --- reset LFO
3557  lfo.reset(_sampleRate);
3558 
3559  // --- reset APFs
3560  for (int i = 0; i < PHASER_STAGES; i++){
3561  apf[i].reset(_sampleRate);
3562  }
3563 
3564  return true;
3565  }
3566 
3572  virtual double processAudioSample(double xn)
3573  {
3574  SignalGenData lfoData = lfo.renderAudioOutput();
3575 
3576  // --- create the bipolar modulator value
3577  double lfoValue = lfoData.normalOutput;
3579  lfoValue = lfoData.quadPhaseOutput_pos;
3580 
3581  double depth = parameters.lfoDepth_Pct / 100.0;
3582  double modulatorValue = lfoValue*depth;
3583 
3584  // --- calculate modulated values for each APF; note they have different ranges
3585  AudioFilterParameters params = apf[0].getParameters();
3586  params.fc = doBipolarModulation(modulatorValue, apf0_minF, apf0_maxF);
3587  apf[0].setParameters(params);
3588 
3589  params = apf[1].getParameters();
3590  params.fc = doBipolarModulation(modulatorValue, apf1_minF, apf1_maxF);
3591  apf[1].setParameters(params);
3592 
3593  params = apf[2].getParameters();
3594  params.fc = doBipolarModulation(modulatorValue, apf2_minF, apf2_maxF);
3595  apf[2].setParameters(params);
3596 
3597  params = apf[3].getParameters();
3598  params.fc = doBipolarModulation(modulatorValue, apf3_minF, apf3_maxF);
3599  apf[3].setParameters(params);
3600 
3601  params = apf[4].getParameters();
3602  params.fc = doBipolarModulation(modulatorValue, apf4_minF, apf4_maxF);
3603  apf[4].setParameters(params);
3604 
3605  params = apf[5].getParameters();
3606  params.fc = doBipolarModulation(modulatorValue, apf5_minF, apf5_maxF);
3607  apf[5].setParameters(params);
3608 
3609  // --- calculate gamma values
3610  double gamma1 = apf[5].getG_value();
3611  double gamma2 = apf[4].getG_value() * gamma1;
3612  double gamma3 = apf[3].getG_value() * gamma2;
3613  double gamma4 = apf[2].getG_value() * gamma3;
3614  double gamma5 = apf[1].getG_value() * gamma4;
3615  double gamma6 = apf[0].getG_value() * gamma5;
3616 
3617  // --- set the alpha0 value
3618  double K = parameters.intensity_Pct / 100.0;
3619  double alpha0 = 1.0 / (1.0 + K*gamma6);
3620 
3621  // --- create combined feedback
3622  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();
3623 
3624  // --- form input to first APF
3625  double u = alpha0*(xn - K*Sn);
3626 
3627  // --- cascade of APFs (could also nest these in one massive line of code)
3628  double APF1 = apf[0].processAudioSample(u);
3629  double APF2 = apf[1].processAudioSample(APF1);
3630  double APF3 = apf[2].processAudioSample(APF2);
3631  double APF4 = apf[3].processAudioSample(APF3);
3632  double APF5 = apf[4].processAudioSample(APF4);
3633  double APF6 = apf[5].processAudioSample(APF5);
3634 
3635  // --- sum with -3dB coefficients
3636  double output = 0.707*xn + 0.707*APF6;
3637  return output;
3638  }
3639 
3641  virtual bool canProcessAudioFrame() { return false; }
3642 
3648 
3654  {
3655  // --- update LFO rate
3656  if (params.lfoRate_Hz != parameters.lfoRate_Hz)
3657  {
3658  OscillatorParameters lfoparams = lfo.getParameters();
3659  lfoparams.frequency_Hz = params.lfoRate_Hz;
3660  lfo.setParameters(lfoparams);
3661  }
3662 
3663  // --- save new
3664  parameters = params;
3665  }
3666 protected:
3668  AudioFilter apf[PHASER_STAGES];
3670 };
3671 
3684 {
3685  SimpleLPFParameters() {}
3687  SimpleLPFParameters& operator=(const SimpleLPFParameters& params) // need this override for collections to work
3688  {
3689  if (this == &params)
3690  return *this;
3691 
3692  g = params.g;
3693  return *this;
3694  }
3695 
3696  // --- individual parameters
3697  double g = 0.0;
3698 };
3699 
3718 {
3719 public:
3720  SimpleLPF(void) {} /* C-TOR */
3721  ~SimpleLPF(void) {} /* D-TOR */
3722 
3723 public:
3725  virtual bool reset(double _sampleRate)
3726  {
3727  state = 0.0;
3728  return true;
3729  }
3730 
3736  {
3737  return simpleLPFParameters;
3738  }
3739 
3745  {
3746  simpleLPFParameters = params;
3747  }
3748 
3754  virtual double processAudioSample(double xn)
3755  {
3756  double g = simpleLPFParameters.g;
3757  double yn = (1.0 - g)*xn + g*state;
3758  state = yn;
3759  return yn;
3760  }
3761 
3763  virtual bool canProcessAudioFrame() { return false; }
3764 
3765 private:
3766  SimpleLPFParameters simpleLPFParameters;
3767  double state = 0.0;
3768 };
3769 
3782 {
3785  SimpleDelayParameters& operator=(const SimpleDelayParameters& params) // need this override for collections to work
3786  {
3787  if (this == &params)
3788  return *this;
3789 
3790  delayTime_mSec = params.delayTime_mSec;
3791  interpolate = params.interpolate;
3792  delay_Samples = params.delay_Samples;
3793  return *this;
3794  }
3795 
3796  // --- individual parameters
3797  double delayTime_mSec = 0.0;
3798  bool interpolate = false;
3799 
3800  // --- outbound parameters
3801  double delay_Samples = 0.0;
3802 };
3803 
3822 {
3823 public:
3824  SimpleDelay(void) {} /* C-TOR */
3825  ~SimpleDelay(void) {} /* D-TOR */
3826 
3827 public:
3829  virtual bool reset(double _sampleRate)
3830  {
3831  // --- if sample rate did not change
3832  if (sampleRate == _sampleRate)
3833  {
3834  // --- just flush buffer and return
3835  delayBuffer.flushBuffer();
3836  return true;
3837  }
3838 
3839  // --- create new buffer, will store sample rate and length(mSec)
3840  createDelayBuffer(_sampleRate, bufferLength_mSec);
3841 
3842  return true;
3843  }
3844 
3850  {
3851  return simpleDelayParameters;
3852  }
3853 
3859  {
3860  simpleDelayParameters = params;
3861  simpleDelayParameters.delay_Samples = simpleDelayParameters.delayTime_mSec*(samplesPerMSec);
3862  delayBuffer.setInterpolate(simpleDelayParameters.interpolate);
3863  }
3864 
3870  virtual double processAudioSample(double xn)
3871  {
3872  // --- read delay
3873  if (simpleDelayParameters.delay_Samples == 0)
3874  return xn;
3875 
3876  double yn = delayBuffer.readBuffer(simpleDelayParameters.delay_Samples);
3877 
3878  // --- write to delay buffer
3879  delayBuffer.writeBuffer(xn);
3880 
3881  // --- done
3882  return yn;
3883  }
3884 
3886  virtual bool canProcessAudioFrame() { return false; }
3887 
3889  void createDelayBuffer(double _sampleRate, double _bufferLength_mSec)
3890  {
3891  // --- store for math
3892  bufferLength_mSec = _bufferLength_mSec;
3893  sampleRate = _sampleRate;
3894  samplesPerMSec = sampleRate / 1000.0;
3895 
3896  // --- total buffer length including fractional part
3897  bufferLength = (unsigned int)(bufferLength_mSec*(samplesPerMSec)) + 1; // +1 for fractional part
3898 
3899  // --- create new buffer
3900  delayBuffer.createCircularBuffer(bufferLength);
3901  }
3902 
3904  double readDelay()
3905  {
3906  // --- simple read
3907  return delayBuffer.readBuffer(simpleDelayParameters.delay_Samples);
3908  }
3909 
3911  double readDelayAtTime_mSec(double _delay_mSec)
3912  {
3913  // --- calculate total delay time in samples + fraction
3914  double _delay_Samples = _delay_mSec*(samplesPerMSec);
3915 
3916  // --- simple read
3917  return delayBuffer.readBuffer(_delay_Samples);
3918  }
3919 
3921  double readDelayAtPercentage(double delayPercent)
3922  {
3923  // --- simple read
3924  return delayBuffer.readBuffer((delayPercent / 100.0)*simpleDelayParameters.delay_Samples);
3925  }
3926 
3928  void writeDelay(double xn)
3929  {
3930  // --- simple write
3931  delayBuffer.writeBuffer(xn);
3932  }
3933 
3934 private:
3935  SimpleDelayParameters simpleDelayParameters;
3936 
3937  double sampleRate = 0.0;
3938  double samplesPerMSec = 0.0;
3939  double bufferLength_mSec = 0.0;
3940  unsigned int bufferLength = 0;
3941 
3942  // --- delay buffer of doubles
3943  CircularBuffer<double> delayBuffer;
3944 };
3945 
3946 
3959 {
3962  CombFilterParameters& operator=(const CombFilterParameters& params) // need this override for collections to work
3963  {
3964  if (this == &params)
3965  return *this;
3966 
3967  delayTime_mSec = params.delayTime_mSec;
3968  RT60Time_mSec = params.RT60Time_mSec;
3969  enableLPF = params.enableLPF;
3970  lpf_g = params.lpf_g;
3971  interpolate = params.interpolate;
3972  return *this;
3973  }
3974 
3975  // --- individual parameters
3976  double delayTime_mSec = 0.0;
3977  double RT60Time_mSec = 0.0;
3978  bool enableLPF = false;
3979  double lpf_g = 0.0;
3980  bool interpolate = false;
3981 };
3982 
3983 
4002 {
4003 public:
4004  CombFilter(void) {} /* C-TOR */
4005  ~CombFilter(void) {} /* D-TOR */
4006 
4007 public:
4009  virtual bool reset(double _sampleRate)
4010  {
4011  // --- flush
4012  lpf_state = 0.0;
4013 
4014  // --- create new buffer, will store sample rate and length(mSec)
4015  createDelayBuffer(sampleRate, bufferLength_mSec);
4016 
4017  return true;
4018  }
4019 
4025  virtual double processAudioSample(double xn)
4026  {
4027  double yn = delay.readDelay();
4028  double input = 0.0;
4029 
4030  // --- form input & write
4031  if (combFilterParameters.enableLPF)
4032  {
4033  // --- apply simple 1st order pole LPF
4034  double g2 = lpf_g*(1.0 - comb_g); // see book for equation 11.27 (old book)
4035  double filteredSignal = yn + g2*lpf_state;
4036  input = xn + comb_g*(filteredSignal);
4037  lpf_state = filteredSignal;
4038  }
4039  else
4040  {
4041  input = xn + comb_g*yn;
4042  }
4043 
4044  delay.writeDelay(input);
4045 
4046  // --- done
4047  return yn;
4048  }
4049 
4051  virtual bool canProcessAudioFrame() { return false; }
4052 
4058  {
4059  return combFilterParameters;
4060  }
4061 
4067  {
4068  combFilterParameters = params;
4069 
4070  // --- update the delay line parameters first
4071  SimpleDelayParameters delayParams = delay.getParameters();
4072  delayParams.delayTime_mSec = combFilterParameters.delayTime_mSec;
4073  delayParams.interpolate = combFilterParameters.interpolate;
4074  delay.setParameters(delayParams); // this will set the delay time in samples
4075 
4076  // --- calculate g with RT60 time (requires updated delay above^^)
4077  double exponent = -3.0*delayParams.delay_Samples*(1.0 / sampleRate);
4078  double rt60_mSec = combFilterParameters.RT60Time_mSec / 1000.0; // RT is in mSec!
4079  comb_g = pow(10.0, exponent / rt60_mSec);
4080 
4081  // --- set LPF g
4082  lpf_g = combFilterParameters.lpf_g;
4083  }
4084 
4086  void createDelayBuffer(double _sampleRate, double delay_mSec)
4087  {
4088  sampleRate = _sampleRate;
4089  bufferLength_mSec = delay_mSec;
4090 
4091  // --- create new buffer, will store sample rate and length(mSec)
4092  delay.createDelayBuffer(_sampleRate, delay_mSec);
4093  }
4094 
4095 private:
4096  CombFilterParameters combFilterParameters;
4097  double sampleRate = 0.0;
4098  double comb_g = 0.0;
4099  double bufferLength_mSec = 0.0;
4100 
4101  // --- LPF support
4102  double lpf_g = 0.0;
4103  double lpf_state = 0.0;
4104 
4105  // --- delay buffer of doubles
4106  SimpleDelay delay;
4107 };
4108 
4121 {
4122  DelayAPFParameters() {}
4124  DelayAPFParameters& operator=(const DelayAPFParameters& params) // need this override for collections to work
4125  {
4126  if (this == &params)
4127  return *this;
4128 
4129  delayTime_mSec = params.delayTime_mSec;
4130  apf_g = params.apf_g;
4131  enableLPF = params.enableLPF;
4132  lpf_g = params.lpf_g;
4133  interpolate = params.interpolate;
4134  enableLFO = params.enableLFO;
4135  lfoRate_Hz = params.lfoRate_Hz;
4136  lfoDepth = params.lfoDepth;
4138  return *this;
4139  }
4140 
4141  // --- individual parameters
4142  double delayTime_mSec = 0.0;
4143  double apf_g = 0.0;
4144  bool enableLPF = false;
4145  double lpf_g = 0.0;
4146  bool interpolate = false;
4147  bool enableLFO = false;
4148  double lfoRate_Hz = 0.0;
4149  double lfoDepth = 0.0;
4150  double lfoMaxModulation_mSec = 0.0;
4151 
4152 };
4153 
4172 {
4173 public:
4174  DelayAPF(void) {} /* C-TOR */
4175  ~DelayAPF(void) {} /* D-TOR */
4176 
4177 public:
4179  virtual bool reset(double _sampleRate)
4180  {
4181  // --- reset children
4182  modLFO.reset(_sampleRate);
4183 
4184  // --- flush
4185  lpf_state = 0.0;
4186 
4187  // --- create new buffer, will store sample rate and length(mSec)
4189 
4190  return true;
4191  }
4192 
4198  virtual double processAudioSample(double xn)
4199  {
4200  SimpleDelayParameters delayParams = delay.getParameters();
4201  if (delayParams.delay_Samples == 0)
4202  return xn;
4203 
4204  // --- delay line output
4205  double wnD = 0.0;
4206  double apf_g = delayAPFParameters.apf_g;
4207  double lpf_g = delayAPFParameters.lpf_g;
4208  double lfoDepth = delayAPFParameters.lfoDepth;
4209 
4210  // --- for modulated APFs
4212  {
4213  SignalGenData lfoOutput = modLFO.renderAudioOutput();
4214  double maxDelay = delayParams.delayTime_mSec;
4215  double minDelay = maxDelay - delayAPFParameters.lfoMaxModulation_mSec;
4216  minDelay = fmax(0.0, minDelay); // bound minDelay to 0 as minimum
4217 
4218  // --- calc max-down modulated value with unipolar converted LFO output
4219  // NOTE: LFO output is scaled by lfoDepth
4220  double modDelay_mSec = doUnipolarModulationFromMax(bipolarToUnipolar(lfoDepth*lfoOutput.normalOutput),
4221  minDelay, maxDelay);
4222 
4223  // --- read modulated value to get w(n-D);
4224  wnD = delay.readDelayAtTime_mSec(modDelay_mSec);
4225  }
4226  else
4227  // --- read the delay line to get w(n-D)
4228  wnD = delay.readDelay();
4229 
4231  {
4232  // --- apply simple 1st order pole LPF, overwrite wnD
4233  wnD = wnD*(1.0 - lpf_g) + lpf_g*lpf_state;
4234  lpf_state = wnD;
4235  }
4236 
4237  // form w(n) = x(n) + gw(n-D)
4238  double wn = xn + apf_g*wnD;
4239 
4240  // form y(n) = -gw(n) + w(n-D)
4241  double yn = -apf_g*wn + wnD;
4242 
4243  // underflow check
4244  checkFloatUnderflow(yn);
4245 
4246  // write delay line
4247  delay.writeDelay(wn);
4248 
4249  return yn;
4250  }
4251 
4253  virtual bool canProcessAudioFrame() { return false; }
4254 
4260  {
4261  return delayAPFParameters;
4262  }
4263 
4268  void setParameters(const DelayAPFParameters& params)
4269  {
4270  delayAPFParameters = params;
4271 
4272  // --- update delay line
4273  SimpleDelayParameters delayParams = delay.getParameters();
4275  delay.setParameters(delayParams);
4276  }
4277 
4279  void createDelayBuffer(double _sampleRate, double delay_mSec)
4280  {
4281  sampleRate = _sampleRate;
4282  bufferLength_mSec = delay_mSec;
4283 
4284  // --- create new buffer, will store sample rate and length(mSec)
4285  delay.createDelayBuffer(_sampleRate, delay_mSec);
4286  }
4287 
4288 protected:
4289  // --- component parameters
4291  double sampleRate = 0.0;
4292  double bufferLength_mSec = 0.0;
4293 
4294  // --- delay buffer of doubles
4296 
4297  // --- optional LFO
4299 
4300  // --- LPF support
4301  double lpf_state = 0.0;
4302 };
4303 
4304 
4317 {
4320  NestedDelayAPFParameters& operator=(const NestedDelayAPFParameters& params) // need this override for collections to work
4321  {
4322  if (this == &params)
4323  return *this;
4324 
4327  outerAPF_g = params.outerAPF_g;
4328  innerAPF_g = params.innerAPF_g;
4329 
4330  // --- outer LFO
4331  enableLFO = params.enableLFO;
4332  lfoRate_Hz = params.lfoRate_Hz;
4333  lfoDepth = params.lfoDepth;
4335 
4336  return *this;
4337  }
4338 
4339  // --- individual parameters
4340  double outerAPFdelayTime_mSec = 0.0;
4341  double innerAPFdelayTime_mSec = 0.0;
4342  double outerAPF_g = 0.0;
4343  double innerAPF_g = 0.0;
4344 
4345  // --- this LFO belongs to the outer APF only
4346  bool enableLFO = false;
4347  double lfoRate_Hz = 0.0;
4348  double lfoDepth = 1.0;
4349  double lfoMaxModulation_mSec = 0.0;
4350 
4351 };
4352 
4372 class NestedDelayAPF : public DelayAPF
4373 {
4374 public:
4375  NestedDelayAPF(void) { } /* C-TOR */
4376  ~NestedDelayAPF(void) { } /* D-TOR */
4377 
4378 public:
4380  virtual bool reset(double _sampleRate)
4381  {
4382  // --- call base class reset first
4383  DelayAPF::reset(_sampleRate);
4384 
4385  // --- then do our stuff
4386  nestedAPF.reset(_sampleRate);
4387 
4388  return true;
4389  }
4390 
4396  virtual double processAudioSample(double xn)
4397  {
4398  // --- delay line output
4399  double wnD = 0.0;
4400 
4401  SimpleDelayParameters delayParams = delay.getParameters();
4402  if (delayParams.delay_Samples == 0)
4403  return xn;
4404 
4405  double apf_g = delayAPFParameters.apf_g;
4406  double lpf_g = delayAPFParameters.lpf_g;
4407 
4408  // --- for modulated APFs
4410  {
4411  SignalGenData lfoOutput = modLFO.renderAudioOutput();
4412  double maxDelay = delayParams.delayTime_mSec;
4413  double minDelay = maxDelay - delayAPFParameters.lfoMaxModulation_mSec;
4414  minDelay = fmax(0.0, minDelay); // bound minDelay to 0 as minimum
4415  double lfoDepth = delayAPFParameters.lfoDepth;
4416 
4417  // --- calc max-down modulated value with unipolar converted LFO output
4418  // NOTE: LFO output is scaled by lfoDepth
4419  double modDelay_mSec = doUnipolarModulationFromMax(bipolarToUnipolar(lfoDepth*lfoOutput.normalOutput),
4420  minDelay, maxDelay);
4421 
4422  // --- read modulated value to get w(n-D);
4423  wnD = delay.readDelayAtTime_mSec(modDelay_mSec);
4424  }
4425  else
4426  // --- read the delay line to get w(n-D)
4427  wnD = delay.readDelay();
4428 
4430  {
4431  // --- apply simple 1st order pole LPF, overwrite wnD
4432  wnD = wnD*(1.0 - lpf_g) + lpf_g*lpf_state;
4433  lpf_state = wnD;
4434  }
4435 
4436  // --- form w(n) = x(n) + gw(n-D)
4437  double wn = xn + apf_g*wnD;
4438 
4439  // --- process wn through inner APF
4440  double ynInner = nestedAPF.processAudioSample(wn);
4441 
4442  // --- form y(n) = -gw(n) + w(n-D)
4443  double yn = -apf_g*wn + wnD;
4444 
4445  // --- underflow check
4446  checkFloatUnderflow(yn);
4447 
4448  // --- write delay line
4449  delay.writeDelay(ynInner);
4450 
4451  return yn;
4452  }
4453 
4458  NestedDelayAPFParameters getParameters() { return nestedAPFParameters; }
4459 
4465  {
4466  nestedAPFParameters = params;
4467 
4468  DelayAPFParameters outerAPFParameters = DelayAPF::getParameters();
4469  DelayAPFParameters innerAPFParameters = nestedAPF.getParameters();
4470 
4471  // --- outer APF
4472  outerAPFParameters.apf_g = nestedAPFParameters.outerAPF_g;
4473  outerAPFParameters.delayTime_mSec = nestedAPFParameters.outerAPFdelayTime_mSec;
4474 
4475  // --- LFO support
4476  outerAPFParameters.enableLFO = nestedAPFParameters.enableLFO;
4477  outerAPFParameters.lfoDepth = nestedAPFParameters.lfoDepth;
4478  outerAPFParameters.lfoRate_Hz = nestedAPFParameters.lfoRate_Hz;
4479  outerAPFParameters.lfoMaxModulation_mSec = nestedAPFParameters.lfoMaxModulation_mSec;
4480 
4481  // --- inner APF
4482  innerAPFParameters.apf_g = nestedAPFParameters.innerAPF_g;
4483  innerAPFParameters.delayTime_mSec = nestedAPFParameters.innerAPFdelayTime_mSec;
4484 
4485  DelayAPF::setParameters(outerAPFParameters);
4486  nestedAPF.setParameters(innerAPFParameters);
4487  }
4488 
4490  void createDelayBuffers(double _sampleRate, double delay_mSec, double nestedAPFDelay_mSec)
4491  {
4492  // --- base class
4493  DelayAPF::createDelayBuffer(_sampleRate, delay_mSec);
4494 
4495  // --- then our stuff
4496  nestedAPF.createDelayBuffer(_sampleRate, nestedAPFDelay_mSec);
4497  }
4498 
4499 private:
4500  NestedDelayAPFParameters nestedAPFParameters;
4501  DelayAPF nestedAPF;
4502 };
4503 
4516 {
4519  TwoBandShelvingFilterParameters& operator=(const TwoBandShelvingFilterParameters& params) // need this override for collections to work
4520  {
4521  if (this == &params)
4522  return *this;
4523 
4524  lowShelf_fc = params.lowShelf_fc;
4526  highShelf_fc = params.highShelf_fc;
4528  return *this;
4529  }
4530 
4531  // --- individual parameters
4532  double lowShelf_fc = 0.0;
4533  double lowShelfBoostCut_dB = 0.0;
4534  double highShelf_fc = 0.0;
4535  double highShelfBoostCut_dB = 0.0;
4536 };
4537 
4556 {
4557 public:
4559  {
4560  AudioFilterParameters params = lowShelfFilter.getParameters();
4561  params.algorithm = filterAlgorithm::kLowShelf;
4562  lowShelfFilter.setParameters(params);
4563 
4564  params = highShelfFilter.getParameters();
4565  params.algorithm = filterAlgorithm::kHiShelf;
4566  highShelfFilter.setParameters(params);
4567  } /* C-TOR */
4568 
4569  ~TwoBandShelvingFilter() {} /* D-TOR */
4570 
4572  virtual bool reset(double _sampleRate)
4573  {
4574  lowShelfFilter.reset(_sampleRate);
4575  highShelfFilter.reset(_sampleRate);
4576  return true;
4577  }
4578 
4580  virtual bool canProcessAudioFrame() { return false; }
4581 
4587  virtual double processAudioSample(double xn)
4588  {
4589  // --- all modes do Full Wave Rectification
4590  double filteredSignal = lowShelfFilter.processAudioSample(xn);
4591  filteredSignal = highShelfFilter.processAudioSample(filteredSignal);
4592 
4593  return filteredSignal;
4594  }
4595 
4601  {
4602  return parameters;
4603  }
4604 
4610  {
4611  parameters = params;
4612  AudioFilterParameters filterParams = lowShelfFilter.getParameters();
4613  filterParams.fc = parameters.lowShelf_fc;
4614  filterParams.boostCut_dB = parameters.lowShelfBoostCut_dB;
4615  lowShelfFilter.setParameters(filterParams);
4616 
4617  filterParams = highShelfFilter.getParameters();
4618  filterParams.fc = parameters.highShelf_fc;
4619  filterParams.boostCut_dB = parameters.highShelfBoostCut_dB;
4620  highShelfFilter.setParameters(filterParams);
4621  }
4622 
4623 private:
4624  TwoBandShelvingFilterParameters parameters;
4625  AudioFilter lowShelfFilter;
4626  AudioFilter highShelfFilter;
4627 };
4628 
4642 enum class reverbDensity { kThick, kSparse };
4643 
4656 {
4659  ReverbTankParameters& operator=(const ReverbTankParameters& params) // need this override for collections to work
4660  {
4661  if (this == &params)
4662  return *this;
4663 
4664  density = params.density;
4665 
4666  // --- tweaker variables
4672 
4673  lpf_g = params.lpf_g;
4674  kRT = params.kRT;
4675 
4676  lowShelf_fc = params.lowShelf_fc;
4678  highShelf_fc = params.highShelf_fc;
4680 
4681  wetLevel_dB = params.wetLevel_dB;
4682  dryLevel_dB = params.dryLevel_dB;
4683  return *this;
4684  }
4685 
4686  // --- individual parameters
4687  reverbDensity density = reverbDensity::kThick;
4688 
4689  // --- tweaking parameters - you may not want to expose these
4690  // in the final plugin!
4691  // --- See the book for all the details on how these tweakers work!!
4692  double apfDelayMax_mSec = 5.0;
4693  double apfDelayWeight_Pct = 100.0;
4694  double fixeDelayMax_mSec = 50.0;
4695  double fixeDelayWeight_Pct = 100.0;
4696 
4697  // --- direct control parameters
4698  double preDelayTime_mSec = 0.0;
4699  double lpf_g = 0.0;
4700  double kRT = 0.0;
4701 
4702  double lowShelf_fc = 0.0;
4703  double lowShelfBoostCut_dB = 0.0;
4704  double highShelf_fc = 0.0;
4705  double highShelfBoostCut_dB = 0.0;
4706 
4707  double wetLevel_dB = -3.0;
4708  double dryLevel_dB = -3.0;
4709 };
4710 
4711 // --- constants for reverb tank
4712 const unsigned int NUM_BRANCHES = 4;
4713 const unsigned int NUM_CHANNELS = 2; // stereo
4714 
4733 {
4734 public:
4735  ReverbTank() {} /* C-TOR */
4736  ~ReverbTank() {} /* D-TOR */
4737 
4739  virtual bool reset(double _sampleRate)
4740  {
4741  // ---store
4742  sampleRate = _sampleRate;
4743 
4744  // ---set up preDelay
4745  preDelay.reset(_sampleRate);
4746  preDelay.createDelayBuffer(_sampleRate, 100.0);
4747 
4748  for (int i = 0; i < NUM_BRANCHES; i++)
4749  {
4750  branchDelays[i].reset(_sampleRate);
4751  branchDelays[i].createDelayBuffer(_sampleRate, 100.0);
4752 
4753  branchNestedAPFs[i].reset(_sampleRate);
4754  branchNestedAPFs[i].createDelayBuffers(_sampleRate, 100.0, 100.0);
4755 
4756  branchLPFs[i].reset(_sampleRate);
4757  }
4758  for (int i = 0; i < NUM_CHANNELS; i++)
4759  {
4760  shelvingFilters[i].reset(_sampleRate);
4761  }
4762 
4763  return true;
4764  }
4765 
4767  virtual bool canProcessAudioFrame() { return true; }
4768 
4774  virtual double processAudioSample(double xn)
4775  {
4776  float inputs[2] = { 0.0 };
4777  float outputs[2] = { 0.0 };
4778  processAudioFrame(inputs, outputs, 1, 1);
4779  return outputs[0];
4780  }
4781 
4783  virtual bool processAudioFrame(const float* inputFrame,
4784  float* outputFrame,
4785  uint32_t inputChannels,
4786  uint32_t outputChannels)
4787  {
4788  double output = 0.0;
4789 
4790  // --- global feedback from delay in last branch
4791  double globFB = branchDelays[NUM_BRANCHES-1].readDelay();
4792 
4793  // --- feedback value
4794  double fb = parameters.kRT*(globFB);
4795 
4796  // --- mono-ized input signal
4797  double xnL = inputFrame[0];
4798  double xnR = inputChannels > 1 ? inputFrame[1] : 0.0;
4799  double monoXn = double(1.0 / inputChannels)*xnL + double(1.0 / inputChannels)*xnR;
4800 
4801  // --- pre delay output
4802  double preDelayOut = preDelay.processAudioSample(monoXn);
4803 
4804  // --- input to first branch = preDalay + globFB
4805  double input = preDelayOut + fb;
4806  for (int i = 0; i < NUM_BRANCHES; i++)
4807  {
4808  double apfOut = branchNestedAPFs[i].processAudioSample(input);
4809  double lpfOut = branchLPFs[i].processAudioSample(apfOut);
4810  double delayOut = parameters.kRT*branchDelays[i].processAudioSample(lpfOut);
4811  input = delayOut + preDelayOut;
4812  }
4813  // --- gather outputs
4814  /*
4815  There are 25 prime numbers between 1 and 100.
4816  They are 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
4817  43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, and 97
4818 
4819  we want 16 of them: 23, 29, 31, 37, 41,
4820  43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, and 97
4821  */
4822 
4823  double weight = 0.707;
4824 
4825  double outL= 0.0;
4826  outL += weight*branchDelays[0].readDelayAtPercentage(23.0);
4827  outL -= weight*branchDelays[1].readDelayAtPercentage(41.0);
4828  outL += weight*branchDelays[2].readDelayAtPercentage(59.0);
4829  outL -= weight*branchDelays[3].readDelayAtPercentage(73.0);
4830 
4831  double outR = 0.0;
4832  outR -= weight*branchDelays[0].readDelayAtPercentage(29.0);
4833  outR += weight*branchDelays[1].readDelayAtPercentage(43.0);
4834  outR -= weight*branchDelays[2].readDelayAtPercentage(61.0);
4835  outR += weight*branchDelays[3].readDelayAtPercentage(79.0);
4836 
4837  if (parameters.density == reverbDensity::kThick)
4838  {
4839  outL += weight*branchDelays[0].readDelayAtPercentage(31.0);
4840  outL -= weight*branchDelays[1].readDelayAtPercentage(47.0);
4841  outL += weight*branchDelays[2].readDelayAtPercentage(67.0);
4842  outL -= weight*branchDelays[3].readDelayAtPercentage(83.0);
4843 
4844  outR -= weight*branchDelays[0].readDelayAtPercentage(37.0);
4845  outR += weight*branchDelays[1].readDelayAtPercentage(53.0);
4846  outR -= weight*branchDelays[2].readDelayAtPercentage(71.0);
4847  outR += weight*branchDelays[3].readDelayAtPercentage(89.0);
4848  }
4849 
4850  // --- filter
4851  double tankOutL = shelvingFilters[0].processAudioSample(outL);
4852  double tankOutR = shelvingFilters[1].processAudioSample(outR);
4853 
4854  // --- sum with dry
4855  double dry = pow(10.0, parameters.dryLevel_dB / 20.0);
4856  double wet = pow(10.0, parameters.wetLevel_dB / 20.0);
4857 
4858  if (outputChannels == 1)
4859  outputFrame[0] = dry*xnL + wet*(0.5*tankOutL + 0.5*tankOutR);
4860  else
4861  {
4862  outputFrame[0] = dry*xnL + wet*tankOutL;
4863  outputFrame[1] = dry*xnR + wet*tankOutR;
4864  }
4865 
4866  return true;
4867  }
4868 
4873  ReverbTankParameters getParameters() { return parameters; }
4874 
4880  {
4881  // --- do the updates here, the sub-components will only update themselves if
4882  // their parameters changed, so we let those object handle that chore
4883  TwoBandShelvingFilterParameters filterParams = shelvingFilters[0].getParameters();
4884  filterParams.highShelf_fc = params.highShelf_fc;
4885  filterParams.highShelfBoostCut_dB = params.highShelfBoostCut_dB;
4886  filterParams.lowShelf_fc = params.lowShelf_fc;
4887  filterParams.lowShelfBoostCut_dB = params.lowShelfBoostCut_dB;
4888 
4889  // --- copy to both channels
4890  shelvingFilters[0].setParameters(filterParams);
4891  shelvingFilters[1].setParameters(filterParams);
4892 
4893  SimpleLPFParameters lpfParams = branchLPFs[0].getParameters();
4894  lpfParams.g = params.lpf_g;
4895 
4896  for (int i = 0; i < NUM_BRANCHES; i++)
4897  {
4898  branchLPFs[i].setParameters(lpfParams);
4899  }
4900 
4901  // --- update pre delay
4902  SimpleDelayParameters delayParams = preDelay.getParameters();
4903  delayParams.delayTime_mSec = params.preDelayTime_mSec;
4904  preDelay.setParameters(delayParams);
4905 
4906  // --- set apf and delay parameters
4907  int m = 0;
4908  NestedDelayAPFParameters apfParams = branchNestedAPFs[0].getParameters();
4909  delayParams = branchDelays[0].getParameters();
4910 
4911  // --- global max Delay times
4912  double globalAPFMaxDelay = (parameters.apfDelayWeight_Pct / 100.0)*parameters.apfDelayMax_mSec;
4913  double globalFixedMaxDelay = (parameters.fixeDelayWeight_Pct / 100.0)*parameters.fixeDelayMax_mSec;
4914 
4915  // --- lfo
4916  apfParams.enableLFO = true;
4917  apfParams.lfoMaxModulation_mSec = 0.3;
4918  apfParams.lfoDepth = 1.0;
4919 
4920  for (int i = 0; i < NUM_BRANCHES; i++)
4921  {
4922  // --- setup APFs
4923  apfParams.outerAPFdelayTime_mSec = globalAPFMaxDelay*apfDelayWeight[m++];
4924  apfParams.innerAPFdelayTime_mSec = globalAPFMaxDelay*apfDelayWeight[m++];
4925  apfParams.innerAPF_g = -0.5;
4926  apfParams.outerAPF_g = 0.5;
4927  if (i == 0)
4928  apfParams.lfoRate_Hz = 0.15;
4929  else if (i == 1)
4930  apfParams.lfoRate_Hz = 0.33;
4931  else if (i == 2)
4932  apfParams.lfoRate_Hz = 0.57;
4933  else if (i == 3)
4934  apfParams.lfoRate_Hz = 0.73;
4935 
4936  branchNestedAPFs[i].setParameters(apfParams);
4937 
4938  // --- fixedDelayWeight
4939  delayParams.delayTime_mSec = globalFixedMaxDelay*fixedDelayWeight[i];
4940  branchDelays[i].setParameters(delayParams);
4941  }
4942 
4943  // --- save our copy
4944  parameters = params;
4945  }
4946 
4947 
4948 private:
4949  ReverbTankParameters parameters;
4950 
4951  SimpleDelay preDelay;
4952  SimpleDelay branchDelays[NUM_BRANCHES];
4953  NestedDelayAPF branchNestedAPFs[NUM_BRANCHES];
4954  SimpleLPF branchLPFs[NUM_BRANCHES];
4955 
4956  TwoBandShelvingFilter shelvingFilters[NUM_CHANNELS];
4957 
4958  // --- weighting values to make various and low-correlated APF delay values easily
4959  double apfDelayWeight[NUM_BRANCHES * 2] = { 0.317, 0.873, 0.477, 0.291, 0.993, 0.757, 0.179, 0.575 };
4960  double fixedDelayWeight[NUM_BRANCHES] = { 1.0, 0.873, 0.707, 0.667 };
4961  double sampleRate = 0.0;
4962 };
4963 
4964 
4985 {
4986 public:
4987  PeakLimiter() { setThreshold_dB(-3.0); }
4988  ~PeakLimiter() {}
4989 
4991  virtual bool reset(double _sampleRate)
4992  {
4993  // --- init; true = analog time-constant
4994  detector.setSampleRate(_sampleRate);
4995 
4996  AudioDetectorParameters detectorParams = detector.getParameters();
4997  detectorParams.detect_dB = true;
4998  detectorParams.attackTime_mSec = 5.0;
4999  detectorParams.releaseTime_mSec = 25.0;
5000  detectorParams.clampToUnityMax = false;
5001  detectorParams.detectMode = ENVELOPE_DETECT_MODE_PEAK;
5002  detector.setParameters(detectorParams);
5003 
5004  return true;
5005  }
5006 
5008  virtual bool canProcessAudioFrame() { return false; }
5009 
5015  virtual double processAudioSample(double xn)
5016  {
5018  }
5019 
5021  double computeGain(double detect_dB)
5022  {
5023  double output_dB = 0.0;
5024 
5025  // --- defaults - you can change these here
5026  bool softknee = true;
5027  double kneeWidth_dB = 10.0;
5028 
5029  // --- hard knee
5030  if (!softknee)
5031  {
5032  // --- below threshold, unity
5033  if (detect_dB <= threshold_dB)
5034  output_dB = detect_dB;
5035  // --- above threshold, compress
5036  else
5037  output_dB = threshold_dB;
5038  }
5039  else
5040  {
5041  // --- calc gain with knee
5042  // --- left side of knee, outside of width, unity gain zone
5043  if (2.0*(detect_dB - threshold_dB) < -kneeWidth_dB)
5044  output_dB = detect_dB;
5045  // --- inside the knee,
5046  else if (2.0*(fabs(detect_dB - threshold_dB)) <= kneeWidth_dB)
5047  output_dB = detect_dB - pow((detect_dB - threshold_dB + (kneeWidth_dB / 2.0)), 2.0) / (2.0*kneeWidth_dB);
5048  // --- right of knee, compression zone
5049  else if (2.0*(detect_dB - threshold_dB) > kneeWidth_dB)
5050  output_dB = threshold_dB;
5051  }
5052 
5053  // --- convert difference between threshold and detected to raw
5054  return pow(10.0, (output_dB - detect_dB) / 20.0);
5055  }
5056 
5058  void setThreshold_dB(double _threshold_dB) { threshold_dB = _threshold_dB; }
5059 
5061  void setMakeUpGain_dB(double _makeUpGain_dB) { makeUpGain_dB = _makeUpGain_dB; }
5062 
5063 protected:
5065  double threshold_dB = 0.0;
5066  double makeUpGain_dB = 0.0;
5067 };
5068 
5069 
5083 enum class vaFilterAlgorithm {
5084  kLPF1, kHPF1, kAPF1, kSVF_LP, kSVF_HP, kSVF_BP, kSVF_BS
5085 }; // --- you will add more here...
5086 
5087 
5100 {
5101  ZVAFilterParameters() {}
5103  ZVAFilterParameters& operator=(const ZVAFilterParameters& params) // need this override for collections to work
5104  {
5105  if (this == &params)
5106  return *this;
5107 
5109  fc = params.fc;
5110  Q = params.Q;
5112  enableGainComp = params.enableGainComp;
5114  selfOscillate = params.selfOscillate;
5115  enableNLP = params.enableNLP;
5116  return *this;
5117  }
5118 
5119  // --- individual parameters
5120  vaFilterAlgorithm filterAlgorithm = vaFilterAlgorithm::kSVF_LP;
5121  double fc = 1000.0;
5122  double Q = 0.707;
5123  double filterOutputGain_dB = 0.0;
5124  bool enableGainComp = false;
5125  bool matchAnalogNyquistLPF = false;
5126  bool selfOscillate = false;
5127  bool enableNLP = false;
5128 };
5129 
5130 
5148 {
5149 public:
5150  ZVAFilter() {} /* C-TOR */
5151  ~ZVAFilter() {} /* D-TOR */
5152 
5154  virtual bool reset(double _sampleRate)
5155  {
5156  sampleRate = _sampleRate;
5157  integrator_z[0] = 0.0;
5158  integrator_z[1] = 0.0;
5159 
5160  return true;
5161  }
5162 
5168  {
5169  return zvaFilterParameters;
5170  }
5171 
5177  {
5178  if (params.fc != zvaFilterParameters.fc ||
5179  params.Q != zvaFilterParameters.Q ||
5183 
5184  zvaFilterParameters = params;
5185  }
5186 
5188  virtual bool canProcessAudioFrame() { return false; }
5189 
5195  virtual double processAudioSample(double xn)
5196  {
5197  // --- with gain comp enabled, we reduce the input by
5198  // half the gain in dB at resonant peak
5199  // NOTE: you can change that logic here!
5201  bool matchAnalogNyquistLPF = zvaFilterParameters.matchAnalogNyquistLPF;
5202 
5204  {
5205  double peak_dB = dBPeakGainFor_Q(zvaFilterParameters.Q);
5206  if (peak_dB > 0.0)
5207  {
5208  double halfPeak_dBGain = dB2Raw(-peak_dB / 2.0);
5209  xn *= halfPeak_dBGain;
5210  }
5211  }
5212 
5213  // --- for 1st order filters:
5214  if (filterAlgorithm == vaFilterAlgorithm::kLPF1 ||
5215  filterAlgorithm == vaFilterAlgorithm::kHPF1 ||
5216  filterAlgorithm == vaFilterAlgorithm::kAPF1)
5217  {
5218  // --- create vn node
5219  double vn = (xn - integrator_z[0])*alpha;
5220 
5221  // --- form LP output
5222  double lpf = ((xn - integrator_z[0])*alpha) + integrator_z[0];
5223 
5224  double sn = integrator_z[0];
5225 
5226  // --- update memory
5227  integrator_z[0] = vn + lpf;
5228 
5229  // --- form the HPF = INPUT = LPF
5230  double hpf = xn - lpf;
5231 
5232  // --- form the APF = LPF - HPF
5233  double apf = lpf - hpf;
5234 
5235  // --- set the outputs
5236  if (filterAlgorithm == vaFilterAlgorithm::kLPF1)
5237  {
5238  // --- this is a very close match as-is at Nyquist!
5239  if (matchAnalogNyquistLPF)
5240  return lpf + alpha*hpf;
5241  else
5242  return lpf;
5243  }
5244  else if (filterAlgorithm == vaFilterAlgorithm::kHPF1)
5245  return hpf;
5246  else if (filterAlgorithm == vaFilterAlgorithm::kAPF1)
5247  return apf;
5248 
5249  // --- unknown filter
5250  return xn;
5251  }
5252 
5253  // --- form the HP output first
5254  double hpf = alpha0*(xn - rho*integrator_z[0] - integrator_z[1]);
5255 
5256  // --- BPF Out
5257  double bpf = alpha*hpf + integrator_z[0];
5259  bpf = softClipWaveShaper(bpf, 1.0);
5260 
5261  // --- LPF Out
5262  double lpf = alpha*bpf + integrator_z[1];
5263 
5264  // --- BSF Out
5265  double bsf = hpf + lpf;
5266 
5267  // --- finite gain at Nyquist; slight error at VHF
5268  double sn = integrator_z[0];
5269 
5270  // update memory
5271  integrator_z[0] = alpha*hpf + bpf;
5272  integrator_z[1] = alpha*bpf + lpf;
5273 
5274  double filterOutputGain = pow(10.0, zvaFilterParameters.filterOutputGain_dB / 20.0);
5275 
5276  // return our selected type
5277  if (filterAlgorithm == vaFilterAlgorithm::kSVF_LP)
5278  {
5279  if (matchAnalogNyquistLPF)
5280  lpf += analogMatchSigma*(sn);
5281  return filterOutputGain*lpf;
5282  }
5283  else if (filterAlgorithm == vaFilterAlgorithm::kSVF_HP)
5284  return filterOutputGain*hpf;
5285  else if (filterAlgorithm == vaFilterAlgorithm::kSVF_BP)
5286  return filterOutputGain*bpf;
5287  else if (filterAlgorithm == vaFilterAlgorithm::kSVF_BS)
5288  return filterOutputGain*bsf;
5289 
5290  // --- unknown filter
5291  return filterOutputGain*lpf;
5292  }
5293 
5296  {
5297  double fc = zvaFilterParameters.fc;
5298  double Q = zvaFilterParameters.Q;
5300 
5301  // --- normal Zavalishin SVF calculations here
5302  // prewarp the cutoff- these are bilinear-transform filters
5303  double wd = kTwoPi*fc;
5304  double T = 1.0 / sampleRate;
5305  double wa = (2.0 / T)*tan(wd*T / 2.0);
5306  double g = wa*T / 2.0;
5307 
5308  // --- for 1st order filters:
5309  if (filterAlgorithm == vaFilterAlgorithm::kLPF1 ||
5310  filterAlgorithm == vaFilterAlgorithm::kHPF1 ||
5311  filterAlgorithm == vaFilterAlgorithm::kAPF1)
5312  {
5313  // --- calculate alpha
5314  alpha = g / (1.0 + g);
5315  }
5316  else // state variable variety
5317  {
5318  // --- note R is the traditional analog damping factor zeta
5319  double R = zvaFilterParameters.selfOscillate ? 0.0 : 1.0 / (2.0*Q);
5320  alpha0 = 1.0 / (1.0 + 2.0*R*g + g*g);
5321  alpha = g;
5322  rho = 2.0*R + g;
5323 
5324  // --- sigma for analog matching version
5325  double f_o = (sampleRate / 2.0) / fc;
5326  analogMatchSigma = 1.0 / (alpha*f_o*f_o);
5327  }
5328  }
5329 
5331  void setBeta(double _beta) { beta = _beta; }
5332 
5334  double getBeta() { return beta; }
5335 
5336 protected:
5338  double sampleRate = 44100.0;
5339 
5340  // --- state storage
5341  double integrator_z[2];
5342 
5343  // --- filter coefficients
5344  double alpha0 = 0.0;
5345  double alpha = 0.0;
5346  double rho = 0.0;
5347 
5348  double beta = 0.0;
5349 
5350  // --- for analog Nyquist matching
5351  double analogMatchSigma = 0.0;
5352 
5353 };
5354 
5367 {
5370  EnvelopeFollowerParameters& operator=(const EnvelopeFollowerParameters& params) // need this override for collections to work
5371  {
5372  if (this == &params)
5373  return *this;
5374 
5375  fc = params.fc;
5376  Q = params.Q;
5379  threshold_dB = params.threshold_dB;
5380  sensitivity = params.sensitivity;
5381 
5382  return *this;
5383  }
5384 
5385  // --- individual parameters
5386  double fc = 0.0;
5387  double Q = 0.707;
5388  double attackTime_mSec = 10.0;
5389  double releaseTime_mSec = 10.0;
5390  double threshold_dB = 0.0;
5391  double sensitivity = 1.0;
5392 };
5393 
5413 {
5414 public:
5415  EnvelopeFollower() {
5416  // --- setup the filter
5417  ZVAFilterParameters filterParams;
5418  filterParams.filterAlgorithm = vaFilterAlgorithm::kSVF_LP;
5419  filterParams.fc = 1000.0;
5420  filterParams.enableGainComp = true;
5421  filterParams.enableNLP = true;
5422  filterParams.matchAnalogNyquistLPF = true;
5423  filter.setParameters(filterParams);
5424 
5425  // --- setup the detector
5426  AudioDetectorParameters adParams;
5427  adParams.attackTime_mSec = -1.0;
5428  adParams.releaseTime_mSec = -1.0;
5429  adParams.detectMode = TLD_AUDIO_DETECT_MODE_RMS;
5430  adParams.detect_dB = true;
5431  adParams.clampToUnityMax = false;
5432  detector.setParameters(adParams);
5433 
5434  } /* C-TOR */
5435  ~EnvelopeFollower() {} /* D-TOR */
5436 
5438  virtual bool reset(double _sampleRate)
5439  {
5440  filter.reset(_sampleRate);
5441  detector.reset(_sampleRate);
5442  return true;
5443  }
5444 
5450 
5456  {
5457  ZVAFilterParameters filterParams = filter.getParameters();
5459 
5460  if (params.fc != parameters.fc || params.Q != parameters.Q)
5461  {
5462  filterParams.fc = params.fc;
5463  filterParams.Q = params.Q;
5464  filter.setParameters(filterParams);
5465  }
5466  if (params.attackTime_mSec != parameters.attackTime_mSec ||
5468  {
5469  adParams.attackTime_mSec = params.attackTime_mSec;
5470  adParams.releaseTime_mSec = params.releaseTime_mSec;
5471  detector.setParameters(adParams);
5472  }
5473 
5474  // --- save
5475  parameters = params;
5476  }
5477 
5479  virtual bool canProcessAudioFrame() { return false; }
5480 
5486  virtual double processAudioSample(double xn)
5487  {
5488  // --- calc threshold
5489  double threshValue = pow(10.0, parameters.threshold_dB / 20.0);
5490 
5491  // --- detect the signal
5492  double detect_dB = detector.processAudioSample(xn);
5493  double detectValue = pow(10.0, detect_dB / 20.0);
5494  double deltaValue = detectValue - threshValue;
5495 
5496  ZVAFilterParameters filterParams = filter.getParameters();
5497  filterParams.fc = parameters.fc;
5498 
5499  // --- if above the threshold, modulate the filter fc
5500  if (deltaValue > 0.0)// || delta_dB > 0.0)
5501  {
5502  // --- fc Computer
5503  double modulatorValue = 0.0;
5504 
5505  // --- best results are with linear values when detector is in dB mode
5506  modulatorValue = (deltaValue * parameters.sensitivity);
5507 
5508  // --- calculate modulated frequency
5509  filterParams.fc = doUnipolarModulationFromMin(modulatorValue, parameters.fc, kMaxFilterFrequency);
5510  }
5511 
5512  // --- update with new modulated frequency
5513  filter.setParameters(filterParams);
5514 
5515  // --- perform the filtering operation
5516  return filter.processAudioSample(xn);
5517  }
5518 
5519 protected:
5521 
5522  // --- 1 filter and 1 detector
5525 };
5526 
5540 enum class distortionModel { kSoftClip, kArcTan, kFuzzAsym };
5541 
5554 {
5557  TriodeClassAParameters& operator=(const TriodeClassAParameters& params) // need this override for collections to work
5558  {
5559  if (this == &params)
5560  return *this;
5561 
5562  waveshaper = params.waveshaper;
5563  saturation = params.saturation;
5564  asymmetry = params.asymmetry;
5565  outputGain = params.outputGain;
5566 
5567  invertOutput = params.invertOutput;
5568  enableHPF = params.enableHPF;
5569  enableLSF = params.enableLSF;
5570 
5571  hpf_Fc = params.hpf_Fc;
5572  lsf_Fshelf = params.lsf_Fshelf;
5574 
5575  return *this;
5576  }
5577 
5578  // --- individual parameters
5579  distortionModel waveshaper = distortionModel::kSoftClip;
5580 
5581  double saturation = 1.0;
5582  double asymmetry = 0.0;
5583  double outputGain = 1.0;
5584 
5585  bool invertOutput = true;
5586  bool enableHPF = true;
5587  bool enableLSF = false;
5588 
5589  double hpf_Fc = 1.0;
5590  double lsf_Fshelf = 80.0;
5591  double lsf_BoostCut_dB = 0.0;
5592 };
5593 
5613 {
5614 public:
5615  TriodeClassA() {
5616  AudioFilterParameters params;
5617  params.algorithm = filterAlgorithm::kHPF1;
5618  params.fc = parameters.hpf_Fc;
5619  outputHPF.setParameters(params);
5620 
5621  params.algorithm = filterAlgorithm::kLowShelf;
5622  params.fc = parameters.lsf_Fshelf;
5624  outputLSF.setParameters(params);
5625  } /* C-TOR */
5626  ~TriodeClassA() {} /* D-TOR */
5627 
5629  virtual bool reset(double _sampleRate)
5630  {
5631  outputHPF.reset(_sampleRate);
5632  outputLSF.reset(_sampleRate);
5633 
5634  // ---
5635  return true;
5636  }
5637 
5643 
5649  {
5650  parameters = params;
5651 
5652  AudioFilterParameters filterParams;
5653  filterParams.algorithm = filterAlgorithm::kHPF1;
5654  filterParams.fc = parameters.hpf_Fc;
5655  outputHPF.setParameters(filterParams);
5656 
5657  filterParams.algorithm = filterAlgorithm::kLowShelf;
5658  filterParams.fc = parameters.lsf_Fshelf;
5659  filterParams.boostCut_dB = parameters.lsf_BoostCut_dB;
5660  outputLSF.setParameters(filterParams);
5661  }
5662 
5664  virtual bool canProcessAudioFrame() { return false; }
5665 
5671  virtual double processAudioSample(double xn)
5672  {
5673  // --- perform waveshaping
5674  double output = 0.0;
5675 
5676  if (parameters.waveshaper == distortionModel::kSoftClip)
5678  else if (parameters.waveshaper == distortionModel::kArcTan)
5679  output = atanWaveShaper(xn, parameters.saturation);
5680  else if (parameters.waveshaper == distortionModel::kFuzzAsym)
5682 
5683  // --- inversion, normal for plate of class A triode
5685  output *= -1.0;
5686 
5687  // --- Output (plate) capacitor = HPF, remove DC offset
5688  if (parameters.enableHPF)
5689  output = outputHPF.processAudioSample(output);
5690 
5691  // --- if cathode resistor bypass, will create low shelf
5692  if (parameters.enableLSF)
5693  output = outputLSF.processAudioSample(output);
5694 
5695  // --- final resistor divider/potentiometer
5696  output *= parameters.outputGain;
5697 
5698  return output;
5699  }
5700 
5701 protected:
5705 };
5706 
5707 const unsigned int NUM_TUBES = 4;
5708 
5721 {
5724  ClassATubePreParameters& operator=(const ClassATubePreParameters& params) // need this override for collections to work
5725  {
5726  if (this == &params)
5727  return *this;
5728 
5729  inputLevel_dB = params.inputLevel_dB;
5730  saturation = params.saturation;
5731  asymmetry = params.asymmetry;
5732  outputLevel_dB = params.outputLevel_dB;
5733 
5734  lowShelf_fc = params.lowShelf_fc;
5736  highShelf_fc = params.highShelf_fc;
5738 
5739  return *this;
5740  }
5741 
5742  // --- individual parameters
5743  double inputLevel_dB = 0.0;
5744  double saturation = 0.0;
5745  double asymmetry = 0.0;
5746  double outputLevel_dB = 0.0;
5747 
5748  // --- shelving filter params
5749  double lowShelf_fc = 0.0;
5750  double lowShelfBoostCut_dB = 0.0;
5751  double highShelf_fc = 0.0;
5752  double highShelfBoostCut_dB = 0.0;
5753 
5754 };
5755 
5774 {
5775 public:
5776  ClassATubePre() {} /* C-TOR */
5777  ~ClassATubePre() {} /* D-TOR */
5778 
5780  virtual bool reset(double _sampleRate)
5781  {
5782  TriodeClassAParameters tubeParams = triodes[0].getParameters();
5783  tubeParams.invertOutput = true;
5784  tubeParams.enableHPF = true; // remove DC offsets
5785  tubeParams.outputGain = 1.0;
5786  tubeParams.saturation = 1.0;
5787  tubeParams.asymmetry = 0.0;
5788  tubeParams.enableLSF = true;
5789  tubeParams.lsf_Fshelf = 88.0;
5790  tubeParams.lsf_BoostCut_dB = -12.0;
5791  tubeParams.waveshaper = distortionModel::kFuzzAsym;
5792 
5793  for (int i = 0; i < NUM_TUBES; i++)
5794  {
5795  triodes[i].reset(_sampleRate);
5796  triodes[i].setParameters(tubeParams);
5797  }
5798 
5799  shelvingFilter.reset(_sampleRate);
5800 
5801  return true;
5802  }
5803 
5809 
5815  {
5816  // --- check for re-calc
5817  if (params.inputLevel_dB != parameters.inputLevel_dB)
5818  inputLevel = pow(10.0, params.inputLevel_dB / 20.0);
5820  outputLevel = pow(10.0, params.outputLevel_dB / 20.0);
5821 
5822  // --- store
5823  parameters = params;
5824 
5825  // --- shelving filter update
5827  sfParams.lowShelf_fc = parameters.lowShelf_fc;
5831  shelvingFilter.setParameters(sfParams);
5832 
5833  // --- triode updates
5834  TriodeClassAParameters tubeParams = triodes[0].getParameters();
5835  tubeParams.saturation = parameters.saturation;
5836  tubeParams.asymmetry = parameters.asymmetry;
5837 
5838  for (int i = 0; i < NUM_TUBES; i++)
5839  triodes[i].setParameters(tubeParams);
5840  }
5841 
5843  virtual bool canProcessAudioFrame() { return false; }
5844 
5850  virtual double processAudioSample(double xn)
5851  {
5852  double output1 = triodes[0].processAudioSample(xn*inputLevel);
5853  double output2 = triodes[1].processAudioSample(output1);
5854  double output3 = triodes[2].processAudioSample(output2);
5855 
5856  // --- filter stage is between 3 and 4
5857  double outputEQ = shelvingFilter.processAudioSample(output3);
5858  double output4 = triodes[3].processAudioSample(outputEQ);
5859 
5860  return output4*outputLevel;
5861  }
5862 
5863 protected:
5865  TriodeClassA triodes[NUM_TUBES];
5867 
5868  double inputLevel = 1.0;
5869  double outputLevel = 1.0;
5870 };
5871 
5872 
5885 {
5888  BitCrusherParameters& operator=(const BitCrusherParameters& params) // need this override for collections to work
5889  {
5890  if (this == &params)
5891  return *this;
5892 
5894 
5895  return *this;
5896  }
5897 
5898  double quantizedBitDepth = 4.0;
5899 };
5900 
5919 {
5920 public:
5921  BitCrusher() {} /* C-TOR */
5922  ~BitCrusher() {} /* D-TOR */
5923 
5925  virtual bool reset(double _sampleRate){ return true; }
5926 
5932 
5938  {
5939  // --- calculate and store
5941  QL = 2.0 / (pow(2.0, params.quantizedBitDepth) - 1.0);
5942 
5943  parameters = params;
5944  }
5945 
5947  virtual bool canProcessAudioFrame() { return false; }
5948 
5954  virtual double processAudioSample(double xn)
5955  {
5956  return QL*(int(xn / QL));
5957  }
5958 
5959 protected:
5961  double QL = 1.0;
5962 };
5963 
5964 
5965 // ------------------------------------------------------------------ //
5966 // --- WDF LIBRARY -------------------------------------------------- //
5967 // ------------------------------------------------------------------ //
5968 
5981 {
5982 public:
5984  virtual void initialize(double _R1) {}
5985 
5987  virtual void initializeAdaptorChain() {}
5988 
5990  virtual void setInput(double _in) {}
5991 
5993  virtual double getOutput() { return 0.0; }
5994 
5995  // --- for adaptors
5997  virtual void setInput1(double _in1) = 0;
5998 
6000  virtual void setInput2(double _in2) = 0;
6001 
6003  virtual void setInput3(double _in3) = 0;
6004 
6006  virtual double getOutput1() = 0;
6007 
6009  virtual double getOutput2() = 0;
6010 
6012  virtual double getOutput3() = 0;
6013 
6015  virtual void reset(double _sampleRate) {}
6016 
6018  virtual double getComponentResistance() { return 0.0; }
6019 
6021  virtual double getComponentConductance() { return 0.0; }
6022 
6024  virtual void updateComponentResistance() {}
6025 
6027  virtual void setComponentValue(double _componentValue) { }
6028 
6030  virtual void setComponentValue_LC(double componentValue_L, double componentValue_C) { }
6031 
6033  virtual void setComponentValue_RL(double componentValue_R, double componentValue_L) { }
6034 
6036  virtual void setComponentValue_RC(double componentValue_R, double componentValue_C) { }
6037 
6039  virtual double getComponentValue() { return 0.0; }
6040 };
6041 
6042 // ------------------------------------------------------------------ //
6043 // --- WDF COMPONENTS & COMMBO COMPONENTS --------------------------- //
6044 // ------------------------------------------------------------------ //
6058 {
6059 public:
6060  WdfResistor(double _componentValue) { componentValue = _componentValue; }
6061  WdfResistor() { }
6062  virtual ~WdfResistor() {}
6063 
6065  void setSampleRate(double _sampleRate)
6066  {
6067  sampleRate = _sampleRate;
6069  }
6070 
6072  virtual double getComponentResistance() { return componentResistance; }
6073 
6075  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6076 
6078  virtual double getComponentValue() { return componentValue; }
6079 
6081  virtual void setComponentValue(double _componentValue)
6082  {
6083  componentValue = _componentValue;
6085  }
6086 
6089 
6091  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6092 
6094  virtual void setInput(double in) {}
6095 
6097  virtual double getOutput() { return 0.0; }
6098 
6100  virtual double getOutput1() { return getOutput(); }
6101 
6103  virtual double getOutput2() { return getOutput(); }
6104 
6106  virtual double getOutput3() { return getOutput(); }
6107 
6109  virtual void setInput1(double _in1) {}
6110 
6112  virtual void setInput2(double _in2) {}
6113 
6115  virtual void setInput3(double _in3) {}
6116 
6117 protected:
6118  double zRegister = 0.0;
6119  double componentValue = 0.0;
6120  double componentResistance = 0.0;
6121  double sampleRate = 0.0;
6122 };
6123 
6124 
6138 {
6139 public:
6140  WdfCapacitor(double _componentValue) { componentValue = _componentValue; }
6141  WdfCapacitor() { }
6142  virtual ~WdfCapacitor() {}
6143 
6145  void setSampleRate(double _sampleRate)
6146  {
6147  sampleRate = _sampleRate;
6149  }
6150 
6152  virtual double getComponentResistance() { return componentResistance; }
6153 
6155  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6156 
6158  virtual double getComponentValue() { return componentValue; }
6159 
6161  virtual void setComponentValue(double _componentValue)
6162  {
6163  componentValue = _componentValue;
6165  }
6166 
6169  {
6171  }
6172 
6174  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6175 
6177  virtual void setInput(double in) { zRegister = in; }
6178 
6180  virtual double getOutput() { return zRegister; } // z^-1
6181 
6183  virtual double getOutput1() { return getOutput(); }
6184 
6186  virtual double getOutput2() { return getOutput(); }
6187 
6189  virtual double getOutput3() { return getOutput(); }
6190 
6192  virtual void setInput1(double _in1) {}
6193 
6195  virtual void setInput2(double _in2) {}
6196 
6198  virtual void setInput3(double _in3) {}
6199 
6200 protected:
6201  double zRegister = 0.0;
6202  double componentValue = 0.0;
6203  double componentResistance = 0.0;
6204  double sampleRate = 0.0;
6205 };
6206 
6220 {
6221 public:
6222  WdfInductor(double _componentValue) { componentValue = _componentValue; }
6223  WdfInductor() { }
6224  virtual ~WdfInductor() {}
6225 
6227  void setSampleRate(double _sampleRate)
6228  {
6229  sampleRate = _sampleRate;
6231  }
6232 
6234  virtual double getComponentResistance() { return componentResistance; }
6235 
6237  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6238 
6240  virtual double getComponentValue() { return componentValue; }
6241 
6243  virtual void setComponentValue(double _componentValue)
6244  {
6245  componentValue = _componentValue;
6247  }
6248 
6251 
6253  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6254 
6256  virtual void setInput(double in) { zRegister = in; }
6257 
6259  virtual double getOutput() { return -zRegister; } // -z^-1
6260 
6262  virtual double getOutput1() { return getOutput(); }
6263 
6265  virtual double getOutput2() { return getOutput(); }
6266 
6268  virtual double getOutput3() { return getOutput(); }
6269 
6271  virtual void setInput1(double _in1) {}
6272 
6274  virtual void setInput2(double _in2) {}
6275 
6277  virtual void setInput3(double _in3) {}
6278 
6279 protected:
6280  double zRegister = 0.0;
6281  double componentValue = 0.0;
6282  double componentResistance = 0.0;
6283  double sampleRate = 0.0;
6284 };
6285 
6286 
6301 {
6302 public:
6303  WdfSeriesLC() {}
6304  WdfSeriesLC(double _componentValue_L, double _componentValue_C)
6305  {
6306  componentValue_L = _componentValue_L;
6307  componentValue_C = _componentValue_C;
6308  }
6309  virtual ~WdfSeriesLC() {}
6310 
6312  void setSampleRate(double _sampleRate)
6313  {
6314  sampleRate = _sampleRate;
6316  }
6317 
6319  virtual double getComponentResistance() { return componentResistance; }
6320 
6322  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6323 
6326  {
6328  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6329  componentResistance = RL + (1.0 / RC);
6330  }
6331 
6333  virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
6334  {
6335  componentValue_L = _componentValue_L;
6336  componentValue_C = _componentValue_C;
6338  }
6339 
6341  virtual void setComponentValue_L(double _componentValue_L)
6342  {
6343  componentValue_L = _componentValue_L;
6345  }
6346 
6348  virtual void setComponentValue_C(double _componentValue_C)
6349  {
6350  componentValue_C = _componentValue_C;
6352  }
6353 
6355  virtual double getComponentValue_L() { return componentValue_L; }
6356 
6358  virtual double getComponentValue_C() { return componentValue_C; }
6359 
6361  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6362 
6364  virtual void setInput(double in)
6365  {
6366  double YC = 1.0 / RC;
6367  double K = (1.0 - RL*YC) / (1.0 + RL*YC);
6368  double N1 = K*(in - zRegister_L);
6369  zRegister_L = N1 + zRegister_C;
6370  zRegister_C = in;
6371  }
6372 
6374  virtual double getOutput(){ return zRegister_L; }
6375 
6377  virtual double getOutput1() { return getOutput(); }
6378 
6380  virtual double getOutput2() { return getOutput(); }
6381 
6383  virtual double getOutput3() { return getOutput(); }
6384 
6386  virtual void setInput1(double _in1) {}
6387 
6389  virtual void setInput2(double _in2) {}
6390 
6392  virtual void setInput3(double _in3) {}
6393 
6394 protected:
6395  double zRegister_L = 0.0;
6396  double zRegister_C = 0.0;
6397 
6398  double componentValue_L = 0.0;
6399  double componentValue_C = 0.0;
6400 
6401  double RL = 0.0;
6402  double RC = 0.0;
6403  double componentResistance = 0.0;
6404  double sampleRate = 0.0;
6405 };
6406 
6421 {
6422 public:
6423  WdfParallelLC() {}
6424  WdfParallelLC(double _componentValue_L, double _componentValue_C)
6425  {
6426  componentValue_L = _componentValue_L;
6427  componentValue_C = _componentValue_C;
6428  }
6429  virtual ~WdfParallelLC() {}
6430 
6432  void setSampleRate(double _sampleRate)
6433  {
6434  sampleRate = _sampleRate;
6436  }
6437 
6439  virtual double getComponentResistance() { return componentResistance; }
6440 
6442  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6443 
6446  {
6448  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6449  componentResistance = (RC + 1.0 / RL);
6450  }
6451 
6453  virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
6454  {
6455  componentValue_L = _componentValue_L;
6456  componentValue_C = _componentValue_C;
6458  }
6459 
6461  virtual void setComponentValue_L(double _componentValue_L)
6462  {
6463  componentValue_L = _componentValue_L;
6465  }
6466 
6468  virtual void setComponentValue_C(double _componentValue_C)
6469  {
6470  componentValue_C = _componentValue_C;
6472  }
6473 
6475  virtual double getComponentValue_L() { return componentValue_L; }
6476 
6478  virtual double getComponentValue_C() { return componentValue_C; }
6479 
6481  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6482 
6484  virtual void setInput(double in)
6485  {
6486  double YL = 1.0 / RL;
6487  double K = (YL*RC - 1.0) / (YL*RC + 1.0);
6488  double N1 = K*(in - zRegister_L);
6489  zRegister_L = N1 + zRegister_C;
6490  zRegister_C = in;
6491  }
6492 
6494  virtual double getOutput(){ return -zRegister_L; }
6495 
6497  virtual double getOutput1() { return getOutput(); }
6498 
6500  virtual double getOutput2() { return getOutput(); }
6501 
6503  virtual double getOutput3() { return getOutput(); }
6504 
6506  virtual void setInput1(double _in1) {}
6507 
6509  virtual void setInput2(double _in2) {}
6510 
6512  virtual void setInput3(double _in3) {}
6513 
6514 protected:
6515  double zRegister_L = 0.0;
6516  double zRegister_C = 0.0;
6517 
6518  double componentValue_L = 0.0;
6519  double componentValue_C = 0.0;
6520 
6521  double RL = 0.0;
6522  double RC = 0.0;
6523  double componentResistance = 0.0;
6524  double sampleRate = 0.0;
6525 };
6526 
6527 
6542 {
6543 public:
6544  WdfSeriesRL() {}
6545  WdfSeriesRL(double _componentValue_R, double _componentValue_L)
6546  {
6547  componentValue_L = _componentValue_L;
6548  componentValue_R = _componentValue_R;
6549  }
6550  virtual ~WdfSeriesRL() {}
6551 
6553  void setSampleRate(double _sampleRate)
6554  {
6555  sampleRate = _sampleRate;
6557  }
6558 
6560  virtual double getComponentResistance() { return componentResistance; }
6561 
6563  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6564 
6567  {
6568  RR = componentValue_R;
6571  K = RR / componentResistance;
6572  }
6573 
6575  virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
6576  {
6577  componentValue_L = _componentValue_L;
6578  componentValue_R = _componentValue_R;
6580  }
6581 
6583  virtual void setComponentValue_L(double _componentValue_L)
6584  {
6585  componentValue_L = _componentValue_L;
6587  }
6588 
6590  virtual void setComponentValue_R(double _componentValue_R)
6591  {
6592  componentValue_R = _componentValue_R;
6594  }
6595 
6597  virtual double getComponentValue_L() { return componentValue_L; }
6598 
6600  virtual double getComponentValue_R() { return componentValue_R; }
6601 
6603  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6604 
6606  virtual void setInput(double in){ zRegister_L = in; }
6607 
6609  virtual double getOutput()
6610  {
6611  double NL = -zRegister_L;
6612  double out = NL*(1.0 - K) - K*zRegister_C;
6613  zRegister_C = out;
6614 
6615  return out;
6616  }
6617 
6619  virtual double getOutput1() { return getOutput(); }
6620 
6622  virtual double getOutput2() { return getOutput(); }
6623 
6625  virtual double getOutput3() { return getOutput(); }
6626 
6628  virtual void setInput1(double _in1) {}
6629 
6631  virtual void setInput2(double _in2) {}
6632 
6634  virtual void setInput3(double _in3) {}
6635 
6636 protected:
6637  double zRegister_L = 0.0;
6638  double zRegister_C = 0.0;
6639  double K = 0.0;
6640 
6641  double componentValue_L = 0.0;
6642  double componentValue_R = 0.0;
6643 
6644  double RL = 0.0;
6645  double RC = 0.0;
6646  double RR = 0.0;
6647 
6648  double componentResistance = 0.0;
6649  double sampleRate = 0.0;
6650 };
6651 
6665 {
6666 public:
6667  WdfParallelRL() {}
6668  WdfParallelRL(double _componentValue_R, double _componentValue_L)
6669  {
6670  componentValue_L = _componentValue_L;
6671  componentValue_R = _componentValue_R;
6672  }
6673  virtual ~WdfParallelRL() {}
6674 
6676  void setSampleRate(double _sampleRate)
6677  {
6678  sampleRate = _sampleRate;
6680  }
6681 
6683  virtual double getComponentResistance() { return componentResistance; }
6684 
6686  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6687 
6690  {
6691  RR = componentValue_R;
6693  componentResistance = 1.0 / ((1.0 / RR) + (1.0 / RL));
6694  K = componentResistance / RR;
6695  }
6696 
6697 
6699  virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
6700  {
6701  componentValue_L = _componentValue_L;
6702  componentValue_R = _componentValue_R;
6704  }
6705 
6707  virtual void setComponentValue_L(double _componentValue_L)
6708  {
6709  componentValue_L = _componentValue_L;
6711  }
6712 
6714  virtual void setComponentValue_R(double _componentValue_R)
6715  {
6716  componentValue_R = _componentValue_R;
6718  }
6719 
6721  virtual double getComponentValue_L() { return componentValue_L; }
6722 
6724  virtual double getComponentValue_R() { return componentValue_R; }
6725 
6727  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6728 
6730  virtual void setInput(double in){ zRegister_L = in; }
6731 
6733  virtual double getOutput()
6734  {
6735  double NL = -zRegister_L;
6736  double out = NL*(1.0 - K) + K*zRegister_C;
6737  zRegister_C = out;
6738  return out;
6739  }
6740 
6742  virtual double getOutput1() { return getOutput(); }
6743 
6745  virtual double getOutput2() { return getOutput(); }
6746 
6748  virtual double getOutput3() { return getOutput(); }
6749 
6751  virtual void setInput1(double _in1) {}
6752 
6754  virtual void setInput2(double _in2) {}
6755 
6757  virtual void setInput3(double _in3) {}
6758 
6759 protected:
6760  double zRegister_L = 0.0;
6761  double zRegister_C = 0.0;
6762  double K = 0.0;
6763 
6764  double componentValue_L = 0.0;
6765  double componentValue_R = 0.0;
6766 
6767  double RL = 0.0;
6768  double RC = 0.0;
6769  double RR = 0.0;
6770 
6771  double componentResistance = 0.0;
6772  double sampleRate = 0.0;
6773 };
6774 
6789 {
6790 public:
6791  WdfSeriesRC() {}
6792  WdfSeriesRC(double _componentValue_R, double _componentValue_C)
6793  {
6794  componentValue_C = _componentValue_C;
6795  componentValue_R = _componentValue_R;
6796  }
6797  virtual ~WdfSeriesRC() {}
6798 
6800  void setSampleRate(double _sampleRate)
6801  {
6802  sampleRate = _sampleRate;
6804  }
6805 
6807  virtual double getComponentResistance() { return componentResistance; }
6808 
6810  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6811 
6814  {
6815  RR = componentValue_R;
6816  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6818  K = RR / componentResistance;
6819  }
6820 
6822  virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
6823  {
6824  componentValue_R = _componentValue_R;
6825  componentValue_C = _componentValue_C;
6827  }
6828 
6830  virtual void setComponentValue_R(double _componentValue_R)
6831  {
6832  componentValue_R = _componentValue_R;
6834  }
6835 
6837  virtual void setComponentValue_C(double _componentValue_C)
6838  {
6839  componentValue_C = _componentValue_C;
6841  }
6842 
6844  virtual double getComponentValue_R() { return componentValue_R; }
6845 
6847  virtual double getComponentValue_C() { return componentValue_C; }
6848 
6850  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6851 
6853  virtual void setInput(double in){ zRegister_L = in; }
6854 
6856  virtual double getOutput()
6857  {
6858  double NL = zRegister_L;
6859  double out = NL*(1.0 - K) + K*zRegister_C;
6860  zRegister_C = out;
6861  return out;
6862  }
6863 
6865  virtual double getOutput1() { return getOutput(); }
6866 
6868  virtual double getOutput2() { return getOutput(); }
6869 
6871  virtual double getOutput3() { return getOutput(); }
6872 
6874  virtual void setInput1(double _in1) {}
6875 
6877  virtual void setInput2(double _in2) {}
6878 
6880  virtual void setInput3(double _in3) {}
6881 
6882 protected:
6883  double zRegister_L = 0.0;
6884  double zRegister_C = 0.0;
6885  double K = 0.0;
6886 
6887  double componentValue_R = 0.0;
6888  double componentValue_C = 0.0;
6889 
6890  double RL = 0.0;
6891  double RC = 0.0;
6892  double RR = 0.0;
6893 
6894  double componentResistance = 0.0;
6895  double sampleRate = 0.0;
6896 };
6897 
6912 {
6913 public:
6914  WdfParallelRC() {}
6915  WdfParallelRC(double _componentValue_R, double _componentValue_C)
6916  {
6917  componentValue_C = _componentValue_C;
6918  componentValue_R = _componentValue_R;
6919  }
6920  virtual ~WdfParallelRC() {}
6921 
6923  void setSampleRate(double _sampleRate)
6924  {
6925  sampleRate = _sampleRate;
6927  }
6928 
6930  virtual double getComponentResistance() { return componentResistance; }
6931 
6933  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6934 
6937  {
6938  RR = componentValue_R;
6939  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6940  componentResistance = 1.0 / ((1.0 / RR) + (1.0 / RC));
6941  K = componentResistance / RR;
6942  }
6943 
6945  virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
6946  {
6947  componentValue_R = _componentValue_R;
6948  componentValue_C = _componentValue_C;
6950  }
6951 
6953  virtual void setComponentValue_R(double _componentValue_R)
6954  {
6955  componentValue_R = _componentValue_R;
6957  }
6958 
6960  virtual void setComponentValue_C(double _componentValue_C)
6961  {
6962  componentValue_C = _componentValue_C;
6964  }
6965 
6967  virtual double getComponentValue_R() { return componentValue_R; }
6968 
6970  virtual double getComponentValue_C() { return componentValue_C; }
6971 
6973  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6974 
6976  virtual void setInput(double in){ zRegister_L = in; }
6977 
6979  virtual double getOutput()
6980  {
6981  double NL = zRegister_L;
6982  double out = NL*(1.0 - K) - K*zRegister_C;
6983  zRegister_C = out;
6984  return out;
6985  }
6986 
6988  virtual double getOutput1() { return getOutput(); }
6989 
6991  virtual double getOutput2() { return getOutput(); }
6992 
6994  virtual double getOutput3() { return getOutput(); }
6995 
6997  virtual void setInput1(double _in1) {}
6998 
7000  virtual void setInput2(double _in2) {}
7001 
7003  virtual void setInput3(double _in3) {}
7004 
7005 protected:
7006  double zRegister_L = 0.0;
7007  double zRegister_C = 0.0;
7008  double K = 0.0;
7009 
7010  double componentValue_C = 0.0;
7011  double componentValue_R = 0.0;
7012 
7013  double RL = 0.0;
7014  double RC = 0.0;
7015  double RR = 0.0;
7016 
7017  double componentResistance = 0.0;
7018  double sampleRate = 0.0;
7019 };
7020 
7021 
7022 // ------------------------------------------------------------------ //
7023 // --- WDF ADAPTORS ------------------------------------------------- //
7024 // ------------------------------------------------------------------ //
7025 
7039 enum class wdfComponent { R, L, C, seriesLC, parallelLC, seriesRL, parallelRL, seriesRC, parallelRC };
7040 
7053 {
7054  WdfComponentInfo() { }
7055 
7056  WdfComponentInfo(wdfComponent _componentType, double value1 = 0.0, double value2 = 0.0)
7057  {
7058  componentType = _componentType;
7059  if (componentType == wdfComponent::R)
7060  R = value1;
7061  else if (componentType == wdfComponent::L)
7062  L = value1;
7063  else if (componentType == wdfComponent::C)
7064  C = value1;
7065  else if (componentType == wdfComponent::seriesLC || componentType == wdfComponent::parallelLC)
7066  {
7067  L = value1;
7068  C = value2;
7069  }
7070  else if (componentType == wdfComponent::seriesRL || componentType == wdfComponent::parallelRL)
7071  {
7072  R = value1;
7073  L = value2;
7074  }
7075  else if (componentType == wdfComponent::seriesRC || componentType == wdfComponent::parallelRC)
7076  {
7077  R = value1;
7078  C = value2;
7079  }
7080  }
7081 
7082  double R = 0.0;
7083  double L = 0.0;
7084  double C = 0.0;
7085  wdfComponent componentType = wdfComponent::R;
7086 };
7087 
7088 
7102 {
7103 public:
7104  WdfAdaptorBase() {
7105  if (wdfComponent)
7106  delete wdfComponent;
7107  }
7108  virtual ~WdfAdaptorBase() {}
7109 
7111  void setTerminalResistance(double _terminalResistance) { terminalResistance = _terminalResistance; }
7112 
7114  void setOpenTerminalResistance(bool _openTerminalResistance = true)
7115  {
7116  // --- flag overrides value
7117  openTerminalResistance = _openTerminalResistance;
7118  terminalResistance = 1.0e+34; // avoid /0.0
7119  }
7120 
7122  void setSourceResistance(double _sourceResistance) { sourceResistance = _sourceResistance; }
7123 
7125  void setPort1_CompAdaptor(IComponentAdaptor* _port1CompAdaptor) { port1CompAdaptor = _port1CompAdaptor; }
7126 
7128  void setPort2_CompAdaptor(IComponentAdaptor* _port2CompAdaptor) { port2CompAdaptor = _port2CompAdaptor; }
7129 
7131  void setPort3_CompAdaptor(IComponentAdaptor* _port3CompAdaptor) { port3CompAdaptor = _port3CompAdaptor; }
7132 
7134  virtual void reset(double _sampleRate)
7135  {
7136  if (wdfComponent)
7137  wdfComponent->reset(_sampleRate);
7138  }
7139 
7141  void setComponent(wdfComponent componentType, double value1 = 0.0, double value2 = 0.0)
7142  {
7143  if (wdfComponent)
7144  delete wdfComponent;
7145 
7146  // --- decode and set
7147  if (componentType == wdfComponent::R)
7148  {
7149  wdfComponent = new WdfResistor;
7152  }
7153  else if (componentType == wdfComponent::L)
7154  {
7155  wdfComponent = new WdfInductor;
7158  }
7159  else if (componentType == wdfComponent::C)
7160  {
7161  wdfComponent = new WdfCapacitor;
7164  }
7165  else if (componentType == wdfComponent::seriesLC)
7166  {
7167  wdfComponent = new WdfSeriesLC;
7168  wdfComponent->setComponentValue_LC(value1, value2);
7170  }
7171  else if (componentType == wdfComponent::parallelLC)
7172  {
7174  wdfComponent->setComponentValue_LC(value1, value2);
7176  }
7177  else if (componentType == wdfComponent::seriesRL)
7178  {
7179  wdfComponent = new WdfSeriesRL;
7180  wdfComponent->setComponentValue_RL(value1, value2);
7182  }
7183  else if (componentType == wdfComponent::parallelRL)
7184  {
7186  wdfComponent->setComponentValue_RL(value1, value2);
7188  }
7189  else if (componentType == wdfComponent::seriesRC)
7190  {
7191  wdfComponent = new WdfSeriesRC;
7192  wdfComponent->setComponentValue_RC(value1, value2);
7194  }
7195  else if (componentType == wdfComponent::parallelRC)
7196  {
7198  wdfComponent->setComponentValue_RC(value1, value2);
7200  }
7201  }
7202 
7204  static void connectAdaptors(WdfAdaptorBase* upstreamAdaptor, WdfAdaptorBase* downstreamAdaptor)
7205  {
7206  upstreamAdaptor->setPort2_CompAdaptor(downstreamAdaptor);
7207  downstreamAdaptor->setPort1_CompAdaptor(upstreamAdaptor);
7208  }
7209 
7211  virtual void initializeAdaptorChain()
7212  {
7214  }
7215 
7217  virtual void setComponentValue(double _componentValue)
7218  {
7219  if (wdfComponent)
7220  wdfComponent->setComponentValue(_componentValue);
7221  }
7222 
7224  virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
7225  {
7226  if (wdfComponent)
7227  wdfComponent->setComponentValue_LC(componentValue_L, componentValue_C);
7228  }
7229 
7231  virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
7232  {
7233  if (wdfComponent)
7234  wdfComponent->setComponentValue_RL(componentValue_R, componentValue_L);
7235  }
7236 
7238  virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
7239  {
7240  if (wdfComponent)
7241  wdfComponent->setComponentValue_RC(componentValue_R, componentValue_C);
7242  }
7243 
7246 
7249 
7252 
7253 protected:
7254  // --- can in theory connect any port to a component OR adaptor;
7255  // though this library is setup with a convention R3 = component
7260 
7261  // --- These hold the input (R1), component (R3) and output (R2) resistances
7262  double R1 = 0.0;
7263  double R2 = 0.0;
7264  double R3 = 0.0;
7265 
7266  // --- these are input variables that are stored;
7267  // not used in this implementation but may be required for extended versions
7268  double in1 = 0.0;
7269  double in2 = 0.0;
7270  double in3 = 0.0;
7271 
7272  // --- these are output variables that are stored;
7273  // currently out2 is the only one used as it is y(n) for this library
7274  // out1 and out2 are stored; not used in this implementation but may be required for extended versions
7275  double out1 = 0.0;
7276  double out2 = 0.0;
7277  double out3 = 0.0;
7278 
7279  // --- terminal impedance
7280  double terminalResistance = 600.0;
7281  bool openTerminalResistance = false;
7282 
7283  // --- source impedance, OK for this to be set to 0.0 for Rs = 0
7284  double sourceResistance = 600.0;
7285 };
7286 
7299 {
7300 public:
7301  WdfSeriesAdaptor() {}
7302  virtual ~WdfSeriesAdaptor() {}
7303 
7305  virtual double getR2()
7306  {
7307  double componentResistance = 0.0;
7308  if (getPort3_CompAdaptor())
7309  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7310 
7311  R2 = R1 + componentResistance;
7312  return R2;
7313  }
7314 
7316  virtual void initialize(double _R1)
7317  {
7318  // --- R1 is source resistance for this adaptor
7319  R1 = _R1;
7320 
7321  double componentResistance = 0.0;
7322  if (getPort3_CompAdaptor())
7323  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7324 
7325  // --- calculate B coeff
7326  B = R1 / (R1 + componentResistance);
7327 
7328  // --- init downstream adaptor
7329  if (getPort2_CompAdaptor())
7331 
7332  // --- not used in this implementation but saving for extended use
7333  R3 = componentResistance;
7334  }
7335 
7337  virtual void setInput1(double _in1)
7338  {
7339  // --- save
7340  in1 = _in1;
7341 
7342  // --- read component value
7343  N2 = 0.0;
7344  if (getPort3_CompAdaptor())
7345  N2 = getPort3_CompAdaptor()->getOutput();
7346 
7347  // --- form output
7348  out2 = -(in1 + N2);
7349 
7350  // --- deliver downstream
7351  if (getPort2_CompAdaptor())
7353  }
7354 
7356  virtual void setInput2(double _in2)
7357  {
7358  // --- save
7359  in2 = _in2;
7360 
7361  // --- calc N1
7362  N1 = -(in1 - B*(in1 + N2 + in2) + in2);
7363 
7364  // --- calc out1
7365  out1 = in1 - B*(N2 + in2);
7366 
7367  // --- deliver upstream
7368  if (getPort1_CompAdaptor())
7370 
7371  // --- set component state
7372  if (getPort3_CompAdaptor())
7374  }
7375 
7377  virtual void setInput3(double _in3){ }
7378 
7380  virtual double getOutput1() { return out1; }
7381 
7383  virtual double getOutput2() { return out2; }
7384 
7386  virtual double getOutput3() { return out3; }
7387 
7388 private:
7389  double N1 = 0.0;
7390  double N2 = 0.0;
7391  double B = 0.0;
7392 };
7393 
7405 // --- Series terminated adaptor
7407 {
7408 public:
7410  virtual ~WdfSeriesTerminatedAdaptor() {}
7411 
7413  virtual double getR2()
7414  {
7415  double componentResistance = 0.0;
7416  if (getPort3_CompAdaptor())
7417  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7418 
7419  R2 = R1 + componentResistance;
7420  return R2;
7421  }
7422 
7424  virtual void initialize(double _R1)
7425  {
7426  // --- source impedance
7427  R1 = _R1;
7428 
7429  double componentResistance = 0.0;
7430  if (getPort3_CompAdaptor())
7431  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7432 
7433  B1 = (2.0*R1) / (R1 + componentResistance + terminalResistance);
7434  B3 = (2.0*terminalResistance) / (R1 + componentResistance + terminalResistance);
7435 
7436  // --- init downstream
7437  if (getPort2_CompAdaptor())
7439 
7440  // --- not used in this implementation but saving for extended use
7441  R3 = componentResistance;
7442  }
7443 
7445  virtual void setInput1(double _in1)
7446  {
7447  // --- save
7448  in1 = _in1;
7449 
7450  N2 = 0.0;
7451  if (getPort3_CompAdaptor())
7452  N2 = getPort3_CompAdaptor()->getOutput();
7453 
7454  double N3 = in1 + N2;
7455 
7456  // --- calc out2 y(n)
7457  out2 = -B3*N3;
7458 
7459  // --- form output1
7460  out1 = in1 - B1*N3;
7461 
7462  // --- form N1
7463  N1 = -(out1 + out2 + N3);
7464 
7465  // --- deliver upstream to input2
7466  if (getPort1_CompAdaptor())
7468 
7469  // --- set component state
7470  if (getPort3_CompAdaptor())
7472  }
7473 
7476  virtual void setInput2(double _in2) { in2 = _in2;}
7477 
7479  virtual void setInput3(double _in3) { in3 = _in3;}
7480 
7482  virtual double getOutput1() { return out1; }
7483 
7485  virtual double getOutput2() { return out2; }
7486 
7488  virtual double getOutput3() { return out3; }
7489 
7490 private:
7491  double N1 = 0.0;
7492  double N2 = 0.0;
7493  double B1 = 0.0;
7494  double B3 = 0.0;
7495 };
7496 
7509 {
7510 public:
7511  WdfParallelAdaptor() {}
7512  virtual ~WdfParallelAdaptor() {}
7513 
7515  virtual double getR2()
7516  {
7517  double componentConductance = 0.0;
7518  if (getPort3_CompAdaptor())
7519  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7520 
7521  // --- 1 / (sum of admittances)
7522  R2 = 1.0 / ((1.0 / R1) + componentConductance);
7523  return R2;
7524  }
7525 
7527  virtual void initialize(double _R1)
7528  {
7529  // --- save R1
7530  R1 = _R1;
7531 
7532  double G1 = 1.0 / R1;
7533  double componentConductance = 0.0;
7534  if (getPort3_CompAdaptor())
7535  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7536 
7537  // --- calculate B coeff
7538  A = G1 / (G1 + componentConductance);
7539 
7540  // --- now, do we init our downstream??
7541  if (getPort2_CompAdaptor())
7543 
7544  // --- not used in this implementation but saving for extended use
7545  R3 = 1.0/ componentConductance;
7546  }
7547 
7549  virtual void setInput1(double _in1)
7550  {
7551  // --- save
7552  in1 = _in1;
7553 
7554  // --- read component
7555  N2 = 0.0;
7556  if (getPort3_CompAdaptor())
7557  N2 = getPort3_CompAdaptor()->getOutput();
7558 
7559  // --- form output
7560  out2 = N2 - A*(-in1 + N2);
7561 
7562  // --- deliver downstream
7563  if (getPort2_CompAdaptor())
7565  }
7566 
7568  virtual void setInput2(double _in2)
7569  {
7570  // --- save
7571  in2 = _in2;
7572 
7573  // --- calc N1
7574  N1 = in2 - A*(-in1 + N2);
7575 
7576  // --- calc out1
7577  out1 = -in1 + N2 + N1;
7578 
7579  // --- deliver upstream
7580  if (getPort1_CompAdaptor())
7582 
7583  // --- set component state
7584  if (getPort3_CompAdaptor())
7586  }
7587 
7589  virtual void setInput3(double _in3) { }
7590 
7592  virtual double getOutput1() { return out1; }
7593 
7595  virtual double getOutput2() { return out2; }
7596 
7598  virtual double getOutput3() { return out3; }
7599 
7600 private:
7601  double N1 = 0.0;
7602  double N2 = 0.0;
7603  double A = 0.0;
7604 };
7605 
7606 
7619 {
7620 public:
7622  virtual ~WdfParallelTerminatedAdaptor() {}
7623 
7625  virtual double getR2()
7626  {
7627  double componentConductance = 0.0;
7628  if (getPort3_CompAdaptor())
7629  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7630 
7631  // --- 1 / (sum of admittances)
7632  R2 = 1.0 / ((1.0 / R1) + componentConductance);
7633  return R2;
7634  }
7635 
7637  virtual void initialize(double _R1)
7638  {
7639  // --- save R1
7640  R1 = _R1;
7641 
7642  double G1 = 1.0 / R1;
7643  if (terminalResistance <= 0.0)
7644  terminalResistance = 1e-15;
7645 
7646  double G2 = 1.0 / terminalResistance;
7647  double componentConductance = 0.0;
7648  if (getPort3_CompAdaptor())
7649  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7650 
7651  A1 = 2.0*G1 / (G1 + componentConductance + G2);
7652  A3 = openTerminalResistance ? 0.0 : 2.0*G2 / (G1 + componentConductance + G2);
7653 
7654  // --- init downstream
7655  if (getPort2_CompAdaptor())
7657 
7658  // --- not used in this implementation but saving for extended use
7659  R3 = 1.0 / componentConductance;
7660  }
7661 
7663  virtual void setInput1(double _in1)
7664  {
7665  // --- save
7666  in1 = _in1;
7667 
7668  N2 = 0.0;
7669  if (getPort3_CompAdaptor())
7670  N2 = getPort3_CompAdaptor()->getOutput();
7671 
7672  // --- form N1
7673  N1 = -A1*(-in1 + N2) + N2 - A3*N2;
7674 
7675  // --- form output1
7676  out1 = -in1 + N2 + N1;
7677 
7678  // --- deliver upstream to input2
7679  if (getPort1_CompAdaptor())
7681 
7682  // --- calc out2 y(n)
7683  out2 = N2 + N1;
7684 
7685  // --- set component state
7686  if (getPort3_CompAdaptor())
7688  }
7689 
7691  virtual void setInput2(double _in2){ in2 = _in2;}
7692 
7694  virtual void setInput3(double _in3) { }
7695 
7697  virtual double getOutput1() { return out1; }
7698 
7700  virtual double getOutput2() { return out2; }
7701 
7703  virtual double getOutput3() { return out3; }
7704 
7705 private:
7706  double N1 = 0.0;
7707  double N2 = 0.0;
7708  double A1 = 0.0;
7709  double A3 = 0.0;
7710 };
7711 
7712 // ------------------------------------------------------------------------------ //
7713 // --- WDF Ladder Filter Design Examples --------------------------------------- //
7714 // ------------------------------------------------------------------------------ //
7715 //
7716 // --- 3rd order Butterworth LPF designed with Elsie www.TonneSoftware.comm
7717 //
7718 /*
7719  3rd Order Inductor-Leading LPF
7720 
7721  Rs = Rload = 600 ohms
7722 
7723  Series(L1) -> Parallel(C1) -> Series(L2)
7724 
7725  --L1-- | --L2--
7726  C1
7727  |
7728 
7729  fc = 1kHz
7730  L1 = 95.49e-3;
7731  C1 = 0.5305e-6;
7732  L2 = 95.49e-3;
7733 
7734  fc = 10kHz
7735  L1 = 9.549e-3;
7736  C1 = 0.05305e-6;
7737  L2 = 9.549e-3;
7738 */
7739 
7759 {
7760 public:
7761  WDFButterLPF3(void) { createWDF(); } /* C-TOR */
7762  ~WDFButterLPF3(void) {} /* D-TOR */
7763 
7765  virtual bool reset(double _sampleRate)
7766  {
7767  // --- rest WDF components (flush state registers)
7768  seriesAdaptor_L1.reset(_sampleRate);
7769  parallelAdaptor_C1.reset(_sampleRate);
7770  seriesTerminatedAdaptor_L2.reset(_sampleRate);
7771 
7772  // --- intialize the chain of adapters
7774  return true;
7775  }
7776 
7778  virtual bool canProcessAudioFrame() { return false; }
7779 
7785  virtual double processAudioSample(double xn)
7786  {
7787  // --- push audio sample into series L1
7789 
7790  // --- output is at terminated L2's output2
7792  }
7793 
7795  void createWDF()
7796  {
7797  // --- actual component values fc = 1kHz
7798  double L1_value = 95.49e-3; // 95.5 mH
7799  double C1_value = 0.5305e-6; // 0.53 uF
7800  double L2_value = 95.49e-3; // 95.5 mH
7801 
7802  // --- set adapter components
7803  seriesAdaptor_L1.setComponent(wdfComponent::L, L1_value);
7804  parallelAdaptor_C1.setComponent(wdfComponent::C, C1_value);
7805  seriesTerminatedAdaptor_L2.setComponent(wdfComponent::L, L2_value);
7806 
7807  // --- connect adapters
7810 
7811  // --- set source resistance
7812  seriesAdaptor_L1.setSourceResistance(600.0); // --- Rs = 600
7813 
7814  // --- set terminal resistance
7815  seriesTerminatedAdaptor_L2.setTerminalResistance(600.0); // --- Rload = 600
7816  }
7817 
7818 protected:
7819  // --- three adapters
7823 };
7824 
7845 {
7846 public:
7847  WDFTunableButterLPF3(void) { createWDF(); } /* C-TOR */
7848  ~WDFTunableButterLPF3(void) {} /* D-TOR */
7849 
7851  virtual bool reset(double _sampleRate)
7852  {
7853  sampleRate = _sampleRate;
7854  // --- rest WDF components (flush state registers)
7855  seriesAdaptor_L1.reset(_sampleRate);
7856  parallelAdaptor_C1.reset(_sampleRate);
7857  seriesTerminatedAdaptor_L2.reset(_sampleRate);
7858 
7859  // --- intialize the chain of adapters
7861  return true;
7862  }
7863 
7865  virtual bool canProcessAudioFrame() { return false; }
7866 
7872  virtual double processAudioSample(double xn)
7873  {
7874  // --- push audio sample into series L1
7876 
7877  // --- output is at terminated L2's output2
7879  }
7880 
7882  void createWDF()
7883  {
7884  // --- create components, init to noramlized values fc = 1Hz
7885  seriesAdaptor_L1.setComponent(wdfComponent::L, L1_norm);
7886  parallelAdaptor_C1.setComponent(wdfComponent::C, C1_norm);
7887  seriesTerminatedAdaptor_L2.setComponent(wdfComponent::L, L2_norm);
7888 
7889  // --- connect adapters
7892 
7893  // --- set source resistance
7894  seriesAdaptor_L1.setSourceResistance(600.0); // --- Rs = 600
7895 
7896  // --- set terminal resistance
7897  seriesTerminatedAdaptor_L2.setTerminalResistance(600.0); // --- Rload = 600
7898  }
7899 
7902 
7904  void setFilterFc(double fc_Hz)
7905  {
7906  if (useFrequencyWarping)
7907  {
7908  double arg = (kPi*fc_Hz) / sampleRate;
7909  fc_Hz = fc_Hz*(tan(arg) / arg);
7910  }
7911 
7912  seriesAdaptor_L1.setComponentValue(L1_norm / fc_Hz);
7913  parallelAdaptor_C1.setComponentValue(C1_norm / fc_Hz);
7915  }
7916 
7917 protected:
7918  // --- three adapters
7922 
7923  double L1_norm = 95.493; // 95.5 mH
7924  double C1_norm = 530.516e-6; // 0.53 uF
7925  double L2_norm = 95.493; // 95.5 mH
7926 
7927  bool useFrequencyWarping = false;
7928  double sampleRate = 1.0;
7929 };
7930 
7950 {
7951 public:
7952  WDFBesselBSF3(void) { createWDF(); } /* C-TOR */
7953  ~WDFBesselBSF3(void) {} /* D-TOR */
7954 
7956  virtual bool reset(double _sampleRate)
7957  {
7958  // --- rest WDF components (flush state registers)
7959  seriesAdaptor_L1C1.reset(_sampleRate);
7960  parallelAdaptor_L2C2.reset(_sampleRate);
7961  seriesTerminatedAdaptor_L3C3.reset(_sampleRate);
7962 
7963  // --- intialize the chain of adapters
7965 
7966  return true;
7967  }
7968 
7970  virtual bool canProcessAudioFrame() { return false; }
7971 
7977  virtual double processAudioSample(double xn)
7978  {
7979  // --- push audio sample into series L1
7981 
7982  // --- output is at terminated L2's output2
7984  }
7985 
7987  void createWDF()
7988  {
7989  // --- set component values
7990  // --- fo = 5kHz
7991  // BW = 2kHz or Q = 2.5
7992  seriesAdaptor_L1C1.setComponent(wdfComponent::parallelLC, 16.8327e-3, 0.060193e-6); /* L, C */
7993  parallelAdaptor_L2C2.setComponent(wdfComponent::seriesLC, 49.1978e-3, 0.02059e-6); /* L, C */
7994  seriesTerminatedAdaptor_L3C3.setComponent(wdfComponent::parallelLC, 2.57755e-3, 0.393092e-6); /* L, C */
7995 
7996  // --- connect adapters
7999 
8000  // --- set source resistance
8001  seriesAdaptor_L1C1.setSourceResistance(600.0); // Ro = 600
8002 
8003  // --- set terminal resistance
8005  }
8006 
8007 protected:
8008  // --- three adapters
8012 };
8013 
8014 
8034 {
8035 public:
8036  WDFConstKBPF6(void) { createWDF(); } /* C-TOR */
8037  ~WDFConstKBPF6(void) {} /* D-TOR */
8038 
8040  virtual bool reset(double _sampleRate)
8041  {
8042  // --- rest WDF components (flush state registers)
8043  seriesAdaptor_L1C1.reset(_sampleRate);
8044  parallelAdaptor_L2C2.reset(_sampleRate);
8045 
8046  seriesAdaptor_L3C3.reset(_sampleRate);
8047  parallelAdaptor_L4C4.reset(_sampleRate);
8048 
8049  seriesAdaptor_L5C5.reset(_sampleRate);
8051 
8052  // --- intialize the chain of adapters
8054  return true;
8055  }
8056 
8058  virtual bool canProcessAudioFrame() { return false; }
8059 
8065  virtual double processAudioSample(double xn)
8066  {
8067  // --- push audio sample into series L1
8069 
8070  // --- output is at terminated L6C6 output2
8071  double output = parallelTerminatedAdaptor_L6C6.getOutput2();
8072 
8073  return output;
8074  }
8075 
8077  void createWDF()
8078  {
8079  // --- fo = 5kHz
8080  // BW = 2kHz or Q = 2.5
8081  seriesAdaptor_L1C1.setComponent(wdfComponent::seriesLC, 47.7465e-3, 0.02122e-6);
8082  parallelAdaptor_L2C2.setComponent(wdfComponent::parallelLC, 3.81972e-3, 0.265258e-6);
8083 
8084  seriesAdaptor_L3C3.setComponent(wdfComponent::seriesLC, 95.493e-3, 0.01061e-6);
8085  parallelAdaptor_L4C4.setComponent(wdfComponent::parallelLC, 3.81972e-3, 0.265258e-6);
8086 
8087  seriesAdaptor_L5C5.setComponent(wdfComponent::seriesLC, 95.493e-3, 0.01061e-6);
8088  parallelTerminatedAdaptor_L6C6.setComponent(wdfComponent::parallelLC, 7.63944e-3, 0.132629e-6);
8089 
8090  // --- connect adapters
8096 
8097  // --- set source resistance
8098  seriesAdaptor_L1C1.setSourceResistance(600.0); // Ro = 600
8099 
8100  // --- set terminal resistance
8102  }
8103 
8104 protected:
8105  // --- six adapters
8108 
8111 
8114 };
8115 
8116 
8129 {
8130  WDFParameters() {}
8133  {
8134  if (this == &params)
8135  return *this;
8136 
8137  fc = params.fc;
8138  Q = params.Q;
8139  boostCut_dB = params.boostCut_dB;
8141  return *this;
8142  }
8143 
8144  // --- individual parameters
8145  double fc = 100.0;
8146  double Q = 0.707;
8147  double boostCut_dB = 0.0;
8148  bool frequencyWarping = true;
8149 };
8150 
8169 {
8170 public:
8171  WDFIdealRLCLPF(void) { createWDF(); } /* C-TOR */
8172  ~WDFIdealRLCLPF(void) {} /* D-TOR */
8173 
8175  virtual bool reset(double _sampleRate)
8176  {
8177  sampleRate = _sampleRate;
8178 
8179  // --- rest WDF components (flush state registers)
8180  seriesAdaptor_RL.reset(_sampleRate);
8181  parallelTerminatedAdaptor_C.reset(_sampleRate);
8182 
8183  // --- intialize the chain of adapters
8185  return true;
8186  }
8187 
8189  virtual bool canProcessAudioFrame() { return false; }
8190 
8196  virtual double processAudioSample(double xn)
8197  {
8198  // --- push audio sample into series L1
8200 
8201  // --- output is at terminated L2's output2
8202  // note compensation scaling by -6dB = 0.5
8203  // because of WDF assumption about Rs and Rload
8205  }
8206 
8208  void createWDF()
8209  {
8210  // --- create components, init to noramlized values fc =
8211  // initial values for fc = 1kHz Q = 0.707
8212  // Holding C Constant at 1e-6
8213  // L = 2.533e-2
8214  // R = 2.251131 e2
8215  seriesAdaptor_RL.setComponent(wdfComponent::seriesRL, 2.251131e2, 2.533e-2);
8216  parallelTerminatedAdaptor_C.setComponent(wdfComponent::C, 1.0e-6);
8217 
8218  // --- connect adapters
8220 
8221  // --- set source resistance
8222  seriesAdaptor_RL.setSourceResistance(0.0); // --- Rs = 600
8223 
8224  // --- set open ckt termination
8226  }
8227 
8233 
8238  void setParameters(const WDFParameters& _wdfParameters)
8239  {
8240  if (_wdfParameters.fc != wdfParameters.fc ||
8241  _wdfParameters.Q != wdfParameters.Q ||
8242  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8244  {
8245  wdfParameters = _wdfParameters;
8246  double fc_Hz = wdfParameters.fc;
8247 
8249  {
8250  double arg = (kPi*fc_Hz) / sampleRate;
8251  fc_Hz = fc_Hz*(tan(arg) / arg);
8252  }
8253 
8254  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8255  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8256 
8257  seriesAdaptor_RL.setComponentValue_RL(resistorValue, inductorValue);
8258  }
8259  }
8260 
8261 protected:
8263 
8264  // --- adapters
8267 
8268  double sampleRate = 1.0;
8269 
8270 };
8271 
8290 {
8291 public:
8292  WDFIdealRLCHPF(void) { createWDF(); } /* C-TOR */
8293  ~WDFIdealRLCHPF(void) {} /* D-TOR */
8294 
8296  virtual bool reset(double _sampleRate)
8297  {
8298  sampleRate = _sampleRate;
8299  // --- rest WDF components (flush state registers)
8300  seriesAdaptor_RC.reset(_sampleRate);
8301  parallelTerminatedAdaptor_L.reset(_sampleRate);
8302 
8303  // --- intialize the chain of adapters
8305  return true;
8306  }
8307 
8309  virtual bool canProcessAudioFrame() { return false; }
8310 
8316  virtual double processAudioSample(double xn)
8317  {
8318  // --- push audio sample into series L1
8320 
8321  // --- output is at terminated L2's output2
8322  // note compensation scaling by -6dB = 0.5
8323  // because of WDF assumption about Rs and Rload
8325  }
8326 
8328  void createWDF()
8329  {
8330  // --- create components, init to noramlized values fc =
8331  // initial values for fc = 1kHz Q = 0.707
8332  // Holding C Constant at 1e-6
8333  // L = 2.533e-2
8334  // R = 2.251131 e2
8335  seriesAdaptor_RC.setComponent(wdfComponent::seriesRC, 2.251131e2, 1.0e-6);
8336  parallelTerminatedAdaptor_L.setComponent(wdfComponent::L, 2.533e-2);
8337 
8338  // --- connect adapters
8340 
8341  // --- set source resistance
8342  seriesAdaptor_RC.setSourceResistance(0.0); // --- Rs = 600
8343 
8344  // --- set open ckt termination
8346  }
8347 
8353 
8358  void setParameters(const WDFParameters& _wdfParameters)
8359  {
8360  if (_wdfParameters.fc != wdfParameters.fc ||
8361  _wdfParameters.Q != wdfParameters.Q ||
8362  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8364  {
8365  wdfParameters = _wdfParameters;
8366  double fc_Hz = wdfParameters.fc;
8367 
8369  {
8370  double arg = (kPi*fc_Hz) / sampleRate;
8371  fc_Hz = fc_Hz*(tan(arg) / arg);
8372  }
8373 
8374  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8375  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8376 
8377  seriesAdaptor_RC.setComponentValue_RC(resistorValue, 1.0e-6);
8379  }
8380  }
8381 
8382 
8383 protected:
8385 
8386  // --- three
8389 
8390  double sampleRate = 1.0;
8391 };
8392 
8411 {
8412 public:
8413  WDFIdealRLCBPF(void) { createWDF(); } /* C-TOR */
8414  ~WDFIdealRLCBPF(void) {} /* D-TOR */
8415 
8417  virtual bool reset(double _sampleRate)
8418  {
8419  sampleRate = _sampleRate;
8420  // --- rest WDF components (flush state registers)
8421  seriesAdaptor_LC.reset(_sampleRate);
8422  parallelTerminatedAdaptor_R.reset(_sampleRate);
8423 
8424  // --- intialize the chain of adapters
8426  return true;
8427  }
8428 
8430  virtual bool canProcessAudioFrame() { return false; }
8431 
8437  virtual double processAudioSample(double xn)
8438  {
8439  // --- push audio sample into series L1
8441 
8442  // --- output is at terminated L2's output2
8443  // note compensation scaling by -6dB = 0.5
8444  // because of WDF assumption about Rs and Rload
8446  }
8447 
8449  void createWDF()
8450  {
8451  // --- create components, init to noramlized values fc =
8452  // initial values for fc = 1kHz Q = 0.707
8453  // Holding C Constant at 1e-6
8454  // L = 2.533e-2
8455  // R = 2.251131 e2
8456  seriesAdaptor_LC.setComponent(wdfComponent::seriesLC, 2.533e-2, 1.0e-6);
8457  parallelTerminatedAdaptor_R.setComponent(wdfComponent::R, 2.251131e2);
8458 
8459  // --- connect adapters
8461 
8462  // --- set source resistance
8463  seriesAdaptor_LC.setSourceResistance(0.0); // --- Rs = 600
8464 
8465  // --- set open ckt termination
8467  }
8468 
8474 
8479  void setParameters(const WDFParameters& _wdfParameters)
8480  {
8481  if (_wdfParameters.fc != wdfParameters.fc ||
8482  _wdfParameters.Q != wdfParameters.Q ||
8483  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8485  {
8486  wdfParameters = _wdfParameters;
8487  double fc_Hz = wdfParameters.fc;
8488 
8490  {
8491  double arg = (kPi*fc_Hz) / sampleRate;
8492  fc_Hz = fc_Hz*(tan(arg) / arg);
8493  }
8494 
8495  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8496  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8497 
8498  seriesAdaptor_LC.setComponentValue_LC(inductorValue, 1.0e-6);
8500  }
8501  }
8502 
8503 protected:
8505 
8506  // --- adapters
8509 
8510  double sampleRate = 1.0;
8511 };
8512 
8513 
8532 {
8533 public:
8534  WDFIdealRLCBSF(void) { createWDF(); } /* C-TOR */
8535  ~WDFIdealRLCBSF(void) {} /* D-TOR */
8536 
8538  virtual bool reset(double _sampleRate)
8539  {
8540  sampleRate = _sampleRate;
8541  // --- rest WDF components (flush state registers)
8542  seriesAdaptor_R.reset(_sampleRate);
8543  parallelTerminatedAdaptor_LC.reset(_sampleRate);
8544 
8545  // --- intialize the chain of adapters
8547  return true;
8548  }
8549 
8551  virtual bool canProcessAudioFrame() { return false; }
8552 
8558  virtual double processAudioSample(double xn)
8559  {
8560  // --- push audio sample into series L1
8562 
8563  // --- output is at terminated L2's output2
8564  // note compensation scaling by -6dB = 0.5
8565  // because of WDF assumption about Rs and Rload
8567  }
8568 
8570  void createWDF()
8571  {
8572  // --- create components, init to noramlized values fc =
8573  // initial values for fc = 1kHz Q = 0.707
8574  // Holding C Constant at 1e-6
8575  // L = 2.533e-2
8576  // R = 2.251131 e2
8577  seriesAdaptor_R.setComponent(wdfComponent::R, 2.533e-2);
8578  parallelTerminatedAdaptor_LC.setComponent(wdfComponent::seriesLC, 2.533e-2, 1.0e-6);
8579 
8580  // --- connect adapters
8582 
8583  // --- set source resistance
8584  seriesAdaptor_R.setSourceResistance(0.0); // --- Rs = 600
8585 
8586  // --- set open ckt termination
8588  }
8589 
8595 
8600  void setParameters(const WDFParameters& _wdfParameters)
8601  {
8602  if (_wdfParameters.fc != wdfParameters.fc ||
8603  _wdfParameters.Q != wdfParameters.Q ||
8604  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8606  {
8607  wdfParameters = _wdfParameters;
8608  double fc_Hz = wdfParameters.fc;
8609 
8611  {
8612  double arg = (kPi*fc_Hz) / sampleRate;
8613  fc_Hz = fc_Hz*(tan(arg) / arg);
8614  }
8615 
8616  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8617  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8618 
8619  seriesAdaptor_R.setComponentValue(resistorValue);
8620  parallelTerminatedAdaptor_LC.setComponentValue_LC(inductorValue, 1.0e-6);
8621  }
8622  }
8623 
8624 protected:
8626 
8627  // --- adapters
8630 
8631  double sampleRate = 1.0;
8632 };
8633 
8634 
8635 // ------------------------------------------------------------------ //
8636 // --- OBJECTS REQUIRING FFTW --------------------------------------- //
8637 // ------------------------------------------------------------------ //
8638 
8652 enum class windowType {kNoWindow, kRectWindow, kHannWindow, kBlackmanHarrisWindow, kHammingWindow };
8653 
8664 inline std::unique_ptr<double[]> makeWindow(unsigned int windowLength, unsigned int hopSize, windowType window, double& gainCorrectionValue)
8665 {
8666  std::unique_ptr<double[]> windowBuffer;
8667  windowBuffer.reset(new double[windowLength]);
8668 
8669  if (!windowBuffer) return nullptr;
8670 
8671  double overlap = hopSize > 0.0 ? 1.0 - (double)hopSize / (double)windowLength : 0.0;
8672  gainCorrectionValue = 0.0;
8673 
8674  for (int n = 0; n < windowLength; n++)
8675  {
8676  if (window == windowType::kRectWindow)
8677  {
8678  if (n >= 1 && n <= windowLength - 1)
8679  windowBuffer[n] = 1.0;
8680  }
8681  else if (window == windowType::kHammingWindow)
8682  {
8683  windowBuffer[n] = 0.54 - 0.46*cos((n*2.0*kPi) / (windowLength));
8684  }
8685  else if (window == windowType::kHannWindow)
8686  {
8687  windowBuffer[n] = 0.5 * (1 - cos((n*2.0*kPi) / (windowLength)));
8688  }
8689  else if (window == windowType::kBlackmanHarrisWindow)
8690  {
8691  windowBuffer[n] = (0.42323 - (0.49755*cos((n*2.0*kPi) / (windowLength))) + 0.07922*cos((2 * n*2.0*kPi) / (windowLength)));
8692  }
8693  else if (window == windowType::kNoWindow)
8694  {
8695  windowBuffer[n] = 1.0;
8696  }
8697 
8698  gainCorrectionValue += windowBuffer[n];
8699  }
8700 
8701  // --- calculate gain correction factor
8702  if (window != windowType::kNoWindow)
8703  gainCorrectionValue = (1.0 - overlap) / gainCorrectionValue;
8704  else
8705  gainCorrectionValue = 1.0 / gainCorrectionValue;
8706 
8707  return windowBuffer;
8708 }
8709 
8710 #define HAVE_FFTW 1
8711 
8712 // --- FFTW ---
8713 #ifdef HAVE_FFTW
8714 #include "fftw3.h"
8715 
8733 class FastFFT
8734 {
8735 public:
8736  FastFFT() {} /* C-TOR */
8737  ~FastFFT() {
8738  if (windowBuffer) delete[] windowBuffer;
8739  destroyFFTW();
8740  } /* D-TOR */
8741 
8743  void initialize(unsigned int _frameLength, windowType _window);
8744 
8746  void destroyFFTW();
8747 
8749  fftw_complex* doFFT(double* inputReal, double* inputImag = nullptr);
8750 
8752  fftw_complex* doInverseFFT(double* inputReal, double* inputImag);
8753 
8755  unsigned int getFrameLength() { return frameLength; }
8756 
8757 protected:
8758  // --- setup FFTW
8759  fftw_complex* fft_input = nullptr;
8760  fftw_complex* fft_result = nullptr;
8761  fftw_complex* ifft_input = nullptr;
8762  fftw_complex* ifft_result = nullptr;
8763  fftw_plan plan_forward = nullptr;
8764  fftw_plan plan_backward = nullptr;
8765 
8766  double* windowBuffer = nullptr;
8767  double windowGainCorrection = 1.0;
8768  windowType window = windowType::kHannWindow;
8769  unsigned int frameLength = 0;
8770 };
8771 
8772 
8793 {
8794 public:
8795  PhaseVocoder() {} /* C-TOR */
8796  ~PhaseVocoder() {
8797  if (inputBuffer) delete[] inputBuffer;
8798  if (outputBuffer) delete[] outputBuffer;
8799  if (windowBuffer) delete[] windowBuffer;
8800  destroyFFTW();
8801  } /* D-TOR */
8802 
8804  void initialize(unsigned int _frameLength, unsigned int _hopSize, windowType _window);
8805 
8807  void destroyFFTW();
8808 
8810  double processAudioSample(double input, bool& fftReady);
8811 
8813  bool addZeroPad(unsigned int count);
8814 
8816  bool advanceAndCheckFFT();
8817 
8819  fftw_complex* getFFTData() { return fft_result; }
8820 
8822  fftw_complex* getIFFTData() { return ifft_result; }
8823 
8825  void doInverseFFT();
8826 
8828  void doOverlapAdd(double* outputData = nullptr, int length = 0);
8829 
8831  unsigned int getFrameLength() { return frameLength; }
8832 
8834  unsigned int getHopSize() { return hopSize; }
8835 
8837  double getOverlap() { return overlap; }
8838 
8840  // --- for fast convolution and other overlap-add algorithms
8841  // that are not hop-size dependent
8842  void setOverlapAddOnly(bool b){ bool overlapAddOnly = b; }
8843 
8844 protected:
8845  // --- setup FFTW
8846  fftw_complex* fft_input = nullptr;
8847  fftw_complex* fft_result = nullptr;
8848  fftw_complex* ifft_result = nullptr;
8849  fftw_plan plan_forward = nullptr;
8850  fftw_plan plan_backward = nullptr;
8851 
8852  // --- linear buffer for window
8853  double* windowBuffer = nullptr;
8854 
8855  // --- circular buffers for input and output
8856  double* inputBuffer = nullptr;
8857  double* outputBuffer = nullptr;
8858 
8859  // --- index and wrap masks for input and output buffers
8860  unsigned int inputWriteIndex = 0;
8861  unsigned int outputWriteIndex = 0;
8862  unsigned int inputReadIndex = 0;
8863  unsigned int outputReadIndex = 0;
8864  unsigned int wrapMask = 0;
8865  unsigned int wrapMaskOut = 0;
8866 
8867  // --- amplitude correction factor, aking into account both hopsize (overlap)
8868  // and the window power itself
8869  double windowHopCorrection = 1.0;
8870 
8871  // --- these allow a more robust combination of user interaction
8872  bool needInverseFFT = false;
8873  bool needOverlapAdd = false;
8874 
8875  // --- our window type; you can add more windows if you like
8876  windowType window = windowType::kHannWindow;
8877 
8878  // --- counters
8879  unsigned int frameLength = 0;
8880  unsigned int fftCounter = 0;
8881 
8882  // --- hop-size and overlap (mathematically related)
8883  unsigned int hopSize = 0;
8884  double overlap = 1.0;
8885 
8886  // --- flag for overlap-add algorithms that do not involve hop-size, other
8887  // than setting the overlap
8888  bool overlapAddOnly = false;
8889 
8890 };
8891 
8912 {
8913 public:
8914  FastConvolver() {
8915  vocoder.setOverlapAddOnly(true);
8916  } /* C-TOR */
8917  ~FastConvolver() {
8918  if (filterIR)
8919  delete[] filterIR;
8920 
8921  if (filterFFT)
8922  fftw_free(filterFFT);
8923  } /* D-TOR */
8924 
8929  void initialize(unsigned int _filterImpulseLength)
8930  {
8931  if (filterImpulseLength == _filterImpulseLength)
8932  return;
8933 
8934  // --- setup a specialized vocoder with 50% hop size
8935  filterImpulseLength = _filterImpulseLength;
8936  vocoder.initialize(filterImpulseLength * 2, filterImpulseLength, windowType::kNoWindow);
8937 
8938  // --- initialize the FFT object for capturing the filter FFT
8939  filterFastFFT.initialize(filterImpulseLength * 2, windowType::kNoWindow);
8940 
8941  // --- array to hold the filter IR; this could be localized to the particular function that uses it
8942  if (filterIR)
8943  delete [] filterIR;
8944  filterIR = new double[filterImpulseLength * 2];
8945  memset(&filterIR[0], 0, filterImpulseLength * 2 * sizeof(double));
8946 
8947  // --- allocate the filter FFT arrays
8948  if(filterFFT)
8949  fftw_free(filterFFT);
8950 
8951  filterFFT = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * filterImpulseLength * 2);
8952 
8953  // --- reset
8954  inputCount = 0;
8955  }
8956 
8958  void setFilterIR(double* irBuffer)
8959  {
8960  if (!irBuffer) return;
8961 
8962  memset(&filterIR[0], 0, filterImpulseLength * 2 * sizeof(double));
8963 
8964  // --- copy over first half; filterIR len = filterImpulseLength * 2
8965  int m = 0;
8966  for (unsigned int i = 0; i < filterImpulseLength; i++)
8967  {
8968  filterIR[i] = irBuffer[i];
8969  }
8970 
8971  // --- take FFT of the h(n)
8972  fftw_complex* fftOfFilter = filterFastFFT.doFFT(&filterIR[0]);
8973 
8974  // --- copy the FFT into our local buffer for storage; also
8975  // we never want to hold a pointer to a FFT output
8976  // for more than one local function's worth
8977  // could replace with memcpy( )
8978  for (int i = 0; i < 2; i++)
8979  {
8980  for (unsigned int j = 0; j < filterImpulseLength * 2; j++)
8981  {
8982  filterFFT[j][i] = fftOfFilter[j][i];
8983  }
8984  }
8985  }
8986 
8988  double processAudioSample(double input)
8989  {
8990  bool fftReady = false;
8991  double output = 0.0;
8992 
8994  {
8996 
8997  if (fftReady) // should happen on time
8998  {
8999  // --- multiply our filter IR with the vocoder FFT
9000  fftw_complex* signalFFT = vocoder.getFFTData();
9001  if (signalFFT)
9002  {
9003  unsigned int fff = vocoder.getFrameLength();
9004 
9005  // --- complex multiply with FFT of IR
9006  for (unsigned int i = 0; i < filterImpulseLength * 2; i++)
9007  {
9008  // --- get real/imag parts of each FFT
9009  ComplexNumber signal(signalFFT[i][0], signalFFT[i][1]);
9010  ComplexNumber filter(filterFFT[i][0], filterFFT[i][1]);
9011 
9012  // --- use complex multiply function; this convolves in the time domain
9013  ComplexNumber product = complexMultiply(signal, filter);
9014 
9015  // --- overwrite the FFT bins
9016  signalFFT[i][0] = product.real;
9017  signalFFT[i][1] = product.imag;
9018  }
9019  }
9020  }
9021 
9022  // --- reset counter
9023  inputCount = 0;
9024  }
9025 
9026  // --- process next sample
9027  output = vocoder.processAudioSample(input, fftReady);
9028  inputCount++;
9029 
9030  return output;
9031  }
9032 
9034  unsigned int getFrameLength() { return vocoder.getFrameLength(); }
9035 
9037  unsigned int getFilterIRLength() { return filterImpulseLength; }
9038 
9039 protected:
9042  fftw_complex* filterFFT = nullptr;
9043  double* filterIR = nullptr;
9044  unsigned int inputCount = 0;
9045  unsigned int filterImpulseLength = 0;
9046 };
9047 
9048 // --- PSM Vocoder
9049 const unsigned int PSM_FFT_LEN = 4096;
9050 
9064 struct BinData
9065 {
9066  BinData() {}
9068  BinData& operator=(const BinData& params) // need this override for collections to work
9069  {
9070  if (this == &params)
9071  return *this;
9072 
9073  isPeak = params.isPeak;
9074  magnitude = params.magnitude;
9075  phi = params.phi;
9076 
9077  psi = params.psi;
9078  localPeakBin = params.localPeakBin;
9080  updatedPhase = params.updatedPhase;
9081 
9082  return *this;
9083  }
9084 
9086  void reset()
9087  {
9088  isPeak = false;
9089  magnitude = 0.0;
9090  phi = 0.0;
9091 
9092  psi = 0.0;
9093  localPeakBin = 0;
9094  previousPeakBin = -1; // -1 is flag
9095  updatedPhase = 0.0;
9096  }
9097 
9098  bool isPeak = false;
9099  double magnitude = 0.0;
9100  double phi = 0.0;
9101  double psi = 0.0;
9102  unsigned int localPeakBin = 0;
9103  int previousPeakBin = -1;
9104  double updatedPhase = 0.0;
9105 };
9106 
9119 {
9122  PSMVocoderParameters& operator=(const PSMVocoderParameters& params) // need this override for collections to work
9123  {
9124  if (this == &params)
9125  return *this;
9126 
9130 
9131  return *this;
9132  }
9133 
9134  // --- params
9135  double pitchShiftSemitones = 0.0;
9137  bool enablePeakTracking = false;
9138 };
9139 
9159 {
9160 public:
9161  PSMVocoder() {
9162  vocoder.initialize(PSM_FFT_LEN, PSM_FFT_LEN/4, windowType::kHannWindow); // 75% overlap
9163  } /* C-TOR */
9164  ~PSMVocoder() {
9165  if (windowBuff) delete[] windowBuff;
9166  if (outputBuff) delete[] outputBuff;
9167 
9168  } /* D-TOR */
9169 
9171  virtual bool reset(double _sampleRate)
9172  {
9173  memset(&phi[0], 0, sizeof(double)*PSM_FFT_LEN);
9174  memset(&psi[0], 0, sizeof(double)* PSM_FFT_LEN);
9175  if(outputBuff)
9176  memset(outputBuff, 0, sizeof(double)*outputBufferLength);
9177 
9178  for (int i = 0; i < PSM_FFT_LEN; i++)
9179  {
9180  binData[i].reset();
9181  binDataPrevious[i].reset();
9182 
9183  peakBins[i] = -1;
9184  peakBinsPrevious[i] = -1;
9185  }
9186 
9187  return true;
9188  }
9189 
9191  virtual bool canProcessAudioFrame() { return false; }
9192 
9194  void setPitchShift(double semitones)
9195  {
9196  // --- this is costly so only update when things changed
9197  double newAlpha = pow(2.0, semitones / 12.0);
9198  double newOutputBufferLength = round((1.0/newAlpha)*(double)PSM_FFT_LEN);
9199 
9200  // --- check for change
9201  if (newOutputBufferLength == outputBufferLength)
9202  return;
9203 
9204  // --- new stuff
9205  alphaStretchRatio = newAlpha;
9206  ha = hs / alphaStretchRatio;
9207 
9208  // --- set output resample buffer
9209  outputBufferLength = newOutputBufferLength;
9210 
9211  // --- create Hann window
9212  if (windowBuff) delete[] windowBuff;
9213  windowBuff = new double[outputBufferLength];
9214  windowCorrection = 0.0;
9215  for (unsigned int i = 0; i < outputBufferLength; i++)
9216  {
9217  windowBuff[i] = 0.5 * (1.0 - cos((i*2.0*kPi) / (outputBufferLength)));
9219  }
9221 
9222  // --- create output buffer
9223  if (outputBuff) delete[] outputBuff;
9224  outputBuff = new double[outputBufferLength];
9225  memset(outputBuff, 0, sizeof(double)*outputBufferLength);
9226  }
9227 
9229  int findPreviousNearestPeak(int peakIndex)
9230  {
9231  if (peakBinsPrevious[0] == -1) // first run, there is no peak
9232  return -1;
9233 
9234  int delta = -1;
9235  int previousPeak = -1;
9236  for (int i = 0; i < PSM_FFT_LEN; i++)
9237  {
9238  if (peakBinsPrevious[i] < 0)
9239  break;
9240 
9241  int dist = abs(peakIndex - peakBinsPrevious[i]);
9242  if (dist > PSM_FFT_LEN/4)
9243  break;
9244 
9245  if (i == 0)
9246  {
9247  previousPeak = i;
9248  delta = dist;
9249  }
9250  else if (dist < delta)
9251  {
9252  previousPeak = i;
9253  delta = dist;
9254  }
9255  }
9256 
9257  return previousPeak;
9258  }
9259 
9262  {
9263  // --- FIND PEAKS --- //
9264  //
9265  // --- find local maxima in 4-sample window
9266  double localWindow[4] = { 0.0 };
9267  int m = 0;
9268  for (int i = 0; i < PSM_FFT_LEN; i++)
9269  {
9270  if (i == 0)
9271  {
9272  localWindow[0] = 0.0;
9273  localWindow[1] = 0.0;
9274  localWindow[2] = binData[i + 1].magnitude;
9275  localWindow[3] = binData[i + 2].magnitude;
9276  }
9277  else if (i == 1)
9278  {
9279  localWindow[0] = 0.0;
9280  localWindow[1] = binData[i - 1].magnitude;
9281  localWindow[2] = binData[i + 1].magnitude;
9282  localWindow[3] = binData[i + 2].magnitude;
9283  }
9284  else if (i == PSM_FFT_LEN - 1)
9285  {
9286  localWindow[0] = binData[i - 2].magnitude;
9287  localWindow[1] = binData[i - 1].magnitude;
9288  localWindow[2] = 0.0;
9289  localWindow[3] = 0.0;
9290  }
9291  else if (i == PSM_FFT_LEN - 2)
9292  {
9293  localWindow[0] = binData[i - 2].magnitude;
9294  localWindow[1] = binData[i - 1].magnitude;
9295  localWindow[2] = binData[i + 1].magnitude;
9296  localWindow[3] = 0.0;
9297  }
9298  else
9299  {
9300  localWindow[0] = binData[i - 2].magnitude;
9301  localWindow[1] = binData[i - 1].magnitude;
9302  localWindow[2] = binData[i + 1].magnitude;
9303  localWindow[3] = binData[i + 2].magnitude;
9304  }
9305 
9306  // --- found peak bin!
9307  if (binData[i].magnitude > 0.00001 &&
9308  binData[i].magnitude > localWindow[0]
9309  && binData[i].magnitude > localWindow[1]
9310  && binData[i].magnitude > localWindow[2]
9311  && binData[i].magnitude > localWindow[3])
9312  {
9313  binData[i].isPeak = true;
9314  peakBins[m++] = i;
9315 
9316  // --- for peak bins, assume that it is part of a previous, moving peak
9319  else
9320  binData[i].previousPeakBin = -1;
9321  }
9322  }
9323 
9324  // --- assign peak bosses
9325  if (m > 0)
9326  {
9327  int n = 0;
9328  int bossPeakBin = peakBins[n];
9329  double nextPeak = peakBins[++n];
9330  int midBoundary = (nextPeak - (double)bossPeakBin) / 2.0 + bossPeakBin;
9331 
9332  if (nextPeak >= 0)
9333  {
9334  for (int i = 0; i < PSM_FFT_LEN; i++)
9335  {
9336  if (i <= bossPeakBin)
9337  {
9338  binData[i].localPeakBin = bossPeakBin;
9339  }
9340  else if (i < midBoundary)
9341  {
9342  binData[i].localPeakBin = bossPeakBin;
9343  }
9344  else // > boundary, calc next set
9345  {
9346  bossPeakBin = nextPeak;
9347  nextPeak = peakBins[++n];
9348  if (nextPeak > bossPeakBin)
9349  midBoundary = (nextPeak - (double)bossPeakBin) / 2.0 + bossPeakBin;
9350  else // nextPeak == -1
9351  midBoundary = PSM_FFT_LEN;
9352 
9353  binData[i].localPeakBin = bossPeakBin;
9354  }
9355  }
9356  }
9357  }
9358  }
9359 
9365  virtual double processAudioSample(double input)
9366  {
9367  bool fftReady = false;
9368  double output = 0.0;
9369 
9370  // --- normal processing
9371  output = vocoder.processAudioSample(input, fftReady);
9372 
9373  // --- if FFT is here, GO!
9374  if (fftReady)
9375  {
9376  // --- get the FFT data
9377  fftw_complex* fftData = vocoder.getFFTData();
9378 
9380  {
9381  // --- get the magnitudes for searching
9382  for (int i = 0; i < PSM_FFT_LEN; i++)
9383  {
9384  binData[i].reset();
9385  peakBins[i] = -1;
9386 
9387  // --- store mag and phase
9388  binData[i].magnitude = getMagnitude(fftData[i][0], fftData[i][1]);
9389  binData[i].phi = getPhase(fftData[i][0], fftData[i][1]);
9390  }
9391 
9393 
9394  // --- each bin data should now know its local boss-peak
9395  //
9396  // --- now propagate phases accordingly
9397  //
9398  // FIRST: set PSI angles of bosses
9399  for (int i = 0; i < PSM_FFT_LEN; i++)
9400  {
9401  double mag_k = binData[i].magnitude;
9402  double phi_k = binData[i].phi;
9403 
9404  // --- horizontal phase propagation
9405  //
9406  // --- omega_k = bin frequency(k)
9407  double omega_k = kTwoPi*i / PSM_FFT_LEN;
9408 
9409  // --- phase deviation is actual - expected phase
9410  // = phi_k -(phi(last frame) + wk*ha
9411  double phaseDev = phi_k - phi[i] - omega_k*ha;
9412 
9413  // --- unwrapped phase increment
9414  double deltaPhi = omega_k*ha + principalArg(phaseDev);
9415 
9416  // --- save for next frame
9417  phi[i] = phi_k;
9418 
9419  // --- if peak, assume it could have hopped from a different bin
9420  if (binData[i].isPeak)
9421  {
9422  // --- calculate new phase based on stretch factor; save phase for next time
9423  if(binData[i].previousPeakBin < 0)
9424  psi[i] = principalArg(psi[i] + deltaPhi * alphaStretchRatio);
9425  else
9426  psi[i] = principalArg(psi[binDataPrevious[i].previousPeakBin] + deltaPhi * alphaStretchRatio);
9427  }
9428 
9429  // --- save peak PSI (new angle)
9430  binData[i].psi = psi[i];
9431 
9432  // --- for IFFT
9433  binData[i].updatedPhase = binData[i].psi;
9434  }
9435 
9436  // --- now set non-peaks
9437  for (int i = 0; i < PSM_FFT_LEN; i++)
9438  {
9439  if (!binData[i].isPeak)
9440  {
9441  int myPeakBin = binData[i].localPeakBin;
9442 
9443  double PSI_kp = binData[myPeakBin].psi;
9444  double phi_kp = binData[myPeakBin].phi;
9445 
9446  // --- save for next frame
9447  // phi[i] = binData[myPeakBin].phi;
9448 
9449  // --- calculate new phase, locked to boss peak
9450  psi[i] = principalArg(PSI_kp - phi_kp - binData[i].phi);
9451  binData[i].updatedPhase = psi[i];// principalArg(PSI_kp - phi_kp - binData[i].phi);
9452  }
9453  }
9454 
9455  for (int i = 0; i < PSM_FFT_LEN; i++)
9456  {
9457  double mag_k = binData[i].magnitude;
9458 
9459  // --- convert back
9460  fftData[i][0] = mag_k*cos(binData[i].updatedPhase);
9461  fftData[i][1] = mag_k*sin(binData[i].updatedPhase);
9462 
9463  // --- save for next frame
9464  binDataPrevious[i] = binData[i];
9465  peakBinsPrevious[i] = peakBins[i];
9466 
9467  }
9468  }// end if peak locking
9469 
9470  else // ---> old school
9471  {
9472  for (int i = 0; i < PSM_FFT_LEN; i++)
9473  {
9474  double mag_k = getMagnitude(fftData[i][0], fftData[i][1]);
9475  double phi_k = getPhase(fftData[i][0], fftData[i][1]);
9476 
9477  // --- horizontal phase propagation
9478  //
9479  // --- omega_k = bin frequency(k)
9480  double omega_k = kTwoPi*i / PSM_FFT_LEN;
9481 
9482  // --- phase deviation is actual - expected phase
9483  // = phi_k -(phi(last frame) + wk*ha
9484  double phaseDev = phi_k - phi[i] - omega_k*ha;
9485 
9486  // --- unwrapped phase increment
9487  double deltaPhi = omega_k*ha + principalArg(phaseDev);
9488 
9489  // --- save for next frame
9490  phi[i] = phi_k;
9491 
9492  // --- calculate new phase based on stretch factor; save phase for next time
9493  psi[i] = principalArg(psi[i] + deltaPhi * alphaStretchRatio);
9494 
9495  // --- convert back
9496  fftData[i][0] = mag_k*cos(psi[i]);
9497  fftData[i][1] = mag_k*sin(psi[i]);
9498  }
9499  }
9500 
9501 
9502  // --- manually so the IFFT (OPTIONAL)
9504 
9505  // --- can get the iFFT buffers
9506  fftw_complex* inv_fftData = vocoder.getIFFTData();
9507 
9508  // --- make copy (can speed this up)
9509  double ifft[PSM_FFT_LEN] = { 0.0 };
9510  for (int i = 0; i < PSM_FFT_LEN; i++)
9511  ifft[i] = inv_fftData[i][0];
9512 
9513  // --- resample the audio as if it were stretched
9514  resample(&ifft[0], outputBuff, PSM_FFT_LEN, outputBufferLength, interpolation::kLinear, windowCorrection, windowBuff);
9515 
9516  // --- overlap-add the interpolated buffer to complete the operation
9518  }
9519 
9520  return output;
9521  }
9522 
9528  {
9529  return parameters;
9530  }
9531 
9537  {
9539  {
9541  }
9542 
9543  // --- save
9544  parameters = params;
9545  }
9546 
9547 protected:
9550  double alphaStretchRatio = 1.0;
9551 
9552  // --- FFT is 4096 with 75% overlap
9553  const double hs = PSM_FFT_LEN / 4;
9554  double ha = PSM_FFT_LEN / 4;
9555  double phi[PSM_FFT_LEN] = { 0.0 };
9556  double psi[PSM_FFT_LEN] = { 0.0 };
9557 
9558  // --- for peak-locking
9559  BinData binData[PSM_FFT_LEN];
9560  BinData binDataPrevious[PSM_FFT_LEN];
9561 
9562  int peakBins[PSM_FFT_LEN] = { -1 };
9563  int peakBinsPrevious[PSM_FFT_LEN] = { -1 };
9564 
9565  double* windowBuff = nullptr;
9566  double* outputBuff = nullptr;
9567  double windowCorrection = 0.0;
9568  unsigned int outputBufferLength = 0;
9569 };
9570 
9571 // --- sample rate conversion
9572 //
9573 // --- supported conversion ratios - you can EASILY add more to this
9587 enum class rateConversionRatio { k2x, k4x };
9588 const unsigned int maxSamplingRatio = 4;
9589 
9599 inline unsigned int countForRatio(rateConversionRatio ratio)
9600 {
9601  if (ratio == rateConversionRatio::k2x)
9602  return 2;
9603  else if (ratio == rateConversionRatio::k4x || ratio == rateConversionRatio::k4x)
9604  return 4;
9605 
9606  return 0;
9607 }
9608 
9609 // --- get table pointer for built-in anti-aliasing LPFs
9621 inline double* getFilterIRTable(unsigned int FIRLength, rateConversionRatio ratio, unsigned int sampleRate)
9622 {
9623  // --- we only have built in filters for 44.1 and 48 kHz
9624  if (sampleRate != 44100 && sampleRate != 48000) return nullptr;
9625 
9626  // --- choose 2xtable
9627  if (ratio == rateConversionRatio::k2x)
9628  {
9629  if (sampleRate == 44100)
9630  {
9631  if (FIRLength == 128)
9632  return &LPF128_882[0];
9633  else if (FIRLength == 256)
9634  return &LPF256_882[0];
9635  else if (FIRLength == 512)
9636  return &LPF512_882[0];
9637  else if (FIRLength == 1024)
9638  return &LPF1024_882[0];
9639  }
9640  if (sampleRate == 48000)
9641  {
9642  if (FIRLength == 128)
9643  return &LPF128_96[0];
9644  else if (FIRLength == 256)
9645  return &LPF256_96[0];
9646  else if (FIRLength == 512)
9647  return &LPF512_96[0];
9648  else if (FIRLength == 1024)
9649  return &LPF1024_96[0];
9650  }
9651  }
9652 
9653  // --- choose 4xtable
9654  if (ratio == rateConversionRatio::k4x)
9655  {
9656  if (sampleRate == 44100)
9657  {
9658  if (FIRLength == 128)
9659  return &LPF128_1764[0];
9660  else if (FIRLength == 256)
9661  return &LPF256_1764[0];
9662  else if (FIRLength == 512)
9663  return &LPF512_1764[0];
9664  else if (FIRLength == 1024)
9665  return &LPF1024_1764[0];
9666  }
9667  if (sampleRate == 48000)
9668  {
9669  if (FIRLength == 128)
9670  return &LPF128_192[0];
9671  else if (FIRLength == 256)
9672  return &LPF256_192[0];
9673  else if (FIRLength == 512)
9674  return &LPF512_192[0];
9675  else if (FIRLength == 1024)
9676  return &LPF1024_192[0];
9677  }
9678  }
9679  return nullptr;
9680 }
9681 
9682 // --- get table pointer for built-in anti-aliasing LPFs
9694 inline double** decomposeFilter(double* filterIR, unsigned int FIRLength, unsigned int ratio)
9695 {
9696  unsigned int subBandLength = FIRLength / ratio;
9697  double ** polyFilterSet = new double*[ratio];
9698  for (unsigned int i = 0; i < ratio; i++)
9699  {
9700  double* polyFilter = new double[subBandLength];
9701  polyFilterSet[i] = polyFilter;
9702  }
9703 
9704  int m = 0;
9705  for (int i = 0; i < subBandLength; i++)
9706  {
9707  for (int j = ratio - 1; j >= 0; j--)
9708  {
9709  double* polyFilter = polyFilterSet[j];
9710  polyFilter[i] = filterIR[m++];
9711  }
9712  }
9713 
9714  return polyFilterSet;
9715 }
9716 
9729 {
9730  InterpolatorOutput() {}
9731  double audioData[maxSamplingRatio] = { 0.0 };
9732  unsigned int count = maxSamplingRatio;
9733 };
9734 
9735 
9754 {
9755 public:
9756  Interpolator() { } /* C-TOR */
9757  ~Interpolator() { } /* D-TOR */
9758 
9766  inline void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase = true)
9767  {
9768  polyphase = _polyphase;
9769  sampleRate = _sampleRate;
9770  FIRLength = _FIRLength;
9771  ratio = _ratio;
9772  unsigned int count = countForRatio(ratio);
9773  unsigned int subBandLength = FIRLength / count;
9774 
9775  // --- straight SRC, no polyphase
9777 
9778  // --- set filterIR from built-in set - user can always override this!
9779  double* filterTable = getFilterIRTable(FIRLength, ratio, sampleRate);
9780  if (!filterTable) return;
9781  convolver.setFilterIR(filterTable);
9782 
9783  if (!polyphase) return;
9784 
9785  // --- decompose filter
9786  double** polyPhaseFilters = decomposeFilter(filterTable, FIRLength, count);
9787  if (!polyPhaseFilters)
9788  {
9789  polyphase = false;
9790  return;
9791  }
9792 
9793  // --- set the individual polyphase filter IRs on the convolvers
9794  for (unsigned int i = 0; i < count; i++)
9795  {
9796  polyPhaseConvolvers[i].initialize(subBandLength);
9797  polyPhaseConvolvers[i].setFilterIR(polyPhaseFilters[i]);
9798  delete[] polyPhaseFilters[i];
9799  }
9800 
9801  delete[] polyPhaseFilters;
9802  }
9803 
9806  {
9807  unsigned int count = countForRatio(ratio);
9808 
9809  // --- setup output
9810  InterpolatorOutput output;
9811  output.count = count;
9812 
9813  // --- interpolators need the amp correction
9814  double ampCorrection = double(count);
9815 
9816  // --- polyphase uses "backwards" indexing for interpolator; see book
9817  int m = count-1;
9818  for (unsigned int i = 0; i < count; i++)
9819  {
9820  if (!polyphase)
9821  output.audioData[i] = i == 0 ? ampCorrection*convolver.processAudioSample(xn) : ampCorrection*convolver.processAudioSample(0.0);
9822  else
9823  output.audioData[i] = ampCorrection*polyPhaseConvolvers[m--].processAudioSample(xn);
9824  }
9825  return output;
9826  }
9827 
9828 protected:
9829  // --- for straight, non-polyphase
9831 
9832  // --- we save these for future expansion, currently only sparsely used
9833  unsigned int sampleRate = 44100;
9834  unsigned int FIRLength = 256;
9835  rateConversionRatio ratio = rateConversionRatio::k2x;
9836 
9837  // --- polyphase: 4x is max right now
9838  bool polyphase = true;
9840 };
9841 
9854 {
9855  DecimatorInput() {}
9856  double audioData[maxSamplingRatio] = { 0.0 };
9857  unsigned int count = maxSamplingRatio;
9858 };
9859 
9879 {
9880 public:
9881  Decimator() { } /* C-TOR */
9882  ~Decimator() { } /* D-TOR */
9883 
9891  inline void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase = true)
9892  {
9893  polyphase = _polyphase;
9894  sampleRate = _sampleRate;
9895  FIRLength = _FIRLength;
9896  ratio = _ratio;
9897  unsigned int count = countForRatio(ratio);
9898  unsigned int subBandLength = FIRLength / count;
9899 
9900  // --- straight SRC, no polyphase
9902 
9903  // --- set filterIR from built-in set - user can always override this!
9904  double* filterTable = getFilterIRTable(FIRLength, ratio, sampleRate);
9905  if (!filterTable) return;
9906  convolver.setFilterIR(filterTable);
9907 
9908  if (!polyphase) return;
9909 
9910  // --- decompose filter
9911  double** polyPhaseFilters = decomposeFilter(filterTable, FIRLength, count);
9912  if (!polyPhaseFilters)
9913  {
9914  polyphase = false;
9915  return;
9916  }
9917 
9918  // --- set the individual polyphase filter IRs on the convolvers
9919  for (unsigned int i = 0; i < count; i++)
9920  {
9921  polyPhaseConvolvers[i].initialize(subBandLength);
9922  polyPhaseConvolvers[i].setFilterIR(polyPhaseFilters[i]);
9923  delete[] polyPhaseFilters[i];
9924  }
9925 
9926  delete[] polyPhaseFilters;
9927  }
9928 
9930  inline double decimateAudio(DecimatorInput data)
9931  {
9932  unsigned int count = countForRatio(ratio);
9933 
9934  // --- setup output
9935  double output = 0.0;
9936 
9937  // --- polyphase uses "forwards" indexing for decimator; see book
9938  for (unsigned int i = 0; i < count; i++)
9939  {
9940  if (!polyphase) // overwrites output; only the last output is saved
9941  output = convolver.processAudioSample(data.audioData[i]);
9942  else
9943  output += polyPhaseConvolvers[i].processAudioSample(data.audioData[i]);
9944  }
9945  return output;
9946  }
9947 
9948 protected:
9949  // --- for straight, non-polyphase
9951 
9952  // --- we save these for future expansion, currently only sparsely used
9953  unsigned int sampleRate = 44100;
9954  unsigned int FIRLength = 256;
9955  rateConversionRatio ratio = rateConversionRatio::k2x;
9956 
9957  // --- polyphase: 4x is max right now
9958  bool polyphase = true;
9960 };
9961 
9962 #endif
virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
Definition: fxobjects.h:6822
DFOscillatorStates
Use this non-typed enum to easily access the direct form oscillator state registers.
Definition: fxobjects.h:3130
rateConversionRatio ratio
conversion ration
Definition: fxobjects.h:9955
EnvelopeFollowerParameters parameters
object parameters
Definition: fxobjects.h:5520
virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
Definition: fxobjects.h:6699
virtual double getOutput()
Definition: fxobjects.h:6180
double componentValue_L
component value L
Definition: fxobjects.h:6641
double preDelayTime_mSec
pre-delay time in mSec
Definition: fxobjects.h:4698
Custom parameter structure for the LFO and DFOscillator objects.
Definition: fxobjects.h:2954
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6118
unsigned int getFrameLength()
Definition: fxobjects.h:9034
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1552
double attackTime_mSec
attack mSec
Definition: fxobjects.h:2019
unsigned int stopBin
ending bin for transition band
Definition: fxobjects.h:608
Custom parameter structure for the ModulatedDelay object.
Definition: fxobjects.h:3281
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5780
void createWDF()
Definition: fxobjects.h:8570
SimpleDelay delay
delay
Definition: fxobjects.h:4295
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8538
void setImpulseResponse(double *irArray, unsigned int lengthPowerOfTwo)
Definition: fxobjects.h:2465
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5850
bool frequencyWarping
enable frequency warping
Definition: fxobjects.h:8148
unsigned int getFilterIRLength()
Definition: fxobjects.h:9037
AudioDetectorParameters getParameters()
Definition: fxobjects.h:1908
bool getTransitionBandData(double testFreq, double bin1Freq, unsigned int relax_Bins, TransitionBandData &transitionData)
get bin data for a filter&#39;s transitino band (see FX book for details)
Definition: fxobjects.h:640
virtual double getComponentConductance()
Definition: fxobjects.h:6075
void setParameters(const ReverbTankParameters &params)
Definition: fxobjects.h:4879
fftw_complex * fft_result
array for FFT output
Definition: fxobjects.h:8847
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6361
The WdfAdaptorBase object acts as the base class for all WDF Adaptors; the static members allow for s...
Definition: fxobjects.h:7101
double f_High
brickwall f_high
Definition: fxobjects.h:571
virtual double getComponentResistance()
Definition: fxobjects.h:6234
virtual double getOutput1()
Definition: fxobjects.h:6619
virtual double getOutput2()
Definition: fxobjects.h:6186
vaFilterAlgorithm
Use this strongly typed enum to easily set the virtual analog filter algorithm.
Definition: fxobjects.h:5083
double windowCorrection
window correction value
Definition: fxobjects.h:9567
virtual double getOutput3()
Definition: fxobjects.h:6871
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4253
virtual double getOutput3()
Definition: fxobjects.h:6383
void setParameters(const SimpleDelayParameters &params)
Definition: fxobjects.h:3858
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:8664
double zRegister_L
storage register for L
Definition: fxobjects.h:6760
TwoBandShelvingFilterParameters & operator=(const TwoBandShelvingFilterParameters &params)
Definition: fxobjects.h:4519
PSMVocoderParameters parameters
object parameters
Definition: fxobjects.h:9548
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6202
virtual void setInput(double in)
Definition: fxobjects.h:6853
SimpleLPFParameters & operator=(const SimpleLPFParameters &params)
Definition: fxobjects.h:3687
void setBeta(double _beta)
Definition: fxobjects.h:5331
void writeBuffer(unsigned int index, T input)
Definition: fxobjects.h:2256
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2428
virtual void setInput3(double _in3)
Definition: fxobjects.h:6277
bool detect_dB
detect in dB DEFAULT = false (linear NOT log)
Definition: fxobjects.h:1809
void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase=true)
Definition: fxobjects.h:9766
double audioData[maxSamplingRatio]
input array of samples to be decimated
Definition: fxobjects.h:9856
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6243
double RL
RL value.
Definition: fxobjects.h:7013
AudioFilterParameters & operator=(const AudioFilterParameters &params)
Definition: fxobjects.h:1488
virtual void setInput3(double _in3)
Definition: fxobjects.h:7694
double L
value of L component
Definition: fxobjects.h:7083
void setOpenTerminalResistance(bool _openTerminalResistance=true)
Definition: fxobjects.h:7114
double processAudioSample(double input)
Definition: fxobjects.h:8988
double audioData[maxSamplingRatio]
array of interpolated output samples
Definition: fxobjects.h:9731
wdfComponent componentType
selected component type
Definition: fxobjects.h:7085
bool interpolate
interpolate flag (diagnostics)
Definition: fxobjects.h:4146
fftw_complex * filterFFT
filterFFT output arrays
Definition: fxobjects.h:9042
Custom parameter structure for the LRFilterBank object which splits the input signal into multiple ba...
Definition: fxobjects.h:1642
unsigned int inputWriteIndex
circular buffer index: input write
Definition: fxobjects.h:8860
virtual double getOutput3()
Definition: fxobjects.h:6106
Custom parameter structure for the PhaseShifter object.
Definition: fxobjects.h:3473
AudioFilter apf[PHASER_STAGES]
six APF objects
Definition: fxobjects.h:3668
double sensitivity
detector sensitivity
Definition: fxobjects.h:5391
double RR
RR value.
Definition: fxobjects.h:6769
void setParameters(const DynamicsProcessorParameters &_parameters)
Definition: fxobjects.h:2087
Structure to hold a complex value.
Definition: fxobjects.h:469
double highShelfBoostCut_dB
high shelf gain
Definition: fxobjects.h:4535
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6707
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6771
double readDelay()
Definition: fxobjects.h:3904
double sampleRate
sample rate
Definition: fxobjects.h:3037
ModulatedDelayParameters getParameters()
Definition: fxobjects.h:3431
virtual double getComponentValue_R()
Definition: fxobjects.h:6724
generatorWaveform
Use this strongly typed enum to easily set the oscillator waveform.
Definition: fxobjects.h:2941
InterpolatorOutput interpolateAudio(double xn)
Definition: fxobjects.h:9805
void setParameters(AudioDelayParameters _parameters)
Definition: fxobjects.h:2856
double lowShelfBoostCut_dB
low shelf gain
Definition: fxobjects.h:4703
ZVAFilter filter
filter to modulate
Definition: fxobjects.h:5523
virtual double getComponentResistance()
Definition: fxobjects.h:6152
void setParameters(ModulatedDelayParameters _parameters)
Definition: fxobjects.h:3437
filterAlgorithm
Use this strongly typed enum to easily set the filter algorithm for the AudioFilter object or any oth...
Definition: fxobjects.h:1465
ClassATubePreParameters & operator=(const ClassATubePreParameters &params)
Definition: fxobjects.h:5724
TriodeClassAParameters getParameters()
Definition: fxobjects.h:5642
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1178
double RL
RL value.
Definition: fxobjects.h:6890
virtual double getOutput1()
Definition: fxobjects.h:6742
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L2
adaptor for L2
Definition: fxobjects.h:7921
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6583
Custom parameter structure for the Biquad object. Default version defines the biquad structure used i...
Definition: fxobjects.h:1339
double fc
filter fc
Definition: fxobjects.h:5386
double componentValue_R
component value R
Definition: fxobjects.h:6887
virtual void setInput3(double _in3)
Definition: fxobjects.h:6198
double out2
stored port 2 output; it is y(n) for this library
Definition: fxobjects.h:7276
double Q
filter Q
Definition: fxobjects.h:1503
virtual void setInput3(double _in3)
Definition: fxobjects.h:7003
unsigned int getHopSize()
Definition: fxobjects.h:8834
double alphaStretchRatio
alpha stretch ratio = hs/ha
Definition: fxobjects.h:9550
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3763
double highShelfBoostCut_dB
high shelf gain
Definition: fxobjects.h:4705
virtual void setInput2(double _in2)
Definition: fxobjects.h:6274
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3572
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1696
reverbDensity
Use this strongly typed enum to easily set the density in the reverb object.
Definition: fxobjects.h:4642
double parabolicSine(double angle)
Definition: fxobjects.h:3094
WdfSeriesAdaptor seriesAdaptor_L1C1
adaptor for L1 and C1
Definition: fxobjects.h:8106
LFO lfo
the one and only LFO
Definition: fxobjects.h:3669
virtual void updateComponentResistance()
Definition: fxobjects.h:6813
double overlap
overlap as raw value (75% = 0.75)
Definition: fxobjects.h:8884
virtual double getOutput1()=0
double getS_value()
Definition: fxobjects.h:1435
The ImpulseConvolver object implements a linear conovlver. NOTE: compile in Release mode or you may e...
Definition: fxobjects.h:2407
double alpha
alpha is (wcT/2)
Definition: fxobjects.h:5345
virtual void updateComponentResistance()
Definition: fxobjects.h:6566
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:2769
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8309
The DelayAPF object implements a delaying APF with optional LPF and optional modulated delay time wit...
Definition: fxobjects.h:4171
bool invertOutput
invertOutput - triodes invert output
Definition: fxobjects.h:5585
The WdfSeriesRL object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6541
T readBuffer(unsigned int index)
Definition: fxobjects.h:2265
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5015
unsigned int wrapMask
input wrap mask
Definition: fxobjects.h:8864
double sampleRate
sample rate storage
Definition: fxobjects.h:8390
double bipolarToUnipolar(double value)
calculates the unipolar [0.0, +1.0] value FROM a bipolar [-1.0, +1.0] value
Definition: fxobjects.h:254
void initialize(unsigned int _frameLength, unsigned int _hopSize, windowType _window)
initialize the Fast FFT object for operation
Definition: fxobjects.cpp:1228
virtual double getOutput2()=0
double highShelf_fc
HSF shelf frequency.
Definition: fxobjects.h:5751
virtual double getOutput2()
Definition: fxobjects.h:6868
double tanhWaveShaper(double xn, double saturation)
calculates hyptan waveshaper
Definition: fxobjects.h:397
void setParameters(const ClassATubePreParameters &params)
Definition: fxobjects.h:5814
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_L
adaptor for L
Definition: fxobjects.h:8388
bool enablePeakTracking
flag to enable peak tracking
Definition: fxobjects.h:9137
The LFO object implements a mathematically perfect LFO generator for modulation uses only...
Definition: fxobjects.h:2991
virtual double getOutput2()
Definition: fxobjects.h:7700
virtual void updateComponentResistance()
Definition: fxobjects.h:6689
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1389
double saturation
input level in dB
Definition: fxobjects.h:5744
dynamicsProcessorType
Use this strongly typed enum to set the dynamics processor type.
Definition: fxobjects.h:1972
virtual const SignalGenData renderAudioOutput()=0
double delayTime_mSec
delay time in mSec
Definition: fxobjects.h:3976
virtual void setInput(double in)
Definition: fxobjects.h:6976
double QL
the quantization level
Definition: fxobjects.h:5961
The PeakLimiter object implements a simple peak limiter; it is really a simplified and hard-wired ver...
Definition: fxobjects.h:4984
WdfSeriesAdaptor seriesAdaptor_RC
adaptor for RC
Definition: fxobjects.h:8387
double fc
filter fc
Definition: fxobjects.h:2523
double sampleRate
sample rate
Definition: fxobjects.h:6524
virtual double getComponentResistance()
Definition: fxobjects.h:6930
double boostCut_dB
filter gain; note not used in all types
Definition: fxobjects.h:1504
const double hs
hs = N/4 — 75% overlap
Definition: fxobjects.h:9553
The EnvelopeFollower object implements a traditional envelope follower effect modulating a LPR fc val...
Definition: fxobjects.h:5412
virtual void setInput1(double _in1)
Definition: fxobjects.h:6271
virtual double getOutput3()
Definition: fxobjects.h:7703
double inputLevel_dB
input level in dB
Definition: fxobjects.h:5743
double sampleRate
stored sample rate
Definition: fxobjects.h:1944
fftw_complex * getIFFTData()
Definition: fxobjects.h:8822
double lpf_g
LPF g coefficient.
Definition: fxobjects.h:4699
void setParameters(const TwoBandShelvingFilterParameters &params)
Definition: fxobjects.h:4609
double zRegister_L
storage register for L
Definition: fxobjects.h:6637
double magnitude
bin magnitude angle
Definition: fxobjects.h:9099
void setParameters(const AudioDetectorParameters &parameters)
Definition: fxobjects.h:1917
virtual double getComponentValue_R()
Definition: fxobjects.h:6844
virtual void updateComponentResistance()
Definition: fxobjects.h:6936
double lpf_state
LPF state register (z^-1)
Definition: fxobjects.h:4301
void flushBuffer()
Definition: fxobjects.h:2301
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7977
void destroyFFTW()
destroys the FFTW arrays and plans.
Definition: fxobjects.cpp:1028
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1839
virtual double getComponentConductance()
Definition: fxobjects.h:6322
double zRegister_C
storage register for C
Definition: fxobjects.h:7007
double dB2Raw(double dB)
converts dB to raw value
Definition: fxobjects.h:282
void setParameters(const PhaseShifterParameters &params)
Definition: fxobjects.h:3653
virtual double processAuxInputAudioSample(double xn)
Definition: fxobjects.h:1185
double componentValue_L
component value L
Definition: fxobjects.h:6764
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4025
void setParameters(const PSMVocoderParameters &params)
Definition: fxobjects.h:9536
virtual void setInput(double in)
Definition: fxobjects.h:6177
double RC
RC value.
Definition: fxobjects.h:6768
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6960
double RL
RL value.
Definition: fxobjects.h:6767
double RC
RC value.
Definition: fxobjects.h:6645
The WdfSeriesTerminatedAdaptor object implements the series terminated (non-reflection-free) adaptor...
Definition: fxobjects.h:7406
AudioDetector detector
detector to track input signal
Definition: fxobjects.h:5524
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5438
double componentValue_C
component value C
Definition: fxobjects.h:6888
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7851
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8600
Custom parameter structure calculating analog magnitude response arrays with calculateAnalogMagArray(...
Definition: fxobjects.h:834
bool advanceAndCheckWrapModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3065
biquadAlgorithm biquadCalcType
biquad structure to use
Definition: fxobjects.h:1353
virtual double getOutput3()
Definition: fxobjects.h:6268
WdfParallelAdaptor parallelAdaptor_C1
adaptor for C1
Definition: fxobjects.h:7920
void createWDF()
Definition: fxobjects.h:8077
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8316
unsigned int countForRatio(rateConversionRatio ratio)
returns the up or downsample ratio as a numeric value
Definition: fxobjects.h:9599
WDFParameters getParameters()
Definition: fxobjects.h:8232
The WdfParallelTerminatedAdaptor object implements the parallel terminated (non-reflection-free) adap...
Definition: fxobjects.h:7618
The WDFConstKBPF6 object implements a 6th order constant K BPF NOTE: designed with Elsie www...
Definition: fxobjects.h:8033
fftw_plan plan_backward
FFTW plan for IFFT.
Definition: fxobjects.h:8850
double beta
beta value, not used
Definition: fxobjects.h:5348
double storageComponent
Definition: fxobjects.h:1448
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6227
virtual double getComponentConductance()
Definition: fxobjects.h:6810
double getS_value()
Definition: fxobjects.h:1587
double gainReduction
output value for gain reduction that occurred
Definition: fxobjects.h:2024
double asymmetry
input level in dB
Definition: fxobjects.h:5745
double out1
stored port 1 output; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7275
double lfoDepth
LFO deoth (not in %) if enabled.
Definition: fxobjects.h:4149
const double kTwoPi
2pi to 80 decimal places
Definition: guiconstants.h:173
void createWDF()
Definition: fxobjects.h:8449
Custom parameter structure for the AudioDetector object. NOTE: this object uses constant defintions: ...
Definition: fxobjects.h:1789
virtual double getComponentConductance()
Definition: fxobjects.h:6155
double threshold_dB
threshold in dB
Definition: fxobjects.h:2013
The Biquad object implements a first or second order H(z) transfer function using one of four standar...
Definition: fxobjects.h:1373
double apf_g
APF g coefficient.
Definition: fxobjects.h:4143
bool enableLPF
enable LPF flag
Definition: fxobjects.h:3978
virtual void setInput2(double _in2)
Definition: fxobjects.h:6389
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6800
double f_Low
brickwall f_low
Definition: fxobjects.h:570
virtual void setInput2(double _in2)
Definition: fxobjects.h:7000
double doWhiteNoise()
calculates a random value between -1.0 and +1.0
Definition: fxobjects.h:324
ZVAFilterParameters zvaFilterParameters
object parameters
Definition: fxobjects.h:5337
virtual void setInput1(double _in1)=0
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6923
double fc
filter cutoff or center frequency (Hz)
Definition: fxobjects.h:1502
virtual void setInput2(double _in2)
Definition: fxobjects.h:6112
void createWDF()
Definition: fxobjects.h:7795
virtual void setInput2(double _in2)
Definition: fxobjects.h:6754
unsigned int getFrameLength()
Definition: fxobjects.h:8831
virtual void setInput2(double _in2)
Definition: fxobjects.h:7356
double zRegister_C
storage register for C
Definition: fxobjects.h:6884
virtual double getOutput3()
Definition: fxobjects.h:7598
virtual void reset(double _sampleRate)
Definition: fxobjects.h:7134
virtual double getOutput3()
Definition: fxobjects.h:7386
bool quadPhaseLFO
quad phase LFO flag
Definition: fxobjects.h:3493
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8430
double saturation
saturation level
Definition: fxobjects.h:5581
void setPort2_CompAdaptor(IComponentAdaptor *_port2CompAdaptor)
Definition: fxobjects.h:7128
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4380
fftw_complex * ifft_input
array for IFFT input
Definition: fxobjects.h:8761
CircularBuffer< double > signalBuffer
circulat buffer for the signal
Definition: fxobjects.h:2484
virtual double getComponentValue()
Definition: fxobjects.h:6158
double delayRatio_Pct
dela ratio: right length = (delayRatio)*(left length)
Definition: fxobjects.h:2698
virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
Definition: fxobjects.h:6036
double R2
output port resistance
Definition: fxobjects.h:7263
The WdfCapacitor object implements the reflection coefficient and signal flow through a WDF simulated...
Definition: fxobjects.h:6137
virtual void setInput3(double _in3)
Definition: fxobjects.h:6880
The AudioDelay object implements a stereo audio delay with multiple delay algorithms.
Definition: fxobjects.h:2718
double attackTime
attack time coefficient
Definition: fxobjects.h:1942
virtual double getR2()
Definition: fxobjects.h:7625
double zRegister_C
storage register for C
Definition: fxobjects.h:6516
double lfoRate_Hz
mod delay LFO rate in Hz
Definition: fxobjects.h:3299
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1542
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2065
double threshold_dB
detector threshold in dB
Definition: fxobjects.h:5390
TwoBandShelvingFilterParameters getParameters()
Definition: fxobjects.h:4600
double in2
stored port 2 input; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7269
double rightDelay_mSec
right delay time
Definition: fxobjects.h:2697
bool interpolate
interpolation flag (diagnostics)
Definition: fxobjects.h:3980
bool enableHPF
HPF simulates DC blocking cap on output.
Definition: fxobjects.h:5586
double getPhase(double re, double im)
calculates phase of a complex numb er
Definition: fxobjects.h:1019
virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
Definition: fxobjects.h:7224
double sampleRate
sample rate
Definition: fxobjects.h:6121
double sampleRate
sample rate
Definition: fxobjects.h:6283
void createDelayBuffers(double _sampleRate, double delay_mSec, double nestedAPFDelay_mSec)
Definition: fxobjects.h:4490
double * getStateArray()
Definition: fxobjects.h:1425
WdfSeriesAdaptor seriesAdaptor_LC
adaptor for LC
Definition: fxobjects.h:8507
AnalogFIRFilterParameters & operator=(const AnalogFIRFilterParameters &params)
Definition: fxobjects.h:2509
ReverbTankParameters & operator=(const ReverbTankParameters &params)
Definition: fxobjects.h:4659
fftw_plan plan_forward
FFTW plan for FFT.
Definition: fxobjects.h:8763
AudioDetectorParameters audioDetectorParameters
parameters for object
Definition: fxobjects.h:1941
AudioFilter hpFilter
high-band filter
Definition: fxobjects.h:1761
virtual double getOutput3()
Definition: fxobjects.h:7488
The ReverbTank object implements the cyclic reverb tank in the FX book listed below.
Definition: fxobjects.h:4732
double modCounter
modulo counter [0.0, +1.0]
Definition: fxobjects.h:3040
virtual double getComponentConductance()
Definition: fxobjects.h:6933
double zRegister_L
storage register for L
Definition: fxobjects.h:6883
WDFParameters getParameters()
Definition: fxobjects.h:8594
double LFOut
low frequency output sample
Definition: fxobjects.h:1622
DelayAPFParameters delayAPFParameters
obeject parameters
Definition: fxobjects.h:4290
virtual double processAudioSample(double xn)
Definition: fxobjects.h:1854
PSMVocoderParameters & operator=(const PSMVocoderParameters &params)
Definition: fxobjects.h:9122
void createDelayBuffer(double _sampleRate, double delay_mSec)
Definition: fxobjects.h:4086
unsigned int fftCounter
FFT sample counter.
Definition: fxobjects.h:8880
double sampleRate
sample rate storage
Definition: fxobjects.h:8631
void createWDF()
Definition: fxobjects.h:8208
modDelaylgorithm
Use this strongly typed enum to easily set modulated delay algorithm.
Definition: fxobjects.h:3267
double feedback_Pct
feedback as a % value
Definition: fxobjects.h:2693
virtual double getOutput()
Definition: fxobjects.h:6259
void setParameters(const OscillatorParameters &params)
Definition: fxobjects.h:3179
unsigned int inputReadIndex
circular buffer index: input read
Definition: fxobjects.h:8862
unsigned int frameLength
current FFT length
Definition: fxobjects.h:8769
unsigned int hopSize
hop: ha = hs
Definition: fxobjects.h:8883
double componentValue_R
component value R
Definition: fxobjects.h:6642
The DynamicsProcessor object implements a dynamics processor suite: compressor, limiter, downward expander, gate.
Definition: fxobjects.h:2045
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6201
double sidechainInputSample
storage for sidechain sample
Definition: fxobjects.h:2133
double RC
RC value.
Definition: fxobjects.h:6522
void setTerminalResistance(double _terminalResistance)
Definition: fxobjects.h:7111
Custom parameter structure for the ClassATubePre object.
Definition: fxobjects.h:5720
AudioDetectorParameters & operator=(const AudioDetectorParameters &params)
Definition: fxobjects.h:1793
virtual double getOutput()
Definition: fxobjects.h:6374
DFOscillatorCoeffs
Use this non-typed enum to easily access the direct form oscillator coefficients. ...
Definition: fxobjects.h:3115
IComponentAdaptor * getPort1_CompAdaptor()
Definition: fxobjects.h:7245
The CombFilter object implements a comb filter with optional LPF in feedback loop. Used for reverb algorithms in book.
Definition: fxobjects.h:4001
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6461
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5629
bool enableLSF
LSF simulates shelf due to cathode self biasing.
Definition: fxobjects.h:5587
double doLagrangeInterpolation(double *x, double *y, int n, double xbar)
implements n-order Lagrange Interpolation
Definition: fxobjects.h:133
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6727
virtual void initialize(double _R1)
Definition: fxobjects.h:7637
void advanceModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3088
DynamicsProcessorParameters getParameters()
Definition: fxobjects.h:2081
virtual double getComponentValue_C()
Definition: fxobjects.h:6358
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4739
double fuzzExp1WaveShaper(double xn, double saturation, double asymmetry)
calculates fuzz exp1 waveshaper
Definition: fxobjects.h:427
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7970
static void connectAdaptors(WdfAdaptorBase *upstreamAdaptor, WdfAdaptorBase *downstreamAdaptor)
Definition: fxobjects.h:7204
Custom parameter structure for the NestedDelayAPF object. Used for reverb algorithms in book...
Definition: fxobjects.h:4316
LRFilterBankParameters parameters
parameters for the object
Definition: fxobjects.h:1764
virtual double processAuxInputAudioSample(double xn)
Definition: fxobjects.h:2071
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7785
double processAudioSample(double input, bool &fftReady)
process one input sample throug the vocoder to produce one output sample
Definition: fxobjects.cpp:1453
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4991
virtual void setInput3(double _in3)
Definition: fxobjects.h:7589
double lfoDepth_Pct
mod delay LFO depth in %
Definition: fxobjects.h:3300
unsigned int length
length of convolution (buffer)
Definition: fxobjects.h:2487
void setParameters(const OscillatorParameters &params)
Definition: fxobjects.h:3020
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4009
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2053
virtual void setInput(double in)
Definition: fxobjects.h:6484
void createLinearBuffer(unsigned int _bufferLength)
Definition: fxobjects.h:2243
The AudioFilter object implements all filters in Designing Audio Effects Plugins in C++ 2nd Ed...
Definition: fxobjects.h:1524
double HFOut
high frequency output sample
Definition: fxobjects.h:1623
double terminalResistance
value of terminal (load) resistance
Definition: fxobjects.h:7280
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6341
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3350
dynamicsProcessorType calculation
processor calculation type
Definition: fxobjects.h:2018
void reset()
Definition: fxobjects.h:9086
WdfSeriesAdaptor seriesAdaptor_L5C5
adaptor for L5 and C5
Definition: fxobjects.h:8112
PhaseShifterParameters parameters
the object parameters
Definition: fxobjects.h:3667
double lfoRate_Hz
LFO rate in Hz (if enabled)
Definition: fxobjects.h:4347
delayUpdateType updateType
update algorithm
Definition: fxobjects.h:2695
virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
Definition: fxobjects.h:6033
TwoBandShelvingFilter shelvingFilter
shelving filters
Definition: fxobjects.h:5866
virtual void initialize(double _R1)
Definition: fxobjects.h:7424
bool needInverseFFT
internal flag to signal IFFT required
Definition: fxobjects.h:8872
double stateArray[numDFOStates]
array of state registers
Definition: fxobjects.h:3246
virtual double getOutput()
Definition: fxobjects.h:6609
virtual void setInput1(double _in1)
Definition: fxobjects.h:7445
void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase=true)
Definition: fxobjects.h:9891
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6830
unsigned int outputReadIndex
circular buffer index: output read
Definition: fxobjects.h:8863
Custom structure that holds transition band information for FIR filter calculations.
Definition: fxobjects.h:602
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8065
double filterOutputGain_dB
va filter gain (normally unused)
Definition: fxobjects.h:5123
bool openTerminalResistance
flag for open circuit load
Definition: fxobjects.h:7281
void setParameters(const CombFilterParameters &params)
Definition: fxobjects.h:4066
WdfSeriesAdaptor seriesAdaptor_RL
adaptor for series RL
Definition: fxobjects.h:8265
WdfSeriesAdaptor seriesAdaptor_L3C3
adaptor for L3 and C3
Definition: fxobjects.h:8109
double sampleRate
current sample rate
Definition: fxobjects.h:1598
double componentValue_C
component value C
Definition: fxobjects.h:6519
virtual void enableAuxInput(bool enableAuxInput)
Definition: fxobjects.h:2068
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:199
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7765
biquadAlgorithm
Use this strongly typed enum to easily set the biquad calculation type.
Definition: fxobjects.h:1325
bool useFrequencyWarping
flag for freq warping
Definition: fxobjects.h:7927
virtual void setInput3(double _in3)=0
rateConversionRatio ratio
conversion ration
Definition: fxobjects.h:9835
ZVAFilterParameters getParameters()
Definition: fxobjects.h:5167
double sampleRate
sample rate
Definition: fxobjects.h:6204
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4587
void writeBuffer(T input)
Definition: fxobjects.h:2332
fftw_complex * fft_result
array for FFT output
Definition: fxobjects.h:8760
double calcWSGain(double xn, double saturation, double asymmetry)
calculates gain of a waveshaper
Definition: fxobjects.h:368
void setParameters(const BitCrusherParameters &params)
Definition: fxobjects.h:5937
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3330
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6590
double intensity_Pct
phaser feedback in %
Definition: fxobjects.h:3492
void setParameters(const EnvelopeFollowerParameters &params)
Definition: fxobjects.h:5455
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6065
Use this interface for objects that render an output without an input, such as oscillators. May also be used for envelope generators whose input is a note-on or other switchable event.
Definition: fxobjects.h:1241
double RR
RR value.
Definition: fxobjects.h:6892
OscillatorParameters getParameters()
Definition: fxobjects.h:3170
double frequency_Hz
oscillator frequency
Definition: fxobjects.h:2970
void setAttackTime(double attack_in_ms, bool forceCalc=false)
sets the new attack time and re-calculates the time constant
Definition: fxobjects.cpp:935
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3754
vaFilterAlgorithm filterAlgorithm
va filter algorithm
Definition: fxobjects.h:5120
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8040
bool checkFloatUnderflow(double &value)
Perform underflow check; returns true if we did underflow (user may not care)
Definition: fxobjects.h:57
double K
K value.
Definition: fxobjects.h:6762
modDelaylgorithm algorithm
mod delay algorithm
Definition: fxobjects.h:3298
double sgn(double xn)
calculates sgn( ) of input
Definition: fxobjects.h:353
double componentValue_C
component value C
Definition: fxobjects.h:7010
double threshold_dB
stored threshold (dB)
Definition: fxobjects.h:5065
virtual double getComponentResistance()
Definition: fxobjects.h:6018
WdfParallelAdaptor parallelAdaptor_L4C4
adaptor for L4 and C4
Definition: fxobjects.h:8110
The WdfParallelLC object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6420
TriodeClassA triodes[NUM_TUBES]
array of triode tube objects
Definition: fxobjects.h:5865
double hpf_Fc
fc of DC blocking cap
Definition: fxobjects.h:5589
void findPeaksAndRegionsOfInfluence()
Definition: fxobjects.h:9261
double unipolarToBipolar(double value)
calculates the bipolar [-1.0, +1.0] value FROM a unipolar [0.0, +1.0] value
Definition: fxobjects.h:240
double boostCut_dB
filter boost or cut in dB
Definition: fxobjects.h:8147
virtual double getR2()
Definition: fxobjects.h:7515
int findPreviousNearestPeak(int peakIndex)
Definition: fxobjects.h:9229
const uint32_t ENVELOPE_DETECT_MODE_PEAK
|x|
Definition: guiconstants.h:181
virtual double processAudioSample(double xn)
process one sample through the biquad
Definition: fxobjects.cpp:38
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5843
double splitFrequency
LF/HF split frequency.
Definition: fxobjects.h:1655
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8558
double delayTime_mSec
delay tine in mSec
Definition: fxobjects.h:3797
Biquad biquad
the biquad object
Definition: fxobjects.h:1591
The AudioDetector object implements the audio detector defined in the book source below...
Definition: fxobjects.h:1831
double windowGainCorrection
window gain correction
Definition: fxobjects.h:8767
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6280
AudioFilterParameters audioFilterParameters
parameters
Definition: fxobjects.h:1597
The WdfParallelRC object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6911
virtual double getComponentValue()
Definition: fxobjects.h:6039
AudioFilter outputHPF
HPF to simulate output DC blocking cap.
Definition: fxobjects.h:5703
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4396
double attackTime_mSec
attack time in milliseconds
Definition: fxobjects.h:1806
Custom parameter structure for the WDF filter examples.
Definition: fxobjects.h:8128
virtual void setInput1(double _in1)
Definition: fxobjects.h:6506
double outerAPFdelayTime_mSec
delay time for outer APF
Definition: fxobjects.h:4340
double in1
stored port 1 input; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7268
virtual void setInput2(double _in2)
Definition: fxobjects.h:6509
double componentValue_R
component value R
Definition: fxobjects.h:7011
double sampleRate
current sample rate
Definition: fxobjects.h:4291
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4767
double RC
RC value.
Definition: fxobjects.h:6891
double kneeWidth_dB
knee width in dB for soft-knee operation
Definition: fxobjects.h:2014
double zRegister_L
storage register for L
Definition: fxobjects.h:6395
virtual double getOutput()
Definition: fxobjects.h:5993
The WDFButterLPF3 object implements a 3rd order Butterworth ladder filter. NOTE: designed with Elsie ...
Definition: fxobjects.h:7758
virtual double getOutput2()
Definition: fxobjects.h:6265
DelayAPFParameters getParameters()
Definition: fxobjects.h:4259
The FastConvolver provides a fast convolver - the user supplies the filter IR and the object snapshot...
Definition: fxobjects.h:8911
virtual void setInput1(double _in1)
Definition: fxobjects.h:6997
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6174
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8058
double lowShelf_fc
low shelf fc
Definition: fxobjects.h:4702
double getG_value()
Definition: fxobjects.h:1432
distortionModel waveshaper
waveshaper
Definition: fxobjects.h:5579
double getOverlap()
Definition: fxobjects.h:8837
bool needOverlapAdd
internal flag to signal overlap/add required
Definition: fxobjects.h:8873
double fixeDelayMax_mSec
fixed delay max time
Definition: fxobjects.h:4694
The WDFIdealRLCBSF object implements an ideal RLC BSF using the WDF library.
Definition: fxobjects.h:8531
virtual void setInput(double in)
Definition: fxobjects.h:6730
void setParameters(const SimpleLPFParameters &params)
Definition: fxobjects.h:3744
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_R
adaptor for R
Definition: fxobjects.h:8508
virtual double getOutput1()
Definition: fxobjects.h:7482
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2726
Custom structure to hold component information.
Definition: fxobjects.h:7052
virtual double getOutput1()
Definition: fxobjects.h:6100
double real
real part
Definition: fxobjects.h:478
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_C
adaptopr for parallel C
Definition: fxobjects.h:8266
void updateDFO()
Definition: fxobjects.h:3206
double rho
p = 2R + g (feedback)
Definition: fxobjects.h:5346
double gainReduction_dB
output value for gain reduction that occurred in dB
Definition: fxobjects.h:2025
double delayTime_mSec
APF delay time.
Definition: fxobjects.h:4142
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6603
virtual double getComponentConductance()
Definition: fxobjects.h:6442
LRFilterBankParameters getParameters()
Definition: fxobjects.h:1735
The WDFIdealRLCBPF object implements an ideal RLC BPF using the WDF library.
Definition: fxobjects.h:8410
double componentValue_L
component value L
Definition: fxobjects.h:6398
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5195
double releaseTime_mSec
detector release time
Definition: fxobjects.h:5389
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6973
void setFilterFc(double fc_Hz)
Definition: fxobjects.h:7904
virtual double getOutput1()
Definition: fxobjects.h:6183
BiquadParameters parameters
Definition: fxobjects.h:1445
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3870
AudioDetector detector
the detector object
Definition: fxobjects.h:5064
double lfoDepth
LFO depth (not in %) (if enabled)
Definition: fxobjects.h:4348
BiquadParameters getParameters()
Definition: fxobjects.h:1402
virtual double processAudioSample(double xn)
Definition: fxobjects.h:1711
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8504
double RT60Time_mSec
RT 60 time ini mSec.
Definition: fxobjects.h:3977
IComponentAdaptor * wdfComponent
WDF componant connected to port 3 (default operation)
Definition: fxobjects.h:7259
fftw_plan plan_forward
FFTW plan for FFT.
Definition: fxobjects.h:8849
double softClipWaveShaper(double xn, double saturation)
calculates hyptan waveshaper
Definition: fxobjects.h:411
Custom parameter structure for the ReverbTank object.
Definition: fxobjects.h:4655
double invertedOutput
inverted
Definition: fxobjects.h:1222
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6403
The Decimator object implements a sample rate decimator. Ana array of M input samples is decimated to...
Definition: fxobjects.h:9878
double computeGain(double detect_dB)
Definition: fxobjects.h:5021
virtual double getOutput1()
Definition: fxobjects.h:7697
virtual void setInput(double in)
Definition: fxobjects.h:6256
DynamicsProcessorParameters & operator=(const DynamicsProcessorParameters &params)
Definition: fxobjects.h:1990
void setParameters(const TriodeClassAParameters &params)
Definition: fxobjects.h:5648
double stateArray[numStates]
Definition: fxobjects.h:1442
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3829
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8437
virtual void setInput2(double _in2)
Definition: fxobjects.h:7691
double quantizedBitDepth
bid depth of quantizer
Definition: fxobjects.h:5898
const double kPi
pi to 80 decimal places
Definition: guiconstants.h:166
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6837
ZVAFilterParameters & operator=(const ZVAFilterParameters &params)
Definition: fxobjects.h:5103
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:3362
void destroyFFTW()
destroys the FFTW arrays and plans.
Definition: fxobjects.cpp:1202
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4572
EnvelopeFollowerParameters getParameters()
Definition: fxobjects.h:5449
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7778
bool addZeroPad(unsigned int count)
zero pad the input timeline
Definition: fxobjects.cpp:1369
CombFilterParameters getParameters()
Definition: fxobjects.h:4057
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_LC
adaptor for parallel LC
Definition: fxobjects.h:8629
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6027
SimpleDelayParameters & operator=(const SimpleDelayParameters &params)
Definition: fxobjects.h:3785
BitCrusherParameters parameters
object parameters
Definition: fxobjects.h:5960
virtual double getComponentResistance()
Definition: fxobjects.h:6560
double peakGainFor_Q(double Q)
calculates the peak magnitude for a given Q
Definition: fxobjects.h:296
The CircularBuffer object implements a simple circular buffer. It uses a wrap mask to wrap the read o...
Definition: fxobjects.h:2294
The PSMVocoder object implements a phase vocoder pitch shifter. Phase locking and peak tracking are o...
Definition: fxobjects.h:9158
double * getCoefficients()
Definition: fxobjects.h:1418
double highShelf_fc
fc for high shelf
Definition: fxobjects.h:4534
PhaseVocoder vocoder
vocoder object
Definition: fxobjects.h:9040
double Q
filter Q
Definition: fxobjects.h:5387
double integrator_z[2]
state variables
Definition: fxobjects.h:5341
double componentResistance
simulated resistance
Definition: fxobjects.h:6203
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6281
Custom structure that holds information about each FFT bin. This includes all information needed to p...
Definition: fxobjects.h:9064
virtual double getOutput()
Definition: fxobjects.h:6097
virtual void initialize(double _R1)
Definition: fxobjects.h:5984
virtual void setInput2(double _in2)=0
void setThreshold_dB(double _threshold_dB)
Definition: fxobjects.h:5058
virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
Definition: fxobjects.h:7231
double sampleRate
sample rate
Definition: fxobjects.h:6649
virtual double getComponentConductance()
Definition: fxobjects.h:6021
double getBeta()
Definition: fxobjects.h:5334
void setOverlapAddOnly(bool b)
Definition: fxobjects.h:8842
double lfoRate_Hz
phaser LFO rate in Hz
Definition: fxobjects.h:3490
virtual double processAudioSample(double xn)=0
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8175
IComponentAdaptor * port2CompAdaptor
componant or adaptor connected to port 2
Definition: fxobjects.h:7257
virtual void updateComponentResistance()
Definition: fxobjects.h:6088
void doInverseFFT()
perform the inverse FFT on the processed data
Definition: fxobjects.cpp:1493
Custom parameter structure for the SimpleLPFP object. Used for reverb algorithms in book...
Definition: fxobjects.h:3683
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6015
double fc
va filter fc
Definition: fxobjects.h:5121
double * outputBuff
buffer for resampled output
Definition: fxobjects.h:9566
virtual double getOutput2()
Definition: fxobjects.h:6622
The TriodeClassA object simulates a triode in class A configuration. This is a very simple and basic ...
Definition: fxobjects.h:5612
BiquadParameters & operator=(const BiquadParameters &params)
Definition: fxobjects.h:1344
double RR
RR value.
Definition: fxobjects.h:7015
void createDelayBuffer(double _sampleRate, double delay_mSec)
Definition: fxobjects.h:4279
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6432
virtual void initializeAdaptorChain()
Definition: fxobjects.h:7211
Custom parameter structure for the DelayAPF object. Used for reverb algorithms in book...
Definition: fxobjects.h:4120
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8384
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3886
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7865
void setReleaseTime(double release_in_ms, bool forceCalc=false)
sets the new release time and re-calculates the time constant
Definition: fxobjects.cpp:951
void setMakeUpGain_dB(double _makeUpGain_dB)
Definition: fxobjects.h:5061
void setUsePostWarping(bool b)
Definition: fxobjects.h:7901
virtual void setInput1(double _in1)
Definition: fxobjects.h:7549
bool advanceAndCheckFFT()
advance the sample counter and check to see if we need to do the FFT.
Definition: fxobjects.cpp:1399
virtual void initialize(double _R1)
Definition: fxobjects.h:7316
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3554
virtual double getComponentValue_L()
Definition: fxobjects.h:6597
The WDFIdealRLCLPF object implements an ideal RLC LPF using the WDF library.
Definition: fxobjects.h:8168
The Interpolator object implements a sample rate interpolator. One input sample yields N output sampl...
Definition: fxobjects.h:9753
AudioDelayParameters getParameters()
Definition: fxobjects.h:2850
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6161
FastFFT filterFastFFT
FastFFT object.
Definition: fxobjects.h:9041
double attackTime_mSec
detector attack time
Definition: fxobjects.h:5388
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5671
double quadPhaseOutput_pos
90 degrees out
Definition: fxobjects.h:1223
double componentValue_C
component value C
Definition: fxobjects.h:6399
virtual void setInput(double in)
Definition: fxobjects.h:6094
double dryLevel_dB
dry output level in dB
Definition: fxobjects.h:4708
virtual double processAudioSample(double input)
Definition: fxobjects.h:9365
double sampleRate
stored sample rate
Definition: fxobjects.h:7928
SimpleDelayParameters getParameters()
Definition: fxobjects.h:3849
AudioDelayParameters & operator=(const AudioDelayParameters &params)
Definition: fxobjects.h:2671
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4774
FastConvolver convolver
fast convolver
Definition: fxobjects.h:9950
virtual const SignalGenData renderAudioOutput()
generates the oscillator output for one sample interval; note that there are multiple outputs...
Definition: fxobjects.cpp:963
LRFilterBankParameters & operator=(const LRFilterBankParameters &params)
Definition: fxobjects.h:1646
int peakBins[PSM_FFT_LEN]
array of current peak bin index values (-1 = not peak)
Definition: fxobjects.h:9562
AudioDetector detector
the sidechain audio detector
Definition: fxobjects.h:2130
double readDelayAtPercentage(double delayPercent)
Definition: fxobjects.h:3921
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6676
bool interpolate
interpolation flag (diagnostics usually)
Definition: fxobjects.h:3798
virtual double getComponentValue_R()
Definition: fxobjects.h:6600
AudioFilter outputLSF
LSF to simulate shelf caused by cathode self-biasing cap.
Definition: fxobjects.h:5704
virtual double processAudioSample(double xn)
process one sample through the audio filter
Definition: fxobjects.cpp:921
filterAlgorithm algorithm
filter algorithm
Definition: fxobjects.h:1501
double sampleRate
current sample rate
Definition: fxobjects.h:5338
Custom parameter structure for the CombFilter object. Used for reverb algorithms in book...
Definition: fxobjects.h:3958
bool polyphase
enable polyphase decomposition
Definition: fxobjects.h:9838
virtual void setInput1(double _in1)
Definition: fxobjects.h:6874
virtual void setInput3(double _in3)
Definition: fxobjects.h:7479
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3158
brickwallFilter
Use this strongly typed enum to easily set brickwall filter type for functions that need it...
Definition: fxobjects.h:544
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6468
virtual void setInput3(double _in3)
Definition: fxobjects.h:6115
Custom output structure for filter bank objects that split the inptu into multiple frequency channels...
Definition: fxobjects.h:1617
virtual void setInput1(double _in1)
Definition: fxobjects.h:7337
double computeGain(double detect_dB)
Definition: fxobjects.h:2136
void setFilterIR(double *irBuffer)
Definition: fxobjects.h:8958
AudioFilterParameters getParameters()
Definition: fxobjects.h:1559
virtual void updateComponentResistance()
Definition: fxobjects.h:6024
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:87
double zRegister_L
storage register for L
Definition: fxobjects.h:6515
void setParameters(const NestedDelayAPFParameters &params)
Definition: fxobjects.h:4464
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:179
virtual double getOutput2()
Definition: fxobjects.h:6745
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5486
The SimpleDelay object implements a basic delay line without feedback.
Definition: fxobjects.h:3821
double * windowBuffer
buffer for window (naked)
Definition: fxobjects.h:8766
generatorWaveform waveform
the current waveform
Definition: fxobjects.h:2969
virtual double getOutput()
Definition: fxobjects.h:6979
bool selfOscillate
enable selfOscillation
Definition: fxobjects.h:5126
analogFilter filterType
filter type
Definition: fxobjects.h:2522
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8551
double lowShelf_fc
fc for low shelf
Definition: fxobjects.h:4532
double innerAPFdelayTime_mSec
delay time for inner APF
Definition: fxobjects.h:4341
unsigned int FIRLength
FIR length.
Definition: fxobjects.h:9954
double dBPeakGainFor_Q(double Q)
calculates the peak magnitude in dB for a given Q
Definition: fxobjects.h:312
double lsf_BoostCut_dB
boost/cut due to cathode self biasing
Definition: fxobjects.h:5591
double coeffArray[numDFOCoeffs]
array of coefficients
Definition: fxobjects.h:3247
Custom parameter structure for the TriodeClassA object.
Definition: fxobjects.h:5553
unsigned int sampleRate
sample rate
Definition: fxobjects.h:9833
virtual double getOutput3()
Definition: fxobjects.h:6748
virtual double getComponentResistance()
Definition: fxobjects.h:6072
double kRT
reverb time, 0 to 1
Definition: fxobjects.h:4700
TriodeClassAParameters parameters
object parameters
Definition: fxobjects.h:5702
unsigned int filterImpulseLength
IR length.
Definition: fxobjects.h:9045
bool enableGainComp
enable gain compensation (see book)
Definition: fxobjects.h:5124
WDFParameters getParameters()
Definition: fxobjects.h:8473
The LinearBuffer object implements a linear buffer of type T. It allows easy wrapping of a smart poin...
Definition: fxobjects.h:2232
CombFilterParameters & operator=(const CombFilterParameters &params)
Definition: fxobjects.h:3962
The DFOscillator object implements generates a very pure sinusoidal oscillator by placing poles direc...
Definition: fxobjects.h:3151
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8262
The WdfSeriesLC object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6300
void setPort3_CompAdaptor(IComponentAdaptor *_port3CompAdaptor)
Definition: fxobjects.h:7131
double zRegister_C
storage register for C (not used)
Definition: fxobjects.h:6638
virtual void setInput1(double _in1)
Definition: fxobjects.h:6109
The WdfSeriesRC object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6788
virtual double getR2()
Definition: fxobjects.h:7305
virtual void setInput1(double _in1)
Definition: fxobjects.h:6751
Custom parameter structure for the AnalogFIRFilter object. This is a somewhat silly object that impla...
Definition: fxobjects.h:2505
double out3
stored port 3 output; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7277
double lsf_Fshelf
shelf fc from self bias cap
Definition: fxobjects.h:5590
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6081
fftw_complex * fft_input
array for FFT input
Definition: fxobjects.h:8846
virtual bool reset(double _sampleRate)=0
bool checkAndWrapModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3045
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6523
double sampleRate
sample rate
Definition: fxobjects.h:6772
double apfDelayWeight_Pct
APF max delay weighying.
Definition: fxobjects.h:4693
double principalArg(double phaseIn)
calculates proncipal argument of a phase value; this is the wrapped value on the range of [-pi...
Definition: fxobjects.h:1034
OscillatorParameters lfoParameters
obejcgt parameters
Definition: fxobjects.h:3034
unsigned int relaxationBins
relaxation bins for FIR specification
Definition: fxobjects.h:572
unsigned int FIRLength
FIR length.
Definition: fxobjects.h:9834
This is the output structure for audio generator objects that can render up to four outputs...
Definition: fxobjects.h:1217
edgeTransition edgeType
edge type
Definition: fxobjects.h:606
FastConvolver polyPhaseConvolvers[maxSamplingRatio]
a set of sub-band convolvers for polyphase operation
Definition: fxobjects.h:9959
virtual void setInput(double _in)
Definition: fxobjects.h:5990
Custom parameter structure for the AudioFilter object.
Definition: fxobjects.h:1484
bool enablePeakPhaseLocking
flag to enable phase lock
Definition: fxobjects.h:9136
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L2
adaptor for L2
Definition: fxobjects.h:7822
bool enableNLP
enable non linear processing (use oversampling for best results)
Definition: fxobjects.h:5127
LinearBuffer< double > irBuffer
linear buffer for the IR
Definition: fxobjects.h:2485
stateReg
Use this enum to easily access z^-1 state values inside of arrays. For some structures, fewer storage units are needed. They are divided as follows:
Definition: fxobjects.h:1308
PhaseVocoder vocoder
vocoder to perform PSM
Definition: fxobjects.h:9549
virtual void setInput3(double _in3)
Definition: fxobjects.h:6757
virtual double getOutput()
Definition: fxobjects.h:6733
globally utilized constants and enumerations
virtual bool canProcessAudioFrame()=0
IComponentAdaptor * port1CompAdaptor
componant or adaptor connected to port 1
Definition: fxobjects.h:7256
double outputLevel_dB
input level in dB
Definition: fxobjects.h:5746
The WDFTunableButterLPF3 object implements a tunable 3rd order Butterworth ladder filter...
Definition: fxobjects.h:7844
FilterBankOutput processFilterBank(double xn)
Definition: fxobjects.h:1717
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8358
double raw2dB(double raw)
calculates dB for given input
Definition: fxobjects.h:268
windowType window
window type
Definition: fxobjects.h:8876
virtual void setInput2(double _in2)
Definition: fxobjects.h:6195
DynamicsProcessorParameters parameters
object parameters
Definition: fxobjects.h:2129
T readBuffer(int delayInSamples)
Definition: fxobjects.h:2342
double lowShelfBoostCut_dB
low shelf gain
Definition: fxobjects.h:4533
fftw_complex * fft_input
array for FFT input
Definition: fxobjects.h:8759
fftw_complex * ifft_result
array for IFFT output
Definition: fxobjects.h:8762
double R3
component resistance
Definition: fxobjects.h:7264
virtual void setInput1(double _in1)
Definition: fxobjects.h:6628
void setParameters(const DelayAPFParameters &params)
Definition: fxobjects.h:4268
BinData binData[PSM_FFT_LEN]
array of BinData structures for current FFT frame
Definition: fxobjects.h:9559
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2416
void createWDF()
Definition: fxobjects.h:8328
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4179
FastConvolver polyPhaseConvolvers[maxSamplingRatio]
a set of sub-band convolvers for polyphase operation
Definition: fxobjects.h:9839
virtual void setInput1(double _in1)
Definition: fxobjects.h:6192
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5154
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3725
unsigned int detectMode
detect mode, see TLD_ constants above
Definition: fxobjects.h:1808
void freqSample(int N, double A[], double h[], int symm)
calcuate the IR for an array of magnitude points using the frequency sampling method. NOTE: very old function that is all over the internet.
Definition: fxobjects.h:936
double imag
imaginary part
Definition: fxobjects.h:479
void setPitchShift(double semitones)
Definition: fxobjects.h:9194
virtual void setInput3(double _in3)
Definition: fxobjects.h:6512
distortionModel
Use this strongly typed enum to easily set the waveshaper model for the Triode objects.
Definition: fxobjects.h:5540
int peakBinsPrevious[PSM_FFT_LEN]
array of previous peak bin index values (-1 = not peak)
Definition: fxobjects.h:9563
virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
Definition: fxobjects.h:6453
double componentResistance
simulated resistance
Definition: fxobjects.h:6120
WdfSeriesAdaptor seriesAdaptor_L1
adaptor for L1
Definition: fxobjects.h:7919
SimpleLPFParameters getParameters()
Definition: fxobjects.h:3735
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2453
double inputLevel
input level (not in dB)
Definition: fxobjects.h:5868
bool overlapAddOnly
flag for overlap-add-only algorithms
Definition: fxobjects.h:8888
double ratio
processor I/O gain ratio
Definition: fxobjects.h:2012
int findEdgeTargetBin(double testFreq, double bin1Freq)
find bin for target frequency
Definition: fxobjects.h:623
double fc
brickwall fc
Definition: fxobjects.h:568
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:7017
OscillatorParameters parameters
object parameters
Definition: fxobjects.h:3243
double * filterIR
filter IR
Definition: fxobjects.h:9043
double componentValue_L
component value L
Definition: fxobjects.h:6518
double RL
RL value.
Definition: fxobjects.h:6521
void createWDF()
Definition: fxobjects.h:7882
hard-coded arrays of FIR filter coefficients for the sample rate conversion objects (Interpolator and...
The WdfInductor object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6219
virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
Definition: fxobjects.h:6030
virtual double getComponentValue_C()
Definition: fxobjects.h:6478
double R
value of R component
Definition: fxobjects.h:7082
double * getFilterIRTable(unsigned int FIRLength, rateConversionRatio ratio, unsigned int sampleRate)
returns the up or downsample ratio as a numeric value
Definition: fxobjects.h:9621
double atanWaveShaper(double xn, double saturation)
calculates arctangent waveshaper
Definition: fxobjects.h:383
virtual void setInput1(double _in1)
Definition: fxobjects.h:7663
The ClassATubePre object implements a simple cascade of four (4) triode tube models.
Definition: fxobjects.h:5773
BitCrusherParameters getParameters()
Definition: fxobjects.h:5931
IComponentAdaptor * getPort3_CompAdaptor()
Definition: fxobjects.h:7251
virtual double getComponentResistance()
Definition: fxobjects.h:6439
void doOverlapAdd(double *outputData=nullptr, int length=0)
perform the overlap/add on the IFFT data
Definition: fxobjects.cpp:1512
double updatedPhase
phase update value
Definition: fxobjects.h:9104
double Q
filter Q
Definition: fxobjects.h:2524
double releaseTime_mSec
release mSec
Definition: fxobjects.h:2020
void createDelayBuffers(double _sampleRate, double _bufferLength_mSec)
Definition: fxobjects.h:2895
IComponentAdaptor * port3CompAdaptor
componant or adaptor connected to port 3
Definition: fxobjects.h:7258
void setInterpolate(bool b)
Definition: fxobjects.h:2378
double getG_value()
Definition: fxobjects.h:1584
virtual void setInput(double in)
Definition: fxobjects.h:6364
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8625
virtual const SignalGenData renderAudioOutput()
Definition: fxobjects.h:3189
AudioFilter lpFilter
low-band filter
Definition: fxobjects.h:1760
unsigned int count
number of samples in output array
Definition: fxobjects.h:9732
bool hardLimitGate
threshold in dB
Definition: fxobjects.h:2015
virtual double getOutput1()
Definition: fxobjects.h:6377
virtual void setInput3(double _in3)
Definition: fxobjects.h:6392
virtual void setInput1(double _in1)
Definition: fxobjects.h:6386
WdfSeriesAdaptor seriesAdaptor_L1
adaptor for L1
Definition: fxobjects.h:7820
virtual double getComponentValue_R()
Definition: fxobjects.h:6967
virtual double getOutput1()
Definition: fxobjects.h:7380
bool calculateAnalogMagArray(AnalogMagData &magData)
calculate an arra of magnitude points from analog filter specifications
Definition: fxobjects.h:859
void setPort1_CompAdaptor(IComponentAdaptor *_port1CompAdaptor)
Definition: fxobjects.h:7125
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:9171
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7872
void setCoefficients(double *coeffs)
Definition: fxobjects.h:1412
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2554
fftw_complex * getFFTData()
Definition: fxobjects.h:8819
double sampleRate
sample rate
Definition: fxobjects.h:3250
virtual double getOutput1()
Definition: fxobjects.h:6497
double normalOutput
normal
Definition: fxobjects.h:1221
virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
Definition: fxobjects.h:6945
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:1195
double sampleRate
sample rate
Definition: fxobjects.h:6895
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1532
unsigned int outputWriteIndex
circular buffer index: output write
Definition: fxobjects.h:8861
reverbDensity density
density setting thick or thin
Definition: fxobjects.h:4687
delayAlgorithm algorithm
delay algorithm
Definition: fxobjects.h:2690
virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
Definition: fxobjects.h:7238
bool calculateBrickwallMagArray(BrickwallMagData &magData)
calculate an arra of magnitude points from brickwall specifications
Definition: fxobjects.h:688
virtual void initializeAdaptorChain()
Definition: fxobjects.h:5987
double Q
va filter Q
Definition: fxobjects.h:5122
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8189
double windowHopCorrection
window correction including hop/overlap
Definition: fxobjects.h:8869
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2107
virtual void setInput3(double _in3)
Definition: fxobjects.h:6634
virtual void setInput2(double _in2)
Definition: fxobjects.h:6877
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4580
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8479
The WdfResistor object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6057
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:4783
void init(unsigned int lengthPowerOfTwo)
Definition: fxobjects.h:2456
The ZVAFilter object implements multpile Zavalishin VA Filters. Audio I/O:
Definition: fxobjects.h:5147
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2748
void writeDelay(double xn)
Definition: fxobjects.h:3928
The WdfParallelAdaptor object implements the parallel reflection-free (non-terminated) adaptor...
Definition: fxobjects.h:7508
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6119
double pitchShiftSemitones
pitch shift in half-steps
Definition: fxobjects.h:9135
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6553
virtual double getComponentValue()
Definition: fxobjects.h:6240
double componentResistance
simulated resistance
Definition: fxobjects.h:6282
ModulatedDelayParameters & operator=(const ModulatedDelayParameters &params)
Definition: fxobjects.h:3285
virtual double getOutput()
Definition: fxobjects.h:6856
double quadPhaseOutput_neg
-90 degrees out
Definition: fxobjects.h:1224
bool enableLFO
flag to enable LFO
Definition: fxobjects.h:4147
unsigned int outputBufferLength
lenght of resampled output array
Definition: fxobjects.h:9568
double * windowBuffer
array for window
Definition: fxobjects.h:8853
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3641
unsigned int sampleRate
sample rate
Definition: fxobjects.h:9953
virtual double getComponentConductance()
Definition: fxobjects.h:6237
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8196
void setParameters(const AudioFilterParameters &parameters)
Definition: fxobjects.h:1562
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3359
Custom parameter structure for the AudioDelay object.
Definition: fxobjects.h:2667
double getMagnitude(double re, double im)
calculates magnitude of a complex numb er
Definition: fxobjects.h:1004
virtual bool reset(double _sampleRate)=0
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2574
double lfoDepth_Pct
phaser LFO depth in %
Definition: fxobjects.h:3491
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1704
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:9191
virtual double getComponentValue_C()
Definition: fxobjects.h:6970
wdfComponent
Use this strongly typed enum to easily set the wdfComponent type.
Definition: fxobjects.h:7039
double RC
RC value.
Definition: fxobjects.h:6402
double psi
bin phase correction
Definition: fxobjects.h:9101
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6312
double outputGain_dB
make up gain
Definition: fxobjects.h:2021
unsigned int getFrameLength()
Definition: fxobjects.h:8755
double leftDelay_mSec
left delay time
Definition: fxobjects.h:2696
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_L6C6
adaptor for L6 and C6
Definition: fxobjects.h:8113
double in3
stored port 3 input; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7270
bool isPeak
flag for peak bins
Definition: fxobjects.h:9098
windowType
Use this strongly typed enum to easily set the windowing type for FFT algorithms that use it...
Definition: fxobjects.h:8652
double lfoMaxModulation_mSec
LFO maximum modulation time in mSec.
Definition: fxobjects.h:4150
IComponentAdaptor * getPort2_CompAdaptor()
Definition: fxobjects.h:7248
double lowShelf_fc
LSF shelf frequency.
Definition: fxobjects.h:5749
double lpf_g
LPF g coefficient (if enabled)
Definition: fxobjects.h:4145
virtual double getOutput3()
Definition: fxobjects.h:6994
double zRegister_C
storage register for C
Definition: fxobjects.h:6396
void flushBuffer()
Definition: fxobjects.h:2239
The SimpleLPF object implements a first order one-pole LPF using one coefficient "g" value...
Definition: fxobjects.h:3717
virtual void enableAuxInput(bool enableAuxInput)
Definition: fxobjects.h:1181
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8296
WdfSeriesAdaptor seriesAdaptor_L1C1
adaptor for L1 and C1
Definition: fxobjects.h:8009
double zRegister_L
storage register for L
Definition: fxobjects.h:7006
virtual double getComponentValue_C()
Definition: fxobjects.h:6847
unsigned int count
count of samples in input array
Definition: fxobjects.h:9857
WdfParallelAdaptor parallelAdaptor_C1
adaptor for C1
Definition: fxobjects.h:7821
virtual double getOutput2()
Definition: fxobjects.h:7485
ClassATubePreParameters getParameters()
Definition: fxobjects.h:5808
NestedDelayAPFParameters & operator=(const NestedDelayAPFParameters &params)
Definition: fxobjects.h:4320
NestedDelayAPFParameters getParameters()
Definition: fxobjects.h:4458
void calculateFilterCoeffs()
Definition: fxobjects.h:5295
virtual void setInput2(double _in2)
Definition: fxobjects.h:7568
double wetLevel_dB
wet output level in dB
Definition: fxobjects.h:2691
virtual double getOutput2()
Definition: fxobjects.h:6103
double releaseTime_mSec
release time in milliseconds
Definition: fxobjects.h:1807
double bufferLength_mSec
total buffer length in mSec
Definition: fxobjects.h:4292
Custom parameter structure for the TwoBandShelvingFilter object. Used for reverb algorithms in book...
Definition: fxobjects.h:4515
double R1
input port resistance
Definition: fxobjects.h:7262
Custom parameter structure for the SimpleDelay object. Used for reverb algorithms in book...
Definition: fxobjects.h:3781
double * outputBuffer
output timeline (y)
Definition: fxobjects.h:8857
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:444
virtual double getOutput3()
Definition: fxobjects.h:6625
virtual double getOutput2()
Definition: fxobjects.h:7595
The ModulatedDelay object implements the three basic algorithms: flanger, chorus, vibrato...
Definition: fxobjects.h:3321
Use this interface for objects that process audio input samples to produce audio output samples...
Definition: fxobjects.h:1161
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6091
void createCircularBufferPowerOfTwo(unsigned int _bufferLengthPowerOfTwo)
Definition: fxobjects.h:2313
double RL
RL value.
Definition: fxobjects.h:6644
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L3C3
adaptor for L3 and C3
Definition: fxobjects.h:8011
unsigned int inputCount
input sample counter
Definition: fxobjects.h:9044
void createDelayBuffer(double _sampleRate, double _bufferLength_mSec)
Definition: fxobjects.h:3889
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5479
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1382
double readDelayAtTime_mSec(double _delay_mSec)
Definition: fxobjects.h:3911
double sampleRate
sample rate
Definition: fxobjects.h:7018
virtual double getOutput2()
Definition: fxobjects.h:6991
WdfParallelAdaptor parallelAdaptor_L2C2
adaptor for L2 and C2
Definition: fxobjects.h:8010
double apfDelayMax_mSec
APF max delay time.
Definition: fxobjects.h:4692
PhaseShifterParameters & operator=(const PhaseShifterParameters &params)
Definition: fxobjects.h:3477
double slopeIncrement
transition slope
Definition: fxobjects.h:609
void setComponent(wdfComponent componentType, double value1=0.0, double value2=0.0)
Definition: fxobjects.h:7141
The PhaseShifter object implements a six-stage phaser.
Definition: fxobjects.h:3533
void setParameters(const ZVAFilterParameters &params)
Definition: fxobjects.h:5176
double coeffArray[numCoeffs]
our local copy of biquad coeffs
Definition: fxobjects.h:1594
The FastFFT provides a simple wrapper for the FFTW FFT operation - it is ultra-thin and simple to use...
Definition: fxobjects.h:8733
bool softKnee
soft knee flag
Definition: fxobjects.h:2016
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1847
rateConversionRatio
Use this strongly typed enum to easily set up or down sampling ratios.
Definition: fxobjects.h:9587
virtual double getOutput1()
Definition: fxobjects.h:7592
double modCounterQP
Quad Phase modulo counter [0.0, +1.0].
Definition: fxobjects.h:3042
LFO modLFO
LFO.
Definition: fxobjects.h:4298
double decimateAudio(DecimatorInput data)
Definition: fxobjects.h:9930
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6714
OscillatorParameters & operator=(const OscillatorParameters &params)
Definition: fxobjects.h:2958
void setSourceResistance(double _sourceResistance)
Definition: fxobjects.h:7122
double Q
brickwall Q
Definition: fxobjects.h:569
void createCircularBuffer(unsigned int _bufferLength)
Definition: fxobjects.h:2305
FastConvolver convolver
the convolver
Definition: fxobjects.h:9830
void setParameters(const LRFilterBankParameters &_parameters)
Definition: fxobjects.h:1744
virtual void updateComponentResistance()
Definition: fxobjects.h:6445
WdfParallelAdaptor parallelAdaptor_L2C2
adaptor for L2 and C2
Definition: fxobjects.h:8107
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4198
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6253
double lfoRate_Hz
LFO rate in Hz, if enabled.
Definition: fxobjects.h:4148
bool mirrorMag
optionally mirror the output array
Definition: fxobjects.h:573
virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
Definition: fxobjects.h:6575
double Q
filter Q
Definition: fxobjects.h:8146
double lowShelfBoostCut_dB
LSF shelf gain/cut.
Definition: fxobjects.h:5750
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5664
bool polyphase
enable polyphase decomposition
Definition: fxobjects.h:9958
void initialize(unsigned int _filterImpulseLength)
Definition: fxobjects.h:8929
double RL
RL value.
Definition: fxobjects.h:6401
double lpf_g
gain value for LPF (if enabled)
Definition: fxobjects.h:3979
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5947
double highShelf_fc
high shelf fc
Definition: fxobjects.h:4704
double phi
bin phase angle
Definition: fxobjects.h:9100
double delay_Samples
current delay in samples; other objects may need to access this information
Definition: fxobjects.h:3801
double componentResistance
equivalent resistance of pair of componen
Definition: fxobjects.h:6648
double * inputBuffer
input timeline (x)
Definition: fxobjects.h:8856
The TwoBandShelvingFilter object implements two shelving filters in series in the standard "Bass and ...
Definition: fxobjects.h:4555
double ha
ha = N/4 — 75% overlap
Definition: fxobjects.h:9554
Custom output structure for interpolator; it holds an arry of interpolated output samples...
Definition: fxobjects.h:9728
Custom parameter structure for the EnvelopeFollower object.
Definition: fxobjects.h:5366
double sampleRate
sample rate
Definition: fxobjects.h:6404
BinData binDataPrevious[PSM_FFT_LEN]
array of BinData structures for previous FFT frame
Definition: fxobjects.h:9560
PSMVocoderParameters getParameters()
Definition: fxobjects.h:9527
virtual double getOutput2()
Definition: fxobjects.h:7383
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6145
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1928
virtual void setInput3(double _in3)
Definition: fxobjects.h:7377
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8417
virtual void updateComponentResistance()
Definition: fxobjects.h:6250
virtual double getComponentResistance()
Definition: fxobjects.h:6807
EnvelopeFollowerParameters & operator=(const EnvelopeFollowerParameters &params)
Definition: fxobjects.h:5370
delayUpdateType
Use this strongly typed enum to easily set the delay update type; this varies depending on the design...
Definition: fxobjects.h:2653
WDFParameters & operator=(const WDFParameters &params)
Definition: fxobjects.h:8132
The BitCrusher object implements a quantizing bitcrusher algorithm.
Definition: fxobjects.h:5918
Custom parameter structure for the DynamicsProcessor object. Ths struct includes all information need...
Definition: fxobjects.h:1986
virtual void setInput(double in)
Definition: fxobjects.h:6606
TriodeClassAParameters & operator=(const TriodeClassAParameters &params)
Definition: fxobjects.h:5557
bool enableSidechain
enable external sidechain input to object
Definition: fxobjects.h:2017
double outputGain
outputGain level
Definition: fxobjects.h:5583
virtual void updateComponentResistance()
Definition: fxobjects.h:6168
double zRegister_C
storage register for L
Definition: fxobjects.h:6761
edgeTransition
Use this strongly typed enum to easily set the edge direction (rising or falling) of a transition ban...
Definition: fxobjects.h:589
double lfoMaxModulation_mSec
max modulation time if LFO is enabled
Definition: fxobjects.h:4349
analogFilter
Use this strongy typed enum to set the analog filter type for the AnalogMagData structure.
Definition: fxobjects.h:821
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5954
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5008
Custom parameter structure for the ZVAFilter object.
Definition: fxobjects.h:5099
Use this interface for objects in the WDF Ladder Filter library; see book for more information...
Definition: fxobjects.h:5980
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:1061
virtual double getOutput2()
Definition: fxobjects.h:6380
double asymmetry
asymmetry level
Definition: fxobjects.h:5582
double RC
RC value.
Definition: fxobjects.h:7014
ReverbTankParameters getParameters()
Definition: fxobjects.h:4873
fftw_complex * ifft_result
array for IFFT output
Definition: fxobjects.h:8848
The LRFilterBank object implements 2 Linkwitz-Riley Filters in a parallel filter bank to split the si...
Definition: fxobjects.h:1678
void setParameters(AnalogFIRFilterParameters _parameters)
Definition: fxobjects.h:2586
void createWDF()
Definition: fxobjects.h:7987
virtual double getComponentValue_L()
Definition: fxobjects.h:6355
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:219
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:7217
filterCoeff
Use this enum to easily access coefficents inside of arrays.
Definition: fxobjects.h:1286
The WDFBesselBSF3 object implements a 3rd order Bessel BSF NOTE: designed with Elsie www...
Definition: fxobjects.h:7949
virtual double getComponentValue_L()
Definition: fxobjects.h:6475
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6850
bool enableLFO
flag to enable the modulated delay
Definition: fxobjects.h:4346
virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
Definition: fxobjects.h:6333
virtual double getOutput1()
Definition: fxobjects.h:6262
The WdfSeriesAdaptor object implements the series reflection-free (non-terminated) adaptor...
Definition: fxobjects.h:7298
fftw_complex * doInverseFFT(double *inputReal, double *inputImag)
perform the IFFT operation
Definition: fxobjects.cpp:1181
Custom parameter structure for the Biquad object. Default version defines the biquad structure used i...
Definition: fxobjects.h:9118
unsigned int wrapMaskOut
output wrap mask
Definition: fxobjects.h:8865
ComplexNumber complexMultiply(ComplexNumber c1, ComplexNumber c2)
returns the complex product of two complex numbers
Definition: fxobjects.h:490
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8238
bool calculateFilterCoeffs()
Definition: fxobjects.cpp:130
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6348
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2998
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5188
double C
value of C component
Definition: fxobjects.h:7084
double analogMatchSigma
analog matching Sigma value (see book)
Definition: fxobjects.h:5351
The AnalogFIRFilter object implements a somewhat silly algorithm that implaments an analog magnitude ...
Definition: fxobjects.h:2546
double outputLevel
output level (not in dB)
Definition: fxobjects.h:5869
virtual void updateComponentResistance()
Definition: fxobjects.h:6325
int previousPeakBin
index of peak bin in previous FFT
Definition: fxobjects.h:9103
virtual void setInput2(double _in2)
Definition: fxobjects.h:6631
WDFParameters getParameters()
Definition: fxobjects.h:8352
Custom parameter structure for the BitCrusher object.
Definition: fxobjects.h:5884
double coeffArray[numCoeffs]
Definition: fxobjects.h:1439
AnalogFIRFilterParameters getParameters()
Definition: fxobjects.h:2580
bool matchAnalogNyquistLPF
match analog gain at Nyquist
Definition: fxobjects.h:5125
unsigned int frameLength
current FFT length
Definition: fxobjects.h:8879
virtual double getComponentResistance()
Definition: fxobjects.h:6683
double wetLevel_dB
wet output level in dB
Definition: fxobjects.h:4707
double feedback_Pct
feedback in %
Definition: fxobjects.h:3301
virtual double getR2()
Definition: fxobjects.h:7413
void boundValue(double &value, double minValue, double maxValue)
Bound a value to min and max limits.
Definition: fxobjects.h:162
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:512
OscillatorParameters getParameters()
Definition: fxobjects.h:3014
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6953
virtual double getComponentValue_L()
Definition: fxobjects.h:6721
virtual void initialize(double _R1)
Definition: fxobjects.h:7527
virtual double getOutput3()
Definition: fxobjects.h:6189
void initialize(unsigned int _frameLength, windowType _window)
initialize the Fast FFT object for operation
Definition: fxobjects.cpp:1059
Custom structure that holds magnitude information about a brickwall filter.
Definition: fxobjects.h:557
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2567
double fc
filter fc
Definition: fxobjects.h:8145
double lastEnvelope
output register
Definition: fxobjects.h:1945
virtual double getComponentValue()
Definition: fxobjects.h:6078
virtual double getComponentResistance()
Definition: fxobjects.h:6319
double innerAPF_g
g coefficient for inner APF
Definition: fxobjects.h:4343
double psi[PSM_FFT_LEN]
array of phase correction values for classic algorithm
Definition: fxobjects.h:9556
virtual double getOutput3()
Definition: fxobjects.h:6503
double releaseTime
release time coefficient
Definition: fxobjects.h:1943
double alpha0
input scalar, correct delay-free loop
Definition: fxobjects.h:5344
virtual double getComponentConductance()
Definition: fxobjects.h:6686
bool clampToUnityMax
clamp output to 1.0 (set false for true log detectors)
Definition: fxobjects.h:1810
ClassATubePreParameters parameters
object parameters
Definition: fxobjects.h:5864
double phaseInc
phase inc = fo/fs
Definition: fxobjects.h:3041
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7956
delayAlgorithm
Use this strongly typed enum to easily set the delay algorithm.
Definition: fxobjects.h:2637
double highShelfBoostCut_dB
HSF shelf frequency.
Definition: fxobjects.h:5752
The PhaseVocoder provides a basic phase vocoder that is initialized to N = 4096 and 75% overlap; the ...
Definition: fxobjects.h:8792
virtual double getOutput1()
Definition: fxobjects.h:6865
virtual double getOutput2()
Definition: fxobjects.h:6500
double makeUpGain_dB
stored makeup gain (dB)
Definition: fxobjects.h:5066
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6481
bool enableLPF
flag to enable LPF in structure
Definition: fxobjects.h:4144
double * windowBuff
buffer for window
Definition: fxobjects.h:9565
double sourceResistance
source impedance; OK for this to be set to 0.0 for Rs = 0
Definition: fxobjects.h:7284
double componentValue_R
component value R
Definition: fxobjects.h:6765
BitCrusherParameters & operator=(const BitCrusherParameters &params)
Definition: fxobjects.h:5888
virtual double getComponentConductance()
Definition: fxobjects.h:6563
virtual double getOutput1()
Definition: fxobjects.h:6988
WdfSeriesAdaptor seriesAdaptor_R
adaptor for series R
Definition: fxobjects.h:8628
virtual double getOutput3()=0
DelayAPFParameters & operator=(const DelayAPFParameters &params)
Definition: fxobjects.h:4124
Custom input structure for DecimatorInput; it holds an arry of input samples that will be decimated d...
Definition: fxobjects.h:9853
windowType window
window type
Definition: fxobjects.h:8768
fftw_plan plan_backward
FFTW plan for IFFT.
Definition: fxobjects.h:8764
unsigned int startBin
starting bin for transition band
Definition: fxobjects.h:607
double RR
RR value.
Definition: fxobjects.h:6646
double fixeDelayWeight_Pct
fixed delay max weighying
Definition: fxobjects.h:4695
double g
simple LPF g value
Definition: fxobjects.h:3697
BinData & operator=(const BinData &params)
Definition: fxobjects.h:9068
fftw_complex * doFFT(double *inputReal, double *inputImag=nullptr)
perform the FFT operation
Definition: fxobjects.cpp:1153
double phi[PSM_FFT_LEN]
array of phase values for classic algorithm
Definition: fxobjects.h:9555
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5925
unsigned int localPeakBin
index of peak-boss
Definition: fxobjects.h:9102
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4051
double dryLevel_dB
dry output level in dB
Definition: fxobjects.h:2692
virtual void setInput2(double _in2)
Definition: fxobjects.h:7476
virtual double getOutput()
Definition: fxobjects.h:6494
The WDFIdealRLCHPF object implements an ideal RLC HPF using the WDF library.
Definition: fxobjects.h:8289
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6894
void setParameters(const BiquadParameters &_parameters)
Definition: fxobjects.h:1408
double outerAPF_g
g coefficient for outer APF
Definition: fxobjects.h:4342
The NestedDelayAPF object implements a pair of nested Delaying APF structures. These are labled the o...
Definition: fxobjects.h:4372
PhaseShifterParameters getParameters()
Definition: fxobjects.h:3647
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:9694
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2766
The WdfParallelRL object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6664
T readBuffer(double delayInFractionalSamples)
Definition: fxobjects.h:2357