1 /**
2 * Copyright 2017 Cut Through Recordings
3 * License: MIT License
4 * Author(s): Ethan Reker
5 */
6 module ddsp.util.envelope;
7 
8 import std.math;
9 import std.algorithm;
10 
11 /// Envelop Detector with adjustable attack and release times. Great for compressors
12 /// and meters.
13 /+
14 http://www.musicdsp.org/showArchiveComment.php?ArchiveID=97
15 +/
16 class EnvelopeDetector
17 {
18 public:
19 nothrow:
20 @nogc:
21 
22     this()
23     {
24         _envelope = 0f;    
25     }
26     
27     void setSampleRate(const float sampleRate)
28     {
29         _sampleRate = sampleRate;
30     }
31     
32     void setEnvelope(const float attackTime, const float releaseTime)
33     {
34         _ga = exp(-1/(_sampleRate * attackTime / 1000));
35         _gr = exp(-1 / (_sampleRate * releaseTime / 1000));
36     }
37     
38     void detect(float input)
39     {
40         float envIn = abs(input);
41         
42         if(_envelope < envIn)
43             _envelope = _envelope * _ga + (1 - _ga) * envIn;
44         else
45             _envelope = _envelope * _gr + (1 - _gr) * envIn;
46         
47     }
48     
49     float getEnvelope()
50     {
51         return _envelope;
52     }
53     
54 private:
55     /// Attack coefficient
56     float _ga;
57     
58     /// Release coefficient
59     float _gr;
60     
61     /// stores the current value of the envelope;
62     float _envelope;
63     
64     /// Sample Rate
65     float _sampleRate;
66 }
67 
68 /// Simple Peak envelope follower, useful for meters.
69 /+
70 http://www.musicdsp.org/archive.php?classid=2#19
71 +/
72 class PeakFollower
73 {
74 public:
75 nothrow:
76 @nogc:
77 
78     this()
79     {
80         _envelope = 0f;
81     }
82     
83     void setSampleRate(const float sampleRate)
84     {
85         _sampleRate = sampleRate;
86     }
87     
88     void initialize(const float decayTime)
89     {
90         _decay = pow(0.5, 1.0 / (decayTime * _sampleRate));
91     }
92     
93     void detect(const float input)
94     {
95         float absInput = abs(input);
96         
97         if(absInput >= _envelope)
98             _envelope = absInput;
99         else
100         {
101             _envelope = clamp(_envelope * _decay, 0.0f, 1.0f);
102         }
103     }
104     
105     float getEnvelope()
106     {
107         return _envelope;
108     }
109     
110 private:
111     float _envelope;
112     
113     float _decay;
114     
115     float _sampleRate;
116 }
117 
118 /+class SimpleRMS
119 {
120 public:
121 nothrow:
122 @nogc:
123 
124     this()
125     {
126         _envelope = 0.0f;
127     }
128     
129     void setSampleRate(float sampleRate)
130     {
131         _sampleRate = sampleRate;
132     }
133     
134     void initialize(uint windowSize)
135     {
136         _windowSize = windowSize;
137         buffer = cast(T*) malloc(windowSize * T.sizeof);
138     }
139     
140     void detect(float input)
141     {
142         
143     }
144     
145     float getEnvelope()
146     {
147         return _envelope;
148     }
149     
150 private:
151     float[] buffer;
152 }+/