Advertisement
Guest User

C++ ZDF

a guest
Nov 27th, 2016
425
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.26 KB | None | 0 0
  1. /*************************************************************************************
  2.  
  3.     DynamicFilter - Sidechain plugin filter - v. 0.1.0.
  4.  
  5.     Copyright (C) 2016 Janus Lynggaard Thorborg (www.jthorborg.com)
  6.  
  7.     This program is free software: you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation, either version 3 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  
  20.     See \licenses\ for additional details on licenses associated with this program.
  21.  
  22. **************************************************************************************
  23.  
  24.     file:AC_SVF.h
  25.         Implementation of the linear trapezoidial integration state variable filter,
  26.         as analyzed by Andrew from Cytomic:
  27.         http://www.cytomic.com/technical-papers
  28.  
  29. *************************************************************************************/
  30.  
  31. #ifndef AC_SVF
  32. #define AC_SVF
  33.  
  34. #include <cstdlib>
  35. #include "FilterBasics.h"
  36. #include <cpl/simd.h>
  37.  
  38. namespace cytomic
  39. {
  40.  
  41.     template<typename T>
  42.     struct StateVariableFilter
  43.     {
  44.         struct Coefficients
  45.         {
  46.         public:
  47.             using Consts = cpl::simd::consts<T>;
  48.  
  49.             template<DynamicFilter::Response R>
  50.                 static Coefficients design(T normalizedFrequency, T Q, T linearGain);
  51.  
  52.             template<>
  53.                 static Coefficients design<DynamicFilter::Response::Lowpass>(T normalizedFrequency, T Q, T linearGain)
  54.                 {
  55.                     const T A = linearGain;
  56.                     const T g = std::tan(Consts::pi * normalizedFrequency);
  57.                     const T k = 1 / Q;
  58.                     const T a1 = 1 / (1 + g * (g + k));
  59.                     const T a2 = g * a1;
  60.                     const T a3 = g * a2;
  61.                     const T m0 = 0;
  62.                     const T m1 = 0;
  63.                     const T m2 = 1;
  64.                     return{ A, g, k, a1, a2, a3, m0, m1, m2 };
  65.                 }
  66.  
  67.             template<>
  68.                 static Coefficients design<DynamicFilter::Response::Bandpass>(T normalizedFrequency, T Q, T linearGain)
  69.                 {
  70.                     auto coeffs = design<DynamicFilter::Response::Lowpass>(normalizedFrequency, Q, linearGain);
  71.                     coeffs.m1 = 1;
  72.                     coeffs.m2 = 0;
  73.                     return coeffs;
  74.                 }
  75.  
  76.             template<>
  77.                 static Coefficients design<DynamicFilter::Response::Highpass>(T normalizedFrequency, T Q, T linearGain)
  78.                 {
  79.                     auto coeffs = design<DynamicFilter::Response::Lowpass>(normalizedFrequency, Q, linearGain);
  80.                     coeffs.m0 = 1;
  81.                     coeffs.m1 = -coeffs.k;
  82.                     coeffs.m2 = -1;
  83.                     return coeffs;
  84.                 }
  85.  
  86.             template<>
  87.                 static Coefficients design<DynamicFilter::Response::Notch>(T normalizedFrequency, T Q, T linearGain)
  88.                 {
  89.                     auto coeffs = design<DynamicFilter::Response::Lowpass>(normalizedFrequency, Q, linearGain);
  90.                     coeffs.m0 = 1;
  91.                     coeffs.m1 = -coeffs.k;
  92.                     coeffs.m2 = 0;
  93.                     return coeffs;
  94.                 }
  95.  
  96.             /* template<>
  97.                 static Coefficients design<DynamicFilter::Response::Peak>(T normalizedFrequency, T Q, T linearGain)
  98.                 {
  99.                     // missing A somewhere
  100.                     auto coeffs = design<DynamicFilter::Response::Lowpass>(normalizedFrequency, Q, linearGain);
  101.                     coeffs.m0 = 1;
  102.                     coeffs.m1 = -coeffs.k;
  103.                     coeffs.m2 = -2;
  104.                     return coeffs;
  105.                 } */
  106.  
  107.             template<>
  108.                 static Coefficients design<DynamicFilter::Response::Bell>(T normalizedFrequency, T Q, T linearGain)
  109.                 {
  110.                     const T A = linearGain;
  111.                     const T g = std::tan(Consts::pi * normalizedFrequency);
  112.                     const T k = 1 / (Q * A);
  113.                     const T a1 = 1 / (1 + g * (g + k));
  114.                     const T a2 = g * a1;
  115.                     const T a3 = g * a2;
  116.                     const T m0 = 1;
  117.                     const T m1 = k * (A * A - 1);
  118.                     const T m2 = 0;
  119.                     return{ A, g, k, a1, a2, a3, m0, m1, m2 };
  120.                 }
  121.  
  122.             template<>
  123.                 static Coefficients design<DynamicFilter::Response::Lowshelf>(T normalizedFrequency, T Q, T linearGain)
  124.                 {
  125.                     const T A = linearGain;
  126.                     const T g = std::tan(Consts::pi * normalizedFrequency) / std::sqrt(A);
  127.                     const T k = 1 / Q;
  128.                     const T a1 = 1 / (1 + g * (g + k));
  129.                     const T a2 = g * a1;
  130.                     const T a3 = g * a2;
  131.                     const T m0 = 1;
  132.                     const T m1 = k * (A - 1);
  133.                     const T m2 = A * A - 1;
  134.                     return{ A, g, k, a1, a2, a3, m0, m1, m2 };
  135.                 }
  136.  
  137.             template<>
  138.                 static Coefficients design<DynamicFilter::Response::Highshelf>(T normalizedFrequency, T Q, T linearGain)
  139.                 {
  140.                     const T A = linearGain;
  141.                     const T g = std::tan(Consts::pi * normalizedFrequency) * std::sqrt(A);
  142.                     const T k = 1 / Q;
  143.                     const T a1 = 1 / (1 + g * (g + k));
  144.                     const T a2 = g * a1;
  145.                     const T a3 = g * a2;
  146.                     const T m0 = A * A;
  147.                     const T m1 = k * (1 - A) * A;
  148.                     const T m2 = 1 - A * A;
  149.                     return{ A, g, k, a1, a2, a3, m0, m1, m2 };
  150.                 }
  151.  
  152.  
  153.             static Coefficients design(DynamicFilter::Response response, T normalizedFrequency, T Q, T linearGain)
  154.             {
  155.                 using R = DynamicFilter::Response;
  156.  
  157.                 switch (response)
  158.                 {
  159.                 case R::Lowpass:    return design<R::Lowpass>(normalizedFrequency, Q, linearGain);
  160.                 case R::Bandpass:   return design<R::Bandpass>(normalizedFrequency, Q, linearGain);
  161.                 case R::Highpass:   return design<R::Highpass>(normalizedFrequency, Q, linearGain);
  162.                 case R::Notch:      return design<R::Notch>(normalizedFrequency, Q, linearGain);
  163.                 //case R::Peak:     return design<R::Peak>(normalizedFrequency, Q, linearGain);
  164.                 case R::Bell:       return design<R::Bell>(normalizedFrequency, Q, linearGain);
  165.                 case R::Lowshelf:   return design<R::Lowshelf>(normalizedFrequency, Q, linearGain);
  166.                 case R::Highshelf:  return design<R::Highshelf>(normalizedFrequency, Q, linearGain);
  167.                 default:
  168.                     return Coefficients::zero();
  169.                 }
  170.             }
  171.  
  172.             static Coefficients zero()
  173.             {
  174.                 Coefficients ret;
  175.                 std::memset(&ret, 0, sizeof(Coefficients));
  176.                 return ret;
  177.             }
  178.  
  179.             T A, g, k, a1, a2, a3, m0, m1, m2;
  180.         };
  181.  
  182.  
  183.         T filter(T input, const Coefficients & c)
  184.         {
  185.             const T v3 = input - ic2eq;
  186.             const T v1 = c.a1 * ic1eq + c.a2 * v3;
  187.             const T v2 = ic2eq + c.a2 * ic1eq + c.a3 * v3;
  188.             ic1eq = 2 * v1 - ic1eq;
  189.             ic2eq = 2 * v2 - ic2eq;
  190.             return c.m0 * input + c.m1 * v1 + c.m2 * v2;
  191.         }
  192.  
  193.         T ic1eq = 0, ic2eq = 0;
  194.     };
  195. };
  196.  
  197. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement