OpenShot Library | libopenshot-audio  0.2.0
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 class ADSR
39 {
40 public:
41  //==============================================================================
42  ADSR()
43  {
44  setSampleRate (44100.0);
45  setParameters ({});
46  }
47 
48  //==============================================================================
49  /** Holds the parameters being used by an ADSR object. */
50  struct Parameters
51  {
52  /** Attack time in seconds. */
53  float attack = 0.1f;
54 
55  /** Decay time in seconds. */
56  float decay = 0.1f;
57 
58  /** Sustain level. */
59  float sustain = 1.0f;
60 
61  /** Release time in seconds. */
62  float release = 0.1f;
63  };
64 
65  /** Sets the parameters that will be used by an ADSR object.
66 
67  You must have called setSampleRate() with the correct sample rate before
68  this otherwise the values may be incorrect!
69 
70  @see getParameters
71  */
72  void setParameters (const Parameters& newParameters)
73  {
74  currentParameters = newParameters;
75 
76  sustainLevel = newParameters.sustain;
77  calculateRates (newParameters);
78 
79  if (currentState != State::idle)
80  checkCurrentState();
81  }
82 
83  /** Returns the parameters currently being used by an ADSR object.
84 
85  @see setParameters
86  */
87  const Parameters& getParameters() const { return currentParameters; }
88 
89  /** Returns true if the envelope is in its attack, decay, sustain or release stage. */
90  bool isActive() const noexcept { return currentState != State::idle; }
91 
92  //==============================================================================
93  /** Sets the sample rate that will be used for the envelope.
94 
95  This must be called before the getNextSample() or setParameters() methods.
96  */
97  void setSampleRate (double sampleRate)
98  {
99  jassert (sampleRate > 0.0);
100  sr = sampleRate;
101  }
102 
103  //==============================================================================
104  /** Resets the envelope to an idle state. */
105  void reset()
106  {
107  envelopeVal = 0.0f;
108  currentState = State::idle;
109  }
110 
111  /** Starts the attack phase of the envelope. */
112  void noteOn()
113  {
114  if (attackRate > 0.0f) currentState = State::attack;
115  else if (decayRate > 0.0f) currentState = State::decay;
116  else currentState = State::sustain;
117  }
118 
119  /** Starts the release phase of the envelope. */
120  void noteOff()
121  {
122  if (currentState != State::idle)
123  {
124  if (releaseRate > 0.0f)
125  {
126  if (currentState != State::sustain)
127  releaseRate = static_cast<float> (envelopeVal / (currentParameters.release * sr));
128 
129  currentState = State::release;
130  }
131  else
132  {
133  reset();
134  }
135  }
136  }
137 
138  //==============================================================================
139  /** Returns the next sample value for an ADSR object.
140 
141  @see applyEnvelopeToBuffer
142  */
144  {
145  if (currentState == State::idle)
146  return 0.0f;
147 
148  if (currentState == State::attack)
149  {
150  envelopeVal += attackRate;
151 
152  if (envelopeVal >= 1.0f)
153  {
154  envelopeVal = 1.0f;
155 
156  if (decayRate > 0.0f)
157  currentState = State::decay;
158  else
159  currentState = State::sustain;
160  }
161  }
162  else if (currentState == State::decay)
163  {
164  envelopeVal -= decayRate;
165 
166  if (envelopeVal <= sustainLevel)
167  {
168  envelopeVal = sustainLevel;
169  currentState = State::sustain;
170  }
171  }
172  else if (currentState == State::sustain)
173  {
174  envelopeVal = sustainLevel;
175  }
176  else if (currentState == State::release)
177  {
178  envelopeVal -= releaseRate;
179 
180  if (envelopeVal <= 0.0f)
181  reset();
182  }
183 
184  return envelopeVal;
185  }
186 
187  /** This method will conveniently apply the next numSamples number of envelope values
188  to an AudioBuffer.
189 
190  @see getNextSample
191  */
192  template<typename FloatType>
193  void applyEnvelopeToBuffer (AudioBuffer<FloatType>& buffer, int startSample, int numSamples)
194  {
195  jassert (startSample + numSamples <= buffer.getNumSamples());
196 
197  auto numChannels = buffer.getNumChannels();
198 
199  while (--numSamples >= 0)
200  {
201  auto env = getNextSample();
202 
203  for (int i = 0; i < numChannels; ++i)
204  buffer.getWritePointer (i)[startSample] *= env;
205 
206  ++startSample;
207  }
208  }
209 
210 private:
211  //==============================================================================
212  void calculateRates (const Parameters& parameters)
213  {
214  // need to call setSampleRate() first!
215  jassert (sr > 0.0);
216 
217  attackRate = (parameters.attack > 0.0f ? static_cast<float> (1.0f / (parameters.attack * sr)) : -1.0f);
218  decayRate = (parameters.decay > 0.0f ? static_cast<float> ((1.0f - sustainLevel) / (parameters.decay * sr)) : -1.0f);
219  releaseRate = (parameters.release > 0.0f ? static_cast<float> (sustainLevel / (parameters.release * sr)) : -1.0f);
220  }
221 
222  void checkCurrentState()
223  {
224  if (currentState == State::attack && attackRate <= 0.0f) currentState = decayRate > 0.0f ? State::decay : State::sustain;
225  else if (currentState == State::decay && decayRate <= 0.0f) currentState = State::sustain;
226  else if (currentState == State::release && releaseRate <= 0.0f) reset();
227  }
228 
229  //==============================================================================
230  enum class State { idle, attack, decay, sustain, release };
231 
232  State currentState = State::idle;
233  Parameters currentParameters;
234 
235  double sr = 0.0;
236 
237  float envelopeVal = 0.0f;
238 
239  float sustainLevel = 0.0f;
240  float attackRate = 0.0f, decayRate = 0.0f, releaseRate = 0.0f;
241 };
242 
243 } // namespace juce
244 
245 /** @}*/
void setSampleRate(double sampleRate)
Sets the sample rate that will be used for the envelope.
Definition: juce_ADSR.h:97
void noteOn()
Starts the attack phase of the envelope.
Definition: juce_ADSR.h:112
void reset()
Resets the envelope to an idle state.
Definition: juce_ADSR.h:105
float sustain
Sustain level.
Definition: juce_ADSR.h:59
bool isActive() const noexcept
Returns true if the envelope is in its attack, decay, sustain or release stage.
Definition: juce_ADSR.h:90
float attack
Attack time in seconds.
Definition: juce_ADSR.h:53
Holds the parameters being used by an ADSR object.
Definition: juce_ADSR.h:50
float release
Release time in seconds.
Definition: juce_ADSR.h:62
A very simple ADSR envelope class.
Definition: juce_ADSR.h:38
A multi-channel buffer containing floating point audio samples.
float decay
Decay time in seconds.
Definition: juce_ADSR.h:56
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:143
void noteOff()
Starts the release phase of the envelope.
Definition: juce_ADSR.h:120
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:193
void setParameters(const Parameters &newParameters)
Sets the parameters that will be used by an ADSR object.
Definition: juce_ADSR.h:72
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:87