[go: up one dir, main page]

Menu

[r39]: / Source / TimeVariant.h  Maximize  Restore  History

Download this file

151 lines (123 with data), 4.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**************************************************************************
Copyright (C) 2019 Arnaud Champenois arthelion@free.fr
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
#include "LFOModulated.h"
#include "Utils.h"
#include "DADSR.h"
/*!
* A mother class for all time variant components driven by a LFO, an ADSR enveloppe,
* and which can be modulated by controllers : pitch bend, mod wheel & aftertouch
*
*/
class TimeVariant : public LFOModulated {
public:
TimeVariant(const TimeVariantParameters&adsrParam) :
mAttackRamp(1.0),
LFOModulated(adsrParam),
mPADSR(adsrParam){}
virtual ~TimeVariant();
virtual void init(double sampleRate) override;
virtual void noteOn(int note) override;
virtual void noteOff(double velocity) override;
virtual bool isActive() const;
/*!
* Computes an ADSR sample between [0,1.0] for frequency filter
* \return A new ADSR sample
*/
double nextFreqADSR(bool applyBypass = true) {
if (mIsADSRBypass) {
// We must keep an adsr to avoid plops.
return applyBypass ? mBypassADSR.getNextSample() : 1.0;
}
else {
double ramp = mAttackRamp.getNextValue();
if (mADSRDepthValue > 0)
return ((1.0 - mADSRDepthValue) + mADSRDepthValue * mADSR.getNextSample())*ramp;
else
return ((1.0 + mADSRDepthValue) - mADSRDepthValue * (1.0 - mADSR.getNextSample()))*ramp;
}
}
/*!
* Computes an ADSR sample between [0,1.0] for volume envelope
* \return A new ADSR sample
*/
double nextADSR(bool applyBypass = true) {
if (mIsADSRBypass) {
// We must keep an adsr to avoid plops.
return applyBypass ? mBypassADSR.getNextSample() : 1.0;
}
else {
double byPass = mBypassADSR.getNextSample();
double ramp = mAttackRamp.getNextValue();
if (mADSRDepthValue > 0)
return ((1.0 - mADSRDepthValue)*byPass + mADSRDepthValue * mADSR.getNextSample())*ramp;
else {
if (mADSR.isActive()) {
auto value = ((1.0 + mADSRDepthValue)*byPass - mADSRDepthValue * (1.0 - mADSR.getNextSample()))*ramp;
// Now swith on ramp to smooth the end towards 0 (avoid plop)
if (!mADSR.isActive()) {
mAttackRamp.setCurrentAndTargetValue(value);
mAttackRamp.reset(mSampleRate, ADSRMinAttackRelease);
mAttackRamp.setTargetValue(0.0);
}
return value;
}
else
return mAttackRamp.getNextValue();
}
}
}
/*!
* Computes an ADSR value centered on the sustain level (that is,
* sustain level is always 0, and attack start/release are negative.
* If release time is 0, the end remains at sustain level (i.e. 0).
* Used for pitch envelope
*
* \return an ADSR sample between -1 and 1
*/
double nextCenteredADSR() {
double adsrDelta;
if (!mIsADSRBypass) {
if (mADSR.isActive())
adsrDelta =mADSRDepthValue * (mADSR.getNextSample() - mADSR.getParameters().sustain);
else {
if (mADSR.getParameters().release > 0)
adsrDelta = (-mADSRDepthValue * mADSR.getParameters().sustain);
else
adsrDelta = 0.0f;
}
}
else
adsrDelta = 0.0;
return adsrDelta;
}
bool isADSRBypass() const {
return mIsADSRBypass;
}
virtual void updateInternalValues(int controller = 0) override;
protected:
double mSampleRate = 44100.0;
private:
// Parameters
const TimeVariantParameters& mPADSR;
// Current state (also stored in mADSR)
DADSR mADSR;
bool mIsADSRBypass = true;
double mADSRDepthValue = 1.0;
// Smoothing envelope when adsr is bypassed to avoid plops
DADSR mBypassADSR;
// Attack smoothing
juce::SmoothedValue<double> mAttackRamp;
};