OpenShot Library | OpenShotAudio  0.2.2
juce_ADSR.h
1 
2 /** @weakgroup juce_audio_basics-utilities
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 //==============================================================================
31 /**
32  A very simple ADSR envelope class.
33 
34  To use it, call setSampleRate() with the current sample rate and give it some parameters
35  with setParameters() then call getNextSample() to get the envelope value to be applied
36  to each audio sample or applyEnvelopeToBuffer() to apply the envelope to a whole buffer.
37 
38  @tags{Audio}
39 */
40 class ADSR
41 {
42 public:
43  //==============================================================================
44  ADSR()
45  {
46  setSampleRate (44100.0);
47  setParameters ({});
48  }
49 
50  //==============================================================================
51  /**
52  Holds the parameters being used by an ADSR object.
53 
54  @tags{Audio}
55  */
56  struct Parameters
57  {
58  /** Attack time in seconds. */
59  float attack = 0.1f;
60 
61  /** Decay time in seconds. */
62  float decay = 0.1f;
63 
64  /** Sustain level. */
65  float sustain = 1.0f;
66 
67  /** Release time in seconds. */
68  float release = 0.1f;
69  };
70 
71  /** Sets the parameters that will be used by an ADSR object.
72 
73  You must have called setSampleRate() with the correct sample rate before
74  this otherwise the values may be incorrect!
75 
76  @see getParameters
77  */
78  void setParameters (const Parameters& newParameters)
79  {
80  currentParameters = newParameters;
81 
82  sustainLevel = newParameters.sustain;
83  calculateRates (newParameters);
84 
85  if (currentState != State::idle)
86  checkCurrentState();
87  }
88 
89  /** Returns the parameters currently being used by an ADSR object.
90 
91  @see setParameters
92  */
93  const Parameters& getParameters() const { return currentParameters; }
94 
95  /** Returns true if the envelope is in its attack, decay, sustain or release stage. */
96  bool isActive() const noexcept { return currentState != State::idle; }
97 
98  //==============================================================================
99  /** Sets the sample rate that will be used for the envelope.
100 
101  This must be called before the getNextSample() or setParameters() methods.
102  */
103  void setSampleRate (double sampleRate)
104  {
105  jassert (sampleRate > 0.0);
106  sr = sampleRate;
107  }
108 
109  //==============================================================================
110  /** Resets the envelope to an idle state. */
111  void reset()
112  {
113  envelopeVal = 0.0f;
114  currentState = State::idle;
115  }
116 
117  /** Starts the attack phase of the envelope. */
118  void noteOn()
119  {
120  if (attackRate > 0.0f)
121  {
122  currentState = State::attack;
123  }
124  else if (decayRate > 0.0f)
125  {
126  envelopeVal = 1.0f;
127  currentState = State::decay;
128  }
129  else
130  {
131  currentState = State::sustain;
132  }
133  }
134 
135  /** Starts the release phase of the envelope. */
136  void noteOff()
137  {
138  if (currentState != State::idle)
139  {
140  if (currentParameters.release > 0.0f)
141  {
142  releaseRate = static_cast<float> (envelopeVal / (currentParameters.release * sr));
143  currentState = State::release;
144  }
145  else
146  {
147  reset();
148  }
149  }
150  }
151 
152  //==============================================================================
153  /** Returns the next sample value for an ADSR object.
154 
155  @see applyEnvelopeToBuffer
156  */
158  {
159  if (currentState == State::idle)
160  return 0.0f;
161 
162  if (currentState == State::attack)
163  {
164  envelopeVal += attackRate;
165 
166  if (envelopeVal >= 1.0f)
167  {
168  envelopeVal = 1.0f;
169 
170  if (decayRate > 0.0f)
171  currentState = State::decay;
172  else
173  currentState = State::sustain;
174  }
175  }
176  else if (currentState == State::decay)
177  {
178  envelopeVal -= decayRate;
179 
180  if (envelopeVal <= sustainLevel)
181  {
182  envelopeVal = sustainLevel;
183  currentState = State::sustain;
184  }
185  }
186  else if (currentState == State::sustain)
187  {
188  envelopeVal = sustainLevel;
189  }
190  else if (currentState == State::release)
191  {
192  envelopeVal -= releaseRate;
193 
194  if (envelopeVal <= 0.0f)
195  reset();
196  }
197 
198  return envelopeVal;
199  }
200 
201  /** This method will conveniently apply the next numSamples number of envelope values
202  to an AudioBuffer.
203 
204  @see getNextSample
205  */
206  template<typename FloatType>
207  void applyEnvelopeToBuffer (AudioBuffer<FloatType>& buffer, int startSample, int numSamples)
208  {
209  jassert (startSample + numSamples <= buffer.getNumSamples());
210 
211  auto numChannels = buffer.getNumChannels();
212 
213  while (--numSamples >= 0)
214  {
215  auto env = getNextSample();
216 
217  for (int i = 0; i < numChannels; ++i)
218  buffer.getWritePointer (i)[startSample] *= env;
219 
220  ++startSample;
221  }
222  }
223 
224 private:
225  //==============================================================================
226  void calculateRates (const Parameters& parameters)
227  {
228  // need to call setSampleRate() first!
229  jassert (sr > 0.0);
230 
231  attackRate = (parameters.attack > 0.0f ? static_cast<float> (1.0f / (parameters.attack * sr)) : -1.0f);
232  decayRate = (parameters.decay > 0.0f ? static_cast<float> ((1.0f - sustainLevel) / (parameters.decay * sr)) : -1.0f);
233  }
234 
235  void checkCurrentState()
236  {
237  if (currentState == State::attack && attackRate <= 0.0f) currentState = decayRate > 0.0f ? State::decay : State::sustain;
238  else if (currentState == State::decay && decayRate <= 0.0f) currentState = State::sustain;
239  else if (currentState == State::release && releaseRate <= 0.0f) reset();
240  }
241 
242  //==============================================================================
243  enum class State { idle, attack, decay, sustain, release };
244 
245  State currentState = State::idle;
246  Parameters currentParameters;
247 
248  double sr = 0.0;
249  float envelopeVal = 0.0f, sustainLevel = 0.0f, attackRate = 0.0f, decayRate = 0.0f, releaseRate = 0.0f;
250 };
251 
252 } // namespace juce
253 
254 /** @}*/
void setSampleRate(double sampleRate)
Sets the sample rate that will be used for the envelope.
Definition: juce_ADSR.h:103
void noteOn()
Starts the attack phase of the envelope.
Definition: juce_ADSR.h:118
void reset()
Resets the envelope to an idle state.
Definition: juce_ADSR.h:111
float sustain
Sustain level.
Definition: juce_ADSR.h:65
bool isActive() const noexcept
Returns true if the envelope is in its attack, decay, sustain or release stage.
Definition: juce_ADSR.h:96
float attack
Attack time in seconds.
Definition: juce_ADSR.h:59
Holds the parameters being used by an ADSR object.
Definition: juce_ADSR.h:56
float release
Release time in seconds.
Definition: juce_ADSR.h:68
A very simple ADSR envelope class.
Definition: juce_ADSR.h:40
A multi-channel buffer containing floating point audio samples.
float decay
Decay time in seconds.
Definition: juce_ADSR.h:62
int getNumChannels() const noexcept
Returns the number of channels of audio data that this buffer contains.
float getNextSample()
Returns the next sample value for an ADSR object.
Definition: juce_ADSR.h:157
void noteOff()
Starts the release phase of the envelope.
Definition: juce_ADSR.h:136
void applyEnvelopeToBuffer(AudioBuffer< FloatType > &buffer, int startSample, int numSamples)
This method will conveniently apply the next numSamples number of envelope values to an AudioBuffer...
Definition: juce_ADSR.h:207
void setParameters(const Parameters &newParameters)
Sets the parameters that will be used by an ADSR object.
Definition: juce_ADSR.h:78
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer&#39;s channels.
int getNumSamples() const noexcept
Returns the number of samples allocated in each of the buffer&#39;s channels.
const Parameters & getParameters() const
Returns the parameters currently being used by an ADSR object.
Definition: juce_ADSR.h:93