1 /**
2 * Copyright 2017 Cut Through Recordings
3 * License: MIT License
4 * Author(s): Ethan Reker
5 */
6 module ddsp.osc.cfoscillator;
7 
8 import ddsp.effect.effect;
9 
10 import std.math;
11 
12 /**
13 * Coupled-Form Oscillator (Gordon-Smith Oscillator)
14 */
15 class CFOscillator : AudioEffect
16 {
17 public:
18 nothrow:
19 @nogc:
20 
21     this()
22     {
23         init = false;
24     }
25     
26     void setFrequency(float frequency) nothrow @nogc
27     {
28         fo = frequency;
29         
30         theta = 2 * PI * fo / _sampleRate;
31         epsilon = 2 * sin(theta / 2);
32         
33         if(!init)
34         {
35             yn1 = sin(-1 * theta);
36             yq1 = cos(-1 * theta);
37             init = true;
38         }
39     }
40     
41     override float getNextSample(const float input) nothrow @nogc
42     {
43         yq = yq1-epsilon * yn1;
44         yn = epsilon * yq + yn1;
45         
46         yq1 = yq;
47         yn1 = yn;
48         
49         return yn;
50     }
51     
52     override void reset() nothrow @nogc
53     {
54         init = false;
55         setFrequency(fo);
56     }
57     
58 private:
59     
60     float yq;
61     float yq1;
62     float yn;
63     float yn1;
64     float epsilon;
65     float theta;
66     float fo;
67     
68     bool init;
69 }
70 
71 unittest
72 {
73     import dplug.core.nogc;
74     import ddsp.effect.effect;
75 
76     CFOscillator osc = mallocNew!CFOscillator;
77     osc.setSampleRate(44100);
78     osc.setFrequency(1000);
79 
80     testEffect(osc, "Coupled-Form Oscillator", 20000, false);
81 }