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