LMMS
Loading...
Searching...
No Matches
SFZEG.cpp
Go to the documentation of this file.
1/*************************************************************************************
2 * Original code copyright (C) 2012 Steve Folta
3 * Converted to Juce module (C) 2016 Leo Olivers
4 * Forked from https://github.com/stevefolta/SFZero
5 * For license info please see the LICENSE file distributed with this source code
6 *************************************************************************************/
7#include "SFZEG.h"
8
9namespace sfzero
10{
11
12static const float fastReleaseTime = 0.01f;
13
18
19void EG::setExponentialDecay(bool newExponentialDecay) { exponentialDecay_ = newExponentialDecay; }
20
21void EG::startNote(const EGParameters *newParameters, float floatVelocity, double newSampleRate,
22 const EGParameters *velMod)
23{
24 parameters_ = *newParameters;
25 if (velMod)
26 {
27 parameters_.delay += floatVelocity * velMod->delay;
28 parameters_.attack += floatVelocity * velMod->attack;
29 parameters_.hold += floatVelocity * velMod->hold;
30 parameters_.decay += floatVelocity * velMod->decay;
31 parameters_.sustain += floatVelocity * velMod->sustain;
32 if (parameters_.sustain < 0.0)
33 {
34 parameters_.sustain = 0.0;
35 }
36 else if (parameters_.sustain > 100.0)
37 {
38 parameters_.sustain = 100.0;
39 }
40 parameters_.release += floatVelocity * velMod->release;
41 }
42 sampleRate_ = newSampleRate;
43
44 startDelay();
45}
46
48{
49 switch (segment_)
50 {
51 case Delay:
53 break;
54
55 case Attack:
56 startHold();
57 break;
58
59 case Hold:
60 startDecay();
61 break;
62
63 case Decay:
65 break;
66
67 case Sustain:
68 // Shouldn't be called.
69 break;
70
71 case Release:
72 default:
73 segment_ = Done;
74 break;
75 }
76}
77
79
87
89{
90 if (parameters_.delay <= 0)
91 {
93 }
94 else
95 {
97 level_ = 0.0;
98 slope_ = 0.0;
99 samplesUntilNextSegment_ = static_cast<int>(parameters_.delay * sampleRate_);
100 segmentIsExponential_ = false;
101 }
102}
103
105{
106 if (parameters_.attack <= 0)
107 {
108 startHold();
109 }
110 else
111 {
113 level_ = parameters_.start / 100.0f;
114 samplesUntilNextSegment_ = static_cast<int>(parameters_.attack * sampleRate_);
116 segmentIsExponential_ = false;
117 }
118}
119
121{
122 if (parameters_.hold <= 0)
123 {
124 level_ = 1.0;
125 startDecay();
126 }
127 else
128 {
129 segment_ = Hold;
130 samplesUntilNextSegment_ = static_cast<int>(parameters_.hold * sampleRate_);
131 level_ = 1.0;
132 slope_ = 0.0;
133 segmentIsExponential_ = false;
134 }
135}
136
138{
139 if (parameters_.decay <= 0)
140 {
141 startSustain();
142 }
143 else
144 {
145 segment_ = Decay;
146 samplesUntilNextSegment_ = static_cast<int>(parameters_.decay * sampleRate_);
147 level_ = 1.0;
149 {
150 // I don't truly understand this; just following what LinuxSampler does.
151 float mysterySlope = -9.226f / samplesUntilNextSegment_;
152 slope_ = exp(mysterySlope);
154 if (parameters_.sustain > 0.0)
155 {
156 // Again, this is following LinuxSampler's example, which is similar to
157 // SF2-style decay, where "decay" specifies the time it would take to
158 // get to zero, not to the sustain level. The SFZ spec is not that
159 // specific about what "decay" means, so perhaps it's really supposed
160 // to specify the time to reach the sustain level.
161 samplesUntilNextSegment_ = static_cast<int>(log((parameters_.sustain / 100.0) / level_) / mysterySlope);
163 {
164 startSustain();
165 }
166 }
167 }
168 else
169 {
170 slope_ = (parameters_.sustain / 100.0f - 1.0f) / samplesUntilNextSegment_;
171 segmentIsExponential_ = false;
172 }
173 }
174}
175
177{
178 if (parameters_.sustain <= 0)
179 {
180 startRelease();
181 }
182 else
183 {
185 level_ = parameters_.sustain / 100.0f;
186 slope_ = 0.0;
187 samplesUntilNextSegment_ = 0x7FFFFFFF;
188 segmentIsExponential_ = false;
189 }
190}
191
193{
194 float release = parameters_.release;
195
196 if (release <= 0)
197 {
198 // Enforce a short release, to prevent clicks.
199 release = fastReleaseTime;
200 }
201
203 samplesUntilNextSegment_ = static_cast<int>(release * sampleRate_);
205 {
206 // I don't truly understand this; just following what LinuxSampler does.
207 float mysterySlope = -9.226f / samplesUntilNextSegment_;
208 slope_ = exp(mysterySlope);
210 }
211 else
212 {
214 segmentIsExponential_ = false;
215 }
216}
217
218const float EG::BottomLevel = 0.001f;
219
220}
void startRelease()
Definition SFZEG.cpp:192
void noteOff()
Definition SFZEG.cpp:78
bool segmentIsExponential_
Definition SFZEG.h:65
void startNote(const EGParameters *parameters, float floatVelocity, double sampleRate, const EGParameters *velMod=nullptr)
Definition SFZEG.cpp:21
float slope_
Definition SFZEG.h:63
void startSustain()
Definition SFZEG.cpp:176
EG()
Definition SFZEG.cpp:14
void startDecay()
Definition SFZEG.cpp:137
Segment segment_
Definition SFZEG.h:58
void setExponentialDecay(bool newExponentialDecay)
Definition SFZEG.cpp:19
EGParameters parameters_
Definition SFZEG.h:59
void startHold()
Definition SFZEG.cpp:120
void startDelay()
Definition SFZEG.cpp:88
void startAttack()
Definition SFZEG.cpp:104
@ Sustain
Definition SFZEG.h:46
@ Attack
Definition SFZEG.h:43
@ Release
Definition SFZEG.h:47
@ Done
Definition SFZEG.h:48
@ Delay
Definition SFZEG.h:42
@ Decay
Definition SFZEG.h:45
@ Hold
Definition SFZEG.h:44
int samplesUntilNextSegment_
Definition SFZEG.h:64
bool exponentialDecay_
Definition SFZEG.h:61
double sampleRate_
Definition SFZEG.h:60
static const float BottomLevel
Definition SFZEG.h:66
void fastRelease()
Definition SFZEG.cpp:80
float level_
Definition SFZEG.h:62
void nextSegment()
Definition SFZEG.cpp:47
Definition SFZDebug.cpp:11
static const float fastReleaseTime
Definition SFZEG.cpp:12
#define false
Definition ordinals.h:83
Definition SFZRegion.h:22
float release
Definition SFZRegion.h:23
float hold
Definition SFZRegion.h:23
float delay
Definition SFZRegion.h:23
float sustain
Definition SFZRegion.h:23
float attack
Definition SFZRegion.h:23
float decay
Definition SFZRegion.h:23