OpenShot Audio Library | OpenShotAudio: juce_ADSR.h Source File

OpenShot Audio Library | OpenShotAudio 1.0.0

Loading...
Searching...
No Matches
juce_ADSR.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26//==============================================================================
40 class JUCE_API ADSR
41{
42public:
43 //==============================================================================
44 ADSR()
45 {
46 recalculateRates();
47 }
48
49 //==============================================================================
55 struct JUCE_API Parameters
56 {
57 Parameters() = default;
58
59 Parameters (float attackTimeSeconds,
60 float decayTimeSeconds,
61 float sustainLevel,
62 float releaseTimeSeconds)
63 : attack (attackTimeSeconds),
64 decay (decayTimeSeconds),
65 sustain (sustainLevel),
66 release (releaseTimeSeconds)
67 {
68 }
69
70 float attack = 0.1f, decay = 0.1f, sustain = 1.0f, release = 0.1f;
71 };
72
80 void setParameters (const Parameters& newParameters)
81 {
82 // need to call setSampleRate() first!
83 jassert (sampleRate > 0.0);
84
85 parameters = newParameters;
86 recalculateRates();
87 }
88
93 const Parameters& getParameters() const noexcept { return parameters; }
94
96 bool isActive() const noexcept { return state != State::idle; }
97
98 //==============================================================================
103 void setSampleRate (double newSampleRate) noexcept
104 {
105 jassert (newSampleRate > 0.0);
106 sampleRate = newSampleRate;
107 }
108
109 //==============================================================================
111 void reset() noexcept
112 {
113 envelopeVal = 0.0f;
114 state = State::idle;
115 }
116
118 void noteOn() noexcept
119 {
120 if (attackRate > 0.0f)
121 {
122 state = State::attack;
123 }
124 else if (decayRate > 0.0f)
125 {
126 envelopeVal = 1.0f;
127 state = State::decay;
128 }
129 else
130 {
131 envelopeVal = parameters.sustain;
132 state = State::sustain;
133 }
134 }
135
137 void noteOff() noexcept
138 {
139 if (state != State::idle)
140 {
141 if (parameters.release > 0.0f)
142 {
143 releaseRate = (float) (envelopeVal / (parameters.release * sampleRate));
144 state = State::release;
145 }
146 else
147 {
148 reset();
149 }
150 }
151 }
152
153 //==============================================================================
158 float getNextSample() noexcept
159 {
160 switch (state)
161 {
162 case State::idle:
163 {
164 return 0.0f;
165 }
166
167 case State::attack:
168 {
169 envelopeVal += attackRate;
170
171 if (envelopeVal >= 1.0f)
172 {
173 envelopeVal = 1.0f;
174 goToNextState();
175 }
176
177 break;
178 }
179
180 case State::decay:
181 {
182 envelopeVal -= decayRate;
183
184 if (envelopeVal <= parameters.sustain)
185 {
186 envelopeVal = parameters.sustain;
187 goToNextState();
188 }
189
190 break;
191 }
192
193 case State::sustain:
194 {
195 envelopeVal = parameters.sustain;
196 break;
197 }
198
199 case State::release:
200 {
201 envelopeVal -= releaseRate;
202
203 if (envelopeVal <= 0.0f)
204 goToNextState();
205
206 break;
207 }
208 }
209
210 return envelopeVal;
211 }
212
218 template <typename FloatType>
219 void applyEnvelopeToBuffer (AudioBuffer<FloatType>& buffer, int startSample, int numSamples)
220 {
221 jassert (startSample + numSamples <= buffer.getNumSamples());
222
223 if (state == State::idle)
224 {
225 buffer.clear (startSample, numSamples);
226 return;
227 }
228
229 if (state == State::sustain)
230 {
231 buffer.applyGain (startSample, numSamples, parameters.sustain);
232 return;
233 }
234
235 auto numChannels = buffer.getNumChannels();
236
237 while (--numSamples >= 0)
238 {
239 auto env = getNextSample();
240
241 for (int i = 0; i < numChannels; ++i)
242 buffer.getWritePointer (i)[startSample] *= env;
243
244 ++startSample;
245 }
246 }
247
248private:
249 //==============================================================================
250 void recalculateRates() noexcept
251 {
252 auto getRate = [] (float distance, float timeInSeconds, double sr)
253 {
254 return timeInSeconds > 0.0f ? (float) (distance / (timeInSeconds * sr)) : -1.0f;
255 };
256
257 attackRate = getRate (1.0f, parameters.attack, sampleRate);
258 decayRate = getRate (1.0f - parameters.sustain, parameters.decay, sampleRate);
259 releaseRate = getRate (parameters.sustain, parameters.release, sampleRate);
260
261 if ((state == State::attack && attackRate <= 0.0f)
262 || (state == State::decay && (decayRate <= 0.0f || envelopeVal <= parameters.sustain))
263 || (state == State::release && releaseRate <= 0.0f))
264 {
265 goToNextState();
266 }
267 }
268
269 void goToNextState() noexcept
270 {
271 if (state == State::attack)
272 {
273 state = (decayRate > 0.0f ? State::decay : State::sustain);
274 return;
275 }
276
277 if (state == State::decay)
278 {
279 state = State::sustain;
280 return;
281 }
282
283 if (state == State::release)
284 reset();
285 }
286
287 //==============================================================================
288 enum class State { idle, attack, decay, sustain, release };
289
290 State state = State::idle;
291 Parameters parameters;
292
293 double sampleRate = 44100.0;
294 float envelopeVal = 0.0f, attackRate = 0.0f, decayRate = 0.0f, releaseRate = 0.0f;
295};
296
297} // namespace juce
juce::ADSR::setSampleRate
void setSampleRate(double newSampleRate) noexcept
Definition juce_ADSR.h:103
juce::ADSR::noteOff
void noteOff() noexcept
Definition juce_ADSR.h:137
juce::ADSR::isActive
bool isActive() const noexcept
Definition juce_ADSR.h:96
juce::ADSR::reset
void reset() noexcept
Definition juce_ADSR.h:111
juce::ADSR::getNextSample
float getNextSample() noexcept
Definition juce_ADSR.h:158
juce::ADSR::setParameters
void setParameters(const Parameters &newParameters)
Definition juce_ADSR.h:80
juce::ADSR::noteOn
void noteOn() noexcept
Definition juce_ADSR.h:118
juce::ADSR::getParameters
const Parameters & getParameters() const noexcept
Definition juce_ADSR.h:93
juce::ADSR::applyEnvelopeToBuffer
void applyEnvelopeToBuffer(AudioBuffer< FloatType > &buffer, int startSample, int numSamples)
Definition juce_ADSR.h:219
juce::AudioBuffer
Definition juce_AudioSampleBuffer.h:34
juce::AudioBuffer::getWritePointer
Type * getWritePointer(int channelNumber) noexcept
Definition juce_AudioSampleBuffer.h:291
juce::AudioBuffer::getNumChannels
int getNumChannels() const noexcept
Definition juce_AudioSampleBuffer.h:236
juce::AudioBuffer::getNumSamples
int getNumSamples() const noexcept
Definition juce_AudioSampleBuffer.h:242
juce::AudioBuffer::clear
void clear() noexcept
Definition juce_AudioSampleBuffer.h:556
juce::AudioBuffer::applyGain
void applyGain(int channel, int startSample, int numSamples, Type gain) noexcept
Definition juce_AudioSampleBuffer.h:684
juce::ADSR::Parameters
Definition juce_ADSR.h:56