1 /** 2 * Copyright 2017 Cut Through Recordings 3 * License: MIT License 4 * Author(s): Ethan Reker 5 */ 6 module ddsp.filter.peak; 7 8 import ddsp.filter.biquad; 9 import ddsp.effect.effect; 10 11 import std.math; 12 13 /// The equations for calculating the BiQuad Coefficients are based off of those from vinniefalco/DSPFilters 14 class BandShelf : AudioEffect 15 { 16 public: 17 18 void setGain(float gain) nothrow @nogc 19 { 20 if(_gain != gain) 21 { 22 _gain = gain; 23 calcCoefficients(); 24 } 25 } 26 27 override float getNextSample(const float input) nothrow @nogc 28 { 29 _w = input - _a1 * _w1 - _a2 * _w2; 30 _yn = _b0 * _w + _b1 *_w1 + _b2 * _w2; 31 32 _w2 = _w1; 33 _w1 = _w; 34 35 return _yn; 36 } 37 38 override void reset() nothrow @nogc 39 { 40 _w = 0; 41 _w1 = 0; 42 _w2 = 0; 43 44 _yn = 0; 45 } 46 47 void setFrequency(float frequency) nothrow @nogc 48 { 49 if(_frequency != frequency) 50 { 51 _frequency = frequency; 52 calcCoefficients(); 53 } 54 } 55 56 override string toString() 57 { 58 import std.conv; 59 return "a0: " ~ to!string(_a0) ~ 60 "a1: " ~ to!string(_a1) ~ 61 "a2: " ~ to!string(_a2) ~ 62 "b0: " ~ to!string(_b0) ~ 63 "b1: " ~ to!string(_b1) ~ 64 "b2: " ~ to!string(_b2); 65 } 66 67 private: 68 float _a0 = 0; 69 float _a1 = 0; 70 float _a2 = 0; 71 float _b0 = 0; 72 float _b1 = 0; 73 float _b2 = 0; 74 75 float _w = 0; 76 float _w1 = 0; 77 float _w2 = 0; 78 79 float _yn; 80 81 float _frequency; 82 float _gain; 83 84 const double doubleLn2 =0.69314718055994530941723212145818; 85 86 void calcCoefficients() nothrow @nogc 87 { 88 float bandWidth = 0.707f; 89 float A = pow (10, _gain/40); 90 float w0 = 2 * pi * _frequency / _sampleRate; 91 float cs = cos(w0); 92 float sn = sin(w0); 93 float AL = sn * sinh( doubleLn2/2 * bandWidth * w0/sn ); 94 _b0 = 1 + AL * A; 95 _b1 = -2 * cs; 96 _b2 = 1 - AL * A; 97 _a0 = 1 + AL / A; 98 _a1 = -2 * cs; 99 _a2 = 1 - AL / A; 100 101 _b0 /= _a0; 102 _b1 /= _a0; 103 _b2 /= _a0; 104 _a1 /= _a0; 105 _a2 /= _a0; 106 } 107 } 108 109 unittest 110 { 111 import dplug.core.nogc; 112 import dplug.core.alignedbuffer; 113 import ddsp.effect.effect; 114 115 Vec!BandShelf filters = makeVec!BandShelf; 116 foreach(channel; 0..2) 117 { 118 filters.pushBack(mallocNew!BandShelf); 119 filters[channel].setSampleRate(44100.0f); 120 filters[channel].setFrequency(150.0f); 121 filters[channel].setGain(3.0f); 122 } 123 124 //testEffect(AudioEffect effect, string name, size_t bufferSize = 20000, bool outputResults = false) 125 foreach(filter; filters) 126 testEffect(filter, "BandShelf" , 20000, false); 127 }