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  return sgn(xn)*(1.0 - exp(-fabs(saturation*xn)));
415 }
416 
426 inline double fuzzExp1WaveShaper(double xn, double saturation, double asymmetry)
427 {
428  // --- setup gain
429  double wsGain = calcWSGain(xn, saturation, asymmetry);
430  return sgn(xn)*(1.0 - exp(-fabs(wsGain*xn))) / (1.0 - exp(-wsGain));
431 }
432 
433 
443 inline double getMagResponse(double theta, double a0, double a1, double a2, double b1, double b2)
444 {
445  double magSqr = 0.0;
446  double num = a1*a1 + (a0 - a2)*(a0 - a2) + 2.0*a1*(a0 + a2)*cos(theta) + 4.0*a0*a2*cos(theta)*cos(theta);
447  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);
448 
449  magSqr = num / denom;
450  if (magSqr < 0.0)
451  magSqr = 0.0;
452 
453  double mag = pow(magSqr, 0.5);
454 
455  return mag;
456 }
457 
469 {
470  ComplexNumber() {}
471  ComplexNumber(double _real, double _imag)
472  {
473  real = _real;
474  imag = _imag;
475  }
476 
477  double real = 0.0;
478  double imag = 0.0;
479 };
480 
490 {
491  ComplexNumber complexProduct;
492 
493  // --- real part
494  complexProduct.real = (c1.real*c2.real) - (c1.imag*c2.imag);
495  complexProduct.imag = (c1.real*c2.imag) + (c1.imag*c2.real);
496 
497  return complexProduct;
498 }
499 
511 inline void calcEdgeFrequencies(double fc, double Q, double& f_Low, double& f_High)
512 {
513  bool arithmeticBW = true;
514  double bandwidth = fc / Q;
515 
516  // --- geometric bw = sqrt[ (fLow)(fHigh) ]
517  // arithmetic bw = fHigh - fLow
518  if (arithmeticBW)
519  {
520  f_Low = fc - bandwidth / 2.0;
521  f_High = fc + bandwidth / 2.0;
522  }
523  else
524  {
525  ; // TODO --- add geometric (for homework)
526  }
527 
528 }
529 
543 enum class brickwallFilter { kBrickLPF, kBrickHPF, kBrickBPF, kBrickBSF };
544 
557 {
558  BrickwallMagData() {}
559 
560  brickwallFilter filterType = brickwallFilter::kBrickLPF;
561  double* magArray = nullptr;
562  unsigned int dftArrayLen = 0;
563  double sampleRate = 44100.0;
564 
565  // --- for LPF, HPF fc = corner frequency
566  // for BPF, BSF fc = center frequency
567  double fc = 1000.0;
568  double Q = 0.707;
569  double f_Low = 500.00;
570  double f_High = 1500.00;
571  unsigned int relaxationBins = 0;
572  bool mirrorMag = false;
573 };
574 
588 enum class edgeTransition { kFallingEdge, kRisingEdge };
589 
602 {
603  TransitionBandData() {}
604 
605  edgeTransition edgeType = edgeTransition::kFallingEdge;
606  unsigned int startBin = 0;
607  unsigned int stopBin = 0;
608  double slopeIncrement = 1.0;
609 };
610 
611 
622 inline int findEdgeTargetBin(double testFreq, double bin1Freq)
623 {
624  return (int)(testFreq / bin1Freq);
625 }
626 
639 inline bool getTransitionBandData(double testFreq, double bin1Freq, unsigned int relax_Bins, TransitionBandData& transitionData)
640 {
641  double targetF1 = testFreq;// -(2.0*relax_Pct / 100.0)*testFreq;
642  double targetF2 = testFreq + relax_Bins*bin1Freq;
643 
644  // --- for falling edge...
645  int nF1 = findEdgeTargetBin(targetF1, bin1Freq);
646  int nF2 = findEdgeTargetBin(targetF2, bin1Freq);
647  //int relaxBinsAbsDiff = nF2 - nF1;
648 
649  nF1 = fmax(0, nF1);
650  nF2 = fmax(0, nF2);
651 
652  //if (relaxBinsAbsDiff < 0 || nF1 == 0)
653  // nF2 = nF1 + relaxBinsAbsDiff;
654 
655  int relaxBins = nF2 - nF1;
656 
657  if (relaxBins < 1)
658  return false;
659 
660  // --- force even to make relax band symmetrical around edge
661  //if (relaxBins % 2 != 0)
662  // relaxBins++;
663 
664  // --- for double-sided relax
665  transitionData.startBin = nF1;
666  transitionData.stopBin = relaxBins + nF1;
667 
668  // --- slope calc
669  double run = transitionData.stopBin - transitionData.startBin;
670  double rise = 1.0;
671  if (transitionData.edgeType == edgeTransition::kFallingEdge)
672  rise = -1.0;
673  transitionData.slopeIncrement = rise / run;
674 
675  return true;
676 }
677 
688 {
689  // --- calculate first half of array
690  double actualLength = magData.mirrorMag ? (double)magData.dftArrayLen : (double)magData.dftArrayLen * 2.0;
691  int dumpLength = magData.mirrorMag ? magData.dftArrayLen / 2 : magData.dftArrayLen;
692 
693  // --- first bin in Hz
694  double bin1 = magData.sampleRate / actualLength;
695 
696  // --- zero out array; if filter not supported, this will return a bank of 0's!
697  memset(&magData.magArray[0], 0, magData.dftArrayLen * sizeof(double));
698 
699  // --- preprocess for transition bands
700  TransitionBandData fallingEdge;
701  fallingEdge.edgeType = edgeTransition::kFallingEdge;
702 
703  TransitionBandData risingEdge;
704  risingEdge.edgeType = edgeTransition::kRisingEdge;
705 
706  // --- this will populate FL and FH for BPF and BSF
707  calcEdgeFrequencies(magData.fc, magData.Q, magData.f_Low, magData.f_High);
708 
709  bool relaxIt = false;
710  if (magData.relaxationBins > 0)
711  {
712  if(magData.filterType == brickwallFilter::kBrickLPF)
713  relaxIt = getTransitionBandData(magData.fc, bin1, magData.relaxationBins, fallingEdge);
714  else if (magData.filterType == brickwallFilter::kBrickHPF)
715  relaxIt = getTransitionBandData(magData.fc, bin1, magData.relaxationBins, risingEdge);
716  else if (magData.filterType == brickwallFilter::kBrickBPF)
717  {
718  if(getTransitionBandData(magData.f_Low, bin1, magData.relaxationBins, risingEdge))
719  relaxIt = getTransitionBandData(magData.f_High, bin1, magData.relaxationBins, fallingEdge);
720  }
721  else if (magData.filterType == brickwallFilter::kBrickBSF)
722  {
723  if(getTransitionBandData(magData.f_Low, bin1, magData.relaxationBins, fallingEdge))
724  relaxIt = getTransitionBandData(magData.f_High, bin1, magData.relaxationBins, risingEdge);
725  }
726  }
727 
728  for (int i = 0; i < dumpLength; i++)
729  {
730  double eval_f = i*bin1;
731 
732  if (magData.filterType == brickwallFilter::kBrickLPF)
733  {
734  if (!relaxIt)
735  {
736  if (eval_f <= magData.fc)
737  magData.magArray[i] = 1.0;
738  }
739  else // relax
740  {
741  if (i <= fallingEdge.startBin)
742  magData.magArray[i] = 1.0;
743  else if(i > fallingEdge.startBin && i < fallingEdge.stopBin)
744  magData.magArray[i] = 1.0 + (i - fallingEdge.startBin)*fallingEdge.slopeIncrement;
745  }
746  }
747  else if (magData.filterType == brickwallFilter::kBrickHPF)
748  {
749  if (!relaxIt)
750  {
751  if (eval_f >= magData.fc)
752  magData.magArray[i] = 1.0;
753  }
754  else // relax
755  {
756  if (i >= risingEdge.stopBin)
757  magData.magArray[i] = 1.0;
758  else if (i > risingEdge.startBin && i < risingEdge.stopBin)
759  magData.magArray[i] = 0.0 + (i - risingEdge.startBin)*risingEdge.slopeIncrement;
760  }
761  }
762  else if (magData.filterType == brickwallFilter::kBrickBPF)
763  {
764  if (!relaxIt)
765  {
766  if (eval_f >= magData.f_Low && eval_f <= magData.f_High)
767  magData.magArray[i] = 1.0;
768  }
769  else // --- frankie says relax
770  {
771  if (i >= risingEdge.stopBin && i <= fallingEdge.startBin)
772  magData.magArray[i] = 1.0;
773  else if (i > risingEdge.startBin && i < risingEdge.stopBin)
774  magData.magArray[i] = 0.0 + (i - risingEdge.startBin)*risingEdge.slopeIncrement;
775  else if (i > fallingEdge.startBin && i < fallingEdge.stopBin)
776  magData.magArray[i] = 1.0 + (i - fallingEdge.startBin)*fallingEdge.slopeIncrement;
777 
778  }
779  }
780  else if (magData.filterType == brickwallFilter::kBrickBSF)
781  {
782  if (!relaxIt && eval_f >= magData.f_Low && eval_f <= magData.f_High)
783  magData.magArray[i] = 0.0;
784  else if((!relaxIt && eval_f < magData.f_Low) || eval_f > magData.f_High)
785  magData.magArray[i] = 1.0;
786  else
787  {
788  // --- TODO Fill this in...
789  }
790  }
791  }
792 
793  // -- make sure have legal first half...
794  if (!magData.mirrorMag)
795  return true;
796 
797  // --- now mirror the other half
798  int index = magData.dftArrayLen / 2 - 1;
799  for (unsigned int i = magData.dftArrayLen / 2; i <magData.dftArrayLen; i++)
800  {
801  magData.magArray[i] = magData.magArray[index--];
802  }
803 
804  return true;
805 }
806 
820 enum class analogFilter { kLPF1, kHPF1, kLPF2, kHPF2, kBPF2, kBSF2 };
821 
834 {
835  AnalogMagData() {}
836 
837  analogFilter filterType = analogFilter::kLPF2;
838  double* magArray = nullptr;
839  unsigned int dftArrayLen = 0;
840  double sampleRate = 44100.0;
841 
842  // --- for LPF, HPF fc = corner frequency
843  // for BPF, BSF fc = center frequency
844  double fc = 1000.0;
845  double Q = 0.707;
846  bool mirrorMag = true;
847 };
848 
859 {
860  // --- calculate first half of array
861  double actualLength = magData.mirrorMag ? (double)magData.dftArrayLen : (double)magData.dftArrayLen * 2.0;
862  int dumpLength = magData.mirrorMag ? magData.dftArrayLen / 2 : magData.dftArrayLen;
863 
864  double bin1 = magData.sampleRate / actualLength;// (double)magData.dftArrayLen;
865  double zeta = 1.0 / (2.0*magData.Q);
866  double w_c = 2.0*kPi*magData.fc;
867 
868  // --- zero out array; if filter not supported, this will return a bank of 0's!
869  memset(&magData.magArray[0], 0, magData.dftArrayLen * sizeof(double));
870 
871  for (int i = 0; i < dumpLength; i++)
872  {
873  double eval_w = 2.0*kPi*i*bin1;
874  double w_o = eval_w / w_c;
875 
876  if (magData.filterType == analogFilter::kLPF1)
877  {
878  double denXSq = 1.0 + (w_o*w_o);
879  magData.magArray[i] = 1.0 / (pow(denXSq, 0.5));
880  }
881  else if (magData.filterType == analogFilter::kHPF1)
882  {
883  double denXSq = 1.0 + (w_o*w_o);
884  magData.magArray[i] = w_o / (pow(denXSq, 0.5));
885  }
886  else if (magData.filterType == analogFilter::kLPF2)
887  {
888  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
889  magData.magArray[i] = 1.0 / (pow(denXSq, 0.5));
890  }
891  else if (magData.filterType == analogFilter::kHPF2)
892  {
893  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
894  magData.magArray[i] = (w_o*w_o) / (pow(denXSq, 0.5));
895  }
896  else if (magData.filterType == analogFilter::kBPF2)
897  {
898  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
899  magData.magArray[i] = 2.0*w_o*zeta / (pow(denXSq, 0.5));
900  }
901  else if (magData.filterType == analogFilter::kBSF2)
902  {
903  double numXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o));
904  double denXSq = (1.0 - (w_o*w_o))*(1.0 - (w_o*w_o)) + 4.0*zeta*zeta*w_o*w_o;
905  magData.magArray[i] = (pow(numXSq, 0.5)) / (pow(denXSq, 0.5));
906  }
907  }
908 
909  // -- make sure have legal first half...
910  if (!magData.mirrorMag)
911  return true;
912 
913  // --- now mirror the other half
914  int index = magData.dftArrayLen / 2 - 1;
915  for (unsigned int i = magData.dftArrayLen / 2; i <magData.dftArrayLen; i++)
916  {
917  magData.magArray[i] = magData.magArray[index--];
918  }
919 
920  return true;
921 }
922 
935 inline void freqSample(int N, double A[], double h[], int symm)
936 {
937  int n, k;
938  double x, val, M;
939 
940  M = (N - 1.0) / 2.0;
941  if (symm == POSITIVE)
942  {
943  if (N % 2)
944  {
945  for (n = 0; n<N; n++)
946  {
947  val = A[0];
948  x = kTwoPi * (n - M) / N;
949  for (k = 1; k <= M; k++)
950  val += 2.0 * A[k] * cos(x*k);
951  h[n] = val / N;
952  }
953  }
954  else
955  {
956  for (n = 0; n<N; n++)
957  {
958  val = A[0];
959  x = kTwoPi * (n - M) / N;
960  for (k = 1; k <= (N / 2 - 1); k++)
961  val += 2.0 * A[k] * cos(x*k);
962  h[n] = val / N;
963  }
964  }
965  }
966  else
967  {
968  if (N % 2)
969  {
970  for (n = 0; n<N; n++)
971  {
972  val = 0;
973  x = kTwoPi * (n - M) / N;
974  for (k = 1; k <= M; k++)
975  val += 2.0 * A[k] * sin(x*k);
976  h[n] = val / N;
977  }
978  }
979  else
980  {
981  for (n = 0; n<N; n++)
982  {
983  val = A[N / 2] * sin(kPi * (n - M));
984  x = kTwoPi * (n - M) / N;
985  for (k = 1; k <= (N / 2 - 1); k++)
986  val += 2.0 * A[k] * sin(x*k);
987  h[n] = val / N;
988  }
989  }
990  }
991 }
992 
1003 inline double getMagnitude(double re, double im)
1004 {
1005  return sqrt((re*re) + (im*im));
1006 }
1007 
1018 inline double getPhase(double re, double im)
1019 {
1020  return atan2(im, re);
1021 }
1022 
1033 inline double principalArg(double phaseIn)
1034 {
1035  if (phaseIn >= 0)
1036  return fmod(phaseIn + kPi, kTwoPi) - kPi;
1037  else
1038  return fmod(phaseIn + kPi, -kTwoPi) + kPi;
1039 }
1040 
1041 enum class interpolation {kLinear, kLagrange4};
1042 
1060 inline bool resample(double* input, double* output, uint32_t inLength, uint32_t outLength,
1061  interpolation interpType = interpolation::kLinear,
1062  double scalar = 1.0, double* outWindow = nullptr)
1063 {
1064  if (inLength == 0 || outLength == 0) return false;
1065  if (!input || !output) return false;
1066 
1067  double x[4] = { 0.0 };
1068  double y[4] = { 0.0 };
1069 
1070  // --- inc
1071  double inc = (double)inLength / (double)(outLength);
1072 
1073  // --- first point
1074  if (outWindow)
1075  output[0] = outWindow[0] * scalar * input[0];
1076  else
1077  output[0] = scalar * input[0];
1078 
1079  if (interpType == interpolation::kLagrange4)
1080  {
1081  for (unsigned int i = 1; i < outLength; i++)
1082  {
1083  // --- find interpolation location
1084  double xInterp = i*inc;
1085  int x1 = (int)xInterp; // floor?
1086  // double xbar = xInterp - x1;
1087 
1088  if (xInterp > 1 && x1 < outLength-2)
1089  {
1090  x[0] = x1 - 1;
1091  y[0] = input[(int)x[0]];
1092 
1093  x[1] = x1;
1094  y[1] = input[(int)x[1]];
1095 
1096  x[2] = x1 + 1;
1097  y[2] = input[(int)x[2]];
1098 
1099  x[3] = x1 + 2;
1100  y[3] = input[(int)x[3]];
1101 
1102  if (outWindow)
1103  output[i] = outWindow[i] * scalar * doLagrangeInterpolation(x, y, 4, xInterp);
1104  else
1105  output[i] = scalar * doLagrangeInterpolation(x, y, 4, xInterp);
1106  }
1107  else // --- linear for outer 2 end pts
1108  {
1109  int x2 = x1 + 1;
1110  if (x2 >= outLength)
1111  x2 = x1;
1112  double y1 = input[x1];
1113  double y2 = input[x2];
1114 
1115  if (outWindow)
1116  output[i] = outWindow[i] * scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1117  else
1118  output[i] = scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1119  }
1120  }
1121  }
1122  else // must be linear
1123  {
1124  // --- LINEAR INTERP
1125  for (unsigned int i = 1; i < outLength; i++)
1126  {
1127  double xInterp = i*inc;
1128  int x1 = (int)xInterp; // floor?
1129  int x2 = x1 + 1;
1130  if (x2 >= outLength)
1131  x2 = x1;
1132  double y1 = input[x1];
1133  double y2 = input[x2];
1134 
1135  if (outWindow)
1136  output[i] = outWindow[i] * scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1137  else
1138  output[i] = scalar * doLinearInterpolation(y1, y2, xInterp - x1);
1139  }
1140  }
1141 
1142  return true;
1143 }
1144 
1145 // ------------------------------------------------------------------ //
1146 // --- INTERFACES --------------------------------------------------- //
1147 // ------------------------------------------------------------------ //
1148 
1161 {
1162 public:
1163  // --- pure virtual, derived classes must implement or will not compile
1164  // also means this is a pure abstract base class and is incomplete,
1165  // so it can only be used as a base class
1166  //
1168  virtual bool reset(double _sampleRate) = 0;
1169 
1171  virtual double processAudioSample(double xn) = 0;
1172 
1174  virtual bool canProcessAudioFrame() = 0;
1175 
1177  virtual void setSampleRate(double _sampleRate) {}
1178 
1180  virtual void enableAuxInput(bool enableAuxInput) {}
1181 
1184  virtual double processAuxInputAudioSample(double xn)
1185  {
1186  // --- do nothing
1187  return xn;
1188  }
1189 
1194  virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
1195  float* outputFrame,
1196  uint32_t inputChannels,
1197  uint32_t outputChannels)
1198  {
1199  // --- do nothing
1200  return false; // NOT handled
1201  }
1202 };
1203 
1215 // --- structure to send output data from signal gen; you can add more outputs here
1217 {
1218  SignalGenData() {}
1219 
1220  double normalOutput = 0.0;
1221  double invertedOutput = 0.0;
1222  double quadPhaseOutput_pos = 0.0;
1223  double quadPhaseOutput_neg = 0.0;
1224 };
1225 
1241 {
1242 public:
1243  // --- pure virtual, derived classes must implement or will not compile
1244  // also means this is a pure abstract base class and is incomplete,
1245  // so it can only be used as a base class
1246  //
1248  virtual bool reset(double _sampleRate) = 0;
1249 
1251  virtual const SignalGenData renderAudioOutput() = 0;
1252 };
1253 
1254 
1255 
1256 // ------------------------------------------------------------------ //
1257 // --- OBJECTS ------------------------------------------------------ //
1258 // ------------------------------------------------------------------ //
1259 /*
1260 Class Declarations :
1261 
1262 class name : public IAudioSignalProcessor
1263  - IAudioSignalProcessor functions
1264  - member functions that may be called externally
1265  - mutators & accessors
1266  - helper functions(may be private / protected if needed)
1267  - protected member functions
1268 */
1269 
1283 enum filterCoeff { a0, a1, a2, b1, b2, c0, d0, numCoeffs };
1284 
1301 // --- state array index values
1302 // z^-1 registers;
1303 // Direct Forms: we will allow max of 2 for X (feedforward) and 2 for Y (feedback) data
1304 // Transpose Forms: we will use ONLY the x_z1 and x_z2 registers for the 2 required delays
1305 enum stateReg { x_z1, x_z2, y_z1, y_z2, numStates };
1306 
1321 // --- type of calculation (algorithm)
1322 enum class biquadAlgorithm { kDirect, kCanonical, kTransposeDirect, kTransposeCanonical }; // 4 types of biquad calculations, constants (k)
1323 
1324 
1337 {
1338  BiquadParameters () {}
1339 
1342  {
1343  if (this == &params)
1344  return *this;
1345 
1346  biquadCalcType = params.biquadCalcType;
1347  return *this;
1348  }
1349 
1350  biquadAlgorithm biquadCalcType = biquadAlgorithm::kDirect;
1351 };
1352 
1371 {
1372 public:
1373  Biquad() {} /* C-TOR */
1374  ~Biquad() {} /* D-TOR */
1375 
1376  // --- IAudioSignalProcessor FUNCTIONS --- //
1377  //
1379  virtual bool reset(double _sampleRate)
1380  {
1381  memset(&stateArray[0], 0, sizeof(double)*numStates);
1382  return true; // handled = true
1383  }
1384 
1386  virtual bool canProcessAudioFrame() { return false; }
1387 
1393  virtual double processAudioSample(double xn);
1394 
1400 
1405  void setParameters(const BiquadParameters& _parameters){ parameters = _parameters; }
1406 
1407  // --- MUTATORS & ACCESSORS --- //
1409  void setCoefficients(double* coeffs){
1410  // --- fast block memory copy:
1411  memcpy(&coeffArray[0], &coeffs[0], sizeof(double)*numCoeffs);
1412  }
1413 
1416  {
1417  // --- read/write access to the array (not used)
1418  return &coeffArray[0];
1419  }
1420 
1422  double* getStateArray()
1423  {
1424  // --- read/write access to the array (used only in direct form oscillator)
1425  return &stateArray[0];
1426  }
1427 
1429  double getG_value() { return coeffArray[a0]; }
1430 
1432  double getS_value();// { return storageComponent; }
1433 
1434 protected:
1436  double coeffArray[numCoeffs] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1437 
1439  double stateArray[numStates] = { 0.0, 0.0, 0.0, 0.0 };
1440 
1443 
1445  double storageComponent = 0.0;
1446 };
1447 
1448 
1462 enum class filterAlgorithm {
1463  kLPF1P, kLPF1, kHPF1, kLPF2, kHPF2, kBPF2, kBSF2, kButterLPF2, kButterHPF2, kButterBPF2,
1464  kButterBSF2, kMMALPF2, kMMALPF2B, kLowShelf, kHiShelf, kNCQParaEQ, kCQParaEQ, kLWRLPF2, kLWRHPF2,
1465  kAPF1, kAPF2, kResonA, kResonB, kMatchLP2A, kMatchLP2B, kMatchBP2A, kMatchBP2B,
1466  kImpInvLP1, kImpInvLP2
1467 }; // --- you will add more here...
1468 
1469 
1482 {
1485  AudioFilterParameters& operator=(const AudioFilterParameters& params) // need this override for collections to work
1486  {
1487  if (this == &params)
1488  return *this;
1489  algorithm = params.algorithm;
1490  fc = params.fc;
1491  Q = params.Q;
1492  boostCut_dB = params.boostCut_dB;
1493 
1494  return *this;
1495  }
1496 
1497  // --- individual parameters
1498  filterAlgorithm algorithm = filterAlgorithm::kLPF1;
1499  double fc = 100.0;
1500  double Q = 0.707;
1501  double boostCut_dB = 0.0;
1502 };
1503 
1522 {
1523 public:
1524  AudioFilter() {} /* C-TOR */
1525  ~AudioFilter() {} /* D-TOR */
1526 
1527  // --- IAudioSignalProcessor
1529  virtual bool reset(double _sampleRate)
1530  {
1532 
1533  // --- you can try both forms - do you hear a difference?
1534  bqp.biquadCalcType = biquadAlgorithm::kTransposeCanonical; //<- this is the default operation
1535  // bqp.biquadCalcType = biquadAlgorithm::kDirect;
1536  biquad.setParameters(bqp);
1537 
1538  sampleRate = _sampleRate;
1539  return biquad.reset(_sampleRate);
1540  }
1541 
1543  virtual bool canProcessAudioFrame() { return false; }
1544 
1550  virtual double processAudioSample(double xn);
1551 
1553  virtual void setSampleRate(double _sampleRate)
1554  {
1555  sampleRate = _sampleRate;
1557  }
1558 
1561 
1563  void setParameters(const AudioFilterParameters& parameters)
1564  {
1565  if (audioFilterParameters.algorithm != parameters.algorithm ||
1567  audioFilterParameters.fc != parameters.fc ||
1568  audioFilterParameters.Q != parameters.Q)
1569  {
1570  // --- save new params
1571  audioFilterParameters = parameters;
1572  }
1573  else
1574  return;
1575 
1576  // --- don't allow 0 or (-) values for Q
1577  if (audioFilterParameters.Q <= 0)
1578  audioFilterParameters.Q = 0.707;
1579 
1580  // --- update coeffs
1582  }
1583 
1585  double getG_value() { return biquad.getG_value(); }
1586 
1588  double getS_value() { return biquad.getS_value(); }
1589 
1590 protected:
1591  // --- our calculator
1593 
1594  // --- array to hold coeffs (we need them too)
1595  double coeffArray[numCoeffs] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
1596 
1597  // --- object parameters
1599  double sampleRate = 44100.0;
1600 
1602  bool calculateFilterCoeffs();
1603 };
1604 
1605 
1617 // --- output for filter bank requires multiple channels (bands)
1619 {
1620  FilterBankOutput() {}
1621 
1622  // --- band-split filter output
1623  double LFOut = 0.0;
1624  double HFOut = 0.0;
1625 
1626  // --- add more filter channels here; or use an array[]
1627 };
1628 
1629 
1644 {
1647  LRFilterBankParameters& operator=(const LRFilterBankParameters& params) // need this override for collections to work
1648  {
1649  if (this == &params)
1650  return *this;
1651  splitFrequency = params.splitFrequency;
1652  return *this;
1653  }
1654 
1655  // --- individual parameters
1656  double splitFrequency = 1000.0;
1657 };
1658 
1659 
1680 {
1681 public:
1682  LRFilterBank() /* C-TOR */
1683  {
1684  // --- set filters as Linkwitz-Riley 2nd order
1686  params.algorithm = filterAlgorithm::kLWRLPF2;
1687  lpFilter.setParameters(params);
1688 
1689  params = hpFilter.getParameters();
1690  params.algorithm = filterAlgorithm::kLWRHPF2;
1691  hpFilter.setParameters(params);
1692  }
1693 
1694  ~LRFilterBank() {} /* D-TOR */
1695 
1697  virtual bool reset(double _sampleRate)
1698  {
1699  lpFilter.reset(_sampleRate);
1700  hpFilter.reset(_sampleRate);
1701  return true;
1702  }
1703 
1705  virtual bool canProcessAudioFrame() { return false; }
1706 
1712  virtual double processAudioSample(double xn)
1713  {
1714  return xn;
1715  }
1716 
1719  {
1720  FilterBankOutput output;
1721 
1722  // --- process the LPF
1723  output.LFOut = lpFilter.processAudioSample(xn);
1724 
1725  // --- invert the HP filter output so that recombination will
1726  // result in the correct phase and magnitude responses
1727  output.HFOut = -hpFilter.processAudioSample(xn);
1728 
1729  return output;
1730  }
1731 
1737  {
1738  return parameters;
1739  }
1740 
1745  void setParameters(const LRFilterBankParameters& _parameters)
1746  {
1747  // --- update structure
1748  parameters = _parameters;
1749 
1750  // --- update member objects
1752  params.fc = parameters.splitFrequency;
1753  lpFilter.setParameters(params);
1754 
1755  params = hpFilter.getParameters();
1756  params.fc = parameters.splitFrequency;
1757  hpFilter.setParameters(params);
1758  }
1759 
1760 protected:
1763 
1764  // --- object parameters
1766 };
1767 
1768 // --- constants
1769 const unsigned int TLD_AUDIO_DETECT_MODE_PEAK = 0;
1770 const unsigned int TLD_AUDIO_DETECT_MODE_MS = 1;
1771 const unsigned int TLD_AUDIO_DETECT_MODE_RMS = 2;
1772 const double TLD_AUDIO_ENVELOPE_ANALOG_TC = -0.99967234081320612357829304641019; // ln(36.7%)
1773 
1791 {
1794  AudioDetectorParameters& operator=(const AudioDetectorParameters& params) // need this override for collections to work
1795  {
1796  if (this == &params)
1797  return *this;
1800  detectMode = params.detectMode;
1801  detect_dB = params.detect_dB;
1803  return *this;
1804  }
1805 
1806  // --- individual parameters
1807  double attackTime_mSec = 0.0;
1808  double releaseTime_mSec = 0.0;
1809  unsigned int detectMode = 0;
1810  bool detect_dB = false;
1811  bool clampToUnityMax = true;
1812 };
1813 
1833 {
1834 public:
1835  AudioDetector() {} /* C-TOR */
1836  ~AudioDetector() {} /* D-TOR */
1837 
1838 public:
1840  virtual bool reset(double _sampleRate)
1841  {
1842  setSampleRate(_sampleRate);
1843  lastEnvelope = 0.0;
1844  return true;
1845  }
1846 
1848  virtual bool canProcessAudioFrame() { return false; }
1849 
1850  // --- process audio: detect the log envelope and return it in dB
1855  virtual double processAudioSample(double xn)
1856  {
1857  // --- all modes do Full Wave Rectification
1858  double input = fabs(xn);
1859 
1860  // --- square it for MS and RMS
1861  if (audioDetectorParameters.detectMode == TLD_AUDIO_DETECT_MODE_MS ||
1862  audioDetectorParameters.detectMode == TLD_AUDIO_DETECT_MODE_RMS)
1863  input *= input;
1864 
1865  // --- to store current
1866  double currEnvelope = 0.0;
1867 
1868  // --- do the detection with attack or release applied
1869  if (input > lastEnvelope)
1870  currEnvelope = attackTime * (lastEnvelope - input) + input;
1871  else
1872  currEnvelope = releaseTime * (lastEnvelope - input) + input;
1873 
1874  // --- we are recursive so need to check underflow
1875  checkFloatUnderflow(currEnvelope);
1876 
1877  // --- bound them; can happen when using pre-detector gains of more than 1.0
1879  currEnvelope = fmin(currEnvelope, 1.0);
1880 
1881  // --- can not be (-)
1882  currEnvelope = fmax(currEnvelope, 0.0);
1883 
1884  // --- store envelope prior to sqrt for RMS version
1885  lastEnvelope = currEnvelope;
1886 
1887  // --- if RMS, do the SQRT
1888  if (audioDetectorParameters.detectMode == TLD_AUDIO_DETECT_MODE_RMS)
1889  currEnvelope = pow(currEnvelope, 0.5);
1890 
1891  // --- if not dB, we are done
1893  return currEnvelope;
1894 
1895  // --- setup for log( )
1896  if (currEnvelope <= 0)
1897  {
1898  return -96.0;
1899  }
1900 
1901  // --- true log output in dB, can go above 0dBFS!
1902  return 20.0*log10(currEnvelope);
1903  }
1904 
1910  {
1911  return audioDetectorParameters;
1912  }
1913 
1918  void setParameters(const AudioDetectorParameters& parameters)
1919  {
1920  audioDetectorParameters = parameters;
1921 
1922  // --- update structure
1925 
1926  }
1927 
1929  virtual void setSampleRate(double _sampleRate)
1930  {
1931  if (sampleRate == _sampleRate)
1932  return;
1933 
1934  sampleRate = _sampleRate;
1935 
1936  // --- recalculate RC time-constants
1939  }
1940 
1941 protected:
1943  double attackTime = 0.0;
1944  double releaseTime = 0.0;
1945  double sampleRate = 44100;
1946  double lastEnvelope = 0.0;
1947 
1949  void setAttackTime(double attack_in_ms, bool forceCalc = false);
1950 
1952  void setReleaseTime(double release_in_ms, bool forceCalc = false);
1953 };
1954 
1955 
1972 // --- processorType
1973 enum class dynamicsProcessorType { kCompressor, kDownwardExpander };
1974 
1975 
1988 {
1991  DynamicsProcessorParameters& operator=(const DynamicsProcessorParameters& params) // need this override for collections to work
1992  {
1993  if (this == &params)
1994  return *this;
1995 
1996  ratio = params.ratio;
1997  threshold_dB = params.threshold_dB;
1998  kneeWidth_dB = params.kneeWidth_dB;
1999  hardLimitGate = params.hardLimitGate;
2000  softKnee = params.softKnee;
2002  calculation = params.calculation;
2005  outputGain_dB = params.outputGain_dB;
2006  // --- NOTE: do not set outbound variables??
2007  gainReduction = params.gainReduction;
2009  return *this;
2010  }
2011 
2012  // --- individual parameters
2013  double ratio = 50.0;
2014  double threshold_dB = -10.0;
2015  double kneeWidth_dB = 10.0;
2016  bool hardLimitGate = false;
2017  bool softKnee = true;
2018  bool enableSidechain = false;
2019  dynamicsProcessorType calculation = dynamicsProcessorType::kCompressor;
2020  double attackTime_mSec = 0.0;
2021  double releaseTime_mSec = 0.0;
2022  double outputGain_dB = 0.0;
2023 
2024  // --- outbound values, for owner to use gain-reduction metering
2025  double gainReduction = 1.0;
2026  double gainReduction_dB = 0.0;
2027 };
2028 
2047 {
2048 public:
2049  DynamicsProcessor() {} /* C-TOR */
2050  ~DynamicsProcessor() {} /* D-TOR */
2051 
2052 public:
2054  virtual bool reset(double _sampleRate)
2055  {
2056  sidechainInputSample = 0.0;
2057  detector.reset(_sampleRate);
2058  AudioDetectorParameters detectorParams = detector.getParameters();
2059  detectorParams.clampToUnityMax = false;
2060  detectorParams.detect_dB = true;
2061  detector.setParameters(detectorParams);
2062  return true;
2063  }
2064 
2066  virtual bool canProcessAudioFrame() { return false; }
2067 
2070 
2072  virtual double processAuxInputAudioSample(double xn)
2073  {
2074  sidechainInputSample = xn;
2075  return sidechainInputSample;
2076  }
2077 
2083 
2089  {
2090  parameters = _parameters;
2091 
2092  AudioDetectorParameters detectorParams = detector.getParameters();
2093  detectorParams.attackTime_mSec = parameters.attackTime_mSec;
2094  detectorParams.releaseTime_mSec = parameters.releaseTime_mSec;
2095  detector.setParameters(detectorParams);
2096  }
2097 
2099  /*
2100  1. detect input signal
2101  2. calculate gain
2102  3. apply to input sample
2103  */
2108  virtual double processAudioSample(double xn)
2109  {
2110  // --- detect input
2111  double detect_dB = 0.0;
2112 
2113  // --- if using the sidechain, process the aux input
2116  else
2117  detect_dB = detector.processAudioSample(xn);
2118 
2119  // --- compute gain
2120  double gr = computeGain(detect_dB);
2121 
2122  // --- makeup gain
2123  double makeupGain = pow(10.0, parameters.outputGain_dB / 20.0);
2124 
2125  // --- do DCA + makeup gain
2126  return xn * gr * makeupGain;
2127  }
2128 
2129 protected:
2132 
2133  // --- storage for sidechain audio input (mono only)
2134  double sidechainInputSample = 0.0;
2135 
2137  inline double computeGain(double detect_dB)
2138  {
2139  double output_dB = 0.0;
2140 
2141  if (parameters.calculation == dynamicsProcessorType::kCompressor)
2142  {
2143  // --- hard knee
2144  if (!parameters.softKnee)
2145  {
2146  // --- below threshold, unity
2147  if (detect_dB <= parameters.threshold_dB)
2148  output_dB = detect_dB;
2149  else// --- above threshold, compress
2150  {
2151  if (parameters.hardLimitGate) // is limiter?
2152  output_dB = parameters.threshold_dB;
2153  else
2154  output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) / parameters.ratio;
2155  }
2156  }
2157  else // --- calc gain with knee
2158  {
2159  // --- left side of knee, outside of width, unity gain zone
2160  if (2.0*(detect_dB - parameters.threshold_dB) < -parameters.kneeWidth_dB)
2161  output_dB = detect_dB;
2162  // --- else inside the knee,
2163  else if (2.0*(fabs(detect_dB - parameters.threshold_dB)) <= parameters.kneeWidth_dB)
2164  {
2165  if (parameters.hardLimitGate) // --- is limiter?
2166  output_dB = detect_dB - pow((detect_dB - parameters.threshold_dB + (parameters.kneeWidth_dB / 2.0)), 2.0) / (2.0*parameters.kneeWidth_dB);
2167  else // --- 2nd order poly
2168  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);
2169  }
2170  // --- right of knee, compression zone
2171  else if (2.0*(detect_dB - parameters.threshold_dB) > parameters.kneeWidth_dB)
2172  {
2173  if (parameters.hardLimitGate) // --- is limiter?
2174  output_dB = parameters.threshold_dB;
2175  else
2176  output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) / parameters.ratio;
2177  }
2178  }
2179  }
2180  else if (parameters.calculation == dynamicsProcessorType::kDownwardExpander)
2181  {
2182  // --- hard knee
2183  // --- NOTE: soft knee is not technically possible with a gate because there
2184  // is no "left side" of the knee
2186  {
2187  // --- above threshold, unity gain
2188  if (detect_dB >= parameters.threshold_dB)
2189  output_dB = detect_dB;
2190  else
2191  {
2192  if (parameters.hardLimitGate) // --- gate: -inf(dB)
2193  output_dB = -1.0e34;
2194  else
2195  output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) * parameters.ratio;
2196  }
2197  }
2198  else // --- calc gain with knee
2199  {
2200  // --- right side of knee, unity gain zone
2201  if (2.0*(detect_dB - parameters.threshold_dB) > parameters.kneeWidth_dB)
2202  output_dB = detect_dB;
2203  // --- in the knee
2204  else if (2.0*(fabs(detect_dB - parameters.threshold_dB)) > -parameters.kneeWidth_dB)
2205  output_dB = ((parameters.ratio - 1.0) * pow((detect_dB - parameters.threshold_dB - (parameters.kneeWidth_dB / 2.0)), 2.0)) / (2.0*parameters.kneeWidth_dB);
2206  // --- left side of knee, downward expander zone
2207  else if (2.0*(detect_dB - parameters.threshold_dB) <= -parameters.kneeWidth_dB)
2208  output_dB = parameters.threshold_dB + (detect_dB - parameters.threshold_dB) * parameters.ratio;
2209  }
2210  }
2211 
2212  // --- convert gain; store values for user meters
2213  parameters.gainReduction_dB = output_dB - detect_dB;
2214  parameters.gainReduction = pow(10.0, (parameters.gainReduction_dB) / 20.0);
2215 
2216  // --- the current gain coefficient value
2217  return parameters.gainReduction;
2218  }
2219 };
2220 
2232 template <typename T>
2234 {
2235 public:
2236  LinearBuffer() {} /* C-TOR */
2237  ~LinearBuffer() {} /* D-TOR */
2238 
2240  void flushBuffer() { memset(&buffer[0], 0, bufferLength * sizeof(T)); }
2241 
2244  void createLinearBuffer(unsigned int _bufferLength)
2245  {
2246  // --- find nearest power of 2 for buffer, save it as bufferLength
2247  bufferLength = _bufferLength;
2248 
2249  // --- create new buffer
2250  buffer.reset(new T[bufferLength]);
2251 
2252  // --- flush buffer
2253  flushBuffer();
2254  }
2255 
2257  void writeBuffer(unsigned int index, T input)
2258  {
2259  if (index >= bufferLength) return;
2260 
2261  // --- write and increment index counter
2262  buffer[index] = input;
2263  }
2264 
2266  T readBuffer(unsigned int index)//, bool readBeforeWrite = true)
2267  {
2268  if (index >= bufferLength) return 0.0;
2269 
2270  // --- read it
2271  return buffer[index];
2272  }
2273 
2274 private:
2275  std::unique_ptr<T[]> buffer = nullptr;
2276  unsigned int bufferLength = 1024;
2277 };
2278 
2279 
2294 template <typename T>
2296 {
2297 public:
2298  CircularBuffer() {} /* C-TOR */
2299  ~CircularBuffer() {} /* D-TOR */
2300 
2302  void flushBuffer(){ memset(&buffer[0], 0, bufferLength * sizeof(T)); }
2303 
2306  void createCircularBuffer(unsigned int _bufferLength)
2307  {
2308  // --- find nearest power of 2 for buffer, and create
2309  createCircularBufferPowerOfTwo((unsigned int)(pow(2, ceil(log(_bufferLength) / log(2)))));
2310  }
2311 
2314  void createCircularBufferPowerOfTwo(unsigned int _bufferLengthPowerOfTwo)
2315  {
2316  // --- reset to top
2317  writeIndex = 0;
2318 
2319  // --- find nearest power of 2 for buffer, save it as bufferLength
2320  bufferLength = _bufferLengthPowerOfTwo;
2321 
2322  // --- save (bufferLength - 1) for use as wrapping mask
2323  wrapMask = bufferLength - 1;
2324 
2325  // --- create new buffer
2326  buffer.reset(new T[bufferLength]);
2327 
2328  // --- flush buffer
2329  flushBuffer();
2330  }
2331 
2333  void writeBuffer(T input)
2334  {
2335  // --- write and increment index counter
2336  buffer[writeIndex++] = input;
2337 
2338  // --- wrap if index > bufferlength - 1
2339  writeIndex &= wrapMask;
2340  }
2341 
2343  T readBuffer(int delayInSamples)//, bool readBeforeWrite = true)
2344  {
2345  // --- subtract to make read index
2346  // note: -1 here is because we read-before-write,
2347  // so the *last* write location is what we use for the calculation
2348  int readIndex = (writeIndex - 1) - delayInSamples;
2349 
2350  // --- autowrap index
2351  readIndex &= wrapMask;
2352 
2353  // --- read it
2354  return buffer[readIndex];
2355  }
2356 
2358  T readBuffer(double delayInFractionalSamples)
2359  {
2360  // --- truncate delayInFractionalSamples and read the int part
2361  T y1 = readBuffer((int)delayInFractionalSamples);
2362 
2363  // --- if no interpolation, just return value
2364  if (!interpolate) return y1;
2365 
2366  // --- else do interpolation
2367  //
2368  // --- read the sample at n+1 (one sample OLDER)
2369  T y2 = readBuffer((int)delayInFractionalSamples + 1);
2370 
2371  // --- get fractional part
2372  double fraction = delayInFractionalSamples - (int)delayInFractionalSamples;
2373 
2374  // --- do the interpolation (you could try different types here)
2375  return doLinearInterpolation(y1, y2, fraction);
2376  }
2377 
2379  void setInterpolate(bool b) { interpolate = b; }
2380 
2381 private:
2382  std::unique_ptr<T[]> buffer = nullptr;
2383  unsigned int writeIndex = 0;
2384  unsigned int bufferLength = 1024;
2385  unsigned int wrapMask = 1023;
2386  bool interpolate = true;
2387 };
2388 
2389 
2409 {
2410 public:
2411  ImpulseConvolver() {
2412  init(512);
2413  } /* C-TOR */
2414  ~ImpulseConvolver() {} /* D-TOR */
2415 
2417  virtual bool reset(double _sampleRate)
2418  {
2419  // --- flush signal buffer; IR buffer is static
2421  return true;
2422  }
2423 
2429  virtual double processAudioSample(double xn)
2430  {
2431  double output = 0.0;
2432 
2433  // --- write buffer; x(n) overwrites oldest value
2434  // this is the only time we do not read before write!
2436 
2437  // --- do the convolution
2438  for (unsigned int i = 0; i < length; i++)
2439  {
2440  // --- y(n) += x(n)h(n)
2441  // for signalBuffer.readBuffer(0) -> x(n)
2442  // signalBuffer.readBuffer(n-D)-> x(n-D)
2443  double signal = signalBuffer.readBuffer((int)i);
2444  double irrrrr = irBuffer.readBuffer((int)i);
2445  output += signal*irrrrr;
2446 
2447  //output += signalBuffer.readBuffer((int)i) * irBuffer.readBuffer((int)i);
2448  }
2449 
2450  return output;
2451  }
2452 
2454  virtual bool canProcessAudioFrame() { return false; }
2455 
2457  void init(unsigned int lengthPowerOfTwo)
2458  {
2459  length = lengthPowerOfTwo;
2460  // --- create (and clear out) the buffers
2461  signalBuffer.createCircularBufferPowerOfTwo(lengthPowerOfTwo);
2462  irBuffer.createLinearBuffer(lengthPowerOfTwo);
2463  }
2464 
2466  void setImpulseResponse(double* irArray, unsigned int lengthPowerOfTwo)
2467  {
2468  if (lengthPowerOfTwo != length)
2469  {
2470  length = lengthPowerOfTwo;
2471  // --- create (and clear out) the buffers
2472  signalBuffer.createCircularBufferPowerOfTwo(lengthPowerOfTwo);
2473  irBuffer.createLinearBuffer(lengthPowerOfTwo);
2474  }
2475 
2476  // --- load up the IR buffer
2477  for (unsigned int i = 0; i < length; i++)
2478  {
2479  irBuffer.writeBuffer(i, irArray[i]);
2480  }
2481  }
2482 
2483 protected:
2484  // --- delay buffer of doubles
2487 
2488  unsigned int length = 0;
2489 
2490 };
2491 
2492 const unsigned int IR_LEN = 512;
2507 {
2510  AnalogFIRFilterParameters& operator=(const AnalogFIRFilterParameters& params) // need this override for collections to work
2511  {
2512  if (this == &params)
2513  return *this;
2514 
2515  filterType = params.filterType;
2516  fc = params.fc;
2517  Q = params.Q;
2518 
2519  return *this;
2520  }
2521 
2522  // --- individual parameters
2523  analogFilter filterType = analogFilter::kLPF1;
2524  double fc = 0.0;
2525  double Q = 0.0;
2526 };
2527 
2548 {
2549 public:
2550  AnalogFIRFilter() {} /* C-TOR */
2551  ~AnalogFIRFilter() {} /* D-TOR */
2552 
2553 public:
2555  virtual bool reset(double _sampleRate)
2556  {
2557  sampleRate = _sampleRate;
2558  convolver.reset(_sampleRate);
2559  convolver.init(IR_LEN);
2560  return true;
2561  }
2562 
2568  virtual double processAudioSample(double xn)
2569  {
2570  // --- do the linear convolution
2571  return convolver.processAudioSample(xn);
2572  }
2573 
2575  virtual bool canProcessAudioFrame() { return false; }
2576 
2581  AnalogFIRFilterParameters getParameters() { return parameters; }
2582 
2588  {
2589  if (_parameters.fc != parameters.fc ||
2590  _parameters.Q != parameters.Q ||
2591  _parameters.filterType != parameters.filterType)
2592  {
2593  // --- set the filter IR for the convolver
2594  AnalogMagData analogFilterData;
2595  analogFilterData.sampleRate = sampleRate;
2596  analogFilterData.magArray = &analogMagArray[0];
2597  analogFilterData.dftArrayLen = IR_LEN;
2598  analogFilterData.mirrorMag = false;
2599 
2600  analogFilterData.filterType = _parameters.filterType;
2601  analogFilterData.fc = _parameters.fc; // 1000.0;
2602  analogFilterData.Q = _parameters.Q;
2603 
2604  // --- calculate the analog mag array
2605  calculateAnalogMagArray(analogFilterData);
2606 
2607  // --- frequency sample the mag array
2608  freqSample(IR_LEN, analogMagArray, irArray, POSITIVE);
2609 
2610  // --- update new frequency response
2611  convolver.setImpulseResponse(irArray, IR_LEN);
2612  }
2613 
2614  parameters = _parameters;
2615  }
2616 
2617 private:
2618  AnalogFIRFilterParameters parameters;
2619  ImpulseConvolver convolver;
2620  double analogMagArray[IR_LEN] = { 0.0 };
2621  double irArray[IR_LEN] = { 0.0 };
2622  double sampleRate = 0.0;
2623 };
2624 
2638 enum class delayAlgorithm { kNormal, kPingPong };
2639 
2654 enum class delayUpdateType { kLeftAndRight, kLeftPlusRatio };
2655 
2656 
2669 {
2672  AudioDelayParameters& operator=(const AudioDelayParameters& params) // need this override for collections to work
2673  {
2674  if (this == &params)
2675  return *this;
2676 
2677  algorithm = params.algorithm;
2678  wetLevel_dB = params.wetLevel_dB;
2679  dryLevel_dB = params.dryLevel_dB;
2680  feedback_Pct = params.feedback_Pct;
2681 
2682  updateType = params.updateType;
2683  leftDelay_mSec = params.leftDelay_mSec;
2685  delayRatio_Pct = params.delayRatio_Pct;
2686 
2687  return *this;
2688  }
2689 
2690  // --- individual parameters
2691  delayAlgorithm algorithm = delayAlgorithm::kNormal;
2692  double wetLevel_dB = -3.0;
2693  double dryLevel_dB = -3.0;
2694  double feedback_Pct = 0.0;
2695 
2696  delayUpdateType updateType = delayUpdateType::kLeftAndRight;
2697  double leftDelay_mSec = 0.0;
2698  double rightDelay_mSec = 0.0;
2699  double delayRatio_Pct = 100.0;
2700 };
2701 
2720 {
2721 public:
2722  AudioDelay() {} /* C-TOR */
2723  ~AudioDelay() {} /* D-TOR */
2724 
2725 public:
2727  virtual bool reset(double _sampleRate)
2728  {
2729  // --- if sample rate did not change
2730  if (sampleRate == _sampleRate)
2731  {
2732  // --- just flush buffer and return
2733  delayBuffer_L.flushBuffer();
2734  delayBuffer_R.flushBuffer();
2735  return true;
2736  }
2737 
2738  // --- create new buffer, will store sample rate and length(mSec)
2739  createDelayBuffers(_sampleRate, bufferLength_mSec);
2740 
2741  return true;
2742  }
2743 
2749  virtual double processAudioSample(double xn)
2750  {
2751  // --- read delay
2752  double yn = delayBuffer_L.readBuffer(delayInSamples_L);
2753 
2754  // --- create input for delay buffer
2755  double dn = xn + (parameters.feedback_Pct / 100.0) * yn;
2756 
2757  // --- write to delay buffer
2758  delayBuffer_L.writeBuffer(dn);
2759 
2760  // --- form mixture out = dry*xn + wet*yn
2761  double output = dryMix*xn + wetMix*yn;
2762 
2763  return output;
2764  }
2765 
2767  virtual bool canProcessAudioFrame() { return true; }
2768 
2770  virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
2771  float* outputFrame,
2772  uint32_t inputChannels,
2773  uint32_t outputChannels)
2774  {
2775  // --- make sure we have input and outputs
2776  if (inputChannels == 0 || outputChannels == 0)
2777  return false;
2778 
2779  // --- make sure we support this delay algorithm
2780  if (parameters.algorithm != delayAlgorithm::kNormal &&
2781  parameters.algorithm != delayAlgorithm::kPingPong)
2782  return false;
2783 
2784  // --- if only one output channel, revert to mono operation
2785  if (outputChannels == 1)
2786  {
2787  // --- process left channel only
2788  outputFrame[0] = processAudioSample(inputFrame[0]);
2789  return true;
2790  }
2791 
2792  // --- if we get here we know we have 2 output channels
2793  //
2794  // --- pick up inputs
2795  //
2796  // --- LEFT channel
2797  double xnL = inputFrame[0];
2798 
2799  // --- RIGHT channel (duplicate left input if mono-in)
2800  double xnR = inputChannels > 1 ? inputFrame[1] : xnL;
2801 
2802  // --- read delay LEFT
2803  double ynL = delayBuffer_L.readBuffer(delayInSamples_L);
2804 
2805  // --- read delay RIGHT
2806  double ynR = delayBuffer_R.readBuffer(delayInSamples_R);
2807 
2808  // --- create input for delay buffer with LEFT channel info
2809  double dnL = xnL + (parameters.feedback_Pct / 100.0) * ynL;
2810 
2811  // --- create input for delay buffer with RIGHT channel info
2812  double dnR = xnR + (parameters.feedback_Pct / 100.0) * ynR;
2813 
2814  // --- decode
2815  if (parameters.algorithm == delayAlgorithm::kNormal)
2816  {
2817  // --- write to LEFT delay buffer with LEFT channel info
2818  delayBuffer_L.writeBuffer(dnL);
2819 
2820  // --- write to RIGHT delay buffer with RIGHT channel info
2821  delayBuffer_R.writeBuffer(dnR);
2822  }
2823  else if (parameters.algorithm == delayAlgorithm::kPingPong)
2824  {
2825  // --- write to LEFT delay buffer with RIGHT channel info
2826  delayBuffer_L.writeBuffer(dnR);
2827 
2828  // --- write to RIGHT delay buffer with LEFT channel info
2829  delayBuffer_R.writeBuffer(dnL);
2830  }
2831 
2832  // --- form mixture out = dry*xn + wet*yn
2833  double outputL = dryMix*xnL + wetMix*ynL;
2834 
2835  // --- form mixture out = dry*xn + wet*yn
2836  double outputR = dryMix*xnR + wetMix*ynR;
2837 
2838  // --- set left channel
2839  outputFrame[0] = outputL;
2840 
2841  // --- set right channel
2842  outputFrame[1] = outputR;
2843 
2844  return true;
2845  }
2846 
2851  AudioDelayParameters getParameters() { return parameters; }
2852 
2858  {
2859  // --- check mix in dB for calc
2860  if (_parameters.dryLevel_dB != parameters.dryLevel_dB)
2861  dryMix = pow(10.0, _parameters.dryLevel_dB / 20.0);
2862  if (_parameters.wetLevel_dB != parameters.wetLevel_dB)
2863  wetMix = pow(10.0, _parameters.wetLevel_dB / 20.0);
2864 
2865  // --- save; rest of updates are cheap on CPU
2866  parameters = _parameters;
2867 
2868  // --- check update type first:
2869  if (parameters.updateType == delayUpdateType::kLeftAndRight)
2870  {
2871  // --- set left and right delay times
2872  // --- calculate total delay time in samples + fraction
2873  double newDelayInSamples_L = parameters.leftDelay_mSec*(samplesPerMSec);
2874  double newDelayInSamples_R = parameters.rightDelay_mSec*(samplesPerMSec);
2875 
2876  // --- new delay time with fraction
2877  delayInSamples_L = newDelayInSamples_L;
2878  delayInSamples_R = newDelayInSamples_R;
2879  }
2880  else if (parameters.updateType == delayUpdateType::kLeftPlusRatio)
2881  {
2882  // --- get and validate ratio
2883  double delayRatio = parameters.delayRatio_Pct / 100.0;
2884  boundValue(delayRatio, 0.0, 1.0);
2885 
2886  // --- calculate total delay time in samples + fraction
2887  double newDelayInSamples = parameters.leftDelay_mSec*(samplesPerMSec);
2888 
2889  // --- new delay time with fraction
2890  delayInSamples_L = newDelayInSamples;
2891  delayInSamples_R = delayInSamples_L*delayRatio;
2892  }
2893  }
2894 
2896  void createDelayBuffers(double _sampleRate, double _bufferLength_mSec)
2897  {
2898  // --- store for math
2899  bufferLength_mSec = _bufferLength_mSec;
2900  sampleRate = _sampleRate;
2901  samplesPerMSec = sampleRate / 1000.0;
2902 
2903  // --- total buffer length including fractional part
2904  bufferLength = (unsigned int)(bufferLength_mSec*(samplesPerMSec)) + 1; // +1 for fractional part
2905 
2906  // --- create new buffer
2907  delayBuffer_L.createCircularBuffer(bufferLength);
2908  delayBuffer_R.createCircularBuffer(bufferLength);
2909  }
2910 
2911 private:
2912  AudioDelayParameters parameters;
2913 
2914  double sampleRate = 0.0;
2915  double samplesPerMSec = 0.0;
2916  double delayInSamples_L = 0.0;
2917  double delayInSamples_R = 0.0;
2918  double bufferLength_mSec = 0.0;
2919  unsigned int bufferLength = 0;
2920  double wetMix = 0.707;
2921  double dryMix = 0.707;
2922 
2923  // --- delay buffer of doubles
2924  CircularBuffer<double> delayBuffer_L;
2925  CircularBuffer<double> delayBuffer_R;
2926 };
2927 
2928 
2942 enum class generatorWaveform { kTriangle, kSin, kSaw };
2943 
2956 {
2959  OscillatorParameters& operator=(const OscillatorParameters& params) // need this override for collections to work
2960  {
2961  if (this == &params)
2962  return *this;
2963 
2964  waveform = params.waveform;
2965  frequency_Hz = params.frequency_Hz;
2966  return *this;
2967  }
2968 
2969  // --- individual parameters
2970  generatorWaveform waveform = generatorWaveform::kTriangle;
2971  double frequency_Hz = 0.0;
2972 };
2973 
2993 {
2994 public:
2995  LFO() { srand(time(NULL)); } /* C-TOR */
2996  virtual ~LFO() {} /* D-TOR */
2997 
2999  virtual bool reset(double _sampleRate)
3000  {
3001  sampleRate = _sampleRate;
3003 
3004  // --- timebase variables
3005  modCounter = 0.0;
3006  modCounterQP = 0.25;
3007 
3008  return true;
3009  }
3010 
3016 
3022  {
3024  // --- update phase inc based on osc freq and fs
3025  phaseInc = params.frequency_Hz / sampleRate;
3026 
3027  lfoParameters = params;
3028  }
3029 
3031  virtual const SignalGenData renderAudioOutput();
3032 
3033 protected:
3034  // --- parameters
3036 
3037  // --- sample rate
3038  double sampleRate = 0.0;
3039 
3040  // --- timebase variables
3041  double modCounter = 0.0;
3042  double phaseInc = 0.0;
3043  double modCounterQP = 0.25;
3044 
3046  inline bool checkAndWrapModulo(double& moduloCounter, double phaseInc)
3047  {
3048  // --- for positive frequencies
3049  if (phaseInc > 0 && moduloCounter >= 1.0)
3050  {
3051  moduloCounter -= 1.0;
3052  return true;
3053  }
3054 
3055  // --- for negative frequencies
3056  if (phaseInc < 0 && moduloCounter <= 0.0)
3057  {
3058  moduloCounter += 1.0;
3059  return true;
3060  }
3061 
3062  return false;
3063  }
3064 
3066  inline bool advanceAndCheckWrapModulo(double& moduloCounter, double phaseInc)
3067  {
3068  // --- advance counter
3069  moduloCounter += phaseInc;
3070 
3071  // --- for positive frequencies
3072  if (phaseInc > 0 && moduloCounter >= 1.0)
3073  {
3074  moduloCounter -= 1.0;
3075  return true;
3076  }
3077 
3078  // --- for negative frequencies
3079  if (phaseInc < 0 && moduloCounter <= 0.0)
3080  {
3081  moduloCounter += 1.0;
3082  return true;
3083  }
3084 
3085  return false;
3086  }
3087 
3089  inline void advanceModulo(double& moduloCounter, double phaseInc) { moduloCounter += phaseInc; }
3090 
3091  const double B = 4.0 / kPi;
3092  const double C = -4.0 / (kPi* kPi);
3093  const double P = 0.225;
3095  inline double parabolicSine(double angle)
3096  {
3097  double y = B * angle + C * angle * fabs(angle);
3098  y = P * (y * fabs(y) - y) + y;
3099  return y;
3100  }
3101 };
3102 
3116 enum DFOscillatorCoeffs { df_b1, df_b2, numDFOCoeffs };
3117 
3131 enum DFOscillatorStates { df_yz1, df_yz2, numDFOStates };
3132 
3133 
3153 {
3154 public:
3155  DFOscillator() { } /* C-TOR */
3156  virtual ~DFOscillator() {} /* D-TOR */
3157 
3159  virtual bool reset(double _sampleRate)
3160  {
3161  sampleRate = _sampleRate;
3162  memset(&stateArray[0], 0, sizeof(double)*numDFOStates);
3163  updateDFO();
3164  return true;
3165  }
3166 
3172  {
3173  return parameters;
3174  }
3175 
3181  {
3182  if (parameters.frequency_Hz != params.frequency_Hz)
3183  {
3184  parameters = params;
3185  updateDFO();
3186  }
3187  }
3188 
3191  {
3192  // --- calculates normal and inverted outputs; quadphase are not used
3193  SignalGenData output;
3194 
3195  // -- do difference equation y(n) = -b1y(n-2) - b2y(n-2)
3196  output.normalOutput = (-coeffArray[df_b1]*stateArray[df_yz1] - coeffArray[df_b2]*stateArray[df_yz2]);
3197  output.invertedOutput = -output.normalOutput;
3198 
3199  // --- update states
3200  stateArray[df_yz2] = stateArray[df_yz1];
3201  stateArray[df_yz1] = output.normalOutput;
3202 
3203  return output;
3204  }
3205 
3207  void updateDFO()
3208  {
3209  // --- Oscillation Rate = theta = wT = w/fs
3210  double wT = (kTwoPi*parameters.frequency_Hz) / sampleRate;
3211 
3212  // --- coefficients to place poles right on unit circle
3213  coeffArray[df_b1] = -2.0*cos(wT); // <--- set angle a = -2Rcod(theta)
3214  coeffArray[df_b2] = 1.0; // <--- R^2 = 1, so R = 1
3215 
3216  // --- now update states to reflect the new frequency
3217  // re calculate the new initial conditions
3218  // arcsine of y(n-1) gives us wnT
3219  double wnT1 = asin(stateArray[df_yz1]);
3220 
3221  // find n by dividing wnT by wT
3222  double n = wnT1 / wT;
3223 
3224  // --- re calculate the new initial conditions
3225  // asin returns values from -pi/2 to +pi/2 where the sinusoid
3226  // moves from -1 to +1 -- the leading (rising) edge of the
3227  // sinewave. If we are on that leading edge (increasing)
3228  // then we use the value 1T behind.
3229  //
3230  // If we are on the falling edge, we use the value 1T ahead
3231  // because it mimics the value that would be 1T behind
3232  if (stateArray[df_yz1] > stateArray[df_yz2])
3233  n -= 1;
3234  else
3235  n += 1;
3236 
3237  // --- calculate the new (old) sample
3238  stateArray[df_yz2] = sin((n)*wT);
3239  }
3240 
3241 
3242 protected:
3243  // --- parameters
3245 
3246  // --- implementation of half a biquad - this object is extremely specific
3247  double stateArray[numDFOStates] = { 0.0 };
3248  double coeffArray[numDFOCoeffs] = { 0.0 };
3249 
3250  // --- sample rate
3251  double sampleRate = 0.0;
3252 };
3253 
3254 
3268 enum class modDelaylgorithm { kFlanger, kChorus, kVibrato };
3269 
3270 
3283 {
3286  ModulatedDelayParameters& operator=(const ModulatedDelayParameters& params) // need this override for collections to work
3287  {
3288  if (this == &params)
3289  return *this;
3290 
3291  algorithm = params.algorithm;
3292  lfoRate_Hz = params.lfoRate_Hz;
3293  lfoDepth_Pct = params.lfoDepth_Pct;
3294  feedback_Pct = params.feedback_Pct;
3295  return *this;
3296  }
3297 
3298  // --- individual parameters
3299  modDelaylgorithm algorithm = modDelaylgorithm::kFlanger;
3300  double lfoRate_Hz = 0.0;
3301  double lfoDepth_Pct = 0.0;
3302  double feedback_Pct = 0.0;
3303 };
3304 
3323 {
3324 public:
3325  ModulatedDelay() {
3326  } /* C-TOR */
3327  ~ModulatedDelay() {} /* D-TOR */
3328 
3329 public:
3331  virtual bool reset(double _sampleRate)
3332  {
3333  // --- create new buffer, 100mSec long
3334  delay.reset(_sampleRate);
3335  delay.createDelayBuffers(_sampleRate, 100.0);
3336 
3337  // --- lfo
3338  lfo.reset(_sampleRate);
3339  OscillatorParameters params = lfo.getParameters();
3340  params.waveform = generatorWaveform::kTriangle;
3341  lfo.setParameters(params);
3342 
3343  return true;
3344  }
3345 
3351  virtual double processAudioSample(double xn)
3352  {
3353  float input = xn;
3354  float output = 0.0;
3355  processAudioFrame(&input, &output, 1, 1);
3356  return output;
3357  }
3358 
3360  virtual bool canProcessAudioFrame() { return true; }
3361 
3363  virtual bool processAudioFrame(const float* inputFrame, /* ptr to one frame of data: pInputFrame[0] = left, pInputFrame[1] = right, etc...*/
3364  float* outputFrame,
3365  uint32_t inputChannels,
3366  uint32_t outputChannels)
3367  {
3368  // --- make sure we have input and outputs
3369  if (inputChannels == 0 || outputChannels == 0)
3370  return false;
3371 
3372  // --- render LFO
3373  SignalGenData lfoOutput = lfo.renderAudioOutput();
3374 
3375  // --- setup delay modulation
3376  AudioDelayParameters params = delay.getParameters();
3377  double minDelay_mSec = 0.0;
3378  double maxDepth_mSec = 0.0;
3379 
3380  // --- set delay times, wet/dry and feedback
3381  if (parameters.algorithm == modDelaylgorithm::kFlanger)
3382  {
3383  minDelay_mSec = 0.1;
3384  maxDepth_mSec = 7.0;
3385  params.wetLevel_dB = -3.0;
3386  params.dryLevel_dB = -3.0;
3387  }
3388  if (parameters.algorithm == modDelaylgorithm::kChorus)
3389  {
3390  minDelay_mSec = 10.0;
3391  maxDepth_mSec = 30.0;
3392  params.wetLevel_dB = -3.0;
3393  params.dryLevel_dB = -0.0;
3394  params.feedback_Pct = 0.0;
3395  }
3396  if (parameters.algorithm == modDelaylgorithm::kVibrato)
3397  {
3398  minDelay_mSec = 0.0;
3399  maxDepth_mSec = 7.0;
3400  params.wetLevel_dB = 0.0;
3401  params.dryLevel_dB = -96.0;
3402  params.feedback_Pct = 0.0;
3403  }
3404 
3405  // --- calc modulated delay times
3406  double depth = parameters.lfoDepth_Pct / 100.0;
3407  double modulationMin = minDelay_mSec;
3408  double modulationMax = minDelay_mSec + maxDepth_mSec;
3409 
3410  // --- flanger - unipolar
3411  if (parameters.algorithm == modDelaylgorithm::kFlanger)
3413  modulationMin, modulationMax);
3414  else
3415  params.leftDelay_mSec = doBipolarModulation(depth * lfoOutput.normalOutput, modulationMin, modulationMax);
3416 
3417 
3418  // --- set right delay to match (*Hint Homework!)
3419  params.rightDelay_mSec = params.leftDelay_mSec;
3420 
3421  // --- modulate the delay
3422  delay.setParameters(params);
3423 
3424  // --- just call the function and pass our info in/out
3425  return delay.processAudioFrame(inputFrame, outputFrame, inputChannels, outputChannels);
3426  }
3427 
3432  ModulatedDelayParameters getParameters() { return parameters; }
3433 
3439  {
3440  // --- bulk copy
3441  parameters = _parameters;
3442 
3443  OscillatorParameters lfoParams = lfo.getParameters();
3444  lfoParams.frequency_Hz = parameters.lfoRate_Hz;
3445  if (parameters.algorithm == modDelaylgorithm::kVibrato)
3446  lfoParams.waveform = generatorWaveform::kSin;
3447  else
3448  lfoParams.waveform = generatorWaveform::kTriangle;
3449 
3450  lfo.setParameters(lfoParams);
3451 
3452  AudioDelayParameters adParams = delay.getParameters();
3453  adParams.feedback_Pct = parameters.feedback_Pct;
3454  delay.setParameters(adParams);
3455  }
3456 
3457 private:
3458  ModulatedDelayParameters parameters;
3459  AudioDelay delay;
3460  LFO lfo;
3461 };
3462 
3475 {
3479  {
3480  if (this == &params)
3481  return *this;
3482 
3483  lfoRate_Hz = params.lfoRate_Hz;
3484  lfoDepth_Pct = params.lfoDepth_Pct;
3485  intensity_Pct = params.intensity_Pct;
3486  quadPhaseLFO = params.quadPhaseLFO;
3487  return *this;
3488  }
3489 
3490  // --- individual parameters
3491  double lfoRate_Hz = 0.0;
3492  double lfoDepth_Pct = 0.0;
3493  double intensity_Pct = 0.0;
3494  bool quadPhaseLFO = false;
3495 };
3496 
3497 // --- constants for Phaser
3498 const unsigned int PHASER_STAGES = 6;
3499 
3500 // --- these are the ideal band definitions
3501 //const double apf0_minF = 16.0;
3502 //const double apf0_maxF = 1600.0;
3503 //
3504 //const double apf1_minF = 33.0;
3505 //const double apf1_maxF = 3300.0;
3506 //
3507 //const double apf2_minF = 48.0;
3508 //const double apf2_maxF = 4800.0;
3509 //
3510 //const double apf3_minF = 98.0;
3511 //const double apf3_maxF = 9800.0;
3512 //
3513 //const double apf4_minF = 160.0;
3514 //const double apf4_maxF = 16000.0;
3515 //
3516 //const double apf5_minF = 260.0;
3517 //const double apf5_maxF = 20480.0;
3518 
3519 // --- these are the exact values from the National Semiconductor Phaser design
3520 const double apf0_minF = 32.0;
3521 const double apf0_maxF = 1500.0;
3522 
3523 const double apf1_minF = 68.0;
3524 const double apf1_maxF = 3400.0;
3525 
3526 const double apf2_minF = 96.0;
3527 const double apf2_maxF = 4800.0;
3528 
3529 const double apf3_minF = 212.0;
3530 const double apf3_maxF = 10000.0;
3531 
3532 const double apf4_minF = 320.0;
3533 const double apf4_maxF = 16000.0;
3534 
3535 const double apf5_minF = 636.0;
3536 const double apf5_maxF = 20480.0;
3537 
3556 {
3557 public:
3558  PhaseShifter(void) {
3559  OscillatorParameters lfoparams = lfo.getParameters();
3560  lfoparams.waveform = generatorWaveform::kTriangle; // kTriangle LFO for phaser
3561  // lfoparams.waveform = generatorWaveform::kSin; // kTriangle LFO for phaser
3562  lfo.setParameters(lfoparams);
3563 
3564  AudioFilterParameters params = apf[0].getParameters();
3565  params.algorithm = filterAlgorithm::kAPF1; // can also use 2nd order
3566  // params.Q = 0.001; use low Q if using 2nd order APFs
3567 
3568  for (int i = 0; i < PHASER_STAGES; i++)
3569  {
3570  apf[i].setParameters(params);
3571  }
3572  } /* C-TOR */
3573 
3574  ~PhaseShifter(void) {} /* D-TOR */
3575 
3576 public:
3578  virtual bool reset(double _sampleRate)
3579  {
3580  // --- reset LFO
3581  lfo.reset(_sampleRate);
3582 
3583  // --- reset APFs
3584  for (int i = 0; i < PHASER_STAGES; i++){
3585  apf[i].reset(_sampleRate);
3586  }
3587 
3588  return true;
3589  }
3590 
3596  virtual double processAudioSample(double xn)
3597  {
3598  SignalGenData lfoData = lfo.renderAudioOutput();
3599 
3600  // --- create the bipolar modulator value
3601  double lfoValue = lfoData.normalOutput;
3603  lfoValue = lfoData.quadPhaseOutput_pos;
3604 
3605  double depth = parameters.lfoDepth_Pct / 100.0;
3606  double modulatorValue = lfoValue*depth;
3607 
3608  // --- calculate modulated values for each APF; note they have different ranges
3609  AudioFilterParameters params = apf[0].getParameters();
3610  params.fc = doBipolarModulation(modulatorValue, apf0_minF, apf0_maxF);
3611  apf[0].setParameters(params);
3612 
3613  params = apf[1].getParameters();
3614  params.fc = doBipolarModulation(modulatorValue, apf1_minF, apf1_maxF);
3615  apf[1].setParameters(params);
3616 
3617  params = apf[2].getParameters();
3618  params.fc = doBipolarModulation(modulatorValue, apf2_minF, apf2_maxF);
3619  apf[2].setParameters(params);
3620 
3621  params = apf[3].getParameters();
3622  params.fc = doBipolarModulation(modulatorValue, apf3_minF, apf3_maxF);
3623  apf[3].setParameters(params);
3624 
3625  params = apf[4].getParameters();
3626  params.fc = doBipolarModulation(modulatorValue, apf4_minF, apf4_maxF);
3627  apf[4].setParameters(params);
3628 
3629  params = apf[5].getParameters();
3630  params.fc = doBipolarModulation(modulatorValue, apf5_minF, apf5_maxF);
3631  apf[5].setParameters(params);
3632 
3633  // --- calculate gamma values
3634  double gamma1 = apf[5].getG_value();
3635  double gamma2 = apf[4].getG_value() * gamma1;
3636  double gamma3 = apf[3].getG_value() * gamma2;
3637  double gamma4 = apf[2].getG_value() * gamma3;
3638  double gamma5 = apf[1].getG_value() * gamma4;
3639  double gamma6 = apf[0].getG_value() * gamma5;
3640 
3641  // --- set the alpha0 value
3642  double K = parameters.intensity_Pct / 100.0;
3643  double alpha0 = 1.0 / (1.0 + K*gamma6);
3644 
3645  // --- create combined feedback
3646  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();
3647 
3648  // --- form input to first APF
3649  double u = alpha0*(xn + K*Sn);
3650 
3651  // --- cascade of APFs (could also nest these in one massive line of code)
3652  double APF1 = apf[0].processAudioSample(u);
3653  double APF2 = apf[1].processAudioSample(APF1);
3654  double APF3 = apf[2].processAudioSample(APF2);
3655  double APF4 = apf[3].processAudioSample(APF3);
3656  double APF5 = apf[4].processAudioSample(APF4);
3657  double APF6 = apf[5].processAudioSample(APF5);
3658 
3659  // --- sum with -3dB coefficients
3660  // double output = 0.707*xn + 0.707*APF6;
3661 
3662  // --- sum with National Semiconductor design ratio:
3663  // dry = 0.5, wet = 5.0
3664  // double output = 0.5*xn + 5.0*APF6;
3665  // double output = 0.25*xn + 2.5*APF6;
3666  double output = 0.125*xn + 1.25*APF6;
3667 
3668  return output;
3669  }
3670 
3672  virtual bool canProcessAudioFrame() { return false; }
3673 
3679 
3685  {
3686  // --- update LFO rate
3687  if (params.lfoRate_Hz != parameters.lfoRate_Hz)
3688  {
3689  OscillatorParameters lfoparams = lfo.getParameters();
3690  lfoparams.frequency_Hz = params.lfoRate_Hz;
3691  lfo.setParameters(lfoparams);
3692  }
3693 
3694  // --- save new
3695  parameters = params;
3696  }
3697 protected:
3699  AudioFilter apf[PHASER_STAGES];
3701 };
3702 
3715 {
3716  SimpleLPFParameters() {}
3718  SimpleLPFParameters& operator=(const SimpleLPFParameters& params) // need this override for collections to work
3719  {
3720  if (this == &params)
3721  return *this;
3722 
3723  g = params.g;
3724  return *this;
3725  }
3726 
3727  // --- individual parameters
3728  double g = 0.0;
3729 };
3730 
3749 {
3750 public:
3751  SimpleLPF(void) {} /* C-TOR */
3752  ~SimpleLPF(void) {} /* D-TOR */
3753 
3754 public:
3756  virtual bool reset(double _sampleRate)
3757  {
3758  state = 0.0;
3759  return true;
3760  }
3761 
3767  {
3768  return simpleLPFParameters;
3769  }
3770 
3776  {
3777  simpleLPFParameters = params;
3778  }
3779 
3785  virtual double processAudioSample(double xn)
3786  {
3787  double g = simpleLPFParameters.g;
3788  double yn = (1.0 - g)*xn + g*state;
3789  state = yn;
3790  return yn;
3791  }
3792 
3794  virtual bool canProcessAudioFrame() { return false; }
3795 
3796 private:
3797  SimpleLPFParameters simpleLPFParameters;
3798  double state = 0.0;
3799 };
3800 
3813 {
3816  SimpleDelayParameters& operator=(const SimpleDelayParameters& params) // need this override for collections to work
3817  {
3818  if (this == &params)
3819  return *this;
3820 
3821  delayTime_mSec = params.delayTime_mSec;
3822  interpolate = params.interpolate;
3823  delay_Samples = params.delay_Samples;
3824  return *this;
3825  }
3826 
3827  // --- individual parameters
3828  double delayTime_mSec = 0.0;
3829  bool interpolate = false;
3830 
3831  // --- outbound parameters
3832  double delay_Samples = 0.0;
3833 };
3834 
3853 {
3854 public:
3855  SimpleDelay(void) {} /* C-TOR */
3856  ~SimpleDelay(void) {} /* D-TOR */
3857 
3858 public:
3860  virtual bool reset(double _sampleRate)
3861  {
3862  // --- if sample rate did not change
3863  if (sampleRate == _sampleRate)
3864  {
3865  // --- just flush buffer and return
3866  delayBuffer.flushBuffer();
3867  return true;
3868  }
3869 
3870  // --- create new buffer, will store sample rate and length(mSec)
3871  createDelayBuffer(_sampleRate, bufferLength_mSec);
3872 
3873  return true;
3874  }
3875 
3881  {
3882  return simpleDelayParameters;
3883  }
3884 
3890  {
3891  simpleDelayParameters = params;
3892  simpleDelayParameters.delay_Samples = simpleDelayParameters.delayTime_mSec*(samplesPerMSec);
3893  delayBuffer.setInterpolate(simpleDelayParameters.interpolate);
3894  }
3895 
3901  virtual double processAudioSample(double xn)
3902  {
3903  // --- read delay
3904  if (simpleDelayParameters.delay_Samples == 0)
3905  return xn;
3906 
3907  double yn = delayBuffer.readBuffer(simpleDelayParameters.delay_Samples);
3908 
3909  // --- write to delay buffer
3910  delayBuffer.writeBuffer(xn);
3911 
3912  // --- done
3913  return yn;
3914  }
3915 
3917  virtual bool canProcessAudioFrame() { return false; }
3918 
3920  void createDelayBuffer(double _sampleRate, double _bufferLength_mSec)
3921  {
3922  // --- store for math
3923  bufferLength_mSec = _bufferLength_mSec;
3924  sampleRate = _sampleRate;
3925  samplesPerMSec = sampleRate / 1000.0;
3926 
3927  // --- total buffer length including fractional part
3928  bufferLength = (unsigned int)(bufferLength_mSec*(samplesPerMSec)) + 1; // +1 for fractional part
3929 
3930  // --- create new buffer
3931  delayBuffer.createCircularBuffer(bufferLength);
3932  }
3933 
3935  double readDelay()
3936  {
3937  // --- simple read
3938  return delayBuffer.readBuffer(simpleDelayParameters.delay_Samples);
3939  }
3940 
3942  double readDelayAtTime_mSec(double _delay_mSec)
3943  {
3944  // --- calculate total delay time in samples + fraction
3945  double _delay_Samples = _delay_mSec*(samplesPerMSec);
3946 
3947  // --- simple read
3948  return delayBuffer.readBuffer(_delay_Samples);
3949  }
3950 
3952  double readDelayAtPercentage(double delayPercent)
3953  {
3954  // --- simple read
3955  return delayBuffer.readBuffer((delayPercent / 100.0)*simpleDelayParameters.delay_Samples);
3956  }
3957 
3959  void writeDelay(double xn)
3960  {
3961  // --- simple write
3962  delayBuffer.writeBuffer(xn);
3963  }
3964 
3965 private:
3966  SimpleDelayParameters simpleDelayParameters;
3967 
3968  double sampleRate = 0.0;
3969  double samplesPerMSec = 0.0;
3970  double bufferLength_mSec = 0.0;
3971  unsigned int bufferLength = 0;
3972 
3973  // --- delay buffer of doubles
3974  CircularBuffer<double> delayBuffer;
3975 };
3976 
3977 
3990 {
3993  CombFilterParameters& operator=(const CombFilterParameters& params) // need this override for collections to work
3994  {
3995  if (this == &params)
3996  return *this;
3997 
3998  delayTime_mSec = params.delayTime_mSec;
3999  RT60Time_mSec = params.RT60Time_mSec;
4000  enableLPF = params.enableLPF;
4001  lpf_g = params.lpf_g;
4002  interpolate = params.interpolate;
4003  return *this;
4004  }
4005 
4006  // --- individual parameters
4007  double delayTime_mSec = 0.0;
4008  double RT60Time_mSec = 0.0;
4009  bool enableLPF = false;
4010  double lpf_g = 0.0;
4011  bool interpolate = false;
4012 };
4013 
4014 
4033 {
4034 public:
4035  CombFilter(void) {} /* C-TOR */
4036  ~CombFilter(void) {} /* D-TOR */
4037 
4038 public:
4040  virtual bool reset(double _sampleRate)
4041  {
4042  // --- flush
4043  lpf_state = 0.0;
4044 
4045  // --- create new buffer, will store sample rate and length(mSec)
4046  createDelayBuffer(sampleRate, bufferLength_mSec);
4047 
4048  return true;
4049  }
4050 
4056  virtual double processAudioSample(double xn)
4057  {
4058  double yn = delay.readDelay();
4059  double input = 0.0;
4060 
4061  // --- form input & write
4062  if (combFilterParameters.enableLPF)
4063  {
4064  // --- apply simple 1st order pole LPF
4065  double g2 = lpf_g*(1.0 - comb_g); // see book for equation 11.27 (old book)
4066  double filteredSignal = yn + g2*lpf_state;
4067  input = xn + comb_g*(filteredSignal);
4068  lpf_state = filteredSignal;
4069  }
4070  else
4071  {
4072  input = xn + comb_g*yn;
4073  }
4074 
4075  delay.writeDelay(input);
4076 
4077  // --- done
4078  return yn;
4079  }
4080 
4082  virtual bool canProcessAudioFrame() { return false; }
4083 
4089  {
4090  return combFilterParameters;
4091  }
4092 
4098  {
4099  combFilterParameters = params;
4100 
4101  // --- update the delay line parameters first
4102  SimpleDelayParameters delayParams = delay.getParameters();
4103  delayParams.delayTime_mSec = combFilterParameters.delayTime_mSec;
4104  delayParams.interpolate = combFilterParameters.interpolate;
4105  delay.setParameters(delayParams); // this will set the delay time in samples
4106 
4107  // --- calculate g with RT60 time (requires updated delay above^^)
4108  double exponent = -3.0*delayParams.delay_Samples*(1.0 / sampleRate);
4109  double rt60_mSec = combFilterParameters.RT60Time_mSec / 1000.0; // RT is in mSec!
4110  comb_g = pow(10.0, exponent / rt60_mSec);
4111 
4112  // --- set LPF g
4113  lpf_g = combFilterParameters.lpf_g;
4114  }
4115 
4117  void createDelayBuffer(double _sampleRate, double delay_mSec)
4118  {
4119  sampleRate = _sampleRate;
4120  bufferLength_mSec = delay_mSec;
4121 
4122  // --- create new buffer, will store sample rate and length(mSec)
4123  delay.createDelayBuffer(_sampleRate, delay_mSec);
4124  }
4125 
4126 private:
4127  CombFilterParameters combFilterParameters;
4128  double sampleRate = 0.0;
4129  double comb_g = 0.0;
4130  double bufferLength_mSec = 0.0;
4131 
4132  // --- LPF support
4133  double lpf_g = 0.0;
4134  double lpf_state = 0.0;
4135 
4136  // --- delay buffer of doubles
4137  SimpleDelay delay;
4138 };
4139 
4152 {
4153  DelayAPFParameters() {}
4155  DelayAPFParameters& operator=(const DelayAPFParameters& params) // need this override for collections to work
4156  {
4157  if (this == &params)
4158  return *this;
4159 
4160  delayTime_mSec = params.delayTime_mSec;
4161  apf_g = params.apf_g;
4162  enableLPF = params.enableLPF;
4163  lpf_g = params.lpf_g;
4164  interpolate = params.interpolate;
4165  enableLFO = params.enableLFO;
4166  lfoRate_Hz = params.lfoRate_Hz;
4167  lfoDepth = params.lfoDepth;
4169  return *this;
4170  }
4171 
4172  // --- individual parameters
4173  double delayTime_mSec = 0.0;
4174  double apf_g = 0.0;
4175  bool enableLPF = false;
4176  double lpf_g = 0.0;
4177  bool interpolate = false;
4178  bool enableLFO = false;
4179  double lfoRate_Hz = 0.0;
4180  double lfoDepth = 0.0;
4181  double lfoMaxModulation_mSec = 0.0;
4182 
4183 };
4184 
4203 {
4204 public:
4205  DelayAPF(void) {} /* C-TOR */
4206  ~DelayAPF(void) {} /* D-TOR */
4207 
4208 public:
4210  virtual bool reset(double _sampleRate)
4211  {
4212  // --- reset children
4213  modLFO.reset(_sampleRate);
4214 
4215  // --- flush
4216  lpf_state = 0.0;
4217 
4218  // --- create new buffer, will store sample rate and length(mSec)
4220 
4221  return true;
4222  }
4223 
4229  virtual double processAudioSample(double xn)
4230  {
4231  SimpleDelayParameters delayParams = delay.getParameters();
4232  if (delayParams.delay_Samples == 0)
4233  return xn;
4234 
4235  // --- delay line output
4236  double wnD = 0.0;
4237  double apf_g = delayAPFParameters.apf_g;
4238  double lpf_g = delayAPFParameters.lpf_g;
4239  double lfoDepth = delayAPFParameters.lfoDepth;
4240 
4241  // --- for modulated APFs
4243  {
4244  SignalGenData lfoOutput = modLFO.renderAudioOutput();
4245  double maxDelay = delayParams.delayTime_mSec;
4246  double minDelay = maxDelay - delayAPFParameters.lfoMaxModulation_mSec;
4247  minDelay = fmax(0.0, minDelay); // bound minDelay to 0 as minimum
4248 
4249  // --- calc max-down modulated value with unipolar converted LFO output
4250  // NOTE: LFO output is scaled by lfoDepth
4251  double modDelay_mSec = doUnipolarModulationFromMax(bipolarToUnipolar(lfoDepth*lfoOutput.normalOutput),
4252  minDelay, maxDelay);
4253 
4254  // --- read modulated value to get w(n-D);
4255  wnD = delay.readDelayAtTime_mSec(modDelay_mSec);
4256  }
4257  else
4258  // --- read the delay line to get w(n-D)
4259  wnD = delay.readDelay();
4260 
4262  {
4263  // --- apply simple 1st order pole LPF, overwrite wnD
4264  wnD = wnD*(1.0 - lpf_g) + lpf_g*lpf_state;
4265  lpf_state = wnD;
4266  }
4267 
4268  // form w(n) = x(n) + gw(n-D)
4269  double wn = xn + apf_g*wnD;
4270 
4271  // form y(n) = -gw(n) + w(n-D)
4272  double yn = -apf_g*wn + wnD;
4273 
4274  // underflow check
4275  checkFloatUnderflow(yn);
4276 
4277  // write delay line
4278  delay.writeDelay(wn);
4279 
4280  return yn;
4281  }
4282 
4284  virtual bool canProcessAudioFrame() { return false; }
4285 
4291  {
4292  return delayAPFParameters;
4293  }
4294 
4299  void setParameters(const DelayAPFParameters& params)
4300  {
4301  delayAPFParameters = params;
4302 
4303  // --- update delay line
4304  SimpleDelayParameters delayParams = delay.getParameters();
4306  delay.setParameters(delayParams);
4307  }
4308 
4310  void createDelayBuffer(double _sampleRate, double delay_mSec)
4311  {
4312  sampleRate = _sampleRate;
4313  bufferLength_mSec = delay_mSec;
4314 
4315  // --- create new buffer, will store sample rate and length(mSec)
4316  delay.createDelayBuffer(_sampleRate, delay_mSec);
4317  }
4318 
4319 protected:
4320  // --- component parameters
4322  double sampleRate = 0.0;
4323  double bufferLength_mSec = 0.0;
4324 
4325  // --- delay buffer of doubles
4327 
4328  // --- optional LFO
4330 
4331  // --- LPF support
4332  double lpf_state = 0.0;
4333 };
4334 
4335 
4348 {
4351  NestedDelayAPFParameters& operator=(const NestedDelayAPFParameters& params) // need this override for collections to work
4352  {
4353  if (this == &params)
4354  return *this;
4355 
4358  outerAPF_g = params.outerAPF_g;
4359  innerAPF_g = params.innerAPF_g;
4360 
4361  // --- outer LFO
4362  enableLFO = params.enableLFO;
4363  lfoRate_Hz = params.lfoRate_Hz;
4364  lfoDepth = params.lfoDepth;
4366 
4367  return *this;
4368  }
4369 
4370  // --- individual parameters
4371  double outerAPFdelayTime_mSec = 0.0;
4372  double innerAPFdelayTime_mSec = 0.0;
4373  double outerAPF_g = 0.0;
4374  double innerAPF_g = 0.0;
4375 
4376  // --- this LFO belongs to the outer APF only
4377  bool enableLFO = false;
4378  double lfoRate_Hz = 0.0;
4379  double lfoDepth = 1.0;
4380  double lfoMaxModulation_mSec = 0.0;
4381 
4382 };
4383 
4403 class NestedDelayAPF : public DelayAPF
4404 {
4405 public:
4406  NestedDelayAPF(void) { } /* C-TOR */
4407  ~NestedDelayAPF(void) { } /* D-TOR */
4408 
4409 public:
4411  virtual bool reset(double _sampleRate)
4412  {
4413  // --- call base class reset first
4414  DelayAPF::reset(_sampleRate);
4415 
4416  // --- then do our stuff
4417  nestedAPF.reset(_sampleRate);
4418 
4419  return true;
4420  }
4421 
4427  virtual double processAudioSample(double xn)
4428  {
4429  // --- delay line output
4430  double wnD = 0.0;
4431 
4432  SimpleDelayParameters delayParams = delay.getParameters();
4433  if (delayParams.delay_Samples == 0)
4434  return xn;
4435 
4436  double apf_g = delayAPFParameters.apf_g;
4437  double lpf_g = delayAPFParameters.lpf_g;
4438 
4439  // --- for modulated APFs
4441  {
4442  SignalGenData lfoOutput = modLFO.renderAudioOutput();
4443  double maxDelay = delayParams.delayTime_mSec;
4444  double minDelay = maxDelay - delayAPFParameters.lfoMaxModulation_mSec;
4445  minDelay = fmax(0.0, minDelay); // bound minDelay to 0 as minimum
4446  double lfoDepth = delayAPFParameters.lfoDepth;
4447 
4448  // --- calc max-down modulated value with unipolar converted LFO output
4449  // NOTE: LFO output is scaled by lfoDepth
4450  double modDelay_mSec = doUnipolarModulationFromMax(bipolarToUnipolar(lfoDepth*lfoOutput.normalOutput),
4451  minDelay, maxDelay);
4452 
4453  // --- read modulated value to get w(n-D);
4454  wnD = delay.readDelayAtTime_mSec(modDelay_mSec);
4455  }
4456  else
4457  // --- read the delay line to get w(n-D)
4458  wnD = delay.readDelay();
4459 
4461  {
4462  // --- apply simple 1st order pole LPF, overwrite wnD
4463  wnD = wnD*(1.0 - lpf_g) + lpf_g*lpf_state;
4464  lpf_state = wnD;
4465  }
4466 
4467  // --- form w(n) = x(n) + gw(n-D)
4468  double wn = xn + apf_g*wnD;
4469 
4470  // --- process wn through inner APF
4471  double ynInner = nestedAPF.processAudioSample(wn);
4472 
4473  // --- form y(n) = -gw(n) + w(n-D)
4474  double yn = -apf_g*wn + wnD;
4475 
4476  // --- underflow check
4477  checkFloatUnderflow(yn);
4478 
4479  // --- write delay line
4480  delay.writeDelay(ynInner);
4481 
4482  return yn;
4483  }
4484 
4489  NestedDelayAPFParameters getParameters() { return nestedAPFParameters; }
4490 
4496  {
4497  nestedAPFParameters = params;
4498 
4499  DelayAPFParameters outerAPFParameters = DelayAPF::getParameters();
4500  DelayAPFParameters innerAPFParameters = nestedAPF.getParameters();
4501 
4502  // --- outer APF
4503  outerAPFParameters.apf_g = nestedAPFParameters.outerAPF_g;
4504  outerAPFParameters.delayTime_mSec = nestedAPFParameters.outerAPFdelayTime_mSec;
4505 
4506  // --- LFO support
4507  outerAPFParameters.enableLFO = nestedAPFParameters.enableLFO;
4508  outerAPFParameters.lfoDepth = nestedAPFParameters.lfoDepth;
4509  outerAPFParameters.lfoRate_Hz = nestedAPFParameters.lfoRate_Hz;
4510  outerAPFParameters.lfoMaxModulation_mSec = nestedAPFParameters.lfoMaxModulation_mSec;
4511 
4512  // --- inner APF
4513  innerAPFParameters.apf_g = nestedAPFParameters.innerAPF_g;
4514  innerAPFParameters.delayTime_mSec = nestedAPFParameters.innerAPFdelayTime_mSec;
4515 
4516  DelayAPF::setParameters(outerAPFParameters);
4517  nestedAPF.setParameters(innerAPFParameters);
4518  }
4519 
4521  void createDelayBuffers(double _sampleRate, double delay_mSec, double nestedAPFDelay_mSec)
4522  {
4523  // --- base class
4524  DelayAPF::createDelayBuffer(_sampleRate, delay_mSec);
4525 
4526  // --- then our stuff
4527  nestedAPF.createDelayBuffer(_sampleRate, nestedAPFDelay_mSec);
4528  }
4529 
4530 private:
4531  NestedDelayAPFParameters nestedAPFParameters;
4532  DelayAPF nestedAPF;
4533 };
4534 
4547 {
4550  TwoBandShelvingFilterParameters& operator=(const TwoBandShelvingFilterParameters& params) // need this override for collections to work
4551  {
4552  if (this == &params)
4553  return *this;
4554 
4555  lowShelf_fc = params.lowShelf_fc;
4557  highShelf_fc = params.highShelf_fc;
4559  return *this;
4560  }
4561 
4562  // --- individual parameters
4563  double lowShelf_fc = 0.0;
4564  double lowShelfBoostCut_dB = 0.0;
4565  double highShelf_fc = 0.0;
4566  double highShelfBoostCut_dB = 0.0;
4567 };
4568 
4587 {
4588 public:
4590  {
4591  AudioFilterParameters params = lowShelfFilter.getParameters();
4592  params.algorithm = filterAlgorithm::kLowShelf;
4593  lowShelfFilter.setParameters(params);
4594 
4595  params = highShelfFilter.getParameters();
4596  params.algorithm = filterAlgorithm::kHiShelf;
4597  highShelfFilter.setParameters(params);
4598  } /* C-TOR */
4599 
4600  ~TwoBandShelvingFilter() {} /* D-TOR */
4601 
4603  virtual bool reset(double _sampleRate)
4604  {
4605  lowShelfFilter.reset(_sampleRate);
4606  highShelfFilter.reset(_sampleRate);
4607  return true;
4608  }
4609 
4611  virtual bool canProcessAudioFrame() { return false; }
4612 
4618  virtual double processAudioSample(double xn)
4619  {
4620  // --- all modes do Full Wave Rectification
4621  double filteredSignal = lowShelfFilter.processAudioSample(xn);
4622  filteredSignal = highShelfFilter.processAudioSample(filteredSignal);
4623 
4624  return filteredSignal;
4625  }
4626 
4632  {
4633  return parameters;
4634  }
4635 
4641  {
4642  parameters = params;
4643  AudioFilterParameters filterParams = lowShelfFilter.getParameters();
4644  filterParams.fc = parameters.lowShelf_fc;
4645  filterParams.boostCut_dB = parameters.lowShelfBoostCut_dB;
4646  lowShelfFilter.setParameters(filterParams);
4647 
4648  filterParams = highShelfFilter.getParameters();
4649  filterParams.fc = parameters.highShelf_fc;
4650  filterParams.boostCut_dB = parameters.highShelfBoostCut_dB;
4651  highShelfFilter.setParameters(filterParams);
4652  }
4653 
4654 private:
4655  TwoBandShelvingFilterParameters parameters;
4656  AudioFilter lowShelfFilter;
4657  AudioFilter highShelfFilter;
4658 };
4659 
4673 enum class reverbDensity { kThick, kSparse };
4674 
4687 {
4690  ReverbTankParameters& operator=(const ReverbTankParameters& params) // need this override for collections to work
4691  {
4692  if (this == &params)
4693  return *this;
4694 
4695  density = params.density;
4696 
4697  // --- tweaker variables
4703 
4704  lpf_g = params.lpf_g;
4705  kRT = params.kRT;
4706 
4707  lowShelf_fc = params.lowShelf_fc;
4709  highShelf_fc = params.highShelf_fc;
4711 
4712  wetLevel_dB = params.wetLevel_dB;
4713  dryLevel_dB = params.dryLevel_dB;
4714  return *this;
4715  }
4716 
4717  // --- individual parameters
4718  reverbDensity density = reverbDensity::kThick;
4719 
4720  // --- tweaking parameters - you may not want to expose these
4721  // in the final plugin!
4722  // --- See the book for all the details on how these tweakers work!!
4723  double apfDelayMax_mSec = 5.0;
4724  double apfDelayWeight_Pct = 100.0;
4725  double fixeDelayMax_mSec = 50.0;
4726  double fixeDelayWeight_Pct = 100.0;
4727 
4728  // --- direct control parameters
4729  double preDelayTime_mSec = 0.0;
4730  double lpf_g = 0.0;
4731  double kRT = 0.0;
4732 
4733  double lowShelf_fc = 0.0;
4734  double lowShelfBoostCut_dB = 0.0;
4735  double highShelf_fc = 0.0;
4736  double highShelfBoostCut_dB = 0.0;
4737 
4738  double wetLevel_dB = -3.0;
4739  double dryLevel_dB = -3.0;
4740 };
4741 
4742 // --- constants for reverb tank
4743 const unsigned int NUM_BRANCHES = 4;
4744 const unsigned int NUM_CHANNELS = 2; // stereo
4745 
4764 {
4765 public:
4766  ReverbTank() {} /* C-TOR */
4767  ~ReverbTank() {} /* D-TOR */
4768 
4770  virtual bool reset(double _sampleRate)
4771  {
4772  // ---store
4773  sampleRate = _sampleRate;
4774 
4775  // ---set up preDelay
4776  preDelay.reset(_sampleRate);
4777  preDelay.createDelayBuffer(_sampleRate, 100.0);
4778 
4779  for (int i = 0; i < NUM_BRANCHES; i++)
4780  {
4781  branchDelays[i].reset(_sampleRate);
4782  branchDelays[i].createDelayBuffer(_sampleRate, 100.0);
4783 
4784  branchNestedAPFs[i].reset(_sampleRate);
4785  branchNestedAPFs[i].createDelayBuffers(_sampleRate, 100.0, 100.0);
4786 
4787  branchLPFs[i].reset(_sampleRate);
4788  }
4789  for (int i = 0; i < NUM_CHANNELS; i++)
4790  {
4791  shelvingFilters[i].reset(_sampleRate);
4792  }
4793 
4794  return true;
4795  }
4796 
4798  virtual bool canProcessAudioFrame() { return true; }
4799 
4805  virtual double processAudioSample(double xn)
4806  {
4807  float inputs[2] = { 0.0 };
4808  float outputs[2] = { 0.0 };
4809  processAudioFrame(inputs, outputs, 1, 1);
4810  return outputs[0];
4811  }
4812 
4814  virtual bool processAudioFrame(const float* inputFrame,
4815  float* outputFrame,
4816  uint32_t inputChannels,
4817  uint32_t outputChannels)
4818  {
4819  // --- global feedback from delay in last branch
4820  double globFB = branchDelays[NUM_BRANCHES-1].readDelay();
4821 
4822  // --- feedback value
4823  double fb = parameters.kRT*(globFB);
4824 
4825  // --- mono-ized input signal
4826  double xnL = inputFrame[0];
4827  double xnR = inputChannels > 1 ? inputFrame[1] : 0.0;
4828  double monoXn = double(1.0 / inputChannels)*xnL + double(1.0 / inputChannels)*xnR;
4829 
4830  // --- pre delay output
4831  double preDelayOut = preDelay.processAudioSample(monoXn);
4832 
4833  // --- input to first branch = preDalay + globFB
4834  double input = preDelayOut + fb;
4835  for (int i = 0; i < NUM_BRANCHES; i++)
4836  {
4837  double apfOut = branchNestedAPFs[i].processAudioSample(input);
4838  double lpfOut = branchLPFs[i].processAudioSample(apfOut);
4839  double delayOut = parameters.kRT*branchDelays[i].processAudioSample(lpfOut);
4840  input = delayOut + preDelayOut;
4841  }
4842  // --- gather outputs
4843  /*
4844  There are 25 prime numbers between 1 and 100.
4845  They are 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
4846  43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, and 97
4847 
4848  we want 16 of them: 23, 29, 31, 37, 41,
4849  43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, and 97
4850  */
4851 
4852  double weight = 0.707;
4853 
4854  double outL= 0.0;
4855  outL += weight*branchDelays[0].readDelayAtPercentage(23.0);
4856  outL -= weight*branchDelays[1].readDelayAtPercentage(41.0);
4857  outL += weight*branchDelays[2].readDelayAtPercentage(59.0);
4858  outL -= weight*branchDelays[3].readDelayAtPercentage(73.0);
4859 
4860  double outR = 0.0;
4861  outR -= weight*branchDelays[0].readDelayAtPercentage(29.0);
4862  outR += weight*branchDelays[1].readDelayAtPercentage(43.0);
4863  outR -= weight*branchDelays[2].readDelayAtPercentage(61.0);
4864  outR += weight*branchDelays[3].readDelayAtPercentage(79.0);
4865 
4866  if (parameters.density == reverbDensity::kThick)
4867  {
4868  outL += weight*branchDelays[0].readDelayAtPercentage(31.0);
4869  outL -= weight*branchDelays[1].readDelayAtPercentage(47.0);
4870  outL += weight*branchDelays[2].readDelayAtPercentage(67.0);
4871  outL -= weight*branchDelays[3].readDelayAtPercentage(83.0);
4872 
4873  outR -= weight*branchDelays[0].readDelayAtPercentage(37.0);
4874  outR += weight*branchDelays[1].readDelayAtPercentage(53.0);
4875  outR -= weight*branchDelays[2].readDelayAtPercentage(71.0);
4876  outR += weight*branchDelays[3].readDelayAtPercentage(89.0);
4877  }
4878 
4879  // --- filter
4880  double tankOutL = shelvingFilters[0].processAudioSample(outL);
4881  double tankOutR = shelvingFilters[1].processAudioSample(outR);
4882 
4883  // --- sum with dry
4884  double dry = pow(10.0, parameters.dryLevel_dB / 20.0);
4885  double wet = pow(10.0, parameters.wetLevel_dB / 20.0);
4886 
4887  if (outputChannels == 1)
4888  outputFrame[0] = dry*xnL + wet*(0.5*tankOutL + 0.5*tankOutR);
4889  else
4890  {
4891  outputFrame[0] = dry*xnL + wet*tankOutL;
4892  outputFrame[1] = dry*xnR + wet*tankOutR;
4893  }
4894 
4895  return true;
4896  }
4897 
4902  ReverbTankParameters getParameters() { return parameters; }
4903 
4909  {
4910  // --- do the updates here, the sub-components will only update themselves if
4911  // their parameters changed, so we let those object handle that chore
4912  TwoBandShelvingFilterParameters filterParams = shelvingFilters[0].getParameters();
4913  filterParams.highShelf_fc = params.highShelf_fc;
4914  filterParams.highShelfBoostCut_dB = params.highShelfBoostCut_dB;
4915  filterParams.lowShelf_fc = params.lowShelf_fc;
4916  filterParams.lowShelfBoostCut_dB = params.lowShelfBoostCut_dB;
4917 
4918  // --- copy to both channels
4919  shelvingFilters[0].setParameters(filterParams);
4920  shelvingFilters[1].setParameters(filterParams);
4921 
4922  SimpleLPFParameters lpfParams = branchLPFs[0].getParameters();
4923  lpfParams.g = params.lpf_g;
4924 
4925  for (int i = 0; i < NUM_BRANCHES; i++)
4926  {
4927  branchLPFs[i].setParameters(lpfParams);
4928  }
4929 
4930  // --- update pre delay
4931  SimpleDelayParameters delayParams = preDelay.getParameters();
4932  delayParams.delayTime_mSec = params.preDelayTime_mSec;
4933  preDelay.setParameters(delayParams);
4934 
4935  // --- set apf and delay parameters
4936  int m = 0;
4937  NestedDelayAPFParameters apfParams = branchNestedAPFs[0].getParameters();
4938  delayParams = branchDelays[0].getParameters();
4939 
4940  // --- global max Delay times
4941  double globalAPFMaxDelay = (parameters.apfDelayWeight_Pct / 100.0)*parameters.apfDelayMax_mSec;
4942  double globalFixedMaxDelay = (parameters.fixeDelayWeight_Pct / 100.0)*parameters.fixeDelayMax_mSec;
4943 
4944  // --- lfo
4945  apfParams.enableLFO = true;
4946  apfParams.lfoMaxModulation_mSec = 0.3;
4947  apfParams.lfoDepth = 1.0;
4948 
4949  for (int i = 0; i < NUM_BRANCHES; i++)
4950  {
4951  // --- setup APFs
4952  apfParams.outerAPFdelayTime_mSec = globalAPFMaxDelay*apfDelayWeight[m++];
4953  apfParams.innerAPFdelayTime_mSec = globalAPFMaxDelay*apfDelayWeight[m++];
4954  apfParams.innerAPF_g = -0.5;
4955  apfParams.outerAPF_g = 0.5;
4956  if (i == 0)
4957  apfParams.lfoRate_Hz = 0.15;
4958  else if (i == 1)
4959  apfParams.lfoRate_Hz = 0.33;
4960  else if (i == 2)
4961  apfParams.lfoRate_Hz = 0.57;
4962  else if (i == 3)
4963  apfParams.lfoRate_Hz = 0.73;
4964 
4965  branchNestedAPFs[i].setParameters(apfParams);
4966 
4967  // --- fixedDelayWeight
4968  delayParams.delayTime_mSec = globalFixedMaxDelay*fixedDelayWeight[i];
4969  branchDelays[i].setParameters(delayParams);
4970  }
4971 
4972  // --- save our copy
4973  parameters = params;
4974  }
4975 
4976 
4977 private:
4978  ReverbTankParameters parameters;
4979 
4980  SimpleDelay preDelay;
4981  SimpleDelay branchDelays[NUM_BRANCHES];
4982  NestedDelayAPF branchNestedAPFs[NUM_BRANCHES];
4983  SimpleLPF branchLPFs[NUM_BRANCHES];
4984 
4985  TwoBandShelvingFilter shelvingFilters[NUM_CHANNELS];
4986 
4987  // --- weighting values to make various and low-correlated APF delay values easily
4988  double apfDelayWeight[NUM_BRANCHES * 2] = { 0.317, 0.873, 0.477, 0.291, 0.993, 0.757, 0.179, 0.575 };
4989  double fixedDelayWeight[NUM_BRANCHES] = { 1.0, 0.873, 0.707, 0.667 };
4990  double sampleRate = 0.0;
4991 };
4992 
4993 
5014 {
5015 public:
5016  PeakLimiter() { setThreshold_dB(-3.0); }
5017  ~PeakLimiter() {}
5018 
5020  virtual bool reset(double _sampleRate)
5021  {
5022  // --- init; true = analog time-constant
5023  detector.setSampleRate(_sampleRate);
5024 
5025  AudioDetectorParameters detectorParams = detector.getParameters();
5026  detectorParams.detect_dB = true;
5027  detectorParams.attackTime_mSec = 5.0;
5028  detectorParams.releaseTime_mSec = 25.0;
5029  detectorParams.clampToUnityMax = false;
5030  detectorParams.detectMode = ENVELOPE_DETECT_MODE_PEAK;
5031  detector.setParameters(detectorParams);
5032 
5033  return true;
5034  }
5035 
5037  virtual bool canProcessAudioFrame() { return false; }
5038 
5044  virtual double processAudioSample(double xn)
5045  {
5047  }
5048 
5050  double computeGain(double detect_dB)
5051  {
5052  double output_dB = 0.0;
5053 
5054  // --- defaults - you can change these here
5055  bool softknee = true;
5056  double kneeWidth_dB = 10.0;
5057 
5058  // --- hard knee
5059  if (!softknee)
5060  {
5061  // --- below threshold, unity
5062  if (detect_dB <= threshold_dB)
5063  output_dB = detect_dB;
5064  // --- above threshold, compress
5065  else
5066  output_dB = threshold_dB;
5067  }
5068  else
5069  {
5070  // --- calc gain with knee
5071  // --- left side of knee, outside of width, unity gain zone
5072  if (2.0*(detect_dB - threshold_dB) < -kneeWidth_dB)
5073  output_dB = detect_dB;
5074  // --- inside the knee,
5075  else if (2.0*(fabs(detect_dB - threshold_dB)) <= kneeWidth_dB)
5076  output_dB = detect_dB - pow((detect_dB - threshold_dB + (kneeWidth_dB / 2.0)), 2.0) / (2.0*kneeWidth_dB);
5077  // --- right of knee, compression zone
5078  else if (2.0*(detect_dB - threshold_dB) > kneeWidth_dB)
5079  output_dB = threshold_dB;
5080  }
5081 
5082  // --- convert difference between threshold and detected to raw
5083  return pow(10.0, (output_dB - detect_dB) / 20.0);
5084  }
5085 
5087  void setThreshold_dB(double _threshold_dB) { threshold_dB = _threshold_dB; }
5088 
5090  void setMakeUpGain_dB(double _makeUpGain_dB) { makeUpGain_dB = _makeUpGain_dB; }
5091 
5092 protected:
5094  double threshold_dB = 0.0;
5095  double makeUpGain_dB = 0.0;
5096 };
5097 
5098 
5112 enum class vaFilterAlgorithm {
5113  kLPF1, kHPF1, kAPF1, kSVF_LP, kSVF_HP, kSVF_BP, kSVF_BS
5114 }; // --- you will add more here...
5115 
5116 
5129 {
5130  ZVAFilterParameters() {}
5132  ZVAFilterParameters& operator=(const ZVAFilterParameters& params) // need this override for collections to work
5133  {
5134  if (this == &params)
5135  return *this;
5136 
5138  fc = params.fc;
5139  Q = params.Q;
5141  enableGainComp = params.enableGainComp;
5143  selfOscillate = params.selfOscillate;
5144  enableNLP = params.enableNLP;
5145  return *this;
5146  }
5147 
5148  // --- individual parameters
5149  vaFilterAlgorithm filterAlgorithm = vaFilterAlgorithm::kSVF_LP;
5150  double fc = 1000.0;
5151  double Q = 0.707;
5152  double filterOutputGain_dB = 0.0;
5153  bool enableGainComp = false;
5154  bool matchAnalogNyquistLPF = false;
5155  bool selfOscillate = false;
5156  bool enableNLP = false;
5157 };
5158 
5159 
5177 {
5178 public:
5179  ZVAFilter() {} /* C-TOR */
5180  ~ZVAFilter() {} /* D-TOR */
5181 
5183  virtual bool reset(double _sampleRate)
5184  {
5185  sampleRate = _sampleRate;
5186  integrator_z[0] = 0.0;
5187  integrator_z[1] = 0.0;
5188 
5189  return true;
5190  }
5191 
5197  {
5198  return zvaFilterParameters;
5199  }
5200 
5206  {
5207  if (params.fc != zvaFilterParameters.fc ||
5208  params.Q != zvaFilterParameters.Q ||
5211  {
5212  zvaFilterParameters = params;
5214  }
5215  else
5216  zvaFilterParameters = params;
5217  }
5218 
5220  virtual bool canProcessAudioFrame() { return false; }
5221 
5227  virtual double processAudioSample(double xn)
5228  {
5229  // --- with gain comp enabled, we reduce the input by
5230  // half the gain in dB at resonant peak
5231  // NOTE: you can change that logic here!
5233  bool matchAnalogNyquistLPF = zvaFilterParameters.matchAnalogNyquistLPF;
5234 
5236  {
5237  double peak_dB = dBPeakGainFor_Q(zvaFilterParameters.Q);
5238  if (peak_dB > 0.0)
5239  {
5240  double halfPeak_dBGain = dB2Raw(-peak_dB / 2.0);
5241  xn *= halfPeak_dBGain;
5242  }
5243  }
5244 
5245  // --- for 1st order filters:
5246  if (filterAlgorithm == vaFilterAlgorithm::kLPF1 ||
5247  filterAlgorithm == vaFilterAlgorithm::kHPF1 ||
5248  filterAlgorithm == vaFilterAlgorithm::kAPF1)
5249  {
5250  // --- create vn node
5251  double vn = (xn - integrator_z[0])*alpha;
5252 
5253  // --- form LP output
5254  double lpf = ((xn - integrator_z[0])*alpha) + integrator_z[0];
5255 
5256  // double sn = integrator_z[0];
5257 
5258  // --- update memory
5259  integrator_z[0] = vn + lpf;
5260 
5261  // --- form the HPF = INPUT = LPF
5262  double hpf = xn - lpf;
5263 
5264  // --- form the APF = LPF - HPF
5265  double apf = lpf - hpf;
5266 
5267  // --- set the outputs
5268  if (filterAlgorithm == vaFilterAlgorithm::kLPF1)
5269  {
5270  // --- this is a very close match as-is at Nyquist!
5271  if (matchAnalogNyquistLPF)
5272  return lpf + alpha*hpf;
5273  else
5274  return lpf;
5275  }
5276  else if (filterAlgorithm == vaFilterAlgorithm::kHPF1)
5277  return hpf;
5278  else if (filterAlgorithm == vaFilterAlgorithm::kAPF1)
5279  return apf;
5280 
5281  // --- unknown filter
5282  return xn;
5283  }
5284 
5285  // --- form the HP output first
5286  double hpf = alpha0*(xn - rho*integrator_z[0] - integrator_z[1]);
5287 
5288  // --- BPF Out
5289  double bpf = alpha*hpf + integrator_z[0];
5291  bpf = softClipWaveShaper(bpf, 1.0);
5292 
5293  // --- LPF Out
5294  double lpf = alpha*bpf + integrator_z[1];
5295 
5296  // --- BSF Out
5297  double bsf = hpf + lpf;
5298 
5299  // --- finite gain at Nyquist; slight error at VHF
5300  double sn = integrator_z[0];
5301 
5302  // update memory
5303  integrator_z[0] = alpha*hpf + bpf;
5304  integrator_z[1] = alpha*bpf + lpf;
5305 
5306  double filterOutputGain = pow(10.0, zvaFilterParameters.filterOutputGain_dB / 20.0);
5307 
5308  // return our selected type
5309  if (filterAlgorithm == vaFilterAlgorithm::kSVF_LP)
5310  {
5311  if (matchAnalogNyquistLPF)
5312  lpf += analogMatchSigma*(sn);
5313  return filterOutputGain*lpf;
5314  }
5315  else if (filterAlgorithm == vaFilterAlgorithm::kSVF_HP)
5316  return filterOutputGain*hpf;
5317  else if (filterAlgorithm == vaFilterAlgorithm::kSVF_BP)
5318  return filterOutputGain*bpf;
5319  else if (filterAlgorithm == vaFilterAlgorithm::kSVF_BS)
5320  return filterOutputGain*bsf;
5321 
5322  // --- unknown filter
5323  return filterOutputGain*lpf;
5324  }
5325 
5328  {
5329  double fc = zvaFilterParameters.fc;
5330  double Q = zvaFilterParameters.Q;
5332 
5333  // --- normal Zavalishin SVF calculations here
5334  // prewarp the cutoff- these are bilinear-transform filters
5335  double wd = kTwoPi*fc;
5336  double T = 1.0 / sampleRate;
5337  double wa = (2.0 / T)*tan(wd*T / 2.0);
5338  double g = wa*T / 2.0;
5339 
5340  // --- for 1st order filters:
5341  if (filterAlgorithm == vaFilterAlgorithm::kLPF1 ||
5342  filterAlgorithm == vaFilterAlgorithm::kHPF1 ||
5343  filterAlgorithm == vaFilterAlgorithm::kAPF1)
5344  {
5345  // --- calculate alpha
5346  alpha = g / (1.0 + g);
5347  }
5348  else // state variable variety
5349  {
5350  // --- note R is the traditional analog damping factor zeta
5351  double R = zvaFilterParameters.selfOscillate ? 0.0 : 1.0 / (2.0*Q);
5352  alpha0 = 1.0 / (1.0 + 2.0*R*g + g*g);
5353  alpha = g;
5354  rho = 2.0*R + g;
5355 
5356  // --- sigma for analog matching version
5357  double f_o = (sampleRate / 2.0) / fc;
5358  analogMatchSigma = 1.0 / (alpha*f_o*f_o);
5359  }
5360  }
5361 
5363  void setBeta(double _beta) { beta = _beta; }
5364 
5366  double getBeta() { return beta; }
5367 
5368 protected:
5370  double sampleRate = 44100.0;
5371 
5372  // --- state storage
5373  double integrator_z[2];
5374 
5375  // --- filter coefficients
5376  double alpha0 = 0.0;
5377  double alpha = 0.0;
5378  double rho = 0.0;
5379 
5380  double beta = 0.0;
5381 
5382  // --- for analog Nyquist matching
5383  double analogMatchSigma = 0.0;
5384 
5385 };
5386 
5399 {
5402  EnvelopeFollowerParameters& operator=(const EnvelopeFollowerParameters& params) // need this override for collections to work
5403  {
5404  if (this == &params)
5405  return *this;
5406 
5407  fc = params.fc;
5408  Q = params.Q;
5411  threshold_dB = params.threshold_dB;
5412  sensitivity = params.sensitivity;
5413 
5414  return *this;
5415  }
5416 
5417  // --- individual parameters
5418  double fc = 0.0;
5419  double Q = 0.707;
5420  double attackTime_mSec = 10.0;
5421  double releaseTime_mSec = 10.0;
5422  double threshold_dB = 0.0;
5423  double sensitivity = 1.0;
5424 };
5425 
5445 {
5446 public:
5447  EnvelopeFollower() {
5448  // --- setup the filter
5449  ZVAFilterParameters filterParams;
5450  filterParams.filterAlgorithm = vaFilterAlgorithm::kSVF_LP;
5451  filterParams.fc = 1000.0;
5452  filterParams.enableGainComp = true;
5453  filterParams.enableNLP = true;
5454  filterParams.matchAnalogNyquistLPF = true;
5455  filter.setParameters(filterParams);
5456 
5457  // --- setup the detector
5458  AudioDetectorParameters adParams;
5459  adParams.attackTime_mSec = -1.0;
5460  adParams.releaseTime_mSec = -1.0;
5461  adParams.detectMode = TLD_AUDIO_DETECT_MODE_RMS;
5462  adParams.detect_dB = true;
5463  adParams.clampToUnityMax = false;
5464  detector.setParameters(adParams);
5465 
5466  } /* C-TOR */
5467  ~EnvelopeFollower() {} /* D-TOR */
5468 
5470  virtual bool reset(double _sampleRate)
5471  {
5472  filter.reset(_sampleRate);
5473  detector.reset(_sampleRate);
5474  return true;
5475  }
5476 
5482 
5488  {
5489  ZVAFilterParameters filterParams = filter.getParameters();
5491 
5492  if (params.fc != parameters.fc || params.Q != parameters.Q)
5493  {
5494  filterParams.fc = params.fc;
5495  filterParams.Q = params.Q;
5496  filter.setParameters(filterParams);
5497  }
5498  if (params.attackTime_mSec != parameters.attackTime_mSec ||
5500  {
5501  adParams.attackTime_mSec = params.attackTime_mSec;
5502  adParams.releaseTime_mSec = params.releaseTime_mSec;
5503  detector.setParameters(adParams);
5504  }
5505 
5506  // --- save
5507  parameters = params;
5508  }
5509 
5511  virtual bool canProcessAudioFrame() { return false; }
5512 
5518  virtual double processAudioSample(double xn)
5519  {
5520  // --- calc threshold
5521  double threshValue = pow(10.0, parameters.threshold_dB / 20.0);
5522 
5523  // --- detect the signal
5524  double detect_dB = detector.processAudioSample(xn);
5525  double detectValue = pow(10.0, detect_dB / 20.0);
5526  double deltaValue = detectValue - threshValue;
5527 
5528  ZVAFilterParameters filterParams = filter.getParameters();
5529  filterParams.fc = parameters.fc;
5530 
5531  // --- if above the threshold, modulate the filter fc
5532  if (deltaValue > 0.0)// || delta_dB > 0.0)
5533  {
5534  // --- fc Computer
5535  double modulatorValue = 0.0;
5536 
5537  // --- best results are with linear values when detector is in dB mode
5538  modulatorValue = (deltaValue * parameters.sensitivity);
5539 
5540  // --- calculate modulated frequency
5541  filterParams.fc = doUnipolarModulationFromMin(modulatorValue, parameters.fc, kMaxFilterFrequency);
5542  }
5543 
5544  // --- update with new modulated frequency
5545  filter.setParameters(filterParams);
5546 
5547  // --- perform the filtering operation
5548  return filter.processAudioSample(xn);
5549  }
5550 
5551 protected:
5553 
5554  // --- 1 filter and 1 detector
5557 };
5558 
5572 enum class distortionModel { kSoftClip, kArcTan, kFuzzAsym };
5573 
5586 {
5589  TriodeClassAParameters& operator=(const TriodeClassAParameters& params) // need this override for collections to work
5590  {
5591  if (this == &params)
5592  return *this;
5593 
5594  waveshaper = params.waveshaper;
5595  saturation = params.saturation;
5596  asymmetry = params.asymmetry;
5597  outputGain = params.outputGain;
5598 
5599  invertOutput = params.invertOutput;
5600  enableHPF = params.enableHPF;
5601  enableLSF = params.enableLSF;
5602 
5603  hpf_Fc = params.hpf_Fc;
5604  lsf_Fshelf = params.lsf_Fshelf;
5606 
5607  return *this;
5608  }
5609 
5610  // --- individual parameters
5611  distortionModel waveshaper = distortionModel::kSoftClip;
5612 
5613  double saturation = 1.0;
5614  double asymmetry = 0.0;
5615  double outputGain = 1.0;
5616 
5617  bool invertOutput = true;
5618  bool enableHPF = true;
5619  bool enableLSF = false;
5620 
5621  double hpf_Fc = 1.0;
5622  double lsf_Fshelf = 80.0;
5623  double lsf_BoostCut_dB = 0.0;
5624 };
5625 
5645 {
5646 public:
5647  TriodeClassA() {
5648  AudioFilterParameters params;
5649  params.algorithm = filterAlgorithm::kHPF1;
5650  params.fc = parameters.hpf_Fc;
5651  outputHPF.setParameters(params);
5652 
5653  params.algorithm = filterAlgorithm::kLowShelf;
5654  params.fc = parameters.lsf_Fshelf;
5656  outputLSF.setParameters(params);
5657  } /* C-TOR */
5658  ~TriodeClassA() {} /* D-TOR */
5659 
5661  virtual bool reset(double _sampleRate)
5662  {
5663  outputHPF.reset(_sampleRate);
5664  outputLSF.reset(_sampleRate);
5665 
5666  // ---
5667  return true;
5668  }
5669 
5675 
5681  {
5682  parameters = params;
5683 
5684  AudioFilterParameters filterParams;
5685  filterParams.algorithm = filterAlgorithm::kHPF1;
5686  filterParams.fc = parameters.hpf_Fc;
5687  outputHPF.setParameters(filterParams);
5688 
5689  filterParams.algorithm = filterAlgorithm::kLowShelf;
5690  filterParams.fc = parameters.lsf_Fshelf;
5691  filterParams.boostCut_dB = parameters.lsf_BoostCut_dB;
5692  outputLSF.setParameters(filterParams);
5693  }
5694 
5696  virtual bool canProcessAudioFrame() { return false; }
5697 
5703  virtual double processAudioSample(double xn)
5704  {
5705  // --- perform waveshaping
5706  double output = 0.0;
5707 
5708  if (parameters.waveshaper == distortionModel::kSoftClip)
5710  else if (parameters.waveshaper == distortionModel::kArcTan)
5711  output = atanWaveShaper(xn, parameters.saturation);
5712  else if (parameters.waveshaper == distortionModel::kFuzzAsym)
5714 
5715  // --- inversion, normal for plate of class A triode
5717  output *= -1.0;
5718 
5719  // --- Output (plate) capacitor = HPF, remove DC offset
5720  if (parameters.enableHPF)
5721  output = outputHPF.processAudioSample(output);
5722 
5723  // --- if cathode resistor bypass, will create low shelf
5724  if (parameters.enableLSF)
5725  output = outputLSF.processAudioSample(output);
5726 
5727  // --- final resistor divider/potentiometer
5728  output *= parameters.outputGain;
5729 
5730  return output;
5731  }
5732 
5733 protected:
5737 };
5738 
5739 const unsigned int NUM_TUBES = 4;
5740 
5753 {
5756  ClassATubePreParameters& operator=(const ClassATubePreParameters& params) // need this override for collections to work
5757  {
5758  if (this == &params)
5759  return *this;
5760 
5761  inputLevel_dB = params.inputLevel_dB;
5762  saturation = params.saturation;
5763  asymmetry = params.asymmetry;
5764  outputLevel_dB = params.outputLevel_dB;
5765 
5766  lowShelf_fc = params.lowShelf_fc;
5768  highShelf_fc = params.highShelf_fc;
5770 
5771  return *this;
5772  }
5773 
5774  // --- individual parameters
5775  double inputLevel_dB = 0.0;
5776  double saturation = 0.0;
5777  double asymmetry = 0.0;
5778  double outputLevel_dB = 0.0;
5779 
5780  // --- shelving filter params
5781  double lowShelf_fc = 0.0;
5782  double lowShelfBoostCut_dB = 0.0;
5783  double highShelf_fc = 0.0;
5784  double highShelfBoostCut_dB = 0.0;
5785 
5786 };
5787 
5806 {
5807 public:
5808  ClassATubePre() {} /* C-TOR */
5809  ~ClassATubePre() {} /* D-TOR */
5810 
5812  virtual bool reset(double _sampleRate)
5813  {
5814  TriodeClassAParameters tubeParams = triodes[0].getParameters();
5815  tubeParams.invertOutput = true;
5816  tubeParams.enableHPF = true; // remove DC offsets
5817  tubeParams.outputGain = 1.0;
5818  tubeParams.saturation = 1.0;
5819  tubeParams.asymmetry = 0.0;
5820  tubeParams.enableLSF = true;
5821  tubeParams.lsf_Fshelf = 88.0;
5822  tubeParams.lsf_BoostCut_dB = -12.0;
5823  tubeParams.waveshaper = distortionModel::kFuzzAsym;
5824 
5825  for (int i = 0; i < NUM_TUBES; i++)
5826  {
5827  triodes[i].reset(_sampleRate);
5828  triodes[i].setParameters(tubeParams);
5829  }
5830 
5831  shelvingFilter.reset(_sampleRate);
5832 
5833  return true;
5834  }
5835 
5841 
5847  {
5848  // --- check for re-calc
5849  if (params.inputLevel_dB != parameters.inputLevel_dB)
5850  inputLevel = pow(10.0, params.inputLevel_dB / 20.0);
5852  outputLevel = pow(10.0, params.outputLevel_dB / 20.0);
5853 
5854  // --- store
5855  parameters = params;
5856 
5857  // --- shelving filter update
5859  sfParams.lowShelf_fc = parameters.lowShelf_fc;
5863  shelvingFilter.setParameters(sfParams);
5864 
5865  // --- triode updates
5866  TriodeClassAParameters tubeParams = triodes[0].getParameters();
5867  tubeParams.saturation = parameters.saturation;
5868  tubeParams.asymmetry = parameters.asymmetry;
5869 
5870  for (int i = 0; i < NUM_TUBES; i++)
5871  triodes[i].setParameters(tubeParams);
5872  }
5873 
5875  virtual bool canProcessAudioFrame() { return false; }
5876 
5882  virtual double processAudioSample(double xn)
5883  {
5884  double output1 = triodes[0].processAudioSample(xn*inputLevel);
5885  double output2 = triodes[1].processAudioSample(output1);
5886  double output3 = triodes[2].processAudioSample(output2);
5887 
5888  // --- filter stage is between 3 and 4
5889  double outputEQ = shelvingFilter.processAudioSample(output3);
5890  double output4 = triodes[3].processAudioSample(outputEQ);
5891 
5892  return output4*outputLevel;
5893  }
5894 
5895 protected:
5897  TriodeClassA triodes[NUM_TUBES];
5899 
5900  double inputLevel = 1.0;
5901  double outputLevel = 1.0;
5902 };
5903 
5904 
5917 {
5920  BitCrusherParameters& operator=(const BitCrusherParameters& params) // need this override for collections to work
5921  {
5922  if (this == &params)
5923  return *this;
5924 
5926 
5927  return *this;
5928  }
5929 
5930  double quantizedBitDepth = 4.0;
5931 };
5932 
5951 {
5952 public:
5953  BitCrusher() {} /* C-TOR */
5954  ~BitCrusher() {} /* D-TOR */
5955 
5957  virtual bool reset(double _sampleRate){ return true; }
5958 
5964 
5970  {
5971  // --- calculate and store
5973  QL = 2.0 / (pow(2.0, params.quantizedBitDepth) - 1.0);
5974 
5975  parameters = params;
5976  }
5977 
5979  virtual bool canProcessAudioFrame() { return false; }
5980 
5986  virtual double processAudioSample(double xn)
5987  {
5988  return QL*(int(xn / QL));
5989  }
5990 
5991 protected:
5993  double QL = 1.0;
5994 };
5995 
5996 
5997 // ------------------------------------------------------------------ //
5998 // --- WDF LIBRARY -------------------------------------------------- //
5999 // ------------------------------------------------------------------ //
6000 
6013 {
6014 public:
6016  virtual void initialize(double _R1) {}
6017 
6019  virtual void initializeAdaptorChain() {}
6020 
6022  virtual void setInput(double _in) {}
6023 
6025  virtual double getOutput() { return 0.0; }
6026 
6027  // --- for adaptors
6029  virtual void setInput1(double _in1) = 0;
6030 
6032  virtual void setInput2(double _in2) = 0;
6033 
6035  virtual void setInput3(double _in3) = 0;
6036 
6038  virtual double getOutput1() = 0;
6039 
6041  virtual double getOutput2() = 0;
6042 
6044  virtual double getOutput3() = 0;
6045 
6047  virtual void reset(double _sampleRate) {}
6048 
6050  virtual double getComponentResistance() { return 0.0; }
6051 
6053  virtual double getComponentConductance() { return 0.0; }
6054 
6056  virtual void updateComponentResistance() {}
6057 
6059  virtual void setComponentValue(double _componentValue) { }
6060 
6062  virtual void setComponentValue_LC(double componentValue_L, double componentValue_C) { }
6063 
6065  virtual void setComponentValue_RL(double componentValue_R, double componentValue_L) { }
6066 
6068  virtual void setComponentValue_RC(double componentValue_R, double componentValue_C) { }
6069 
6071  virtual double getComponentValue() { return 0.0; }
6072 };
6073 
6074 // ------------------------------------------------------------------ //
6075 // --- WDF COMPONENTS & COMMBO COMPONENTS --------------------------- //
6076 // ------------------------------------------------------------------ //
6090 {
6091 public:
6092  WdfResistor(double _componentValue) { componentValue = _componentValue; }
6093  WdfResistor() { }
6094  virtual ~WdfResistor() {}
6095 
6097  void setSampleRate(double _sampleRate)
6098  {
6099  sampleRate = _sampleRate;
6101  }
6102 
6104  virtual double getComponentResistance() { return componentResistance; }
6105 
6107  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6108 
6110  virtual double getComponentValue() { return componentValue; }
6111 
6113  virtual void setComponentValue(double _componentValue)
6114  {
6115  componentValue = _componentValue;
6117  }
6118 
6121 
6123  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6124 
6126  virtual void setInput(double in) {}
6127 
6129  virtual double getOutput() { return 0.0; }
6130 
6132  virtual double getOutput1() { return getOutput(); }
6133 
6135  virtual double getOutput2() { return getOutput(); }
6136 
6138  virtual double getOutput3() { return getOutput(); }
6139 
6141  virtual void setInput1(double _in1) {}
6142 
6144  virtual void setInput2(double _in2) {}
6145 
6147  virtual void setInput3(double _in3) {}
6148 
6149 protected:
6150  double zRegister = 0.0;
6151  double componentValue = 0.0;
6152  double componentResistance = 0.0;
6153  double sampleRate = 0.0;
6154 };
6155 
6156 
6170 {
6171 public:
6172  WdfCapacitor(double _componentValue) { componentValue = _componentValue; }
6173  WdfCapacitor() { }
6174  virtual ~WdfCapacitor() {}
6175 
6177  void setSampleRate(double _sampleRate)
6178  {
6179  sampleRate = _sampleRate;
6181  }
6182 
6184  virtual double getComponentResistance() { return componentResistance; }
6185 
6187  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6188 
6190  virtual double getComponentValue() { return componentValue; }
6191 
6193  virtual void setComponentValue(double _componentValue)
6194  {
6195  componentValue = _componentValue;
6197  }
6198 
6201  {
6203  }
6204 
6206  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6207 
6209  virtual void setInput(double in) { zRegister = in; }
6210 
6212  virtual double getOutput() { return zRegister; } // z^-1
6213 
6215  virtual double getOutput1() { return getOutput(); }
6216 
6218  virtual double getOutput2() { return getOutput(); }
6219 
6221  virtual double getOutput3() { return getOutput(); }
6222 
6224  virtual void setInput1(double _in1) {}
6225 
6227  virtual void setInput2(double _in2) {}
6228 
6230  virtual void setInput3(double _in3) {}
6231 
6232 protected:
6233  double zRegister = 0.0;
6234  double componentValue = 0.0;
6235  double componentResistance = 0.0;
6236  double sampleRate = 0.0;
6237 };
6238 
6252 {
6253 public:
6254  WdfInductor(double _componentValue) { componentValue = _componentValue; }
6255  WdfInductor() { }
6256  virtual ~WdfInductor() {}
6257 
6259  void setSampleRate(double _sampleRate)
6260  {
6261  sampleRate = _sampleRate;
6263  }
6264 
6266  virtual double getComponentResistance() { return componentResistance; }
6267 
6269  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6270 
6272  virtual double getComponentValue() { return componentValue; }
6273 
6275  virtual void setComponentValue(double _componentValue)
6276  {
6277  componentValue = _componentValue;
6279  }
6280 
6283 
6285  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister = 0.0; }
6286 
6288  virtual void setInput(double in) { zRegister = in; }
6289 
6291  virtual double getOutput() { return -zRegister; } // -z^-1
6292 
6294  virtual double getOutput1() { return getOutput(); }
6295 
6297  virtual double getOutput2() { return getOutput(); }
6298 
6300  virtual double getOutput3() { return getOutput(); }
6301 
6303  virtual void setInput1(double _in1) {}
6304 
6306  virtual void setInput2(double _in2) {}
6307 
6309  virtual void setInput3(double _in3) {}
6310 
6311 protected:
6312  double zRegister = 0.0;
6313  double componentValue = 0.0;
6314  double componentResistance = 0.0;
6315  double sampleRate = 0.0;
6316 };
6317 
6318 
6333 {
6334 public:
6335  WdfSeriesLC() {}
6336  WdfSeriesLC(double _componentValue_L, double _componentValue_C)
6337  {
6338  componentValue_L = _componentValue_L;
6339  componentValue_C = _componentValue_C;
6340  }
6341  virtual ~WdfSeriesLC() {}
6342 
6344  void setSampleRate(double _sampleRate)
6345  {
6346  sampleRate = _sampleRate;
6348  }
6349 
6351  virtual double getComponentResistance() { return componentResistance; }
6352 
6354  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6355 
6358  {
6360  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6361  componentResistance = RL + (1.0 / RC);
6362  }
6363 
6365  virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
6366  {
6367  componentValue_L = _componentValue_L;
6368  componentValue_C = _componentValue_C;
6370  }
6371 
6373  virtual void setComponentValue_L(double _componentValue_L)
6374  {
6375  componentValue_L = _componentValue_L;
6377  }
6378 
6380  virtual void setComponentValue_C(double _componentValue_C)
6381  {
6382  componentValue_C = _componentValue_C;
6384  }
6385 
6387  virtual double getComponentValue_L() { return componentValue_L; }
6388 
6390  virtual double getComponentValue_C() { return componentValue_C; }
6391 
6393  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6394 
6396  virtual void setInput(double in)
6397  {
6398  double YC = 1.0 / RC;
6399  double K = (1.0 - RL*YC) / (1.0 + RL*YC);
6400  double N1 = K*(in - zRegister_L);
6401  zRegister_L = N1 + zRegister_C;
6402  zRegister_C = in;
6403  }
6404 
6406  virtual double getOutput(){ return zRegister_L; }
6407 
6409  virtual double getOutput1() { return getOutput(); }
6410 
6412  virtual double getOutput2() { return getOutput(); }
6413 
6415  virtual double getOutput3() { return getOutput(); }
6416 
6418  virtual void setInput1(double _in1) {}
6419 
6421  virtual void setInput2(double _in2) {}
6422 
6424  virtual void setInput3(double _in3) {}
6425 
6426 protected:
6427  double zRegister_L = 0.0;
6428  double zRegister_C = 0.0;
6429 
6430  double componentValue_L = 0.0;
6431  double componentValue_C = 0.0;
6432 
6433  double RL = 0.0;
6434  double RC = 0.0;
6435  double componentResistance = 0.0;
6436  double sampleRate = 0.0;
6437 };
6438 
6453 {
6454 public:
6455  WdfParallelLC() {}
6456  WdfParallelLC(double _componentValue_L, double _componentValue_C)
6457  {
6458  componentValue_L = _componentValue_L;
6459  componentValue_C = _componentValue_C;
6460  }
6461  virtual ~WdfParallelLC() {}
6462 
6464  void setSampleRate(double _sampleRate)
6465  {
6466  sampleRate = _sampleRate;
6468  }
6469 
6471  virtual double getComponentResistance() { return componentResistance; }
6472 
6474  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6475 
6478  {
6480  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6481  componentResistance = (RC + 1.0 / RL);
6482  }
6483 
6485  virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
6486  {
6487  componentValue_L = _componentValue_L;
6488  componentValue_C = _componentValue_C;
6490  }
6491 
6493  virtual void setComponentValue_L(double _componentValue_L)
6494  {
6495  componentValue_L = _componentValue_L;
6497  }
6498 
6500  virtual void setComponentValue_C(double _componentValue_C)
6501  {
6502  componentValue_C = _componentValue_C;
6504  }
6505 
6507  virtual double getComponentValue_L() { return componentValue_L; }
6508 
6510  virtual double getComponentValue_C() { return componentValue_C; }
6511 
6513  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6514 
6516  virtual void setInput(double in)
6517  {
6518  double YL = 1.0 / RL;
6519  double K = (YL*RC - 1.0) / (YL*RC + 1.0);
6520  double N1 = K*(in - zRegister_L);
6521  zRegister_L = N1 + zRegister_C;
6522  zRegister_C = in;
6523  }
6524 
6526  virtual double getOutput(){ return -zRegister_L; }
6527 
6529  virtual double getOutput1() { return getOutput(); }
6530 
6532  virtual double getOutput2() { return getOutput(); }
6533 
6535  virtual double getOutput3() { return getOutput(); }
6536 
6538  virtual void setInput1(double _in1) {}
6539 
6541  virtual void setInput2(double _in2) {}
6542 
6544  virtual void setInput3(double _in3) {}
6545 
6546 protected:
6547  double zRegister_L = 0.0;
6548  double zRegister_C = 0.0;
6549 
6550  double componentValue_L = 0.0;
6551  double componentValue_C = 0.0;
6552 
6553  double RL = 0.0;
6554  double RC = 0.0;
6555  double componentResistance = 0.0;
6556  double sampleRate = 0.0;
6557 };
6558 
6559 
6574 {
6575 public:
6576  WdfSeriesRL() {}
6577  WdfSeriesRL(double _componentValue_R, double _componentValue_L)
6578  {
6579  componentValue_L = _componentValue_L;
6580  componentValue_R = _componentValue_R;
6581  }
6582  virtual ~WdfSeriesRL() {}
6583 
6585  void setSampleRate(double _sampleRate)
6586  {
6587  sampleRate = _sampleRate;
6589  }
6590 
6592  virtual double getComponentResistance() { return componentResistance; }
6593 
6595  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6596 
6599  {
6600  RR = componentValue_R;
6603  K = RR / componentResistance;
6604  }
6605 
6607  virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
6608  {
6609  componentValue_L = _componentValue_L;
6610  componentValue_R = _componentValue_R;
6612  }
6613 
6615  virtual void setComponentValue_L(double _componentValue_L)
6616  {
6617  componentValue_L = _componentValue_L;
6619  }
6620 
6622  virtual void setComponentValue_R(double _componentValue_R)
6623  {
6624  componentValue_R = _componentValue_R;
6626  }
6627 
6629  virtual double getComponentValue_L() { return componentValue_L; }
6630 
6632  virtual double getComponentValue_R() { return componentValue_R; }
6633 
6635  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6636 
6638  virtual void setInput(double in){ zRegister_L = in; }
6639 
6641  virtual double getOutput()
6642  {
6643  double NL = -zRegister_L;
6644  double out = NL*(1.0 - K) - K*zRegister_C;
6645  zRegister_C = out;
6646 
6647  return out;
6648  }
6649 
6651  virtual double getOutput1() { return getOutput(); }
6652 
6654  virtual double getOutput2() { return getOutput(); }
6655 
6657  virtual double getOutput3() { return getOutput(); }
6658 
6660  virtual void setInput1(double _in1) {}
6661 
6663  virtual void setInput2(double _in2) {}
6664 
6666  virtual void setInput3(double _in3) {}
6667 
6668 protected:
6669  double zRegister_L = 0.0;
6670  double zRegister_C = 0.0;
6671  double K = 0.0;
6672 
6673  double componentValue_L = 0.0;
6674  double componentValue_R = 0.0;
6675 
6676  double RL = 0.0;
6677  double RC = 0.0;
6678  double RR = 0.0;
6679 
6680  double componentResistance = 0.0;
6681  double sampleRate = 0.0;
6682 };
6683 
6697 {
6698 public:
6699  WdfParallelRL() {}
6700  WdfParallelRL(double _componentValue_R, double _componentValue_L)
6701  {
6702  componentValue_L = _componentValue_L;
6703  componentValue_R = _componentValue_R;
6704  }
6705  virtual ~WdfParallelRL() {}
6706 
6708  void setSampleRate(double _sampleRate)
6709  {
6710  sampleRate = _sampleRate;
6712  }
6713 
6715  virtual double getComponentResistance() { return componentResistance; }
6716 
6718  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6719 
6722  {
6723  RR = componentValue_R;
6725  componentResistance = 1.0 / ((1.0 / RR) + (1.0 / RL));
6726  K = componentResistance / RR;
6727  }
6728 
6729 
6731  virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
6732  {
6733  componentValue_L = _componentValue_L;
6734  componentValue_R = _componentValue_R;
6736  }
6737 
6739  virtual void setComponentValue_L(double _componentValue_L)
6740  {
6741  componentValue_L = _componentValue_L;
6743  }
6744 
6746  virtual void setComponentValue_R(double _componentValue_R)
6747  {
6748  componentValue_R = _componentValue_R;
6750  }
6751 
6753  virtual double getComponentValue_L() { return componentValue_L; }
6754 
6756  virtual double getComponentValue_R() { return componentValue_R; }
6757 
6759  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6760 
6762  virtual void setInput(double in){ zRegister_L = in; }
6763 
6765  virtual double getOutput()
6766  {
6767  double NL = -zRegister_L;
6768  double out = NL*(1.0 - K) + K*zRegister_C;
6769  zRegister_C = out;
6770  return out;
6771  }
6772 
6774  virtual double getOutput1() { return getOutput(); }
6775 
6777  virtual double getOutput2() { return getOutput(); }
6778 
6780  virtual double getOutput3() { return getOutput(); }
6781 
6783  virtual void setInput1(double _in1) {}
6784 
6786  virtual void setInput2(double _in2) {}
6787 
6789  virtual void setInput3(double _in3) {}
6790 
6791 protected:
6792  double zRegister_L = 0.0;
6793  double zRegister_C = 0.0;
6794  double K = 0.0;
6795 
6796  double componentValue_L = 0.0;
6797  double componentValue_R = 0.0;
6798 
6799  double RL = 0.0;
6800  double RC = 0.0;
6801  double RR = 0.0;
6802 
6803  double componentResistance = 0.0;
6804  double sampleRate = 0.0;
6805 };
6806 
6821 {
6822 public:
6823  WdfSeriesRC() {}
6824  WdfSeriesRC(double _componentValue_R, double _componentValue_C)
6825  {
6826  componentValue_C = _componentValue_C;
6827  componentValue_R = _componentValue_R;
6828  }
6829  virtual ~WdfSeriesRC() {}
6830 
6832  void setSampleRate(double _sampleRate)
6833  {
6834  sampleRate = _sampleRate;
6836  }
6837 
6839  virtual double getComponentResistance() { return componentResistance; }
6840 
6842  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6843 
6846  {
6847  RR = componentValue_R;
6848  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6850  K = RR / componentResistance;
6851  }
6852 
6854  virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
6855  {
6856  componentValue_R = _componentValue_R;
6857  componentValue_C = _componentValue_C;
6859  }
6860 
6862  virtual void setComponentValue_R(double _componentValue_R)
6863  {
6864  componentValue_R = _componentValue_R;
6866  }
6867 
6869  virtual void setComponentValue_C(double _componentValue_C)
6870  {
6871  componentValue_C = _componentValue_C;
6873  }
6874 
6876  virtual double getComponentValue_R() { return componentValue_R; }
6877 
6879  virtual double getComponentValue_C() { return componentValue_C; }
6880 
6882  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
6883 
6885  virtual void setInput(double in){ zRegister_L = in; }
6886 
6888  virtual double getOutput()
6889  {
6890  double NL = zRegister_L;
6891  double out = NL*(1.0 - K) + K*zRegister_C;
6892  zRegister_C = out;
6893  return out;
6894  }
6895 
6897  virtual double getOutput1() { return getOutput(); }
6898 
6900  virtual double getOutput2() { return getOutput(); }
6901 
6903  virtual double getOutput3() { return getOutput(); }
6904 
6906  virtual void setInput1(double _in1) {}
6907 
6909  virtual void setInput2(double _in2) {}
6910 
6912  virtual void setInput3(double _in3) {}
6913 
6914 protected:
6915  double zRegister_L = 0.0;
6916  double zRegister_C = 0.0;
6917  double K = 0.0;
6918 
6919  double componentValue_R = 0.0;
6920  double componentValue_C = 0.0;
6921 
6922  double RL = 0.0;
6923  double RC = 0.0;
6924  double RR = 0.0;
6925 
6926  double componentResistance = 0.0;
6927  double sampleRate = 0.0;
6928 };
6929 
6944 {
6945 public:
6946  WdfParallelRC() {}
6947  WdfParallelRC(double _componentValue_R, double _componentValue_C)
6948  {
6949  componentValue_C = _componentValue_C;
6950  componentValue_R = _componentValue_R;
6951  }
6952  virtual ~WdfParallelRC() {}
6953 
6955  void setSampleRate(double _sampleRate)
6956  {
6957  sampleRate = _sampleRate;
6959  }
6960 
6962  virtual double getComponentResistance() { return componentResistance; }
6963 
6965  virtual double getComponentConductance() { return 1.0 / componentResistance; }
6966 
6969  {
6970  RR = componentValue_R;
6971  RC = 1.0 / (2.0*componentValue_C*sampleRate);
6972  componentResistance = 1.0 / ((1.0 / RR) + (1.0 / RC));
6973  K = componentResistance / RR;
6974  }
6975 
6977  virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
6978  {
6979  componentValue_R = _componentValue_R;
6980  componentValue_C = _componentValue_C;
6982  }
6983 
6985  virtual void setComponentValue_R(double _componentValue_R)
6986  {
6987  componentValue_R = _componentValue_R;
6989  }
6990 
6992  virtual void setComponentValue_C(double _componentValue_C)
6993  {
6994  componentValue_C = _componentValue_C;
6996  }
6997 
6999  virtual double getComponentValue_R() { return componentValue_R; }
7000 
7002  virtual double getComponentValue_C() { return componentValue_C; }
7003 
7005  virtual void reset(double _sampleRate) { setSampleRate(_sampleRate); zRegister_L = 0.0; zRegister_C = 0.0; }
7006 
7008  virtual void setInput(double in){ zRegister_L = in; }
7009 
7011  virtual double getOutput()
7012  {
7013  double NL = zRegister_L;
7014  double out = NL*(1.0 - K) - K*zRegister_C;
7015  zRegister_C = out;
7016  return out;
7017  }
7018 
7020  virtual double getOutput1() { return getOutput(); }
7021 
7023  virtual double getOutput2() { return getOutput(); }
7024 
7026  virtual double getOutput3() { return getOutput(); }
7027 
7029  virtual void setInput1(double _in1) {}
7030 
7032  virtual void setInput2(double _in2) {}
7033 
7035  virtual void setInput3(double _in3) {}
7036 
7037 protected:
7038  double zRegister_L = 0.0;
7039  double zRegister_C = 0.0;
7040  double K = 0.0;
7041 
7042  double componentValue_C = 0.0;
7043  double componentValue_R = 0.0;
7044 
7045  double RL = 0.0;
7046  double RC = 0.0;
7047  double RR = 0.0;
7048 
7049  double componentResistance = 0.0;
7050  double sampleRate = 0.0;
7051 };
7052 
7053 
7054 // ------------------------------------------------------------------ //
7055 // --- WDF ADAPTORS ------------------------------------------------- //
7056 // ------------------------------------------------------------------ //
7057 
7071 enum class wdfComponent { R, L, C, seriesLC, parallelLC, seriesRL, parallelRL, seriesRC, parallelRC };
7072 
7085 {
7086  WdfComponentInfo() { }
7087 
7088  WdfComponentInfo(wdfComponent _componentType, double value1 = 0.0, double value2 = 0.0)
7089  {
7090  componentType = _componentType;
7091  if (componentType == wdfComponent::R)
7092  R = value1;
7093  else if (componentType == wdfComponent::L)
7094  L = value1;
7095  else if (componentType == wdfComponent::C)
7096  C = value1;
7097  else if (componentType == wdfComponent::seriesLC || componentType == wdfComponent::parallelLC)
7098  {
7099  L = value1;
7100  C = value2;
7101  }
7102  else if (componentType == wdfComponent::seriesRL || componentType == wdfComponent::parallelRL)
7103  {
7104  R = value1;
7105  L = value2;
7106  }
7107  else if (componentType == wdfComponent::seriesRC || componentType == wdfComponent::parallelRC)
7108  {
7109  R = value1;
7110  C = value2;
7111  }
7112  }
7113 
7114  double R = 0.0;
7115  double L = 0.0;
7116  double C = 0.0;
7117  wdfComponent componentType = wdfComponent::R;
7118 };
7119 
7120 
7134 {
7135 public:
7136  WdfAdaptorBase() {}
7137  virtual ~WdfAdaptorBase() {}
7138 
7140  void setTerminalResistance(double _terminalResistance) { terminalResistance = _terminalResistance; }
7141 
7143  void setOpenTerminalResistance(bool _openTerminalResistance = true)
7144  {
7145  // --- flag overrides value
7146  openTerminalResistance = _openTerminalResistance;
7147  terminalResistance = 1.0e+34; // avoid /0.0
7148  }
7149 
7151  void setSourceResistance(double _sourceResistance) { sourceResistance = _sourceResistance; }
7152 
7154  void setPort1_CompAdaptor(IComponentAdaptor* _port1CompAdaptor) { port1CompAdaptor = _port1CompAdaptor; }
7155 
7157  void setPort2_CompAdaptor(IComponentAdaptor* _port2CompAdaptor) { port2CompAdaptor = _port2CompAdaptor; }
7158 
7160  void setPort3_CompAdaptor(IComponentAdaptor* _port3CompAdaptor) { port3CompAdaptor = _port3CompAdaptor; }
7161 
7163  virtual void reset(double _sampleRate)
7164  {
7165  if (wdfComponent)
7166  wdfComponent->reset(_sampleRate);
7167  }
7168 
7170  void setComponent(wdfComponent componentType, double value1 = 0.0, double value2 = 0.0)
7171  {
7172  // --- decode and set
7173  if (componentType == wdfComponent::R)
7174  {
7175  wdfComponent = new WdfResistor;
7178  }
7179  else if (componentType == wdfComponent::L)
7180  {
7181  wdfComponent = new WdfInductor;
7184  }
7185  else if (componentType == wdfComponent::C)
7186  {
7187  wdfComponent = new WdfCapacitor;
7190  }
7191  else if (componentType == wdfComponent::seriesLC)
7192  {
7193  wdfComponent = new WdfSeriesLC;
7194  wdfComponent->setComponentValue_LC(value1, value2);
7196  }
7197  else if (componentType == wdfComponent::parallelLC)
7198  {
7200  wdfComponent->setComponentValue_LC(value1, value2);
7202  }
7203  else if (componentType == wdfComponent::seriesRL)
7204  {
7205  wdfComponent = new WdfSeriesRL;
7206  wdfComponent->setComponentValue_RL(value1, value2);
7208  }
7209  else if (componentType == wdfComponent::parallelRL)
7210  {
7212  wdfComponent->setComponentValue_RL(value1, value2);
7214  }
7215  else if (componentType == wdfComponent::seriesRC)
7216  {
7217  wdfComponent = new WdfSeriesRC;
7218  wdfComponent->setComponentValue_RC(value1, value2);
7220  }
7221  else if (componentType == wdfComponent::parallelRC)
7222  {
7224  wdfComponent->setComponentValue_RC(value1, value2);
7226  }
7227  }
7228 
7230  static void connectAdaptors(WdfAdaptorBase* upstreamAdaptor, WdfAdaptorBase* downstreamAdaptor)
7231  {
7232  upstreamAdaptor->setPort2_CompAdaptor(downstreamAdaptor);
7233  downstreamAdaptor->setPort1_CompAdaptor(upstreamAdaptor);
7234  }
7235 
7237  virtual void initializeAdaptorChain()
7238  {
7240  }
7241 
7243  virtual void setComponentValue(double _componentValue)
7244  {
7245  if (wdfComponent)
7246  wdfComponent->setComponentValue(_componentValue);
7247  }
7248 
7250  virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
7251  {
7252  if (wdfComponent)
7253  wdfComponent->setComponentValue_LC(componentValue_L, componentValue_C);
7254  }
7255 
7257  virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
7258  {
7259  if (wdfComponent)
7260  wdfComponent->setComponentValue_RL(componentValue_R, componentValue_L);
7261  }
7262 
7264  virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
7265  {
7266  if (wdfComponent)
7267  wdfComponent->setComponentValue_RC(componentValue_R, componentValue_C);
7268  }
7269 
7272 
7275 
7278 
7279 protected:
7280  // --- can in theory connect any port to a component OR adaptor;
7281  // though this library is setup with a convention R3 = component
7286 
7287  // --- These hold the input (R1), component (R3) and output (R2) resistances
7288  double R1 = 0.0;
7289  double R2 = 0.0;
7290  double R3 = 0.0;
7291 
7292  // --- these are input variables that are stored;
7293  // not used in this implementation but may be required for extended versions
7294  double in1 = 0.0;
7295  double in2 = 0.0;
7296  double in3 = 0.0;
7297 
7298  // --- these are output variables that are stored;
7299  // currently out2 is the only one used as it is y(n) for this library
7300  // out1 and out2 are stored; not used in this implementation but may be required for extended versions
7301  double out1 = 0.0;
7302  double out2 = 0.0;
7303  double out3 = 0.0;
7304 
7305  // --- terminal impedance
7306  double terminalResistance = 600.0;
7307  bool openTerminalResistance = false;
7308 
7309  // --- source impedance, OK for this to be set to 0.0 for Rs = 0
7310  double sourceResistance = 600.0;
7311 };
7312 
7325 {
7326 public:
7327  WdfSeriesAdaptor() {}
7328  virtual ~WdfSeriesAdaptor() {}
7329 
7331  virtual double getR2()
7332  {
7333  double componentResistance = 0.0;
7334  if (getPort3_CompAdaptor())
7335  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7336 
7337  R2 = R1 + componentResistance;
7338  return R2;
7339  }
7340 
7342  virtual void initialize(double _R1)
7343  {
7344  // --- R1 is source resistance for this adaptor
7345  R1 = _R1;
7346 
7347  double componentResistance = 0.0;
7348  if (getPort3_CompAdaptor())
7349  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7350 
7351  // --- calculate B coeff
7352  B = R1 / (R1 + componentResistance);
7353 
7354  // --- init downstream adaptor
7355  if (getPort2_CompAdaptor())
7357 
7358  // --- not used in this implementation but saving for extended use
7359  R3 = componentResistance;
7360  }
7361 
7363  virtual void setInput1(double _in1)
7364  {
7365  // --- save
7366  in1 = _in1;
7367 
7368  // --- read component value
7369  N2 = 0.0;
7370  if (getPort3_CompAdaptor())
7371  N2 = getPort3_CompAdaptor()->getOutput();
7372 
7373  // --- form output
7374  out2 = -(in1 + N2);
7375 
7376  // --- deliver downstream
7377  if (getPort2_CompAdaptor())
7379  }
7380 
7382  virtual void setInput2(double _in2)
7383  {
7384  // --- save
7385  in2 = _in2;
7386 
7387  // --- calc N1
7388  N1 = -(in1 - B*(in1 + N2 + in2) + in2);
7389 
7390  // --- calc out1
7391  out1 = in1 - B*(N2 + in2);
7392 
7393  // --- deliver upstream
7394  if (getPort1_CompAdaptor())
7396 
7397  // --- set component state
7398  if (getPort3_CompAdaptor())
7400  }
7401 
7403  virtual void setInput3(double _in3){ }
7404 
7406  virtual double getOutput1() { return out1; }
7407 
7409  virtual double getOutput2() { return out2; }
7410 
7412  virtual double getOutput3() { return out3; }
7413 
7414 private:
7415  double N1 = 0.0;
7416  double N2 = 0.0;
7417  double B = 0.0;
7418 };
7419 
7431 // --- Series terminated adaptor
7433 {
7434 public:
7436  virtual ~WdfSeriesTerminatedAdaptor() {}
7437 
7439  virtual double getR2()
7440  {
7441  double componentResistance = 0.0;
7442  if (getPort3_CompAdaptor())
7443  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7444 
7445  R2 = R1 + componentResistance;
7446  return R2;
7447  }
7448 
7450  virtual void initialize(double _R1)
7451  {
7452  // --- source impedance
7453  R1 = _R1;
7454 
7455  double componentResistance = 0.0;
7456  if (getPort3_CompAdaptor())
7457  componentResistance = getPort3_CompAdaptor()->getComponentResistance();
7458 
7459  B1 = (2.0*R1) / (R1 + componentResistance + terminalResistance);
7460  B3 = (2.0*terminalResistance) / (R1 + componentResistance + terminalResistance);
7461 
7462  // --- init downstream
7463  if (getPort2_CompAdaptor())
7465 
7466  // --- not used in this implementation but saving for extended use
7467  R3 = componentResistance;
7468  }
7469 
7471  virtual void setInput1(double _in1)
7472  {
7473  // --- save
7474  in1 = _in1;
7475 
7476  N2 = 0.0;
7477  if (getPort3_CompAdaptor())
7478  N2 = getPort3_CompAdaptor()->getOutput();
7479 
7480  double N3 = in1 + N2;
7481 
7482  // --- calc out2 y(n)
7483  out2 = -B3*N3;
7484 
7485  // --- form output1
7486  out1 = in1 - B1*N3;
7487 
7488  // --- form N1
7489  N1 = -(out1 + out2 + N3);
7490 
7491  // --- deliver upstream to input2
7492  if (getPort1_CompAdaptor())
7494 
7495  // --- set component state
7496  if (getPort3_CompAdaptor())
7498  }
7499 
7502  virtual void setInput2(double _in2) { in2 = _in2;}
7503 
7505  virtual void setInput3(double _in3) { in3 = _in3;}
7506 
7508  virtual double getOutput1() { return out1; }
7509 
7511  virtual double getOutput2() { return out2; }
7512 
7514  virtual double getOutput3() { return out3; }
7515 
7516 private:
7517  double N1 = 0.0;
7518  double N2 = 0.0;
7519  double B1 = 0.0;
7520  double B3 = 0.0;
7521 };
7522 
7535 {
7536 public:
7537  WdfParallelAdaptor() {}
7538  virtual ~WdfParallelAdaptor() {}
7539 
7541  virtual double getR2()
7542  {
7543  double componentConductance = 0.0;
7544  if (getPort3_CompAdaptor())
7545  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7546 
7547  // --- 1 / (sum of admittances)
7548  R2 = 1.0 / ((1.0 / R1) + componentConductance);
7549  return R2;
7550  }
7551 
7553  virtual void initialize(double _R1)
7554  {
7555  // --- save R1
7556  R1 = _R1;
7557 
7558  double G1 = 1.0 / R1;
7559  double componentConductance = 0.0;
7560  if (getPort3_CompAdaptor())
7561  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7562 
7563  // --- calculate B coeff
7564  A = G1 / (G1 + componentConductance);
7565 
7566  // --- now, do we init our downstream??
7567  if (getPort2_CompAdaptor())
7569 
7570  // --- not used in this implementation but saving for extended use
7571  R3 = 1.0/ componentConductance;
7572  }
7573 
7575  virtual void setInput1(double _in1)
7576  {
7577  // --- save
7578  in1 = _in1;
7579 
7580  // --- read component
7581  N2 = 0.0;
7582  if (getPort3_CompAdaptor())
7583  N2 = getPort3_CompAdaptor()->getOutput();
7584 
7585  // --- form output
7586  out2 = N2 - A*(-in1 + N2);
7587 
7588  // --- deliver downstream
7589  if (getPort2_CompAdaptor())
7591  }
7592 
7594  virtual void setInput2(double _in2)
7595  {
7596  // --- save
7597  in2 = _in2;
7598 
7599  // --- calc N1
7600  N1 = in2 - A*(-in1 + N2);
7601 
7602  // --- calc out1
7603  out1 = -in1 + N2 + N1;
7604 
7605  // --- deliver upstream
7606  if (getPort1_CompAdaptor())
7608 
7609  // --- set component state
7610  if (getPort3_CompAdaptor())
7612  }
7613 
7615  virtual void setInput3(double _in3) { }
7616 
7618  virtual double getOutput1() { return out1; }
7619 
7621  virtual double getOutput2() { return out2; }
7622 
7624  virtual double getOutput3() { return out3; }
7625 
7626 private:
7627  double N1 = 0.0;
7628  double N2 = 0.0;
7629  double A = 0.0;
7630 };
7631 
7632 
7645 {
7646 public:
7648  virtual ~WdfParallelTerminatedAdaptor() {}
7649 
7651  virtual double getR2()
7652  {
7653  double componentConductance = 0.0;
7654  if (getPort3_CompAdaptor())
7655  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7656 
7657  // --- 1 / (sum of admittances)
7658  R2 = 1.0 / ((1.0 / R1) + componentConductance);
7659  return R2;
7660  }
7661 
7663  virtual void initialize(double _R1)
7664  {
7665  // --- save R1
7666  R1 = _R1;
7667 
7668  double G1 = 1.0 / R1;
7669  if (terminalResistance <= 0.0)
7670  terminalResistance = 1e-15;
7671 
7672  double G2 = 1.0 / terminalResistance;
7673  double componentConductance = 0.0;
7674  if (getPort3_CompAdaptor())
7675  componentConductance = getPort3_CompAdaptor()->getComponentConductance();
7676 
7677  A1 = 2.0*G1 / (G1 + componentConductance + G2);
7678  A3 = openTerminalResistance ? 0.0 : 2.0*G2 / (G1 + componentConductance + G2);
7679 
7680  // --- init downstream
7681  if (getPort2_CompAdaptor())
7683 
7684  // --- not used in this implementation but saving for extended use
7685  R3 = 1.0 / componentConductance;
7686  }
7687 
7689  virtual void setInput1(double _in1)
7690  {
7691  // --- save
7692  in1 = _in1;
7693 
7694  N2 = 0.0;
7695  if (getPort3_CompAdaptor())
7696  N2 = getPort3_CompAdaptor()->getOutput();
7697 
7698  // --- form N1
7699  N1 = -A1*(-in1 + N2) + N2 - A3*N2;
7700 
7701  // --- form output1
7702  out1 = -in1 + N2 + N1;
7703 
7704  // --- deliver upstream to input2
7705  if (getPort1_CompAdaptor())
7707 
7708  // --- calc out2 y(n)
7709  out2 = N2 + N1;
7710 
7711  // --- set component state
7712  if (getPort3_CompAdaptor())
7714  }
7715 
7717  virtual void setInput2(double _in2){ in2 = _in2;}
7718 
7720  virtual void setInput3(double _in3) { }
7721 
7723  virtual double getOutput1() { return out1; }
7724 
7726  virtual double getOutput2() { return out2; }
7727 
7729  virtual double getOutput3() { return out3; }
7730 
7731 private:
7732  double N1 = 0.0;
7733  double N2 = 0.0;
7734  double A1 = 0.0;
7735  double A3 = 0.0;
7736 };
7737 
7738 // ------------------------------------------------------------------------------ //
7739 // --- WDF Ladder Filter Design Examples --------------------------------------- //
7740 // ------------------------------------------------------------------------------ //
7741 //
7742 // --- 3rd order Butterworth LPF designed with Elsie www.TonneSoftware.comm
7743 //
7744 /*
7745  3rd Order Inductor-Leading LPF
7746 
7747  Rs = Rload = 600 ohms
7748 
7749  Series(L1) -> Parallel(C1) -> Series(L2)
7750 
7751  --L1-- | --L2--
7752  C1
7753  |
7754 
7755  fc = 1kHz
7756  L1 = 95.49e-3;
7757  C1 = 0.5305e-6;
7758  L2 = 95.49e-3;
7759 
7760  fc = 10kHz
7761  L1 = 9.549e-3;
7762  C1 = 0.05305e-6;
7763  L2 = 9.549e-3;
7764 */
7765 
7785 {
7786 public:
7787  WDFButterLPF3(void) { createWDF(); } /* C-TOR */
7788  ~WDFButterLPF3(void) {} /* D-TOR */
7789 
7791  virtual bool reset(double _sampleRate)
7792  {
7793  // --- rest WDF components (flush state registers)
7794  seriesAdaptor_L1.reset(_sampleRate);
7795  parallelAdaptor_C1.reset(_sampleRate);
7796  seriesTerminatedAdaptor_L2.reset(_sampleRate);
7797 
7798  // --- intialize the chain of adapters
7800  return true;
7801  }
7802 
7804  virtual bool canProcessAudioFrame() { return false; }
7805 
7811  virtual double processAudioSample(double xn)
7812  {
7813  // --- push audio sample into series L1
7815 
7816  // --- output is at terminated L2's output2
7818  }
7819 
7821  void createWDF()
7822  {
7823  // --- actual component values fc = 1kHz
7824  double L1_value = 95.49e-3; // 95.5 mH
7825  double C1_value = 0.5305e-6; // 0.53 uF
7826  double L2_value = 95.49e-3; // 95.5 mH
7827 
7828  // --- set adapter components
7829  seriesAdaptor_L1.setComponent(wdfComponent::L, L1_value);
7830  parallelAdaptor_C1.setComponent(wdfComponent::C, C1_value);
7831  seriesTerminatedAdaptor_L2.setComponent(wdfComponent::L, L2_value);
7832 
7833  // --- connect adapters
7836 
7837  // --- set source resistance
7838  seriesAdaptor_L1.setSourceResistance(600.0); // --- Rs = 600
7839 
7840  // --- set terminal resistance
7841  seriesTerminatedAdaptor_L2.setTerminalResistance(600.0); // --- Rload = 600
7842  }
7843 
7844 protected:
7845  // --- three adapters
7849 };
7850 
7871 {
7872 public:
7873  WDFTunableButterLPF3(void) { createWDF(); } /* C-TOR */
7874  ~WDFTunableButterLPF3(void) {} /* D-TOR */
7875 
7877  virtual bool reset(double _sampleRate)
7878  {
7879  sampleRate = _sampleRate;
7880  // --- rest WDF components (flush state registers)
7881  seriesAdaptor_L1.reset(_sampleRate);
7882  parallelAdaptor_C1.reset(_sampleRate);
7883  seriesTerminatedAdaptor_L2.reset(_sampleRate);
7884 
7885  // --- intialize the chain of adapters
7887  return true;
7888  }
7889 
7891  virtual bool canProcessAudioFrame() { return false; }
7892 
7898  virtual double processAudioSample(double xn)
7899  {
7900  // --- push audio sample into series L1
7902 
7903  // --- output is at terminated L2's output2
7905  }
7906 
7908  void createWDF()
7909  {
7910  // --- create components, init to noramlized values fc = 1Hz
7911  seriesAdaptor_L1.setComponent(wdfComponent::L, L1_norm);
7912  parallelAdaptor_C1.setComponent(wdfComponent::C, C1_norm);
7913  seriesTerminatedAdaptor_L2.setComponent(wdfComponent::L, L2_norm);
7914 
7915  // --- connect adapters
7918 
7919  // --- set source resistance
7920  seriesAdaptor_L1.setSourceResistance(600.0); // --- Rs = 600
7921 
7922  // --- set terminal resistance
7923  seriesTerminatedAdaptor_L2.setTerminalResistance(600.0); // --- Rload = 600
7924  }
7925 
7928 
7930  void setFilterFc(double fc_Hz)
7931  {
7932  if (useFrequencyWarping)
7933  {
7934  double arg = (kPi*fc_Hz) / sampleRate;
7935  fc_Hz = fc_Hz*(tan(arg) / arg);
7936  }
7937 
7938  seriesAdaptor_L1.setComponentValue(L1_norm / fc_Hz);
7939  parallelAdaptor_C1.setComponentValue(C1_norm / fc_Hz);
7941  }
7942 
7943 protected:
7944  // --- three adapters
7948 
7949  double L1_norm = 95.493; // 95.5 mH
7950  double C1_norm = 530.516e-6; // 0.53 uF
7951  double L2_norm = 95.493; // 95.5 mH
7952 
7953  bool useFrequencyWarping = false;
7954  double sampleRate = 1.0;
7955 };
7956 
7976 {
7977 public:
7978  WDFBesselBSF3(void) { createWDF(); } /* C-TOR */
7979  ~WDFBesselBSF3(void) {} /* D-TOR */
7980 
7982  virtual bool reset(double _sampleRate)
7983  {
7984  // --- rest WDF components (flush state registers)
7985  seriesAdaptor_L1C1.reset(_sampleRate);
7986  parallelAdaptor_L2C2.reset(_sampleRate);
7987  seriesTerminatedAdaptor_L3C3.reset(_sampleRate);
7988 
7989  // --- intialize the chain of adapters
7991 
7992  return true;
7993  }
7994 
7996  virtual bool canProcessAudioFrame() { return false; }
7997 
8003  virtual double processAudioSample(double xn)
8004  {
8005  // --- push audio sample into series L1
8007 
8008  // --- output is at terminated L2's output2
8010  }
8011 
8013  void createWDF()
8014  {
8015  // --- set component values
8016  // --- fo = 5kHz
8017  // BW = 2kHz or Q = 2.5
8018  seriesAdaptor_L1C1.setComponent(wdfComponent::parallelLC, 16.8327e-3, 0.060193e-6); /* L, C */
8019  parallelAdaptor_L2C2.setComponent(wdfComponent::seriesLC, 49.1978e-3, 0.02059e-6); /* L, C */
8020  seriesTerminatedAdaptor_L3C3.setComponent(wdfComponent::parallelLC, 2.57755e-3, 0.393092e-6); /* L, C */
8021 
8022  // --- connect adapters
8025 
8026  // --- set source resistance
8027  seriesAdaptor_L1C1.setSourceResistance(600.0); // Ro = 600
8028 
8029  // --- set terminal resistance
8031  }
8032 
8033 protected:
8034  // --- three adapters
8038 };
8039 
8040 
8060 {
8061 public:
8062  WDFConstKBPF6(void) { createWDF(); } /* C-TOR */
8063  ~WDFConstKBPF6(void) {} /* D-TOR */
8064 
8066  virtual bool reset(double _sampleRate)
8067  {
8068  // --- rest WDF components (flush state registers)
8069  seriesAdaptor_L1C1.reset(_sampleRate);
8070  parallelAdaptor_L2C2.reset(_sampleRate);
8071 
8072  seriesAdaptor_L3C3.reset(_sampleRate);
8073  parallelAdaptor_L4C4.reset(_sampleRate);
8074 
8075  seriesAdaptor_L5C5.reset(_sampleRate);
8077 
8078  // --- intialize the chain of adapters
8080  return true;
8081  }
8082 
8084  virtual bool canProcessAudioFrame() { return false; }
8085 
8091  virtual double processAudioSample(double xn)
8092  {
8093  // --- push audio sample into series L1
8095 
8096  // --- output is at terminated L6C6 output2
8097  double output = parallelTerminatedAdaptor_L6C6.getOutput2();
8098 
8099  return output;
8100  }
8101 
8103  void createWDF()
8104  {
8105  // --- fo = 5kHz
8106  // BW = 2kHz or Q = 2.5
8107  seriesAdaptor_L1C1.setComponent(wdfComponent::seriesLC, 47.7465e-3, 0.02122e-6);
8108  parallelAdaptor_L2C2.setComponent(wdfComponent::parallelLC, 3.81972e-3, 0.265258e-6);
8109 
8110  seriesAdaptor_L3C3.setComponent(wdfComponent::seriesLC, 95.493e-3, 0.01061e-6);
8111  parallelAdaptor_L4C4.setComponent(wdfComponent::parallelLC, 3.81972e-3, 0.265258e-6);
8112 
8113  seriesAdaptor_L5C5.setComponent(wdfComponent::seriesLC, 95.493e-3, 0.01061e-6);
8114  parallelTerminatedAdaptor_L6C6.setComponent(wdfComponent::parallelLC, 7.63944e-3, 0.132629e-6);
8115 
8116  // --- connect adapters
8122 
8123  // --- set source resistance
8124  seriesAdaptor_L1C1.setSourceResistance(600.0); // Ro = 600
8125 
8126  // --- set terminal resistance
8128  }
8129 
8130 protected:
8131  // --- six adapters
8134 
8137 
8140 };
8141 
8142 
8155 {
8156  WDFParameters() {}
8159  {
8160  if (this == &params)
8161  return *this;
8162 
8163  fc = params.fc;
8164  Q = params.Q;
8165  boostCut_dB = params.boostCut_dB;
8167  return *this;
8168  }
8169 
8170  // --- individual parameters
8171  double fc = 100.0;
8172  double Q = 0.707;
8173  double boostCut_dB = 0.0;
8174  bool frequencyWarping = true;
8175 };
8176 
8195 {
8196 public:
8197  WDFIdealRLCLPF(void) { createWDF(); } /* C-TOR */
8198  ~WDFIdealRLCLPF(void) {} /* D-TOR */
8199 
8201  virtual bool reset(double _sampleRate)
8202  {
8203  sampleRate = _sampleRate;
8204 
8205  // --- rest WDF components (flush state registers)
8206  seriesAdaptor_RL.reset(_sampleRate);
8207  parallelTerminatedAdaptor_C.reset(_sampleRate);
8208 
8209  // --- intialize the chain of adapters
8211  return true;
8212  }
8213 
8215  virtual bool canProcessAudioFrame() { return false; }
8216 
8222  virtual double processAudioSample(double xn)
8223  {
8224  // --- push audio sample into series L1
8226 
8227  // --- output is at terminated L2's output2
8228  // note compensation scaling by -6dB = 0.5
8229  // because of WDF assumption about Rs and Rload
8231  }
8232 
8234  void createWDF()
8235  {
8236  // --- create components, init to noramlized values fc =
8237  // initial values for fc = 1kHz Q = 0.707
8238  // Holding C Constant at 1e-6
8239  // L = 2.533e-2
8240  // R = 2.251131 e2
8241  seriesAdaptor_RL.setComponent(wdfComponent::seriesRL, 2.251131e2, 2.533e-2);
8242  parallelTerminatedAdaptor_C.setComponent(wdfComponent::C, 1.0e-6);
8243 
8244  // --- connect adapters
8246 
8247  // --- set source resistance
8248  seriesAdaptor_RL.setSourceResistance(0.0); // --- Rs = 600
8249 
8250  // --- set open ckt termination
8252  }
8253 
8259 
8264  void setParameters(const WDFParameters& _wdfParameters)
8265  {
8266  if (_wdfParameters.fc != wdfParameters.fc ||
8267  _wdfParameters.Q != wdfParameters.Q ||
8268  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8270  {
8271  wdfParameters = _wdfParameters;
8272  double fc_Hz = wdfParameters.fc;
8273 
8275  {
8276  double arg = (kPi*fc_Hz) / sampleRate;
8277  fc_Hz = fc_Hz*(tan(arg) / arg);
8278  }
8279 
8280  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8281  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8282 
8283  seriesAdaptor_RL.setComponentValue_RL(resistorValue, inductorValue);
8285  }
8286  }
8287 
8288 protected:
8290 
8291  // --- adapters
8294 
8295  double sampleRate = 1.0;
8296 
8297 };
8298 
8317 {
8318 public:
8319  WDFIdealRLCHPF(void) { createWDF(); } /* C-TOR */
8320  ~WDFIdealRLCHPF(void) {} /* D-TOR */
8321 
8323  virtual bool reset(double _sampleRate)
8324  {
8325  sampleRate = _sampleRate;
8326  // --- rest WDF components (flush state registers)
8327  seriesAdaptor_RC.reset(_sampleRate);
8328  parallelTerminatedAdaptor_L.reset(_sampleRate);
8329 
8330  // --- intialize the chain of adapters
8332  return true;
8333  }
8334 
8336  virtual bool canProcessAudioFrame() { return false; }
8337 
8343  virtual double processAudioSample(double xn)
8344  {
8345  // --- push audio sample into series L1
8347 
8348  // --- output is at terminated L2's output2
8349  // note compensation scaling by -6dB = 0.5
8350  // because of WDF assumption about Rs and Rload
8352  }
8353 
8355  void createWDF()
8356  {
8357  // --- create components, init to noramlized values fc =
8358  // initial values for fc = 1kHz Q = 0.707
8359  // Holding C Constant at 1e-6
8360  // L = 2.533e-2
8361  // R = 2.251131 e2
8362  seriesAdaptor_RC.setComponent(wdfComponent::seriesRC, 2.251131e2, 1.0e-6);
8363  parallelTerminatedAdaptor_L.setComponent(wdfComponent::L, 2.533e-2);
8364 
8365  // --- connect adapters
8367 
8368  // --- set source resistance
8369  seriesAdaptor_RC.setSourceResistance(0.0); // --- Rs = 600
8370 
8371  // --- set open ckt termination
8373  }
8374 
8380 
8385  void setParameters(const WDFParameters& _wdfParameters)
8386  {
8387  if (_wdfParameters.fc != wdfParameters.fc ||
8388  _wdfParameters.Q != wdfParameters.Q ||
8389  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8391  {
8392  wdfParameters = _wdfParameters;
8393  double fc_Hz = wdfParameters.fc;
8394 
8396  {
8397  double arg = (kPi*fc_Hz) / sampleRate;
8398  fc_Hz = fc_Hz*(tan(arg) / arg);
8399  }
8400 
8401  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8402  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8403 
8404  seriesAdaptor_RC.setComponentValue_RC(resistorValue, 1.0e-6);
8407  }
8408  }
8409 
8410 
8411 protected:
8413 
8414  // --- three
8417 
8418  double sampleRate = 1.0;
8419 };
8420 
8439 {
8440 public:
8441  WDFIdealRLCBPF(void) { createWDF(); } /* C-TOR */
8442  ~WDFIdealRLCBPF(void) {} /* D-TOR */
8443 
8445  virtual bool reset(double _sampleRate)
8446  {
8447  sampleRate = _sampleRate;
8448  // --- rest WDF components (flush state registers)
8449  seriesAdaptor_LC.reset(_sampleRate);
8450  parallelTerminatedAdaptor_R.reset(_sampleRate);
8451 
8452  // --- intialize the chain of adapters
8454  return true;
8455  }
8456 
8458  virtual bool canProcessAudioFrame() { return false; }
8459 
8465  virtual double processAudioSample(double xn)
8466  {
8467  // --- push audio sample into series L1
8469 
8470  // --- output is at terminated L2's output2
8471  // note compensation scaling by -6dB = 0.5
8472  // because of WDF assumption about Rs and Rload
8474  }
8475 
8477  void createWDF()
8478  {
8479  // --- create components, init to noramlized values fc =
8480  // initial values for fc = 1kHz Q = 0.707
8481  // Holding C Constant at 1e-6
8482  // L = 2.533e-2
8483  // R = 2.251131 e2
8484  seriesAdaptor_LC.setComponent(wdfComponent::seriesLC, 2.533e-2, 1.0e-6);
8485  parallelTerminatedAdaptor_R.setComponent(wdfComponent::R, 2.251131e2);
8486 
8487  // --- connect adapters
8489 
8490  // --- set source resistance
8491  seriesAdaptor_LC.setSourceResistance(0.0); // --- Rs = 600
8492 
8493  // --- set open ckt termination
8495  }
8496 
8502 
8507  void setParameters(const WDFParameters& _wdfParameters)
8508  {
8509  if (_wdfParameters.fc != wdfParameters.fc ||
8510  _wdfParameters.Q != wdfParameters.Q ||
8511  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8513  {
8514  wdfParameters = _wdfParameters;
8515  double fc_Hz = wdfParameters.fc;
8516 
8518  {
8519  double arg = (kPi*fc_Hz) / sampleRate;
8520  fc_Hz = fc_Hz*(tan(arg) / arg);
8521  }
8522 
8523  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8524  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8525 
8526  seriesAdaptor_LC.setComponentValue_LC(inductorValue, 1.0e-6);
8529  }
8530  }
8531 
8532 protected:
8534 
8535  // --- adapters
8538 
8539  double sampleRate = 1.0;
8540 };
8541 
8542 
8561 {
8562 public:
8563  WDFIdealRLCBSF(void) { createWDF(); } /* C-TOR */
8564  ~WDFIdealRLCBSF(void) {} /* D-TOR */
8565 
8567  virtual bool reset(double _sampleRate)
8568  {
8569  sampleRate = _sampleRate;
8570  // --- rest WDF components (flush state registers)
8571  seriesAdaptor_R.reset(_sampleRate);
8572  parallelTerminatedAdaptor_LC.reset(_sampleRate);
8573 
8574  // --- intialize the chain of adapters
8576  return true;
8577  }
8578 
8580  virtual bool canProcessAudioFrame() { return false; }
8581 
8587  virtual double processAudioSample(double xn)
8588  {
8589  // --- push audio sample into series L1
8591 
8592  // --- output is at terminated L2's output2
8593  // note compensation scaling by -6dB = 0.5
8594  // because of WDF assumption about Rs and Rload
8596  }
8597 
8599  void createWDF()
8600  {
8601  // --- create components, init to noramlized values fc =
8602  // initial values for fc = 1kHz Q = 0.707
8603  // Holding C Constant at 1e-6
8604  // L = 2.533e-2
8605  // R = 2.251131 e2
8606  seriesAdaptor_R.setComponent(wdfComponent::R, 2.533e-2);
8607  parallelTerminatedAdaptor_LC.setComponent(wdfComponent::seriesLC, 2.533e-2, 1.0e-6);
8608 
8609  // --- connect adapters
8611 
8612  // --- set source resistance
8613  seriesAdaptor_R.setSourceResistance(0.0); // --- Rs = 600
8614 
8615  // --- set open ckt termination
8617  }
8618 
8624 
8629  void setParameters(const WDFParameters& _wdfParameters)
8630  {
8631  if (_wdfParameters.fc != wdfParameters.fc ||
8632  _wdfParameters.Q != wdfParameters.Q ||
8633  _wdfParameters.boostCut_dB != wdfParameters.boostCut_dB ||
8635  {
8636  wdfParameters = _wdfParameters;
8637  double fc_Hz = wdfParameters.fc;
8638 
8640  {
8641  double arg = (kPi*fc_Hz) / sampleRate;
8642  fc_Hz = fc_Hz*(tan(arg) / arg);
8643  }
8644 
8645  double inductorValue = 1.0 / (1.0e-6 * pow((2.0*kPi*fc_Hz), 2.0));
8646  double resistorValue = (1.0 / wdfParameters.Q)*(pow(inductorValue / 1.0e-6, 0.5));
8647 
8648  seriesAdaptor_R.setComponentValue(resistorValue);
8649  parallelTerminatedAdaptor_LC.setComponentValue_LC(inductorValue, 1.0e-6);
8651  }
8652  }
8653 
8654 protected:
8656 
8657  // --- adapters
8660 
8661  double sampleRate = 1.0;
8662 };
8663 
8664 
8665 // ------------------------------------------------------------------ //
8666 // --- OBJECTS REQUIRING FFTW --------------------------------------- //
8667 // ------------------------------------------------------------------ //
8668 
8682 enum class windowType {kNoWindow, kRectWindow, kHannWindow, kBlackmanHarrisWindow, kHammingWindow };
8683 
8694 inline std::unique_ptr<double[]> makeWindow(unsigned int windowLength, unsigned int hopSize, windowType window, double& gainCorrectionValue)
8695 {
8696  std::unique_ptr<double[]> windowBuffer;
8697  windowBuffer.reset(new double[windowLength]);
8698 
8699  if (!windowBuffer) return nullptr;
8700 
8701  double overlap = hopSize > 0.0 ? 1.0 - (double)hopSize / (double)windowLength : 0.0;
8702  gainCorrectionValue = 0.0;
8703 
8704  for (int n = 0; n < windowLength; n++)
8705  {
8706  if (window == windowType::kRectWindow)
8707  {
8708  if (n >= 1 && n <= windowLength - 1)
8709  windowBuffer[n] = 1.0;
8710  }
8711  else if (window == windowType::kHammingWindow)
8712  {
8713  windowBuffer[n] = 0.54 - 0.46*cos((n*2.0*kPi) / (windowLength));
8714  }
8715  else if (window == windowType::kHannWindow)
8716  {
8717  windowBuffer[n] = 0.5 * (1 - cos((n*2.0*kPi) / (windowLength)));
8718  }
8719  else if (window == windowType::kBlackmanHarrisWindow)
8720  {
8721  windowBuffer[n] = (0.42323 - (0.49755*cos((n*2.0*kPi) / (windowLength))) + 0.07922*cos((2 * n*2.0*kPi) / (windowLength)));
8722  }
8723  else if (window == windowType::kNoWindow)
8724  {
8725  windowBuffer[n] = 1.0;
8726  }
8727 
8728  gainCorrectionValue += windowBuffer[n];
8729  }
8730 
8731  // --- calculate gain correction factor
8732  if (window != windowType::kNoWindow)
8733  gainCorrectionValue = (1.0 - overlap) / gainCorrectionValue;
8734  else
8735  gainCorrectionValue = 1.0 / gainCorrectionValue;
8736 
8737  return windowBuffer;
8738 }
8739 
8740 #define HAVE_FFTW
8741 
8742 // --- FFTW ---
8743 #ifdef HAVE_FFTW
8744 #include "fftw3.h"
8745 
8763 class FastFFT
8764 {
8765 public:
8766  FastFFT() {} /* C-TOR */
8767  ~FastFFT() {
8768  if (windowBuffer) delete[] windowBuffer;
8769  destroyFFTW();
8770  } /* D-TOR */
8771 
8773  void initialize(unsigned int _frameLength, windowType _window);
8774 
8776  void destroyFFTW();
8777 
8779  fftw_complex* doFFT(double* inputReal, double* inputImag = nullptr);
8780 
8782  fftw_complex* doInverseFFT(double* inputReal, double* inputImag);
8783 
8785  unsigned int getFrameLength() { return frameLength; }
8786 
8787 protected:
8788  // --- setup FFTW
8789  fftw_complex* fft_input = nullptr;
8790  fftw_complex* fft_result = nullptr;
8791  fftw_complex* ifft_input = nullptr;
8792  fftw_complex* ifft_result = nullptr;
8793  fftw_plan plan_forward = nullptr;
8794  fftw_plan plan_backward = nullptr;
8795 
8796  double* windowBuffer = nullptr;
8797  double windowGainCorrection = 1.0;
8798  windowType window = windowType::kHannWindow;
8799  unsigned int frameLength = 0;
8800 };
8801 
8802 
8823 {
8824 public:
8825  PhaseVocoder() {} /* C-TOR */
8826  ~PhaseVocoder() {
8827  if (inputBuffer) delete[] inputBuffer;
8828  if (outputBuffer) delete[] outputBuffer;
8829  if (windowBuffer) delete[] windowBuffer;
8830  destroyFFTW();
8831  } /* D-TOR */
8832 
8834  void initialize(unsigned int _frameLength, unsigned int _hopSize, windowType _window);
8835 
8837  void destroyFFTW();
8838 
8840  double processAudioSample(double input, bool& fftReady);
8841 
8843  bool addZeroPad(unsigned int count);
8844 
8846  bool advanceAndCheckFFT();
8847 
8849  fftw_complex* getFFTData() { return fft_result; }
8850 
8852  fftw_complex* getIFFTData() { return ifft_result; }
8853 
8855  void doInverseFFT();
8856 
8858  void doOverlapAdd(double* outputData = nullptr, int length = 0);
8859 
8861  unsigned int getFrameLength() { return frameLength; }
8862 
8864  unsigned int getHopSize() { return hopSize; }
8865 
8867  double getOverlap() { return overlap; }
8868 
8870  // --- for fast convolution and other overlap-add algorithms
8871  // that are not hop-size dependent
8872  void setOverlapAddOnly(bool b){ bool overlapAddOnly = b; }
8873 
8874 protected:
8875  // --- setup FFTW
8876  fftw_complex* fft_input = nullptr;
8877  fftw_complex* fft_result = nullptr;
8878  fftw_complex* ifft_result = nullptr;
8879  fftw_plan plan_forward = nullptr;
8880  fftw_plan plan_backward = nullptr;
8881 
8882  // --- linear buffer for window
8883  double* windowBuffer = nullptr;
8884 
8885  // --- circular buffers for input and output
8886  double* inputBuffer = nullptr;
8887  double* outputBuffer = nullptr;
8888 
8889  // --- index and wrap masks for input and output buffers
8890  unsigned int inputWriteIndex = 0;
8891  unsigned int outputWriteIndex = 0;
8892  unsigned int inputReadIndex = 0;
8893  unsigned int outputReadIndex = 0;
8894  unsigned int wrapMask = 0;
8895  unsigned int wrapMaskOut = 0;
8896 
8897  // --- amplitude correction factor, aking into account both hopsize (overlap)
8898  // and the window power itself
8899  double windowHopCorrection = 1.0;
8900 
8901  // --- these allow a more robust combination of user interaction
8902  bool needInverseFFT = false;
8903  bool needOverlapAdd = false;
8904 
8905  // --- our window type; you can add more windows if you like
8906  windowType window = windowType::kHannWindow;
8907 
8908  // --- counters
8909  unsigned int frameLength = 0;
8910  unsigned int fftCounter = 0;
8911 
8912  // --- hop-size and overlap (mathematically related)
8913  unsigned int hopSize = 0;
8914  double overlap = 1.0;
8915 
8916  // --- flag for overlap-add algorithms that do not involve hop-size, other
8917  // than setting the overlap
8918  bool overlapAddOnly = false;
8919 
8920 };
8921 
8942 {
8943 public:
8944  FastConvolver() {
8945  vocoder.setOverlapAddOnly(true);
8946  } /* C-TOR */
8947  ~FastConvolver() {
8948  if (filterIR)
8949  delete[] filterIR;
8950 
8951  if (filterFFT)
8952  fftw_free(filterFFT);
8953  } /* D-TOR */
8954 
8959  void initialize(unsigned int _filterImpulseLength)
8960  {
8961  if (filterImpulseLength == _filterImpulseLength)
8962  return;
8963 
8964  // --- setup a specialized vocoder with 50% hop size
8965  filterImpulseLength = _filterImpulseLength;
8966  vocoder.initialize(filterImpulseLength * 2, filterImpulseLength, windowType::kNoWindow);
8967 
8968  // --- initialize the FFT object for capturing the filter FFT
8969  filterFastFFT.initialize(filterImpulseLength * 2, windowType::kNoWindow);
8970 
8971  // --- array to hold the filter IR; this could be localized to the particular function that uses it
8972  if (filterIR)
8973  delete [] filterIR;
8974  filterIR = new double[filterImpulseLength * 2];
8975  memset(&filterIR[0], 0, filterImpulseLength * 2 * sizeof(double));
8976 
8977  // --- allocate the filter FFT arrays
8978  if(filterFFT)
8979  fftw_free(filterFFT);
8980 
8981  filterFFT = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * filterImpulseLength * 2);
8982 
8983  // --- reset
8984  inputCount = 0;
8985  }
8986 
8988  void setFilterIR(double* irBuffer)
8989  {
8990  if (!irBuffer) return;
8991 
8992  memset(&filterIR[0], 0, filterImpulseLength * 2 * sizeof(double));
8993 
8994  // --- copy over first half; filterIR len = filterImpulseLength * 2
8995  int m = 0;
8996  for (unsigned int i = 0; i < filterImpulseLength; i++)
8997  {
8998  filterIR[i] = irBuffer[i];
8999  }
9000 
9001  // --- take FFT of the h(n)
9002  fftw_complex* fftOfFilter = filterFastFFT.doFFT(&filterIR[0]);
9003 
9004  // --- copy the FFT into our local buffer for storage; also
9005  // we never want to hold a pointer to a FFT output
9006  // for more than one local function's worth
9007  // could replace with memcpy( )
9008  for (int i = 0; i < 2; i++)
9009  {
9010  for (unsigned int j = 0; j < filterImpulseLength * 2; j++)
9011  {
9012  filterFFT[j][i] = fftOfFilter[j][i];
9013  }
9014  }
9015  }
9016 
9018  double processAudioSample(double input)
9019  {
9020  bool fftReady = false;
9021  double output = 0.0;
9022 
9024  {
9026 
9027  if (fftReady) // should happen on time
9028  {
9029  // --- multiply our filter IR with the vocoder FFT
9030  fftw_complex* signalFFT = vocoder.getFFTData();
9031  if (signalFFT)
9032  {
9033  unsigned int fff = vocoder.getFrameLength();
9034 
9035  // --- complex multiply with FFT of IR
9036  for (unsigned int i = 0; i < filterImpulseLength * 2; i++)
9037  {
9038  // --- get real/imag parts of each FFT
9039  ComplexNumber signal(signalFFT[i][0], signalFFT[i][1]);
9040  ComplexNumber filter(filterFFT[i][0], filterFFT[i][1]);
9041 
9042  // --- use complex multiply function; this convolves in the time domain
9043  ComplexNumber product = complexMultiply(signal, filter);
9044 
9045  // --- overwrite the FFT bins
9046  signalFFT[i][0] = product.real;
9047  signalFFT[i][1] = product.imag;
9048  }
9049  }
9050  }
9051 
9052  // --- reset counter
9053  inputCount = 0;
9054  }
9055 
9056  // --- process next sample
9057  output = vocoder.processAudioSample(input, fftReady);
9058  inputCount++;
9059 
9060  return output;
9061  }
9062 
9064  unsigned int getFrameLength() { return vocoder.getFrameLength(); }
9065 
9067  unsigned int getFilterIRLength() { return filterImpulseLength; }
9068 
9069 protected:
9072  fftw_complex* filterFFT = nullptr;
9073  double* filterIR = nullptr;
9074  unsigned int inputCount = 0;
9075  unsigned int filterImpulseLength = 0;
9076 };
9077 
9078 // --- PSM Vocoder
9079 const unsigned int PSM_FFT_LEN = 4096;
9080 
9094 struct BinData
9095 {
9096  BinData() {}
9098  BinData& operator=(const BinData& params) // need this override for collections to work
9099  {
9100  if (this == &params)
9101  return *this;
9102 
9103  isPeak = params.isPeak;
9104  magnitude = params.magnitude;
9105  phi = params.phi;
9106 
9107  psi = params.psi;
9108  localPeakBin = params.localPeakBin;
9110  updatedPhase = params.updatedPhase;
9111 
9112  return *this;
9113  }
9114 
9116  void reset()
9117  {
9118  isPeak = false;
9119  magnitude = 0.0;
9120  phi = 0.0;
9121 
9122  psi = 0.0;
9123  localPeakBin = 0;
9124  previousPeakBin = -1; // -1 is flag
9125  updatedPhase = 0.0;
9126  }
9127 
9128  bool isPeak = false;
9129  double magnitude = 0.0;
9130  double phi = 0.0;
9131  double psi = 0.0;
9132  unsigned int localPeakBin = 0;
9133  int previousPeakBin = -1;
9134  double updatedPhase = 0.0;
9135 };
9136 
9149 {
9152  PSMVocoderParameters& operator=(const PSMVocoderParameters& params) // need this override for collections to work
9153  {
9154  if (this == &params)
9155  return *this;
9156 
9160 
9161  return *this;
9162  }
9163 
9164  // --- params
9165  double pitchShiftSemitones = 0.0;
9167  bool enablePeakTracking = false;
9168 };
9169 
9189 {
9190 public:
9191  PSMVocoder() {
9192  vocoder.initialize(PSM_FFT_LEN, PSM_FFT_LEN/4, windowType::kHannWindow); // 75% overlap
9193  } /* C-TOR */
9194  ~PSMVocoder() {
9195  if (windowBuff) delete[] windowBuff;
9196  if (outputBuff) delete[] outputBuff;
9197 
9198  } /* D-TOR */
9199 
9201  virtual bool reset(double _sampleRate)
9202  {
9203  memset(&phi[0], 0, sizeof(double)*PSM_FFT_LEN);
9204  memset(&psi[0], 0, sizeof(double)* PSM_FFT_LEN);
9205  if(outputBuff)
9206  memset(outputBuff, 0, sizeof(double)*outputBufferLength);
9207 
9208  for (int i = 0; i < PSM_FFT_LEN; i++)
9209  {
9210  binData[i].reset();
9211  binDataPrevious[i].reset();
9212 
9213  peakBins[i] = -1;
9214  peakBinsPrevious[i] = -1;
9215  }
9216 
9217  return true;
9218  }
9219 
9221  virtual bool canProcessAudioFrame() { return false; }
9222 
9224  void setPitchShift(double semitones)
9225  {
9226  // --- this is costly so only update when things changed
9227  double newAlpha = pow(2.0, semitones / 12.0);
9228  double newOutputBufferLength = round((1.0/newAlpha)*(double)PSM_FFT_LEN);
9229 
9230  // --- check for change
9231  if (newOutputBufferLength == outputBufferLength)
9232  return;
9233 
9234  // --- new stuff
9235  alphaStretchRatio = newAlpha;
9236  ha = hs / alphaStretchRatio;
9237 
9238  // --- set output resample buffer
9239  outputBufferLength = newOutputBufferLength;
9240 
9241  // --- create Hann window
9242  if (windowBuff) delete[] windowBuff;
9243  windowBuff = new double[outputBufferLength];
9244  windowCorrection = 0.0;
9245  for (unsigned int i = 0; i < outputBufferLength; i++)
9246  {
9247  windowBuff[i] = 0.5 * (1.0 - cos((i*2.0*kPi) / (outputBufferLength)));
9249  }
9251 
9252  // --- create output buffer
9253  if (outputBuff) delete[] outputBuff;
9254  outputBuff = new double[outputBufferLength];
9255  memset(outputBuff, 0, sizeof(double)*outputBufferLength);
9256  }
9257 
9259  int findPreviousNearestPeak(int peakIndex)
9260  {
9261  if (peakBinsPrevious[0] == -1) // first run, there is no peak
9262  return -1;
9263 
9264  int delta = -1;
9265  int previousPeak = -1;
9266  for (int i = 0; i < PSM_FFT_LEN; i++)
9267  {
9268  if (peakBinsPrevious[i] < 0)
9269  break;
9270 
9271  int dist = abs(peakIndex - peakBinsPrevious[i]);
9272  if (dist > PSM_FFT_LEN/4)
9273  break;
9274 
9275  if (i == 0)
9276  {
9277  previousPeak = i;
9278  delta = dist;
9279  }
9280  else if (dist < delta)
9281  {
9282  previousPeak = i;
9283  delta = dist;
9284  }
9285  }
9286 
9287  return previousPeak;
9288  }
9289 
9292  {
9293  // --- FIND PEAKS --- //
9294  //
9295  // --- find local maxima in 4-sample window
9296  double localWindow[4] = { 0.0 };
9297  int m = 0;
9298  for (int i = 0; i < PSM_FFT_LEN; i++)
9299  {
9300  if (i == 0)
9301  {
9302  localWindow[0] = 0.0;
9303  localWindow[1] = 0.0;
9304  localWindow[2] = binData[i + 1].magnitude;
9305  localWindow[3] = binData[i + 2].magnitude;
9306  }
9307  else if (i == 1)
9308  {
9309  localWindow[0] = 0.0;
9310  localWindow[1] = binData[i - 1].magnitude;
9311  localWindow[2] = binData[i + 1].magnitude;
9312  localWindow[3] = binData[i + 2].magnitude;
9313  }
9314  else if (i == PSM_FFT_LEN - 1)
9315  {
9316  localWindow[0] = binData[i - 2].magnitude;
9317  localWindow[1] = binData[i - 1].magnitude;
9318  localWindow[2] = 0.0;
9319  localWindow[3] = 0.0;
9320  }
9321  else if (i == PSM_FFT_LEN - 2)
9322  {
9323  localWindow[0] = binData[i - 2].magnitude;
9324  localWindow[1] = binData[i - 1].magnitude;
9325  localWindow[2] = binData[i + 1].magnitude;
9326  localWindow[3] = 0.0;
9327  }
9328  else
9329  {
9330  localWindow[0] = binData[i - 2].magnitude;
9331  localWindow[1] = binData[i - 1].magnitude;
9332  localWindow[2] = binData[i + 1].magnitude;
9333  localWindow[3] = binData[i + 2].magnitude;
9334  }
9335 
9336  // --- found peak bin!
9337  if (binData[i].magnitude > 0.00001 &&
9338  binData[i].magnitude > localWindow[0]
9339  && binData[i].magnitude > localWindow[1]
9340  && binData[i].magnitude > localWindow[2]
9341  && binData[i].magnitude > localWindow[3])
9342  {
9343  binData[i].isPeak = true;
9344  peakBins[m++] = i;
9345 
9346  // --- for peak bins, assume that it is part of a previous, moving peak
9349  else
9350  binData[i].previousPeakBin = -1;
9351  }
9352  }
9353 
9354  // --- assign peak bosses
9355  if (m > 0)
9356  {
9357  int n = 0;
9358  int bossPeakBin = peakBins[n];
9359  double nextPeak = peakBins[++n];
9360  int midBoundary = (nextPeak - (double)bossPeakBin) / 2.0 + bossPeakBin;
9361 
9362  if (nextPeak >= 0)
9363  {
9364  for (int i = 0; i < PSM_FFT_LEN; i++)
9365  {
9366  if (i <= bossPeakBin)
9367  {
9368  binData[i].localPeakBin = bossPeakBin;
9369  }
9370  else if (i < midBoundary)
9371  {
9372  binData[i].localPeakBin = bossPeakBin;
9373  }
9374  else // > boundary, calc next set
9375  {
9376  bossPeakBin = nextPeak;
9377  nextPeak = peakBins[++n];
9378  if (nextPeak > bossPeakBin)
9379  midBoundary = (nextPeak - (double)bossPeakBin) / 2.0 + bossPeakBin;
9380  else // nextPeak == -1
9381  midBoundary = PSM_FFT_LEN;
9382 
9383  binData[i].localPeakBin = bossPeakBin;
9384  }
9385  }
9386  }
9387  }
9388  }
9389 
9395  virtual double processAudioSample(double input)
9396  {
9397  bool fftReady = false;
9398  double output = 0.0;
9399 
9400  // --- normal processing
9401  output = vocoder.processAudioSample(input, fftReady);
9402 
9403  // --- if FFT is here, GO!
9404  if (fftReady)
9405  {
9406  // --- get the FFT data
9407  fftw_complex* fftData = vocoder.getFFTData();
9408 
9410  {
9411  // --- get the magnitudes for searching
9412  for (int i = 0; i < PSM_FFT_LEN; i++)
9413  {
9414  binData[i].reset();
9415  peakBins[i] = -1;
9416 
9417  // --- store mag and phase
9418  binData[i].magnitude = getMagnitude(fftData[i][0], fftData[i][1]);
9419  binData[i].phi = getPhase(fftData[i][0], fftData[i][1]);
9420  }
9421 
9423 
9424  // --- each bin data should now know its local boss-peak
9425  //
9426  // --- now propagate phases accordingly
9427  //
9428  // FIRST: set PSI angles of bosses
9429  for (int i = 0; i < PSM_FFT_LEN; i++)
9430  {
9431  double mag_k = binData[i].magnitude;
9432  double phi_k = binData[i].phi;
9433 
9434  // --- horizontal phase propagation
9435  //
9436  // --- omega_k = bin frequency(k)
9437  double omega_k = kTwoPi*i / PSM_FFT_LEN;
9438 
9439  // --- phase deviation is actual - expected phase
9440  // = phi_k -(phi(last frame) + wk*ha
9441  double phaseDev = phi_k - phi[i] - omega_k*ha;
9442 
9443  // --- unwrapped phase increment
9444  double deltaPhi = omega_k*ha + principalArg(phaseDev);
9445 
9446  // --- save for next frame
9447  phi[i] = phi_k;
9448 
9449  // --- if peak, assume it could have hopped from a different bin
9450  if (binData[i].isPeak)
9451  {
9452  // --- calculate new phase based on stretch factor; save phase for next time
9453  if(binData[i].previousPeakBin < 0)
9454  psi[i] = principalArg(psi[i] + deltaPhi * alphaStretchRatio);
9455  else
9456  psi[i] = principalArg(psi[binDataPrevious[i].previousPeakBin] + deltaPhi * alphaStretchRatio);
9457  }
9458 
9459  // --- save peak PSI (new angle)
9460  binData[i].psi = psi[i];
9461 
9462  // --- for IFFT
9463  binData[i].updatedPhase = binData[i].psi;
9464  }
9465 
9466  // --- now set non-peaks
9467  for (int i = 0; i < PSM_FFT_LEN; i++)
9468  {
9469  if (!binData[i].isPeak)
9470  {
9471  int myPeakBin = binData[i].localPeakBin;
9472 
9473  double PSI_kp = binData[myPeakBin].psi;
9474  double phi_kp = binData[myPeakBin].phi;
9475 
9476  // --- save for next frame
9477  // phi[i] = binData[myPeakBin].phi;
9478 
9479  // --- calculate new phase, locked to boss peak
9480  psi[i] = principalArg(PSI_kp - phi_kp - binData[i].phi);
9481  binData[i].updatedPhase = psi[i];// principalArg(PSI_kp - phi_kp - binData[i].phi);
9482  }
9483  }
9484 
9485  for (int i = 0; i < PSM_FFT_LEN; i++)
9486  {
9487  double mag_k = binData[i].magnitude;
9488 
9489  // --- convert back
9490  fftData[i][0] = mag_k*cos(binData[i].updatedPhase);
9491  fftData[i][1] = mag_k*sin(binData[i].updatedPhase);
9492 
9493  // --- save for next frame
9494  binDataPrevious[i] = binData[i];
9495  peakBinsPrevious[i] = peakBins[i];
9496 
9497  }
9498  }// end if peak locking
9499 
9500  else // ---> old school
9501  {
9502  for (int i = 0; i < PSM_FFT_LEN; i++)
9503  {
9504  double mag_k = getMagnitude(fftData[i][0], fftData[i][1]);
9505  double phi_k = getPhase(fftData[i][0], fftData[i][1]);
9506 
9507  // --- horizontal phase propagation
9508  //
9509  // --- omega_k = bin frequency(k)
9510  double omega_k = kTwoPi*i / PSM_FFT_LEN;
9511 
9512  // --- phase deviation is actual - expected phase
9513  // = phi_k -(phi(last frame) + wk*ha
9514  double phaseDev = phi_k - phi[i] - omega_k*ha;
9515 
9516  // --- unwrapped phase increment
9517  double deltaPhi = omega_k*ha + principalArg(phaseDev);
9518 
9519  // --- save for next frame
9520  phi[i] = phi_k;
9521 
9522  // --- calculate new phase based on stretch factor; save phase for next time
9523  psi[i] = principalArg(psi[i] + deltaPhi * alphaStretchRatio);
9524 
9525  // --- convert back
9526  fftData[i][0] = mag_k*cos(psi[i]);
9527  fftData[i][1] = mag_k*sin(psi[i]);
9528  }
9529  }
9530 
9531 
9532  // --- manually so the IFFT (OPTIONAL)
9534 
9535  // --- can get the iFFT buffers
9536  fftw_complex* inv_fftData = vocoder.getIFFTData();
9537 
9538  // --- make copy (can speed this up)
9539  double ifft[PSM_FFT_LEN] = { 0.0 };
9540  for (int i = 0; i < PSM_FFT_LEN; i++)
9541  ifft[i] = inv_fftData[i][0];
9542 
9543  // --- resample the audio as if it were stretched
9544  resample(&ifft[0], outputBuff, PSM_FFT_LEN, outputBufferLength, interpolation::kLinear, windowCorrection, windowBuff);
9545 
9546  // --- overlap-add the interpolated buffer to complete the operation
9548  }
9549 
9550  return output;
9551  }
9552 
9558  {
9559  return parameters;
9560  }
9561 
9567  {
9569  {
9571  }
9572 
9573  // --- save
9574  parameters = params;
9575  }
9576 
9577 protected:
9580  double alphaStretchRatio = 1.0;
9581 
9582  // --- FFT is 4096 with 75% overlap
9583  const double hs = PSM_FFT_LEN / 4;
9584  double ha = PSM_FFT_LEN / 4;
9585  double phi[PSM_FFT_LEN] = { 0.0 };
9586  double psi[PSM_FFT_LEN] = { 0.0 };
9587 
9588  // --- for peak-locking
9589  BinData binData[PSM_FFT_LEN];
9590  BinData binDataPrevious[PSM_FFT_LEN];
9591 
9592  int peakBins[PSM_FFT_LEN] = { -1 };
9593  int peakBinsPrevious[PSM_FFT_LEN] = { -1 };
9594 
9595  double* windowBuff = nullptr;
9596  double* outputBuff = nullptr;
9597  double windowCorrection = 0.0;
9598  unsigned int outputBufferLength = 0;
9599 };
9600 
9601 // --- sample rate conversion
9602 //
9603 // --- supported conversion ratios - you can EASILY add more to this
9617 enum class rateConversionRatio { k2x, k4x };
9618 const unsigned int maxSamplingRatio = 4;
9619 
9629 inline unsigned int countForRatio(rateConversionRatio ratio)
9630 {
9631  if (ratio == rateConversionRatio::k2x)
9632  return 2;
9633  else if (ratio == rateConversionRatio::k4x || ratio == rateConversionRatio::k4x)
9634  return 4;
9635 
9636  return 0;
9637 }
9638 
9639 // --- get table pointer for built-in anti-aliasing LPFs
9651 inline double* getFilterIRTable(unsigned int FIRLength, rateConversionRatio ratio, unsigned int sampleRate)
9652 {
9653  // --- we only have built in filters for 44.1 and 48 kHz
9654  if (sampleRate != 44100 && sampleRate != 48000) return nullptr;
9655 
9656  // --- choose 2xtable
9657  if (ratio == rateConversionRatio::k2x)
9658  {
9659  if (sampleRate == 44100)
9660  {
9661  if (FIRLength == 128)
9662  return &LPF128_882[0];
9663  else if (FIRLength == 256)
9664  return &LPF256_882[0];
9665  else if (FIRLength == 512)
9666  return &LPF512_882[0];
9667  else if (FIRLength == 1024)
9668  return &LPF1024_882[0];
9669  }
9670  if (sampleRate == 48000)
9671  {
9672  if (FIRLength == 128)
9673  return &LPF128_96[0];
9674  else if (FIRLength == 256)
9675  return &LPF256_96[0];
9676  else if (FIRLength == 512)
9677  return &LPF512_96[0];
9678  else if (FIRLength == 1024)
9679  return &LPF1024_96[0];
9680  }
9681  }
9682 
9683  // --- choose 4xtable
9684  if (ratio == rateConversionRatio::k4x)
9685  {
9686  if (sampleRate == 44100)
9687  {
9688  if (FIRLength == 128)
9689  return &LPF128_1764[0];
9690  else if (FIRLength == 256)
9691  return &LPF256_1764[0];
9692  else if (FIRLength == 512)
9693  return &LPF512_1764[0];
9694  else if (FIRLength == 1024)
9695  return &LPF1024_1764[0];
9696  }
9697  if (sampleRate == 48000)
9698  {
9699  if (FIRLength == 128)
9700  return &LPF128_192[0];
9701  else if (FIRLength == 256)
9702  return &LPF256_192[0];
9703  else if (FIRLength == 512)
9704  return &LPF512_192[0];
9705  else if (FIRLength == 1024)
9706  return &LPF1024_192[0];
9707  }
9708  }
9709  return nullptr;
9710 }
9711 
9712 // --- get table pointer for built-in anti-aliasing LPFs
9724 inline double** decomposeFilter(double* filterIR, unsigned int FIRLength, unsigned int ratio)
9725 {
9726  unsigned int subBandLength = FIRLength / ratio;
9727  double ** polyFilterSet = new double*[ratio];
9728  for (unsigned int i = 0; i < ratio; i++)
9729  {
9730  double* polyFilter = new double[subBandLength];
9731  polyFilterSet[i] = polyFilter;
9732  }
9733 
9734  int m = 0;
9735  for (int i = 0; i < subBandLength; i++)
9736  {
9737  for (int j = ratio - 1; j >= 0; j--)
9738  {
9739  double* polyFilter = polyFilterSet[j];
9740  polyFilter[i] = filterIR[m++];
9741  }
9742  }
9743 
9744  return polyFilterSet;
9745 }
9746 
9759 {
9760  InterpolatorOutput() {}
9761  double audioData[maxSamplingRatio] = { 0.0 };
9762  unsigned int count = maxSamplingRatio;
9763 };
9764 
9765 
9784 {
9785 public:
9786  Interpolator() { } /* C-TOR */
9787  ~Interpolator() { } /* D-TOR */
9788 
9796  inline void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase = true)
9797  {
9798  polyphase = _polyphase;
9799  sampleRate = _sampleRate;
9800  FIRLength = _FIRLength;
9801  ratio = _ratio;
9802  unsigned int count = countForRatio(ratio);
9803  unsigned int subBandLength = FIRLength / count;
9804 
9805  // --- straight SRC, no polyphase
9807 
9808  // --- set filterIR from built-in set - user can always override this!
9809  double* filterTable = getFilterIRTable(FIRLength, ratio, sampleRate);
9810  if (!filterTable) return;
9811  convolver.setFilterIR(filterTable);
9812 
9813  if (!polyphase) return;
9814 
9815  // --- decompose filter
9816  double** polyPhaseFilters = decomposeFilter(filterTable, FIRLength, count);
9817  if (!polyPhaseFilters)
9818  {
9819  polyphase = false;
9820  return;
9821  }
9822 
9823  // --- set the individual polyphase filter IRs on the convolvers
9824  for (unsigned int i = 0; i < count; i++)
9825  {
9826  polyPhaseConvolvers[i].initialize(subBandLength);
9827  polyPhaseConvolvers[i].setFilterIR(polyPhaseFilters[i]);
9828  delete[] polyPhaseFilters[i];
9829  }
9830 
9831  delete[] polyPhaseFilters;
9832  }
9833 
9836  {
9837  unsigned int count = countForRatio(ratio);
9838 
9839  // --- setup output
9840  InterpolatorOutput output;
9841  output.count = count;
9842 
9843  // --- interpolators need the amp correction
9844  double ampCorrection = double(count);
9845 
9846  // --- polyphase uses "backwards" indexing for interpolator; see book
9847  int m = count-1;
9848  for (unsigned int i = 0; i < count; i++)
9849  {
9850  if (!polyphase)
9851  output.audioData[i] = i == 0 ? ampCorrection*convolver.processAudioSample(xn) : ampCorrection*convolver.processAudioSample(0.0);
9852  else
9853  output.audioData[i] = ampCorrection*polyPhaseConvolvers[m--].processAudioSample(xn);
9854  }
9855  return output;
9856  }
9857 
9858 protected:
9859  // --- for straight, non-polyphase
9861 
9862  // --- we save these for future expansion, currently only sparsely used
9863  unsigned int sampleRate = 44100;
9864  unsigned int FIRLength = 256;
9865  rateConversionRatio ratio = rateConversionRatio::k2x;
9866 
9867  // --- polyphase: 4x is max right now
9868  bool polyphase = true;
9870 };
9871 
9884 {
9885  DecimatorInput() {}
9886  double audioData[maxSamplingRatio] = { 0.0 };
9887  unsigned int count = maxSamplingRatio;
9888 };
9889 
9909 {
9910 public:
9911  Decimator() { } /* C-TOR */
9912  ~Decimator() { } /* D-TOR */
9913 
9921  inline void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase = true)
9922  {
9923  polyphase = _polyphase;
9924  sampleRate = _sampleRate;
9925  FIRLength = _FIRLength;
9926  ratio = _ratio;
9927  unsigned int count = countForRatio(ratio);
9928  unsigned int subBandLength = FIRLength / count;
9929 
9930  // --- straight SRC, no polyphase
9932 
9933  // --- set filterIR from built-in set - user can always override this!
9934  double* filterTable = getFilterIRTable(FIRLength, ratio, sampleRate);
9935  if (!filterTable) return;
9936  convolver.setFilterIR(filterTable);
9937 
9938  if (!polyphase) return;
9939 
9940  // --- decompose filter
9941  double** polyPhaseFilters = decomposeFilter(filterTable, FIRLength, count);
9942  if (!polyPhaseFilters)
9943  {
9944  polyphase = false;
9945  return;
9946  }
9947 
9948  // --- set the individual polyphase filter IRs on the convolvers
9949  for (unsigned int i = 0; i < count; i++)
9950  {
9951  polyPhaseConvolvers[i].initialize(subBandLength);
9952  polyPhaseConvolvers[i].setFilterIR(polyPhaseFilters[i]);
9953  delete[] polyPhaseFilters[i];
9954  }
9955 
9956  delete[] polyPhaseFilters;
9957  }
9958 
9960  inline double decimateAudio(DecimatorInput data)
9961  {
9962  unsigned int count = countForRatio(ratio);
9963 
9964  // --- setup output
9965  double output = 0.0;
9966 
9967  // --- polyphase uses "forwards" indexing for decimator; see book
9968  for (unsigned int i = 0; i < count; i++)
9969  {
9970  if (!polyphase) // overwrites output; only the last output is saved
9971  output = convolver.processAudioSample(data.audioData[i]);
9972  else
9973  output += polyPhaseConvolvers[i].processAudioSample(data.audioData[i]);
9974  }
9975  return output;
9976  }
9977 
9978 protected:
9979  // --- for straight, non-polyphase
9981 
9982  // --- we save these for future expansion, currently only sparsely used
9983  unsigned int sampleRate = 44100;
9984  unsigned int FIRLength = 256;
9985  rateConversionRatio ratio = rateConversionRatio::k2x;
9986 
9987  // --- polyphase: 4x is max right now
9988  bool polyphase = true;
9990 };
9991 
9992 #endif
virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
Definition: fxobjects.h:6854
DFOscillatorStates
Use this non-typed enum to easily access the direct form oscillator state registers.
Definition: fxobjects.h:3131
rateConversionRatio ratio
conversion ration
Definition: fxobjects.h:9985
EnvelopeFollowerParameters parameters
object parameters
Definition: fxobjects.h:5552
virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
Definition: fxobjects.h:6731
virtual double getOutput()
Definition: fxobjects.h:6212
double componentValue_L
component value L
Definition: fxobjects.h:6673
double preDelayTime_mSec
pre-delay time in mSec
Definition: fxobjects.h:4729
Custom parameter structure for the LFO and DFOscillator objects.
Definition: fxobjects.h:2955
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6150
unsigned int getFrameLength()
Definition: fxobjects.h:9064
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1553
double attackTime_mSec
attack mSec
Definition: fxobjects.h:2020
unsigned int stopBin
ending bin for transition band
Definition: fxobjects.h:607
Custom parameter structure for the ModulatedDelay object.
Definition: fxobjects.h:3282
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5812
void createWDF()
Definition: fxobjects.h:8599
SimpleDelay delay
delay
Definition: fxobjects.h:4326
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8567
void setImpulseResponse(double *irArray, unsigned int lengthPowerOfTwo)
Definition: fxobjects.h:2466
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5882
bool frequencyWarping
enable frequency warping
Definition: fxobjects.h:8174
unsigned int getFilterIRLength()
Definition: fxobjects.h:9067
AudioDetectorParameters getParameters()
Definition: fxobjects.h:1909
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:639
virtual double getComponentConductance()
Definition: fxobjects.h:6107
void setParameters(const ReverbTankParameters &params)
Definition: fxobjects.h:4908
fftw_complex * fft_result
array for FFT output
Definition: fxobjects.h:8877
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6393
The WdfAdaptorBase object acts as the base class for all WDF Adaptors; the static members allow for s...
Definition: fxobjects.h:7133
double f_High
brickwall f_high
Definition: fxobjects.h:570
virtual double getComponentResistance()
Definition: fxobjects.h:6266
virtual double getOutput1()
Definition: fxobjects.h:6651
virtual double getOutput2()
Definition: fxobjects.h:6218
vaFilterAlgorithm
Use this strongly typed enum to easily set the virtual analog filter algorithm.
Definition: fxobjects.h:5112
double windowCorrection
window correction value
Definition: fxobjects.h:9597
virtual double getOutput3()
Definition: fxobjects.h:6903
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4284
virtual double getOutput3()
Definition: fxobjects.h:6415
void setParameters(const SimpleDelayParameters &params)
Definition: fxobjects.h:3889
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:8694
double zRegister_L
storage register for L
Definition: fxobjects.h:6792
TwoBandShelvingFilterParameters & operator=(const TwoBandShelvingFilterParameters &params)
Definition: fxobjects.h:4550
PSMVocoderParameters parameters
object parameters
Definition: fxobjects.h:9578
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6234
virtual void setInput(double in)
Definition: fxobjects.h:6885
SimpleLPFParameters & operator=(const SimpleLPFParameters &params)
Definition: fxobjects.h:3718
void setBeta(double _beta)
Definition: fxobjects.h:5363
void writeBuffer(unsigned int index, T input)
Definition: fxobjects.h:2257
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2429
virtual void setInput3(double _in3)
Definition: fxobjects.h:6309
bool detect_dB
detect in dB DEFAULT = false (linear NOT log)
Definition: fxobjects.h:1810
void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase=true)
Definition: fxobjects.h:9796
double audioData[maxSamplingRatio]
input array of samples to be decimated
Definition: fxobjects.h:9886
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6275
double RL
RL value.
Definition: fxobjects.h:7045
AudioFilterParameters & operator=(const AudioFilterParameters &params)
Definition: fxobjects.h:1485
virtual void setInput3(double _in3)
Definition: fxobjects.h:7720
double L
value of L component
Definition: fxobjects.h:7115
void setOpenTerminalResistance(bool _openTerminalResistance=true)
Definition: fxobjects.h:7143
double processAudioSample(double input)
Definition: fxobjects.h:9018
double audioData[maxSamplingRatio]
array of interpolated output samples
Definition: fxobjects.h:9761
wdfComponent componentType
selected component type
Definition: fxobjects.h:7117
bool interpolate
interpolate flag (diagnostics)
Definition: fxobjects.h:4177
fftw_complex * filterFFT
filterFFT output arrays
Definition: fxobjects.h:9072
Custom parameter structure for the LRFilterBank object which splits the input signal into multiple ba...
Definition: fxobjects.h:1643
unsigned int inputWriteIndex
circular buffer index: input write
Definition: fxobjects.h:8890
virtual double getOutput3()
Definition: fxobjects.h:6138
Custom parameter structure for the PhaseShifter object.
Definition: fxobjects.h:3474
AudioFilter apf[PHASER_STAGES]
six APF objects
Definition: fxobjects.h:3699
double sensitivity
detector sensitivity
Definition: fxobjects.h:5423
double RR
RR value.
Definition: fxobjects.h:6801
void setParameters(const DynamicsProcessorParameters &_parameters)
Definition: fxobjects.h:2088
Structure to hold a complex value.
Definition: fxobjects.h:468
double highShelfBoostCut_dB
high shelf gain
Definition: fxobjects.h:4566
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6739
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6803
double readDelay()
Definition: fxobjects.h:3935
double sampleRate
sample rate
Definition: fxobjects.h:3038
ModulatedDelayParameters getParameters()
Definition: fxobjects.h:3432
virtual double getComponentValue_R()
Definition: fxobjects.h:6756
generatorWaveform
Use this strongly typed enum to easily set the oscillator waveform.
Definition: fxobjects.h:2942
InterpolatorOutput interpolateAudio(double xn)
Definition: fxobjects.h:9835
void setParameters(AudioDelayParameters _parameters)
Definition: fxobjects.h:2857
double lowShelfBoostCut_dB
low shelf gain
Definition: fxobjects.h:4734
ZVAFilter filter
filter to modulate
Definition: fxobjects.h:5555
virtual double getComponentResistance()
Definition: fxobjects.h:6184
void setParameters(ModulatedDelayParameters _parameters)
Definition: fxobjects.h:3438
filterAlgorithm
Use this strongly typed enum to easily set the filter algorithm for the AudioFilter object or any oth...
Definition: fxobjects.h:1462
ClassATubePreParameters & operator=(const ClassATubePreParameters &params)
Definition: fxobjects.h:5756
TriodeClassAParameters getParameters()
Definition: fxobjects.h:5674
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1177
double RL
RL value.
Definition: fxobjects.h:6922
virtual double getOutput1()
Definition: fxobjects.h:6774
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L2
adaptor for L2
Definition: fxobjects.h:7947
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6615
Custom parameter structure for the Biquad object. Default version defines the biquad structure used i...
Definition: fxobjects.h:1336
double fc
filter fc
Definition: fxobjects.h:5418
double componentValue_R
component value R
Definition: fxobjects.h:6919
virtual void setInput3(double _in3)
Definition: fxobjects.h:6230
double out2
stored port 2 output; it is y(n) for this library
Definition: fxobjects.h:7302
double Q
filter Q
Definition: fxobjects.h:1500
virtual void setInput3(double _in3)
Definition: fxobjects.h:7035
unsigned int getHopSize()
Definition: fxobjects.h:8864
double alphaStretchRatio
alpha stretch ratio = hs/ha
Definition: fxobjects.h:9580
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3794
double highShelfBoostCut_dB
high shelf gain
Definition: fxobjects.h:4736
virtual void setInput2(double _in2)
Definition: fxobjects.h:6306
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3596
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1697
reverbDensity
Use this strongly typed enum to easily set the density in the reverb object.
Definition: fxobjects.h:4673
double parabolicSine(double angle)
Definition: fxobjects.h:3095
WdfSeriesAdaptor seriesAdaptor_L1C1
adaptor for L1 and C1
Definition: fxobjects.h:8132
LFO lfo
the one and only LFO
Definition: fxobjects.h:3700
virtual void updateComponentResistance()
Definition: fxobjects.h:6845
double overlap
overlap as raw value (75% = 0.75)
Definition: fxobjects.h:8914
virtual double getOutput1()=0
double getS_value()
returns the storage component S(n) for delay-free loop solutions
Definition: fxobjects.cpp:32
The ImpulseConvolver object implements a linear conovlver. NOTE: compile in Release mode or you may e...
Definition: fxobjects.h:2408
double alpha
alpha is (wcT/2)
Definition: fxobjects.h:5377
virtual void updateComponentResistance()
Definition: fxobjects.h:6598
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:2770
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8336
The DelayAPF object implements a delaying APF with optional LPF and optional modulated delay time wit...
Definition: fxobjects.h:4202
bool invertOutput
invertOutput - triodes invert output
Definition: fxobjects.h:5617
The WdfSeriesRL object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6573
T readBuffer(unsigned int index)
Definition: fxobjects.h:2266
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5044
unsigned int wrapMask
input wrap mask
Definition: fxobjects.h:8894
double sampleRate
sample rate storage
Definition: fxobjects.h:8418
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:1251
virtual double getOutput2()=0
double highShelf_fc
HSF shelf frequency.
Definition: fxobjects.h:5783
virtual double getOutput2()
Definition: fxobjects.h:6900
double tanhWaveShaper(double xn, double saturation)
calculates hyptan waveshaper
Definition: fxobjects.h:397
void setParameters(const ClassATubePreParameters &params)
Definition: fxobjects.h:5846
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_L
adaptor for L
Definition: fxobjects.h:8416
bool enablePeakTracking
flag to enable peak tracking
Definition: fxobjects.h:9167
The LFO object implements a mathematically perfect LFO generator for modulation uses only...
Definition: fxobjects.h:2992
virtual double getOutput2()
Definition: fxobjects.h:7726
virtual void updateComponentResistance()
Definition: fxobjects.h:6721
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1386
double saturation
input level in dB
Definition: fxobjects.h:5776
dynamicsProcessorType
Use this strongly typed enum to set the dynamics processor type.
Definition: fxobjects.h:1973
virtual const SignalGenData renderAudioOutput()=0
double delayTime_mSec
delay time in mSec
Definition: fxobjects.h:4007
virtual void setInput(double in)
Definition: fxobjects.h:7008
double QL
the quantization level
Definition: fxobjects.h:5993
The PeakLimiter object implements a simple peak limiter; it is really a simplified and hard-wired ver...
Definition: fxobjects.h:5013
WdfSeriesAdaptor seriesAdaptor_RC
adaptor for RC
Definition: fxobjects.h:8415
double fc
filter fc
Definition: fxobjects.h:2524
double sampleRate
sample rate
Definition: fxobjects.h:6556
virtual double getComponentResistance()
Definition: fxobjects.h:6962
double boostCut_dB
filter gain; note not used in all types
Definition: fxobjects.h:1501
const double hs
hs = N/4 — 75% overlap
Definition: fxobjects.h:9583
The EnvelopeFollower object implements a traditional envelope follower effect modulating a LPR fc val...
Definition: fxobjects.h:5444
virtual void setInput1(double _in1)
Definition: fxobjects.h:6303
virtual double getOutput3()
Definition: fxobjects.h:7729
double inputLevel_dB
input level in dB
Definition: fxobjects.h:5775
double sampleRate
stored sample rate
Definition: fxobjects.h:1945
fftw_complex * getIFFTData()
Definition: fxobjects.h:8852
double lpf_g
LPF g coefficient.
Definition: fxobjects.h:4730
void setParameters(const TwoBandShelvingFilterParameters &params)
Definition: fxobjects.h:4640
double zRegister_L
storage register for L
Definition: fxobjects.h:6669
double magnitude
bin magnitude angle
Definition: fxobjects.h:9129
void setParameters(const AudioDetectorParameters &parameters)
Definition: fxobjects.h:1918
virtual double getComponentValue_R()
Definition: fxobjects.h:6876
virtual void updateComponentResistance()
Definition: fxobjects.h:6968
double lpf_state
LPF state register (z^-1)
Definition: fxobjects.h:4332
void flushBuffer()
Definition: fxobjects.h:2302
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8003
void destroyFFTW()
destroys the FFTW arrays and plans.
Definition: fxobjects.cpp:1051
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1840
virtual double getComponentConductance()
Definition: fxobjects.h:6354
double zRegister_C
storage register for C
Definition: fxobjects.h:7039
double dB2Raw(double dB)
converts dB to raw value
Definition: fxobjects.h:282
void setParameters(const PhaseShifterParameters &params)
Definition: fxobjects.h:3684
virtual double processAuxInputAudioSample(double xn)
Definition: fxobjects.h:1184
double componentValue_L
component value L
Definition: fxobjects.h:6796
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4056
void setParameters(const PSMVocoderParameters &params)
Definition: fxobjects.h:9566
virtual void setInput(double in)
Definition: fxobjects.h:6209
double RC
RC value.
Definition: fxobjects.h:6800
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6992
double RL
RL value.
Definition: fxobjects.h:6799
double RC
RC value.
Definition: fxobjects.h:6677
The WdfSeriesTerminatedAdaptor object implements the series terminated (non-reflection-free) adaptor...
Definition: fxobjects.h:7432
AudioDetector detector
detector to track input signal
Definition: fxobjects.h:5556
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5470
double componentValue_C
component value C
Definition: fxobjects.h:6920
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7877
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8629
Custom parameter structure calculating analog magnitude response arrays with calculateAnalogMagArray(...
Definition: fxobjects.h:833
bool advanceAndCheckWrapModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3066
biquadAlgorithm biquadCalcType
biquad structure to use
Definition: fxobjects.h:1350
virtual double getOutput3()
Definition: fxobjects.h:6300
WdfParallelAdaptor parallelAdaptor_C1
adaptor for C1
Definition: fxobjects.h:7946
void createWDF()
Definition: fxobjects.h:8103
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8343
unsigned int countForRatio(rateConversionRatio ratio)
returns the up or downsample ratio as a numeric value
Definition: fxobjects.h:9629
WDFParameters getParameters()
Definition: fxobjects.h:8258
The WdfParallelTerminatedAdaptor object implements the parallel terminated (non-reflection-free) adap...
Definition: fxobjects.h:7644
The WDFConstKBPF6 object implements a 6th order constant K BPF NOTE: designed with Elsie www...
Definition: fxobjects.h:8059
fftw_plan plan_backward
FFTW plan for IFFT.
Definition: fxobjects.h:8880
double beta
beta value, not used
Definition: fxobjects.h:5380
double storageComponent
Definition: fxobjects.h:1445
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6259
virtual double getComponentConductance()
Definition: fxobjects.h:6842
double getS_value()
Definition: fxobjects.h:1588
double gainReduction
output value for gain reduction that occurred
Definition: fxobjects.h:2025
double asymmetry
input level in dB
Definition: fxobjects.h:5777
double out1
stored port 1 output; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7301
double lfoDepth
LFO deoth (not in %) if enabled.
Definition: fxobjects.h:4180
const double kTwoPi
2pi to 80 decimal places
Definition: guiconstants.h:191
void createWDF()
Definition: fxobjects.h:8477
Custom parameter structure for the AudioDetector object. NOTE: this object uses constant defintions: ...
Definition: fxobjects.h:1790
virtual double getComponentConductance()
Definition: fxobjects.h:6187
double threshold_dB
threshold in dB
Definition: fxobjects.h:2014
The Biquad object implements a first or second order H(z) transfer function using one of four standar...
Definition: fxobjects.h:1370
double apf_g
APF g coefficient.
Definition: fxobjects.h:4174
bool enableLPF
enable LPF flag
Definition: fxobjects.h:4009
virtual void setInput2(double _in2)
Definition: fxobjects.h:6421
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6832
double f_Low
brickwall f_low
Definition: fxobjects.h:569
virtual void setInput2(double _in2)
Definition: fxobjects.h:7032
double doWhiteNoise()
calculates a random value between -1.0 and +1.0
Definition: fxobjects.h:324
ZVAFilterParameters zvaFilterParameters
object parameters
Definition: fxobjects.h:5369
virtual void setInput1(double _in1)=0
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6955
double fc
filter cutoff or center frequency (Hz)
Definition: fxobjects.h:1499
virtual void setInput2(double _in2)
Definition: fxobjects.h:6144
void createWDF()
Definition: fxobjects.h:7821
virtual void setInput2(double _in2)
Definition: fxobjects.h:6786
unsigned int getFrameLength()
Definition: fxobjects.h:8861
virtual void setInput2(double _in2)
Definition: fxobjects.h:7382
double zRegister_C
storage register for C
Definition: fxobjects.h:6916
virtual double getOutput3()
Definition: fxobjects.h:7624
virtual void reset(double _sampleRate)
Definition: fxobjects.h:7163
virtual double getOutput3()
Definition: fxobjects.h:7412
bool quadPhaseLFO
quad phase LFO flag
Definition: fxobjects.h:3494
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8458
double saturation
saturation level
Definition: fxobjects.h:5613
void setPort2_CompAdaptor(IComponentAdaptor *_port2CompAdaptor)
Definition: fxobjects.h:7157
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4411
fftw_complex * ifft_input
array for IFFT input
Definition: fxobjects.h:8791
CircularBuffer< double > signalBuffer
circulat buffer for the signal
Definition: fxobjects.h:2485
virtual double getComponentValue()
Definition: fxobjects.h:6190
double delayRatio_Pct
dela ratio: right length = (delayRatio)*(left length)
Definition: fxobjects.h:2699
virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
Definition: fxobjects.h:6068
double R2
output port resistance
Definition: fxobjects.h:7289
The WdfCapacitor object implements the reflection coefficient and signal flow through a WDF simulated...
Definition: fxobjects.h:6169
virtual void setInput3(double _in3)
Definition: fxobjects.h:6912
The AudioDelay object implements a stereo audio delay with multiple delay algorithms.
Definition: fxobjects.h:2719
double attackTime
attack time coefficient
Definition: fxobjects.h:1943
virtual double getR2()
Definition: fxobjects.h:7651
double zRegister_C
storage register for C
Definition: fxobjects.h:6548
double lfoRate_Hz
mod delay LFO rate in Hz
Definition: fxobjects.h:3300
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1543
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2066
double threshold_dB
detector threshold in dB
Definition: fxobjects.h:5422
TwoBandShelvingFilterParameters getParameters()
Definition: fxobjects.h:4631
double in2
stored port 2 input; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7295
double rightDelay_mSec
right delay time
Definition: fxobjects.h:2698
bool interpolate
interpolation flag (diagnostics)
Definition: fxobjects.h:4011
bool enableHPF
HPF simulates DC blocking cap on output.
Definition: fxobjects.h:5618
double getPhase(double re, double im)
calculates phase of a complex numb er
Definition: fxobjects.h:1018
virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
Definition: fxobjects.h:7250
double sampleRate
sample rate
Definition: fxobjects.h:6153
double sampleRate
sample rate
Definition: fxobjects.h:6315
void createDelayBuffers(double _sampleRate, double delay_mSec, double nestedAPFDelay_mSec)
Definition: fxobjects.h:4521
double * getStateArray()
Definition: fxobjects.h:1422
WdfSeriesAdaptor seriesAdaptor_LC
adaptor for LC
Definition: fxobjects.h:8536
AnalogFIRFilterParameters & operator=(const AnalogFIRFilterParameters &params)
Definition: fxobjects.h:2510
ReverbTankParameters & operator=(const ReverbTankParameters &params)
Definition: fxobjects.h:4690
fftw_plan plan_forward
FFTW plan for FFT.
Definition: fxobjects.h:8793
AudioDetectorParameters audioDetectorParameters
parameters for object
Definition: fxobjects.h:1942
AudioFilter hpFilter
high-band filter
Definition: fxobjects.h:1762
virtual double getOutput3()
Definition: fxobjects.h:7514
The ReverbTank object implements the cyclic reverb tank in the FX book listed below.
Definition: fxobjects.h:4763
double modCounter
modulo counter [0.0, +1.0]
Definition: fxobjects.h:3041
virtual double getComponentConductance()
Definition: fxobjects.h:6965
double zRegister_L
storage register for L
Definition: fxobjects.h:6915
WDFParameters getParameters()
Definition: fxobjects.h:8623
double LFOut
low frequency output sample
Definition: fxobjects.h:1623
DelayAPFParameters delayAPFParameters
obeject parameters
Definition: fxobjects.h:4321
virtual double processAudioSample(double xn)
Definition: fxobjects.h:1855
PSMVocoderParameters & operator=(const PSMVocoderParameters &params)
Definition: fxobjects.h:9152
void createDelayBuffer(double _sampleRate, double delay_mSec)
Definition: fxobjects.h:4117
unsigned int fftCounter
FFT sample counter.
Definition: fxobjects.h:8910
double sampleRate
sample rate storage
Definition: fxobjects.h:8661
void createWDF()
Definition: fxobjects.h:8234
modDelaylgorithm
Use this strongly typed enum to easily set modulated delay algorithm.
Definition: fxobjects.h:3268
double feedback_Pct
feedback as a % value
Definition: fxobjects.h:2694
virtual double getOutput()
Definition: fxobjects.h:6291
void setParameters(const OscillatorParameters &params)
Definition: fxobjects.h:3180
unsigned int inputReadIndex
circular buffer index: input read
Definition: fxobjects.h:8892
unsigned int frameLength
current FFT length
Definition: fxobjects.h:8799
unsigned int hopSize
hop: ha = hs
Definition: fxobjects.h:8913
double componentValue_R
component value R
Definition: fxobjects.h:6674
The DynamicsProcessor object implements a dynamics processor suite: compressor, limiter, downward expander, gate.
Definition: fxobjects.h:2046
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6233
double sidechainInputSample
storage for sidechain sample
Definition: fxobjects.h:2134
double RC
RC value.
Definition: fxobjects.h:6554
void setTerminalResistance(double _terminalResistance)
Definition: fxobjects.h:7140
Custom parameter structure for the ClassATubePre object.
Definition: fxobjects.h:5752
AudioDetectorParameters & operator=(const AudioDetectorParameters &params)
Definition: fxobjects.h:1794
virtual double getOutput()
Definition: fxobjects.h:6406
DFOscillatorCoeffs
Use this non-typed enum to easily access the direct form oscillator coefficients. ...
Definition: fxobjects.h:3116
IComponentAdaptor * getPort1_CompAdaptor()
Definition: fxobjects.h:7271
The CombFilter object implements a comb filter with optional LPF in feedback loop. Used for reverb algorithms in book.
Definition: fxobjects.h:4032
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6493
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5661
bool enableLSF
LSF simulates shelf due to cathode self biasing.
Definition: fxobjects.h:5619
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:6759
virtual void initialize(double _R1)
Definition: fxobjects.h:7663
void advanceModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3089
DynamicsProcessorParameters getParameters()
Definition: fxobjects.h:2082
virtual double getComponentValue_C()
Definition: fxobjects.h:6390
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4770
double fuzzExp1WaveShaper(double xn, double saturation, double asymmetry)
calculates fuzz exp1 waveshaper
Definition: fxobjects.h:426
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7996
static void connectAdaptors(WdfAdaptorBase *upstreamAdaptor, WdfAdaptorBase *downstreamAdaptor)
Definition: fxobjects.h:7230
Custom parameter structure for the NestedDelayAPF object. Used for reverb algorithms in book...
Definition: fxobjects.h:4347
LRFilterBankParameters parameters
parameters for the object
Definition: fxobjects.h:1765
virtual double processAuxInputAudioSample(double xn)
Definition: fxobjects.h:2072
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7811
double processAudioSample(double input, bool &fftReady)
process one input sample throug the vocoder to produce one output sample
Definition: fxobjects.cpp:1476
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5020
virtual void setInput3(double _in3)
Definition: fxobjects.h:7615
double lfoDepth_Pct
mod delay LFO depth in %
Definition: fxobjects.h:3301
unsigned int length
length of convolution (buffer)
Definition: fxobjects.h:2488
void setParameters(const OscillatorParameters &params)
Definition: fxobjects.h:3021
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4040
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2054
virtual void setInput(double in)
Definition: fxobjects.h:6516
void createLinearBuffer(unsigned int _bufferLength)
Definition: fxobjects.h:2244
The AudioFilter object implements all filters in Designing Audio Effects Plugins in C++ 2nd Ed...
Definition: fxobjects.h:1521
double HFOut
high frequency output sample
Definition: fxobjects.h:1624
double terminalResistance
value of terminal (load) resistance
Definition: fxobjects.h:7306
virtual void setComponentValue_L(double _componentValue_L)
Definition: fxobjects.h:6373
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3351
dynamicsProcessorType calculation
processor calculation type
Definition: fxobjects.h:2019
void reset()
Definition: fxobjects.h:9116
WdfSeriesAdaptor seriesAdaptor_L5C5
adaptor for L5 and C5
Definition: fxobjects.h:8138
PhaseShifterParameters parameters
the object parameters
Definition: fxobjects.h:3698
double lfoRate_Hz
LFO rate in Hz (if enabled)
Definition: fxobjects.h:4378
delayUpdateType updateType
update algorithm
Definition: fxobjects.h:2696
virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
Definition: fxobjects.h:6065
TwoBandShelvingFilter shelvingFilter
shelving filters
Definition: fxobjects.h:5898
virtual void initialize(double _R1)
Definition: fxobjects.h:7450
bool needInverseFFT
internal flag to signal IFFT required
Definition: fxobjects.h:8902
double stateArray[numDFOStates]
array of state registers
Definition: fxobjects.h:3247
virtual double getOutput()
Definition: fxobjects.h:6641
virtual void setInput1(double _in1)
Definition: fxobjects.h:7471
void initialize(unsigned int _FIRLength, rateConversionRatio _ratio, unsigned int _sampleRate, bool _polyphase=true)
Definition: fxobjects.h:9921
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6862
unsigned int outputReadIndex
circular buffer index: output read
Definition: fxobjects.h:8893
Custom structure that holds transition band information for FIR filter calculations.
Definition: fxobjects.h:601
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8091
double filterOutputGain_dB
va filter gain (normally unused)
Definition: fxobjects.h:5152
bool openTerminalResistance
flag for open circuit load
Definition: fxobjects.h:7307
void setParameters(const CombFilterParameters &params)
Definition: fxobjects.h:4097
WdfSeriesAdaptor seriesAdaptor_RL
adaptor for series RL
Definition: fxobjects.h:8292
WdfSeriesAdaptor seriesAdaptor_L3C3
adaptor for L3 and C3
Definition: fxobjects.h:8135
double sampleRate
current sample rate
Definition: fxobjects.h:1599
double componentValue_C
component value C
Definition: fxobjects.h:6551
virtual void enableAuxInput(bool enableAuxInput)
Definition: fxobjects.h:2069
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:7791
biquadAlgorithm
Use this strongly typed enum to easily set the biquad calculation type.
Definition: fxobjects.h:1322
bool useFrequencyWarping
flag for freq warping
Definition: fxobjects.h:7953
virtual void setInput3(double _in3)=0
rateConversionRatio ratio
conversion ration
Definition: fxobjects.h:9865
ZVAFilterParameters getParameters()
Definition: fxobjects.h:5196
double sampleRate
sample rate
Definition: fxobjects.h:6236
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4618
void writeBuffer(T input)
Definition: fxobjects.h:2333
fftw_complex * fft_result
array for FFT output
Definition: fxobjects.h:8790
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:5969
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3331
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6622
double intensity_Pct
phaser feedback in %
Definition: fxobjects.h:3493
void setParameters(const EnvelopeFollowerParameters &params)
Definition: fxobjects.h:5487
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6097
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:1240
double RR
RR value.
Definition: fxobjects.h:6924
OscillatorParameters getParameters()
Definition: fxobjects.h:3171
double frequency_Hz
oscillator frequency
Definition: fxobjects.h:2971
void setAttackTime(double attack_in_ms, bool forceCalc=false)
sets the new attack time and re-calculates the time constant
Definition: fxobjects.cpp:958
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3785
vaFilterAlgorithm filterAlgorithm
va filter algorithm
Definition: fxobjects.h:5149
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8066
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:6794
modDelaylgorithm algorithm
mod delay algorithm
Definition: fxobjects.h:3299
double sgn(double xn)
calculates sgn( ) of input
Definition: fxobjects.h:353
double componentValue_C
component value C
Definition: fxobjects.h:7042
double threshold_dB
stored threshold (dB)
Definition: fxobjects.h:5094
virtual double getComponentResistance()
Definition: fxobjects.h:6050
WdfParallelAdaptor parallelAdaptor_L4C4
adaptor for L4 and C4
Definition: fxobjects.h:8136
The WdfParallelLC object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6452
TriodeClassA triodes[NUM_TUBES]
array of triode tube objects
Definition: fxobjects.h:5897
double hpf_Fc
fc of DC blocking cap
Definition: fxobjects.h:5621
void findPeaksAndRegionsOfInfluence()
Definition: fxobjects.h:9291
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:8173
virtual double getR2()
Definition: fxobjects.h:7541
int findPreviousNearestPeak(int peakIndex)
Definition: fxobjects.h:9259
const uint32_t ENVELOPE_DETECT_MODE_PEAK
|x|
Definition: guiconstants.h:199
virtual double processAudioSample(double xn)
process one sample through the biquad
Definition: fxobjects.cpp:67
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5875
double splitFrequency
LF/HF split frequency.
Definition: fxobjects.h:1656
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8587
double delayTime_mSec
delay tine in mSec
Definition: fxobjects.h:3828
Biquad biquad
the biquad object
Definition: fxobjects.h:1592
The AudioDetector object implements the audio detector defined in the book source below...
Definition: fxobjects.h:1832
double windowGainCorrection
window gain correction
Definition: fxobjects.h:8797
double zRegister
storage register (not used with resistor)
Definition: fxobjects.h:6312
AudioFilterParameters audioFilterParameters
parameters
Definition: fxobjects.h:1598
The WdfParallelRC object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6943
virtual double getComponentValue()
Definition: fxobjects.h:6071
AudioFilter outputHPF
HPF to simulate output DC blocking cap.
Definition: fxobjects.h:5735
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4427
double attackTime_mSec
attack time in milliseconds
Definition: fxobjects.h:1807
Custom parameter structure for the WDF filter examples.
Definition: fxobjects.h:8154
virtual void setInput1(double _in1)
Definition: fxobjects.h:6538
double outerAPFdelayTime_mSec
delay time for outer APF
Definition: fxobjects.h:4371
double in1
stored port 1 input; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7294
virtual void setInput2(double _in2)
Definition: fxobjects.h:6541
double componentValue_R
component value R
Definition: fxobjects.h:7043
double sampleRate
current sample rate
Definition: fxobjects.h:4322
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4798
double RC
RC value.
Definition: fxobjects.h:6923
double kneeWidth_dB
knee width in dB for soft-knee operation
Definition: fxobjects.h:2015
double zRegister_L
storage register for L
Definition: fxobjects.h:6427
virtual double getOutput()
Definition: fxobjects.h:6025
The WDFButterLPF3 object implements a 3rd order Butterworth ladder filter. NOTE: designed with Elsie ...
Definition: fxobjects.h:7784
virtual double getOutput2()
Definition: fxobjects.h:6297
DelayAPFParameters getParameters()
Definition: fxobjects.h:4290
The FastConvolver provides a fast convolver - the user supplies the filter IR and the object snapshot...
Definition: fxobjects.h:8941
virtual void setInput1(double _in1)
Definition: fxobjects.h:7029
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6206
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8084
double lowShelf_fc
low shelf fc
Definition: fxobjects.h:4733
double getG_value()
Definition: fxobjects.h:1429
distortionModel waveshaper
waveshaper
Definition: fxobjects.h:5611
double getOverlap()
Definition: fxobjects.h:8867
bool needOverlapAdd
internal flag to signal overlap/add required
Definition: fxobjects.h:8903
double fixeDelayMax_mSec
fixed delay max time
Definition: fxobjects.h:4725
The WDFIdealRLCBSF object implements an ideal RLC BSF using the WDF library.
Definition: fxobjects.h:8560
virtual void setInput(double in)
Definition: fxobjects.h:6762
void setParameters(const SimpleLPFParameters &params)
Definition: fxobjects.h:3775
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_R
adaptor for R
Definition: fxobjects.h:8537
virtual double getOutput1()
Definition: fxobjects.h:7508
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2727
Custom structure to hold component information.
Definition: fxobjects.h:7084
virtual double getOutput1()
Definition: fxobjects.h:6132
double real
real part
Definition: fxobjects.h:477
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_C
adaptopr for parallel C
Definition: fxobjects.h:8293
void updateDFO()
Definition: fxobjects.h:3207
double rho
p = 2R + g (feedback)
Definition: fxobjects.h:5378
double gainReduction_dB
output value for gain reduction that occurred in dB
Definition: fxobjects.h:2026
double delayTime_mSec
APF delay time.
Definition: fxobjects.h:4173
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6635
virtual double getComponentConductance()
Definition: fxobjects.h:6474
LRFilterBankParameters getParameters()
Definition: fxobjects.h:1736
The WDFIdealRLCBPF object implements an ideal RLC BPF using the WDF library.
Definition: fxobjects.h:8438
double componentValue_L
component value L
Definition: fxobjects.h:6430
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5227
double releaseTime_mSec
detector release time
Definition: fxobjects.h:5421
virtual void reset(double _sampleRate)
Definition: fxobjects.h:7005
void setFilterFc(double fc_Hz)
Definition: fxobjects.h:7930
virtual double getOutput1()
Definition: fxobjects.h:6215
BiquadParameters parameters
Definition: fxobjects.h:1442
virtual double processAudioSample(double xn)
Definition: fxobjects.h:3901
AudioDetector detector
the detector object
Definition: fxobjects.h:5093
double lfoDepth
LFO depth (not in %) (if enabled)
Definition: fxobjects.h:4379
BiquadParameters getParameters()
Definition: fxobjects.h:1399
virtual double processAudioSample(double xn)
Definition: fxobjects.h:1712
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8533
double RT60Time_mSec
RT 60 time ini mSec.
Definition: fxobjects.h:4008
IComponentAdaptor * wdfComponent
WDF componant connected to port 3 (default operation)
Definition: fxobjects.h:7285
fftw_plan plan_forward
FFTW plan for FFT.
Definition: fxobjects.h:8879
double softClipWaveShaper(double xn, double saturation)
calculates hyptan waveshaper
Definition: fxobjects.h:411
Custom parameter structure for the ReverbTank object.
Definition: fxobjects.h:4686
double invertedOutput
inverted
Definition: fxobjects.h:1221
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6435
The Decimator object implements a sample rate decimator. Ana array of M input samples is decimated to...
Definition: fxobjects.h:9908
double computeGain(double detect_dB)
Definition: fxobjects.h:5050
virtual double getOutput1()
Definition: fxobjects.h:7723
virtual void setInput(double in)
Definition: fxobjects.h:6288
DynamicsProcessorParameters & operator=(const DynamicsProcessorParameters &params)
Definition: fxobjects.h:1991
void setParameters(const TriodeClassAParameters &params)
Definition: fxobjects.h:5680
double stateArray[numStates]
Definition: fxobjects.h:1439
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3860
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8465
virtual void setInput2(double _in2)
Definition: fxobjects.h:7717
double quantizedBitDepth
bid depth of quantizer
Definition: fxobjects.h:5930
const double kPi
pi to 80 decimal places
Definition: guiconstants.h:184
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6869
ZVAFilterParameters & operator=(const ZVAFilterParameters &params)
Definition: fxobjects.h:5132
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:3363
void destroyFFTW()
destroys the FFTW arrays and plans.
Definition: fxobjects.cpp:1225
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4603
EnvelopeFollowerParameters getParameters()
Definition: fxobjects.h:5481
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7804
bool addZeroPad(unsigned int count)
zero pad the input timeline
Definition: fxobjects.cpp:1392
CombFilterParameters getParameters()
Definition: fxobjects.h:4088
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_LC
adaptor for parallel LC
Definition: fxobjects.h:8659
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6059
SimpleDelayParameters & operator=(const SimpleDelayParameters &params)
Definition: fxobjects.h:3816
BitCrusherParameters parameters
object parameters
Definition: fxobjects.h:5992
virtual double getComponentResistance()
Definition: fxobjects.h:6592
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:2295
The PSMVocoder object implements a phase vocoder pitch shifter. Phase locking and peak tracking are o...
Definition: fxobjects.h:9188
double * getCoefficients()
Definition: fxobjects.h:1415
double highShelf_fc
fc for high shelf
Definition: fxobjects.h:4565
PhaseVocoder vocoder
vocoder object
Definition: fxobjects.h:9070
double Q
filter Q
Definition: fxobjects.h:5419
double integrator_z[2]
state variables
Definition: fxobjects.h:5373
double componentResistance
simulated resistance
Definition: fxobjects.h:6235
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6313
Custom structure that holds information about each FFT bin. This includes all information needed to p...
Definition: fxobjects.h:9094
virtual double getOutput()
Definition: fxobjects.h:6129
virtual void initialize(double _R1)
Definition: fxobjects.h:6016
virtual void setInput2(double _in2)=0
void setThreshold_dB(double _threshold_dB)
Definition: fxobjects.h:5087
virtual void setComponentValue_RL(double componentValue_R, double componentValue_L)
Definition: fxobjects.h:7257
double sampleRate
sample rate
Definition: fxobjects.h:6681
virtual double getComponentConductance()
Definition: fxobjects.h:6053
double getBeta()
Definition: fxobjects.h:5366
void setOverlapAddOnly(bool b)
Definition: fxobjects.h:8872
double lfoRate_Hz
phaser LFO rate in Hz
Definition: fxobjects.h:3491
virtual double processAudioSample(double xn)=0
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8201
IComponentAdaptor * port2CompAdaptor
componant or adaptor connected to port 2
Definition: fxobjects.h:7283
virtual void updateComponentResistance()
Definition: fxobjects.h:6120
void doInverseFFT()
perform the inverse FFT on the processed data
Definition: fxobjects.cpp:1516
Custom parameter structure for the SimpleLPFP object. Used for reverb algorithms in book...
Definition: fxobjects.h:3714
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6047
double fc
va filter fc
Definition: fxobjects.h:5150
double * outputBuff
buffer for resampled output
Definition: fxobjects.h:9596
virtual double getOutput2()
Definition: fxobjects.h:6654
The TriodeClassA object simulates a triode in class A configuration. This is a very simple and basic ...
Definition: fxobjects.h:5644
BiquadParameters & operator=(const BiquadParameters &params)
Definition: fxobjects.h:1341
double RR
RR value.
Definition: fxobjects.h:7047
void createDelayBuffer(double _sampleRate, double delay_mSec)
Definition: fxobjects.h:4310
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6464
virtual void initializeAdaptorChain()
Definition: fxobjects.h:7237
Custom parameter structure for the DelayAPF object. Used for reverb algorithms in book...
Definition: fxobjects.h:4151
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8412
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3917
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:7891
void setReleaseTime(double release_in_ms, bool forceCalc=false)
sets the new release time and re-calculates the time constant
Definition: fxobjects.cpp:974
void setMakeUpGain_dB(double _makeUpGain_dB)
Definition: fxobjects.h:5090
void setUsePostWarping(bool b)
Definition: fxobjects.h:7927
virtual void setInput1(double _in1)
Definition: fxobjects.h:7575
bool advanceAndCheckFFT()
advance the sample counter and check to see if we need to do the FFT.
Definition: fxobjects.cpp:1422
virtual void initialize(double _R1)
Definition: fxobjects.h:7342
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3578
virtual double getComponentValue_L()
Definition: fxobjects.h:6629
The WDFIdealRLCLPF object implements an ideal RLC LPF using the WDF library.
Definition: fxobjects.h:8194
The Interpolator object implements a sample rate interpolator. One input sample yields N output sampl...
Definition: fxobjects.h:9783
AudioDelayParameters getParameters()
Definition: fxobjects.h:2851
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6193
FastFFT filterFastFFT
FastFFT object.
Definition: fxobjects.h:9071
double attackTime_mSec
detector attack time
Definition: fxobjects.h:5420
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5703
double quadPhaseOutput_pos
90 degrees out
Definition: fxobjects.h:1222
double componentValue_C
component value C
Definition: fxobjects.h:6431
virtual void setInput(double in)
Definition: fxobjects.h:6126
double dryLevel_dB
dry output level in dB
Definition: fxobjects.h:4739
virtual double processAudioSample(double input)
Definition: fxobjects.h:9395
double sampleRate
stored sample rate
Definition: fxobjects.h:7954
SimpleDelayParameters getParameters()
Definition: fxobjects.h:3880
AudioDelayParameters & operator=(const AudioDelayParameters &params)
Definition: fxobjects.h:2672
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4805
FastConvolver convolver
fast convolver
Definition: fxobjects.h:9980
virtual const SignalGenData renderAudioOutput()
generates the oscillator output for one sample interval; note that there are multiple outputs...
Definition: fxobjects.cpp:986
LRFilterBankParameters & operator=(const LRFilterBankParameters &params)
Definition: fxobjects.h:1647
int peakBins[PSM_FFT_LEN]
array of current peak bin index values (-1 = not peak)
Definition: fxobjects.h:9592
AudioDetector detector
the sidechain audio detector
Definition: fxobjects.h:2131
double readDelayAtPercentage(double delayPercent)
Definition: fxobjects.h:3952
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6708
bool interpolate
interpolation flag (diagnostics usually)
Definition: fxobjects.h:3829
virtual double getComponentValue_R()
Definition: fxobjects.h:6632
AudioFilter outputLSF
LSF to simulate shelf caused by cathode self-biasing cap.
Definition: fxobjects.h:5736
virtual double processAudioSample(double xn)
process one sample through the audio filter
Definition: fxobjects.cpp:944
filterAlgorithm algorithm
filter algorithm
Definition: fxobjects.h:1498
double sampleRate
current sample rate
Definition: fxobjects.h:5370
Custom parameter structure for the CombFilter object. Used for reverb algorithms in book...
Definition: fxobjects.h:3989
bool polyphase
enable polyphase decomposition
Definition: fxobjects.h:9868
virtual void setInput1(double _in1)
Definition: fxobjects.h:6906
virtual void setInput3(double _in3)
Definition: fxobjects.h:7505
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3159
brickwallFilter
Use this strongly typed enum to easily set brickwall filter type for functions that need it...
Definition: fxobjects.h:543
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6500
virtual void setInput3(double _in3)
Definition: fxobjects.h:6147
Custom output structure for filter bank objects that split the inptu into multiple frequency channels...
Definition: fxobjects.h:1618
virtual void setInput1(double _in1)
Definition: fxobjects.h:7363
double computeGain(double detect_dB)
Definition: fxobjects.h:2137
void setFilterIR(double *irBuffer)
Definition: fxobjects.h:8988
AudioFilterParameters getParameters()
Definition: fxobjects.h:1560
virtual void updateComponentResistance()
Definition: fxobjects.h:6056
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:6547
void setParameters(const NestedDelayAPFParameters &params)
Definition: fxobjects.h:4495
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:6777
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5518
The SimpleDelay object implements a basic delay line without feedback.
Definition: fxobjects.h:3852
double * windowBuffer
buffer for window (naked)
Definition: fxobjects.h:8796
generatorWaveform waveform
the current waveform
Definition: fxobjects.h:2970
virtual double getOutput()
Definition: fxobjects.h:7011
bool selfOscillate
enable selfOscillation
Definition: fxobjects.h:5155
analogFilter filterType
filter type
Definition: fxobjects.h:2523
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8580
double lowShelf_fc
fc for low shelf
Definition: fxobjects.h:4563
double innerAPFdelayTime_mSec
delay time for inner APF
Definition: fxobjects.h:4372
unsigned int FIRLength
FIR length.
Definition: fxobjects.h:9984
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:5623
double coeffArray[numDFOCoeffs]
array of coefficients
Definition: fxobjects.h:3248
Custom parameter structure for the TriodeClassA object.
Definition: fxobjects.h:5585
unsigned int sampleRate
sample rate
Definition: fxobjects.h:9863
virtual double getOutput3()
Definition: fxobjects.h:6780
virtual double getComponentResistance()
Definition: fxobjects.h:6104
double kRT
reverb time, 0 to 1
Definition: fxobjects.h:4731
TriodeClassAParameters parameters
object parameters
Definition: fxobjects.h:5734
unsigned int filterImpulseLength
IR length.
Definition: fxobjects.h:9075
bool enableGainComp
enable gain compensation (see book)
Definition: fxobjects.h:5153
WDFParameters getParameters()
Definition: fxobjects.h:8501
The LinearBuffer object implements a linear buffer of type T. It allows easy wrapping of a smart poin...
Definition: fxobjects.h:2233
CombFilterParameters & operator=(const CombFilterParameters &params)
Definition: fxobjects.h:3993
The DFOscillator object implements generates a very pure sinusoidal oscillator by placing poles direc...
Definition: fxobjects.h:3152
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8289
The WdfSeriesLC object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6332
void setPort3_CompAdaptor(IComponentAdaptor *_port3CompAdaptor)
Definition: fxobjects.h:7160
double zRegister_C
storage register for C (not used)
Definition: fxobjects.h:6670
virtual void setInput1(double _in1)
Definition: fxobjects.h:6141
The WdfSeriesRC object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6820
virtual double getR2()
Definition: fxobjects.h:7331
virtual void setInput1(double _in1)
Definition: fxobjects.h:6783
Custom parameter structure for the AnalogFIRFilter object. This is a somewhat silly object that impla...
Definition: fxobjects.h:2506
double out3
stored port 3 output; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7303
double lsf_Fshelf
shelf fc from self bias cap
Definition: fxobjects.h:5622
virtual void setComponentValue(double _componentValue)
Definition: fxobjects.h:6113
fftw_complex * fft_input
array for FFT input
Definition: fxobjects.h:8876
virtual bool reset(double _sampleRate)=0
bool checkAndWrapModulo(double &moduloCounter, double phaseInc)
Definition: fxobjects.h:3046
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6555
double sampleRate
sample rate
Definition: fxobjects.h:6804
double apfDelayWeight_Pct
APF max delay weighying.
Definition: fxobjects.h:4724
double principalArg(double phaseIn)
calculates proncipal argument of a phase value; this is the wrapped value on the range of [-pi...
Definition: fxobjects.h:1033
OscillatorParameters lfoParameters
obejcgt parameters
Definition: fxobjects.h:3035
unsigned int relaxationBins
relaxation bins for FIR specification
Definition: fxobjects.h:571
unsigned int FIRLength
FIR length.
Definition: fxobjects.h:9864
This is the output structure for audio generator objects that can render up to four outputs...
Definition: fxobjects.h:1216
edgeTransition edgeType
edge type
Definition: fxobjects.h:605
FastConvolver polyPhaseConvolvers[maxSamplingRatio]
a set of sub-band convolvers for polyphase operation
Definition: fxobjects.h:9989
virtual void setInput(double _in)
Definition: fxobjects.h:6022
Custom parameter structure for the AudioFilter object.
Definition: fxobjects.h:1481
bool enablePeakPhaseLocking
flag to enable phase lock
Definition: fxobjects.h:9166
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L2
adaptor for L2
Definition: fxobjects.h:7848
bool enableNLP
enable non linear processing (use oversampling for best results)
Definition: fxobjects.h:5156
LinearBuffer< double > irBuffer
linear buffer for the IR
Definition: fxobjects.h:2486
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:1305
PhaseVocoder vocoder
vocoder to perform PSM
Definition: fxobjects.h:9579
virtual void setInput3(double _in3)
Definition: fxobjects.h:6789
virtual double getOutput()
Definition: fxobjects.h:6765
globally utilized constants and enumerations
virtual bool canProcessAudioFrame()=0
IComponentAdaptor * port1CompAdaptor
componant or adaptor connected to port 1
Definition: fxobjects.h:7282
double outputLevel_dB
input level in dB
Definition: fxobjects.h:5778
The WDFTunableButterLPF3 object implements a tunable 3rd order Butterworth ladder filter...
Definition: fxobjects.h:7870
FilterBankOutput processFilterBank(double xn)
Definition: fxobjects.h:1718
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8385
double raw2dB(double raw)
calculates dB for given input
Definition: fxobjects.h:268
windowType window
window type
Definition: fxobjects.h:8906
virtual void setInput2(double _in2)
Definition: fxobjects.h:6227
DynamicsProcessorParameters parameters
object parameters
Definition: fxobjects.h:2130
T readBuffer(int delayInSamples)
Definition: fxobjects.h:2343
double lowShelfBoostCut_dB
low shelf gain
Definition: fxobjects.h:4564
fftw_complex * fft_input
array for FFT input
Definition: fxobjects.h:8789
fftw_complex * ifft_result
array for IFFT output
Definition: fxobjects.h:8792
double R3
component resistance
Definition: fxobjects.h:7290
virtual void setInput1(double _in1)
Definition: fxobjects.h:6660
void setParameters(const DelayAPFParameters &params)
Definition: fxobjects.h:4299
BinData binData[PSM_FFT_LEN]
array of BinData structures for current FFT frame
Definition: fxobjects.h:9589
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2417
void createWDF()
Definition: fxobjects.h:8355
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:4210
FastConvolver polyPhaseConvolvers[maxSamplingRatio]
a set of sub-band convolvers for polyphase operation
Definition: fxobjects.h:9869
virtual void setInput1(double _in1)
Definition: fxobjects.h:6224
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5183
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:3756
unsigned int detectMode
detect mode, see TLD_ constants above
Definition: fxobjects.h:1809
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:935
double imag
imaginary part
Definition: fxobjects.h:478
void setPitchShift(double semitones)
Definition: fxobjects.h:9224
virtual void setInput3(double _in3)
Definition: fxobjects.h:6544
distortionModel
Use this strongly typed enum to easily set the waveshaper model for the Triode objects.
Definition: fxobjects.h:5572
int peakBinsPrevious[PSM_FFT_LEN]
array of previous peak bin index values (-1 = not peak)
Definition: fxobjects.h:9593
virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
Definition: fxobjects.h:6485
double componentResistance
simulated resistance
Definition: fxobjects.h:6152
WdfSeriesAdaptor seriesAdaptor_L1
adaptor for L1
Definition: fxobjects.h:7945
SimpleLPFParameters getParameters()
Definition: fxobjects.h:3766
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2454
double inputLevel
input level (not in dB)
Definition: fxobjects.h:5900
bool overlapAddOnly
flag for overlap-add-only algorithms
Definition: fxobjects.h:8918
double ratio
processor I/O gain ratio
Definition: fxobjects.h:2013
int findEdgeTargetBin(double testFreq, double bin1Freq)
find bin for target frequency
Definition: fxobjects.h:622
double fc
brickwall fc
Definition: fxobjects.h:567
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:7049
OscillatorParameters parameters
object parameters
Definition: fxobjects.h:3244
double * filterIR
filter IR
Definition: fxobjects.h:9073
double componentValue_L
component value L
Definition: fxobjects.h:6550
double RL
RL value.
Definition: fxobjects.h:6553
void createWDF()
Definition: fxobjects.h:7908
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:6251
virtual void setComponentValue_LC(double componentValue_L, double componentValue_C)
Definition: fxobjects.h:6062
virtual double getComponentValue_C()
Definition: fxobjects.h:6510
double R
value of R component
Definition: fxobjects.h:7114
double * getFilterIRTable(unsigned int FIRLength, rateConversionRatio ratio, unsigned int sampleRate)
returns the up or downsample ratio as a numeric value
Definition: fxobjects.h:9651
double atanWaveShaper(double xn, double saturation)
calculates arctangent waveshaper
Definition: fxobjects.h:383
virtual void setInput1(double _in1)
Definition: fxobjects.h:7689
The ClassATubePre object implements a simple cascade of four (4) triode tube models.
Definition: fxobjects.h:5805
BitCrusherParameters getParameters()
Definition: fxobjects.h:5963
IComponentAdaptor * getPort3_CompAdaptor()
Definition: fxobjects.h:7277
virtual double getComponentResistance()
Definition: fxobjects.h:6471
void doOverlapAdd(double *outputData=nullptr, int length=0)
perform the overlap/add on the IFFT data
Definition: fxobjects.cpp:1535
double updatedPhase
phase update value
Definition: fxobjects.h:9134
double Q
filter Q
Definition: fxobjects.h:2525
double releaseTime_mSec
release mSec
Definition: fxobjects.h:2021
void createDelayBuffers(double _sampleRate, double _bufferLength_mSec)
Definition: fxobjects.h:2896
IComponentAdaptor * port3CompAdaptor
componant or adaptor connected to port 3
Definition: fxobjects.h:7284
void setInterpolate(bool b)
Definition: fxobjects.h:2379
double getG_value()
Definition: fxobjects.h:1585
virtual void setInput(double in)
Definition: fxobjects.h:6396
WDFParameters wdfParameters
object parameters
Definition: fxobjects.h:8655
virtual const SignalGenData renderAudioOutput()
Definition: fxobjects.h:3190
AudioFilter lpFilter
low-band filter
Definition: fxobjects.h:1761
unsigned int count
number of samples in output array
Definition: fxobjects.h:9762
bool hardLimitGate
threshold in dB
Definition: fxobjects.h:2016
virtual double getOutput1()
Definition: fxobjects.h:6409
virtual void setInput3(double _in3)
Definition: fxobjects.h:6424
virtual void setInput1(double _in1)
Definition: fxobjects.h:6418
WdfSeriesAdaptor seriesAdaptor_L1
adaptor for L1
Definition: fxobjects.h:7846
virtual double getComponentValue_R()
Definition: fxobjects.h:6999
virtual double getOutput1()
Definition: fxobjects.h:7406
bool calculateAnalogMagArray(AnalogMagData &magData)
calculate an arra of magnitude points from analog filter specifications
Definition: fxobjects.h:858
void setPort1_CompAdaptor(IComponentAdaptor *_port1CompAdaptor)
Definition: fxobjects.h:7154
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:9201
virtual double processAudioSample(double xn)
Definition: fxobjects.h:7898
void setCoefficients(double *coeffs)
Definition: fxobjects.h:1409
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2555
fftw_complex * getFFTData()
Definition: fxobjects.h:8849
double sampleRate
sample rate
Definition: fxobjects.h:3251
virtual double getOutput1()
Definition: fxobjects.h:6529
double normalOutput
normal
Definition: fxobjects.h:1220
virtual void setComponentValue_RC(double _componentValue_R, double _componentValue_C)
Definition: fxobjects.h:6977
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:1194
double sampleRate
sample rate
Definition: fxobjects.h:6927
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1529
unsigned int outputWriteIndex
circular buffer index: output write
Definition: fxobjects.h:8891
reverbDensity density
density setting thick or thin
Definition: fxobjects.h:4718
delayAlgorithm algorithm
delay algorithm
Definition: fxobjects.h:2691
virtual void setComponentValue_RC(double componentValue_R, double componentValue_C)
Definition: fxobjects.h:7264
bool calculateBrickwallMagArray(BrickwallMagData &magData)
calculate an arra of magnitude points from brickwall specifications
Definition: fxobjects.h:687
virtual void initializeAdaptorChain()
Definition: fxobjects.h:6019
double Q
va filter Q
Definition: fxobjects.h:5151
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:8215
double windowHopCorrection
window correction including hop/overlap
Definition: fxobjects.h:8899
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2108
virtual void setInput3(double _in3)
Definition: fxobjects.h:6666
virtual void setInput2(double _in2)
Definition: fxobjects.h:6909
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4611
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8507
The WdfResistor object implements the reflection coefficient and signal flow through a WDF simulated ...
Definition: fxobjects.h:6089
virtual bool processAudioFrame(const float *inputFrame, float *outputFrame, uint32_t inputChannels, uint32_t outputChannels)
Definition: fxobjects.h:4814
void init(unsigned int lengthPowerOfTwo)
Definition: fxobjects.h:2457
The ZVAFilter object implements multpile Zavalishin VA Filters. Audio I/O:
Definition: fxobjects.h:5176
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2749
void writeDelay(double xn)
Definition: fxobjects.h:3959
The WdfParallelAdaptor object implements the parallel reflection-free (non-terminated) adaptor...
Definition: fxobjects.h:7534
double componentValue
component value in electronic form (ohm, farad, henry)
Definition: fxobjects.h:6151
double pitchShiftSemitones
pitch shift in half-steps
Definition: fxobjects.h:9165
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6585
virtual double getComponentValue()
Definition: fxobjects.h:6272
double componentResistance
simulated resistance
Definition: fxobjects.h:6314
ModulatedDelayParameters & operator=(const ModulatedDelayParameters &params)
Definition: fxobjects.h:3286
virtual double getOutput()
Definition: fxobjects.h:6888
double quadPhaseOutput_neg
-90 degrees out
Definition: fxobjects.h:1223
bool enableLFO
flag to enable LFO
Definition: fxobjects.h:4178
unsigned int outputBufferLength
lenght of resampled output array
Definition: fxobjects.h:9598
double * windowBuffer
array for window
Definition: fxobjects.h:8883
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3672
unsigned int sampleRate
sample rate
Definition: fxobjects.h:9983
virtual double getComponentConductance()
Definition: fxobjects.h:6269
virtual double processAudioSample(double xn)
Definition: fxobjects.h:8222
void setParameters(const AudioFilterParameters &parameters)
Definition: fxobjects.h:1563
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:3360
Custom parameter structure for the AudioDelay object.
Definition: fxobjects.h:2668
double getMagnitude(double re, double im)
calculates magnitude of a complex numb er
Definition: fxobjects.h:1003
virtual bool reset(double _sampleRate)=0
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2575
double lfoDepth_Pct
phaser LFO depth in %
Definition: fxobjects.h:3492
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1705
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:9221
virtual double getComponentValue_C()
Definition: fxobjects.h:7002
wdfComponent
Use this strongly typed enum to easily set the wdfComponent type.
Definition: fxobjects.h:7071
double RC
RC value.
Definition: fxobjects.h:6434
double psi
bin phase correction
Definition: fxobjects.h:9131
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6344
double outputGain_dB
make up gain
Definition: fxobjects.h:2022
unsigned int getFrameLength()
Definition: fxobjects.h:8785
double leftDelay_mSec
left delay time
Definition: fxobjects.h:2697
WdfParallelTerminatedAdaptor parallelTerminatedAdaptor_L6C6
adaptor for L6 and C6
Definition: fxobjects.h:8139
double in3
stored port 3 input; not used in this implementation but may be required for extended versions ...
Definition: fxobjects.h:7296
bool isPeak
flag for peak bins
Definition: fxobjects.h:9128
windowType
Use this strongly typed enum to easily set the windowing type for FFT algorithms that use it...
Definition: fxobjects.h:8682
double lfoMaxModulation_mSec
LFO maximum modulation time in mSec.
Definition: fxobjects.h:4181
IComponentAdaptor * getPort2_CompAdaptor()
Definition: fxobjects.h:7274
double lowShelf_fc
LSF shelf frequency.
Definition: fxobjects.h:5781
double lpf_g
LPF g coefficient (if enabled)
Definition: fxobjects.h:4176
virtual double getOutput3()
Definition: fxobjects.h:7026
double zRegister_C
storage register for C
Definition: fxobjects.h:6428
void flushBuffer()
Definition: fxobjects.h:2240
The SimpleLPF object implements a first order one-pole LPF using one coefficient "g" value...
Definition: fxobjects.h:3748
virtual void enableAuxInput(bool enableAuxInput)
Definition: fxobjects.h:1180
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8323
WdfSeriesAdaptor seriesAdaptor_L1C1
adaptor for L1 and C1
Definition: fxobjects.h:8035
double zRegister_L
storage register for L
Definition: fxobjects.h:7038
virtual double getComponentValue_C()
Definition: fxobjects.h:6879
unsigned int count
count of samples in input array
Definition: fxobjects.h:9887
WdfParallelAdaptor parallelAdaptor_C1
adaptor for C1
Definition: fxobjects.h:7847
virtual double getOutput2()
Definition: fxobjects.h:7511
ClassATubePreParameters getParameters()
Definition: fxobjects.h:5840
NestedDelayAPFParameters & operator=(const NestedDelayAPFParameters &params)
Definition: fxobjects.h:4351
NestedDelayAPFParameters getParameters()
Definition: fxobjects.h:4489
void calculateFilterCoeffs()
Definition: fxobjects.h:5327
virtual void setInput2(double _in2)
Definition: fxobjects.h:7594
double wetLevel_dB
wet output level in dB
Definition: fxobjects.h:2692
virtual double getOutput2()
Definition: fxobjects.h:6135
double releaseTime_mSec
release time in milliseconds
Definition: fxobjects.h:1808
double bufferLength_mSec
total buffer length in mSec
Definition: fxobjects.h:4323
Custom parameter structure for the TwoBandShelvingFilter object. Used for reverb algorithms in book...
Definition: fxobjects.h:4546
double R1
input port resistance
Definition: fxobjects.h:7288
Custom parameter structure for the SimpleDelay object. Used for reverb algorithms in book...
Definition: fxobjects.h:3812
double * outputBuffer
output timeline (y)
Definition: fxobjects.h:8887
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:443
virtual double getOutput3()
Definition: fxobjects.h:6657
virtual double getOutput2()
Definition: fxobjects.h:7621
The ModulatedDelay object implements the three basic algorithms: flanger, chorus, vibrato...
Definition: fxobjects.h:3322
Use this interface for objects that process audio input samples to produce audio output samples...
Definition: fxobjects.h:1160
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6123
void createCircularBufferPowerOfTwo(unsigned int _bufferLengthPowerOfTwo)
Definition: fxobjects.h:2314
double RL
RL value.
Definition: fxobjects.h:6676
WdfSeriesTerminatedAdaptor seriesTerminatedAdaptor_L3C3
adaptor for L3 and C3
Definition: fxobjects.h:8037
unsigned int inputCount
input sample counter
Definition: fxobjects.h:9074
void createDelayBuffer(double _sampleRate, double _bufferLength_mSec)
Definition: fxobjects.h:3920
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5511
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:1379
double readDelayAtTime_mSec(double _delay_mSec)
Definition: fxobjects.h:3942
double sampleRate
sample rate
Definition: fxobjects.h:7050
virtual double getOutput2()
Definition: fxobjects.h:7023
WdfParallelAdaptor parallelAdaptor_L2C2
adaptor for L2 and C2
Definition: fxobjects.h:8036
double apfDelayMax_mSec
APF max delay time.
Definition: fxobjects.h:4723
PhaseShifterParameters & operator=(const PhaseShifterParameters &params)
Definition: fxobjects.h:3478
double slopeIncrement
transition slope
Definition: fxobjects.h:608
void setComponent(wdfComponent componentType, double value1=0.0, double value2=0.0)
Definition: fxobjects.h:7170
The PhaseShifter object implements a six-stage phaser.
Definition: fxobjects.h:3555
void setParameters(const ZVAFilterParameters &params)
Definition: fxobjects.h:5205
double coeffArray[numCoeffs]
our local copy of biquad coeffs
Definition: fxobjects.h:1595
The FastFFT provides a simple wrapper for the FFTW FFT operation - it is ultra-thin and simple to use...
Definition: fxobjects.h:8763
bool softKnee
soft knee flag
Definition: fxobjects.h:2017
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:1848
rateConversionRatio
Use this strongly typed enum to easily set up or down sampling ratios.
Definition: fxobjects.h:9617
virtual double getOutput1()
Definition: fxobjects.h:7618
double modCounterQP
Quad Phase modulo counter [0.0, +1.0].
Definition: fxobjects.h:3043
LFO modLFO
LFO.
Definition: fxobjects.h:4329
double decimateAudio(DecimatorInput data)
Definition: fxobjects.h:9960
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6746
OscillatorParameters & operator=(const OscillatorParameters &params)
Definition: fxobjects.h:2959
void setSourceResistance(double _sourceResistance)
Definition: fxobjects.h:7151
double Q
brickwall Q
Definition: fxobjects.h:568
void createCircularBuffer(unsigned int _bufferLength)
Definition: fxobjects.h:2306
FastConvolver convolver
the convolver
Definition: fxobjects.h:9860
void setParameters(const LRFilterBankParameters &_parameters)
Definition: fxobjects.h:1745
virtual void updateComponentResistance()
Definition: fxobjects.h:6477
WdfParallelAdaptor parallelAdaptor_L2C2
adaptor for L2 and C2
Definition: fxobjects.h:8133
virtual double processAudioSample(double xn)
Definition: fxobjects.h:4229
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6285
double lfoRate_Hz
LFO rate in Hz, if enabled.
Definition: fxobjects.h:4179
bool mirrorMag
optionally mirror the output array
Definition: fxobjects.h:572
virtual void setComponentValue_RL(double _componentValue_R, double _componentValue_L)
Definition: fxobjects.h:6607
double Q
filter Q
Definition: fxobjects.h:8172
double lowShelfBoostCut_dB
LSF shelf gain/cut.
Definition: fxobjects.h:5782
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5696
bool polyphase
enable polyphase decomposition
Definition: fxobjects.h:9988
void initialize(unsigned int _filterImpulseLength)
Definition: fxobjects.h:8959
double RL
RL value.
Definition: fxobjects.h:6433
double lpf_g
gain value for LPF (if enabled)
Definition: fxobjects.h:4010
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5979
double highShelf_fc
high shelf fc
Definition: fxobjects.h:4735
double phi
bin phase angle
Definition: fxobjects.h:9130
double delay_Samples
current delay in samples; other objects may need to access this information
Definition: fxobjects.h:3832
double componentResistance
equivalent resistance of pair of componen
Definition: fxobjects.h:6680
double * inputBuffer
input timeline (x)
Definition: fxobjects.h:8886
The TwoBandShelvingFilter object implements two shelving filters in series in the standard "Bass and ...
Definition: fxobjects.h:4586
double ha
ha = N/4 — 75% overlap
Definition: fxobjects.h:9584
Custom output structure for interpolator; it holds an arry of interpolated output samples...
Definition: fxobjects.h:9758
Custom parameter structure for the EnvelopeFollower object.
Definition: fxobjects.h:5398
double sampleRate
sample rate
Definition: fxobjects.h:6436
BinData binDataPrevious[PSM_FFT_LEN]
array of BinData structures for previous FFT frame
Definition: fxobjects.h:9590
PSMVocoderParameters getParameters()
Definition: fxobjects.h:9557
virtual double getOutput2()
Definition: fxobjects.h:7409
void setSampleRate(double _sampleRate)
Definition: fxobjects.h:6177
virtual void setSampleRate(double _sampleRate)
Definition: fxobjects.h:1929
virtual void setInput3(double _in3)
Definition: fxobjects.h:7403
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:8445
virtual void updateComponentResistance()
Definition: fxobjects.h:6282
virtual double getComponentResistance()
Definition: fxobjects.h:6839
EnvelopeFollowerParameters & operator=(const EnvelopeFollowerParameters &params)
Definition: fxobjects.h:5402
delayUpdateType
Use this strongly typed enum to easily set the delay update type; this varies depending on the design...
Definition: fxobjects.h:2654
WDFParameters & operator=(const WDFParameters &params)
Definition: fxobjects.h:8158
The BitCrusher object implements a quantizing bitcrusher algorithm.
Definition: fxobjects.h:5950
Custom parameter structure for the DynamicsProcessor object. Ths struct includes all information need...
Definition: fxobjects.h:1987
virtual void setInput(double in)
Definition: fxobjects.h:6638
TriodeClassAParameters & operator=(const TriodeClassAParameters &params)
Definition: fxobjects.h:5589
bool enableSidechain
enable external sidechain input to object
Definition: fxobjects.h:2018
double outputGain
outputGain level
Definition: fxobjects.h:5615
virtual void updateComponentResistance()
Definition: fxobjects.h:6200
double zRegister_C
storage register for L
Definition: fxobjects.h:6793
edgeTransition
Use this strongly typed enum to easily set the edge direction (rising or falling) of a transition ban...
Definition: fxobjects.h:588
double lfoMaxModulation_mSec
max modulation time if LFO is enabled
Definition: fxobjects.h:4380
analogFilter
Use this strongy typed enum to set the analog filter type for the AnalogMagData structure.
Definition: fxobjects.h:820
virtual double processAudioSample(double xn)
Definition: fxobjects.h:5986
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5037
Custom parameter structure for the ZVAFilter object.
Definition: fxobjects.h:5128
Use this interface for objects in the WDF Ladder Filter library; see book for more information...
Definition: fxobjects.h:6012
bool resample(double *input, double *output, uint32_t inLength, uint32_t outLength, interpolation interpType=interpolation::kLinear, double scalar=1.0, double *outWindow=nullptr)
function that resamples an input array of length N into an output array of length M...
Definition: fxobjects.h:1060
virtual double getOutput2()
Definition: fxobjects.h:6412
double asymmetry
asymmetry level
Definition: fxobjects.h:5614
double RC
RC value.
Definition: fxobjects.h:7046
ReverbTankParameters getParameters()
Definition: fxobjects.h:4902
fftw_complex * ifft_result
array for IFFT output
Definition: fxobjects.h:8878
The LRFilterBank object implements 2 Linkwitz-Riley Filters in a parallel filter bank to split the si...
Definition: fxobjects.h:1679
void setParameters(AnalogFIRFilterParameters _parameters)
Definition: fxobjects.h:2587
void createWDF()
Definition: fxobjects.h:8013
virtual double getComponentValue_L()
Definition: fxobjects.h:6387
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:7243
filterCoeff
Use this enum to easily access coefficents inside of arrays.
Definition: fxobjects.h:1283
The WDFBesselBSF3 object implements a 3rd order Bessel BSF NOTE: designed with Elsie www...
Definition: fxobjects.h:7975
virtual double getComponentValue_L()
Definition: fxobjects.h:6507
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6882
bool enableLFO
flag to enable the modulated delay
Definition: fxobjects.h:4377
virtual void setComponentValue_LC(double _componentValue_L, double _componentValue_C)
Definition: fxobjects.h:6365
virtual double getOutput1()
Definition: fxobjects.h:6294
The WdfSeriesAdaptor object implements the series reflection-free (non-terminated) adaptor...
Definition: fxobjects.h:7324
fftw_complex * doInverseFFT(double *inputReal, double *inputImag)
perform the IFFT operation
Definition: fxobjects.cpp:1204
Custom parameter structure for the Biquad object. Default version defines the biquad structure used i...
Definition: fxobjects.h:9148
unsigned int wrapMaskOut
output wrap mask
Definition: fxobjects.h:8895
ComplexNumber complexMultiply(ComplexNumber c1, ComplexNumber c2)
returns the complex product of two complex numbers
Definition: fxobjects.h:489
void setParameters(const WDFParameters &_wdfParameters)
Definition: fxobjects.h:8264
bool calculateFilterCoeffs()
Definition: fxobjects.cpp:153
virtual void setComponentValue_C(double _componentValue_C)
Definition: fxobjects.h:6380
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:2999
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:5220
double C
value of C component
Definition: fxobjects.h:7116
double analogMatchSigma
analog matching Sigma value (see book)
Definition: fxobjects.h:5383
The AnalogFIRFilter object implements a somewhat silly algorithm that implaments an analog magnitude ...
Definition: fxobjects.h:2547
double outputLevel
output level (not in dB)
Definition: fxobjects.h:5901
virtual void updateComponentResistance()
Definition: fxobjects.h:6357
int previousPeakBin
index of peak bin in previous FFT
Definition: fxobjects.h:9133
virtual void setInput2(double _in2)
Definition: fxobjects.h:6663
WDFParameters getParameters()
Definition: fxobjects.h:8379
Custom parameter structure for the BitCrusher object.
Definition: fxobjects.h:5916
double coeffArray[numCoeffs]
Definition: fxobjects.h:1436
AnalogFIRFilterParameters getParameters()
Definition: fxobjects.h:2581
bool matchAnalogNyquistLPF
match analog gain at Nyquist
Definition: fxobjects.h:5154
unsigned int frameLength
current FFT length
Definition: fxobjects.h:8909
virtual double getComponentResistance()
Definition: fxobjects.h:6715
double wetLevel_dB
wet output level in dB
Definition: fxobjects.h:4738
double feedback_Pct
feedback in %
Definition: fxobjects.h:3302
virtual double getR2()
Definition: fxobjects.h:7439
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:511
OscillatorParameters getParameters()
Definition: fxobjects.h:3015
virtual void setComponentValue_R(double _componentValue_R)
Definition: fxobjects.h:6985
virtual double getComponentValue_L()
Definition: fxobjects.h:6753
virtual void initialize(double _R1)
Definition: fxobjects.h:7553
virtual double getOutput3()
Definition: fxobjects.h:6221
void initialize(unsigned int _frameLength, windowType _window)
initialize the Fast FFT object for operation
Definition: fxobjects.cpp:1082
Custom structure that holds magnitude information about a brickwall filter.
Definition: fxobjects.h:556
virtual double processAudioSample(double xn)
Definition: fxobjects.h:2568
double fc
filter fc
Definition: fxobjects.h:8171
double lastEnvelope
output register
Definition: fxobjects.h:1946
virtual double getComponentValue()
Definition: fxobjects.h:6110
virtual double getComponentResistance()
Definition: fxobjects.h:6351
double innerAPF_g
g coefficient for inner APF
Definition: fxobjects.h:4374
double psi[PSM_FFT_LEN]
array of phase correction values for classic algorithm
Definition: fxobjects.h:9586
virtual double getOutput3()
Definition: fxobjects.h:6535
double releaseTime
release time coefficient
Definition: fxobjects.h:1944
double alpha0
input scalar, correct delay-free loop
Definition: fxobjects.h:5376
virtual double getComponentConductance()
Definition: fxobjects.h:6718
bool clampToUnityMax
clamp output to 1.0 (set false for true log detectors)
Definition: fxobjects.h:1811
ClassATubePreParameters parameters
object parameters
Definition: fxobjects.h:5896
double phaseInc
phase inc = fo/fs
Definition: fxobjects.h:3042
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:7982
delayAlgorithm
Use this strongly typed enum to easily set the delay algorithm.
Definition: fxobjects.h:2638
double highShelfBoostCut_dB
HSF shelf frequency.
Definition: fxobjects.h:5784
The PhaseVocoder provides a basic phase vocoder that is initialized to N = 4096 and 75% overlap; the ...
Definition: fxobjects.h:8822
virtual double getOutput1()
Definition: fxobjects.h:6897
virtual double getOutput2()
Definition: fxobjects.h:6532
double makeUpGain_dB
stored makeup gain (dB)
Definition: fxobjects.h:5095
virtual void reset(double _sampleRate)
Definition: fxobjects.h:6513
bool enableLPF
flag to enable LPF in structure
Definition: fxobjects.h:4175
double * windowBuff
buffer for window
Definition: fxobjects.h:9595
double sourceResistance
source impedance; OK for this to be set to 0.0 for Rs = 0
Definition: fxobjects.h:7310
double componentValue_R
component value R
Definition: fxobjects.h:6797
BitCrusherParameters & operator=(const BitCrusherParameters &params)
Definition: fxobjects.h:5920
virtual double getComponentConductance()
Definition: fxobjects.h:6595
virtual double getOutput1()
Definition: fxobjects.h:7020
WdfSeriesAdaptor seriesAdaptor_R
adaptor for series R
Definition: fxobjects.h:8658
virtual double getOutput3()=0
DelayAPFParameters & operator=(const DelayAPFParameters &params)
Definition: fxobjects.h:4155
Custom input structure for DecimatorInput; it holds an arry of input samples that will be decimated d...
Definition: fxobjects.h:9883
windowType window
window type
Definition: fxobjects.h:8798
fftw_plan plan_backward
FFTW plan for IFFT.
Definition: fxobjects.h:8794
unsigned int startBin
starting bin for transition band
Definition: fxobjects.h:606
double RR
RR value.
Definition: fxobjects.h:6678
double fixeDelayWeight_Pct
fixed delay max weighying
Definition: fxobjects.h:4726
double g
simple LPF g value
Definition: fxobjects.h:3728
BinData & operator=(const BinData &params)
Definition: fxobjects.h:9098
fftw_complex * doFFT(double *inputReal, double *inputImag=nullptr)
perform the FFT operation
Definition: fxobjects.cpp:1176
double phi[PSM_FFT_LEN]
array of phase values for classic algorithm
Definition: fxobjects.h:9585
virtual bool reset(double _sampleRate)
Definition: fxobjects.h:5957
unsigned int localPeakBin
index of peak-boss
Definition: fxobjects.h:9132
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:4082
double dryLevel_dB
dry output level in dB
Definition: fxobjects.h:2693
virtual void setInput2(double _in2)
Definition: fxobjects.h:7502
virtual double getOutput()
Definition: fxobjects.h:6526
The WDFIdealRLCHPF object implements an ideal RLC HPF using the WDF library.
Definition: fxobjects.h:8316
double componentResistance
equivalent resistance of pair of components
Definition: fxobjects.h:6926
void setParameters(const BiquadParameters &_parameters)
Definition: fxobjects.h:1405
double outerAPF_g
g coefficient for outer APF
Definition: fxobjects.h:4373
The NestedDelayAPF object implements a pair of nested Delaying APF structures. These are labled the o...
Definition: fxobjects.h:4403
PhaseShifterParameters getParameters()
Definition: fxobjects.h:3678
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:9724
virtual bool canProcessAudioFrame()
Definition: fxobjects.h:2767
The WdfParallelRL object implements the reflection coefficient and signal flow through a WDF simulate...
Definition: fxobjects.h:6696
T readBuffer(double delayInFractionalSamples)
Definition: fxobjects.h:2358