1 module ddsp.filter.onepole;
2 
3 import ddsp.effect.effect : AudioEffect;
4 
5 import std.math : PI, cos, sqrt;
6 
7 class OnePoleFilter(T) : AudioEffect!T
8 {
9     abstract void calcCoefficients();
10 
11     void setFrequency(float frequency)
12     {
13         _frequency = frequency;
14         calcCoefficients();
15     }
16 
17     override float getNextSample( const(float) input) nothrow @nogc 
18     {
19         immutable float output = _a0 * input - _b1 * _yn1;
20         _yn1 = input;
21         return output;
22     }
23 
24     override void reset() nothrow @nogc
25     {
26         _thetac = 0;
27         _gamma = 0;
28         _b1 = 0;
29         _a0 = 0;
30         _yn1 = 0;
31     }
32 
33 protected:
34     float _frequency;
35     float _thetac;
36     float _gamma;
37     float _b1;
38     float _a0;
39 
40 private:
41     float _yn1 = 0;
42 }
43 
44 class OnePoleLPF(T) : OnePoleFilter!T
45 {
46     override void calcCoefficients()
47     {
48         _thetac = 2 * PI * _frequency / _sampleRate;
49         _gamma = 2 - cos(_thetac);
50         _b1 = sqrt((_gamma * _gamma) - 1) - _gamma;
51         _a0 = 1 + _b1;
52     }
53 }
54 
55 
56 class OnePoleHPF(T) : OnePoleFilter!T
57 {
58     override void calcCoefficients()
59     {
60         _thetac = 2 * PI * _frequency / _sampleRate;
61         _gamma = 2 + cos(_thetac);
62         _b1 = _gamma - sqrt((_gamma * _gamma) - 1);
63         _a0 = 1 - _b1;
64     }
65 }
66 
67 unittest
68 {
69     import std.stdio;
70     writeln("****************************");
71     writeln("* One-pole Filter tests    *");
72     writeln("****************************");
73 
74     OnePoleLPF!float lowpass = new OnePoleLPF!float();
75     lowpass.setSampleRate(44100);
76     lowpass.setFrequency(1000);
77 
78     OnePoleHPF!float highpass = new OnePoleHPF!float();
79     highpass.setSampleRate(44100);
80     highpass.setFrequency(1000);
81 
82     float[] impulse = [1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f];
83     float[] lpfOutput = [];
84     float[] hpfOutput = [];
85     foreach(sample; impulse)
86     {
87         lpfOutput ~= lowpass.getNextSample(sample);
88         hpfOutput ~= highpass.getNextSample(sample);
89     }
90 
91     writeln("Lowpass Output:");
92     writeln(lpfOutput);
93     writeln("Highpass Output");
94     writeln(hpfOutput);
95 }