@@ -48,8 +48,8 @@ SamplerSound::SamplerSound (const String& soundName, | |||||
source.read (data.get(), 0, length + 4, 0, true, true); | source.read (data.get(), 0, length + 4, 0, true, true); | ||||
attackSamples = roundToInt (attackTimeSecs * sourceSampleRate); | |||||
releaseSamples = roundToInt (releaseTimeSecs * sourceSampleRate); | |||||
params.attack = static_cast<float> (attackTimeSecs); | |||||
params.release = static_cast<float> (releaseTimeSecs); | |||||
} | } | ||||
} | } | ||||
@@ -87,24 +87,10 @@ void SamplerVoice::startNote (int midiNoteNumber, float velocity, SynthesiserSou | |||||
lgain = velocity; | lgain = velocity; | ||||
rgain = velocity; | rgain = velocity; | ||||
isInAttack = (sound->attackSamples > 0); | |||||
isInRelease = false; | |||||
adsr.setSampleRate (sound->sourceSampleRate); | |||||
adsr.setParameters (sound->params); | |||||
if (isInAttack) | |||||
{ | |||||
attackReleaseLevel = 0.0f; | |||||
attackDelta = (float) (pitchRatio / sound->attackSamples); | |||||
} | |||||
else | |||||
{ | |||||
attackReleaseLevel = 1.0f; | |||||
attackDelta = 0.0f; | |||||
} | |||||
if (sound->releaseSamples > 0) | |||||
releaseDelta = (float) (-pitchRatio / sound->releaseSamples); | |||||
else | |||||
releaseDelta = -1.0f; | |||||
adsr.noteOn(); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -116,12 +102,12 @@ void SamplerVoice::stopNote (float /*velocity*/, bool allowTailOff) | |||||
{ | { | ||||
if (allowTailOff) | if (allowTailOff) | ||||
{ | { | ||||
isInAttack = false; | |||||
isInRelease = true; | |||||
adsr.noteOff(); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
clearCurrentNote(); | clearCurrentNote(); | ||||
adsr.reset(); | |||||
} | } | ||||
} | } | ||||
@@ -151,35 +137,10 @@ void SamplerVoice::renderNextBlock (AudioBuffer<float>& outputBuffer, int startS | |||||
float r = (inR != nullptr) ? (inR[pos] * invAlpha + inR[pos + 1] * alpha) | float r = (inR != nullptr) ? (inR[pos] * invAlpha + inR[pos + 1] * alpha) | ||||
: l; | : l; | ||||
l *= lgain; | |||||
r *= rgain; | |||||
if (isInAttack) | |||||
{ | |||||
l *= attackReleaseLevel; | |||||
r *= attackReleaseLevel; | |||||
auto envelopeValue = adsr.getNextSample(); | |||||
attackReleaseLevel += attackDelta; | |||||
if (attackReleaseLevel >= 1.0f) | |||||
{ | |||||
attackReleaseLevel = 1.0f; | |||||
isInAttack = false; | |||||
} | |||||
} | |||||
else if (isInRelease) | |||||
{ | |||||
l *= attackReleaseLevel; | |||||
r *= attackReleaseLevel; | |||||
attackReleaseLevel += releaseDelta; | |||||
if (attackReleaseLevel <= 0.0f) | |||||
{ | |||||
stopNote (0.0f, false); | |||||
break; | |||||
} | |||||
} | |||||
l *= lgain * envelopeValue; | |||||
r *= rgain * envelopeValue; | |||||
if (outR != nullptr) | if (outR != nullptr) | ||||
{ | { | ||||
@@ -83,12 +83,14 @@ public: | |||||
*/ | */ | ||||
AudioBuffer<float>* getAudioData() const noexcept { return data.get(); } | AudioBuffer<float>* getAudioData() const noexcept { return data.get(); } | ||||
//============================================================================== | |||||
/** Changes the parameters of the ADSR envelope which will be applied to the sample. */ | |||||
void setEnvelopeParameters (ADSR::Parameters parametersToUse) { params = parametersToUse; } | |||||
//============================================================================== | //============================================================================== | ||||
bool appliesToNote (int midiNoteNumber) override; | bool appliesToNote (int midiNoteNumber) override; | ||||
bool appliesToChannel (int midiChannel) override; | bool appliesToChannel (int midiChannel) override; | ||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
friend class SamplerVoice; | friend class SamplerVoice; | ||||
@@ -97,8 +99,9 @@ private: | |||||
std::unique_ptr<AudioBuffer<float>> data; | std::unique_ptr<AudioBuffer<float>> data; | ||||
double sourceSampleRate; | double sourceSampleRate; | ||||
BigInteger midiNotes; | BigInteger midiNotes; | ||||
int length = 0, attackSamples = 0, releaseSamples = 0; | |||||
int midiRootNote = 0; | |||||
int length = 0, midiRootNote = 0; | |||||
ADSR::Parameters params; | |||||
JUCE_LEAK_DETECTOR (SamplerSound) | JUCE_LEAK_DETECTOR (SamplerSound) | ||||
}; | }; | ||||
@@ -136,13 +139,13 @@ public: | |||||
void renderNextBlock (AudioBuffer<float>&, int startSample, int numSamples) override; | void renderNextBlock (AudioBuffer<float>&, int startSample, int numSamples) override; | ||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
double pitchRatio = 0; | double pitchRatio = 0; | ||||
double sourceSamplePosition = 0; | double sourceSamplePosition = 0; | ||||
float lgain = 0, rgain = 0, attackReleaseLevel = 0, attackDelta = 0, releaseDelta = 0; | |||||
bool isInAttack = false, isInRelease = false; | |||||
float lgain = 0, rgain = 0; | |||||
ADSR adsr; | |||||
JUCE_LEAK_DETECTOR (SamplerVoice) | JUCE_LEAK_DETECTOR (SamplerVoice) | ||||
}; | }; | ||||