Add a way to change the release rate after the envelope started and separate this from the release() method in the Voice
This commit is contained in:
parent
d3cc4281d9
commit
5ef6141c4b
4 changed files with 64 additions and 25 deletions
|
|
@ -11,22 +11,30 @@
|
|||
|
||||
namespace sfz {
|
||||
|
||||
template<class Type>
|
||||
Type ADSREnvelope<Type>::secondsToSamples (Type timeInSeconds) const noexcept
|
||||
{
|
||||
return static_cast<int>(timeInSeconds * sampleRate);
|
||||
};
|
||||
|
||||
template<class Type>
|
||||
Type ADSREnvelope<Type>::secondsToLinRate (Type timeInSeconds) const noexcept
|
||||
{
|
||||
timeInSeconds = std::max<Type>(timeInSeconds, config::virtuallyZero);
|
||||
return 1 / (sampleRate * timeInSeconds);
|
||||
};
|
||||
|
||||
template<class Type>
|
||||
Type ADSREnvelope<Type>::secondsToExpRate (Type timeInSeconds) const noexcept
|
||||
{
|
||||
timeInSeconds = std::max<Type>(25e-3, timeInSeconds);
|
||||
return std::exp(-8.0 / (timeInSeconds * sampleRate));
|
||||
};
|
||||
|
||||
template <class Type>
|
||||
void ADSREnvelope<Type>::reset(const EGDescription& desc, const Region& region, const MidiState& state, int delay, float velocity, float sampleRate) noexcept
|
||||
{
|
||||
auto secondsToSamples = [sampleRate](Type timeInSeconds) {
|
||||
return static_cast<int>(timeInSeconds * sampleRate);
|
||||
};
|
||||
|
||||
auto secondsToLinRate = [sampleRate](Type timeInSeconds) {
|
||||
timeInSeconds = std::max<Type>(timeInSeconds, config::virtuallyZero);
|
||||
return 1 / (sampleRate * timeInSeconds);
|
||||
};
|
||||
|
||||
auto secondsToExpRate = [sampleRate](Type timeInSeconds) {
|
||||
timeInSeconds = std::max<Type>(25e-3, timeInSeconds);
|
||||
return std::exp(-8.0 / (timeInSeconds * sampleRate));
|
||||
};
|
||||
this->sampleRate = sampleRate;
|
||||
|
||||
this->delay = delay + secondsToSamples(desc.getDelay(state, velocity));
|
||||
this->attackStep = secondsToLinRate(desc.getAttack(state, velocity));
|
||||
|
|
@ -208,13 +216,16 @@ int ADSREnvelope<Type>::getRemainingDelay() const noexcept
|
|||
}
|
||||
|
||||
template <class Type>
|
||||
void ADSREnvelope<Type>::startRelease(int releaseDelay, bool fastRelease) noexcept
|
||||
void ADSREnvelope<Type>::startRelease(int releaseDelay) noexcept
|
||||
{
|
||||
shouldRelease = true;
|
||||
this->releaseDelay = releaseDelay;
|
||||
}
|
||||
|
||||
if (fastRelease)
|
||||
this->releaseRate = 0;
|
||||
template <class Type>
|
||||
void ADSREnvelope<Type>::setReleaseTime(Type timeInSeconds) noexcept
|
||||
{
|
||||
releaseRate = secondsToExpRate(timeInSeconds);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,15 +44,18 @@ public:
|
|||
* @param output
|
||||
*/
|
||||
void getBlock(absl::Span<Type> output) noexcept;
|
||||
/**
|
||||
* @brief Set the release time for the envelope
|
||||
*
|
||||
* @param timeInSeconds
|
||||
*/
|
||||
void setReleaseTime(Type timeInSeconds) noexcept;
|
||||
/**
|
||||
* @brief Start the envelope release after a delay.
|
||||
*
|
||||
* @param releaseDelay the delay before releasing in samples
|
||||
* @param fastRelease whether the release should be fast (i.e. 0 or so) or
|
||||
* follow the release duration that was set when
|
||||
* initializing the envelope
|
||||
*/
|
||||
void startRelease(int releaseDelay, bool fastRelease = false) noexcept;
|
||||
void startRelease(int releaseDelay) noexcept;
|
||||
/**
|
||||
* @brief Is the envelope smoothing?
|
||||
*
|
||||
|
|
@ -75,6 +78,11 @@ public:
|
|||
int getRemainingDelay() const noexcept;
|
||||
|
||||
private:
|
||||
float sampleRate { config::defaultSampleRate };
|
||||
Type secondsToSamples (Type timeInSeconds) const noexcept;
|
||||
Type secondsToLinRate (Type timeInSeconds) const noexcept;
|
||||
Type secondsToExpRate (Type timeInSeconds) const noexcept;
|
||||
|
||||
enum class State {
|
||||
Delay,
|
||||
Attack,
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ bool sfz::Voice::isFree() const noexcept
|
|||
return (state == State::idle);
|
||||
}
|
||||
|
||||
void sfz::Voice::release(int delay, bool fastRelease) noexcept
|
||||
void sfz::Voice::release(int delay) noexcept
|
||||
{
|
||||
if (state != State::playing)
|
||||
return;
|
||||
|
|
@ -163,10 +163,21 @@ void sfz::Voice::release(int delay, bool fastRelease) noexcept
|
|||
if (egEnvelope.getRemainingDelay() > delay) {
|
||||
switchState(State::cleanMeUp);
|
||||
} else {
|
||||
egEnvelope.startRelease(delay, fastRelease);
|
||||
egEnvelope.startRelease(delay);
|
||||
}
|
||||
}
|
||||
|
||||
void sfz::Voice::off(int delay) noexcept
|
||||
{
|
||||
if (region->offMode == SfzOffMode::fast) {
|
||||
egEnvelope.setReleaseTime( Default::offTime );
|
||||
} else if (region->offMode == SfzOffMode::time) {
|
||||
egEnvelope.setReleaseTime(region->offTime);
|
||||
}
|
||||
|
||||
release(delay);
|
||||
}
|
||||
|
||||
void sfz::Voice::registerNoteOff(int delay, int noteNumber, float velocity) noexcept
|
||||
{
|
||||
ASSERT(velocity >= 0.0 && velocity <= 1.0);
|
||||
|
|
@ -561,7 +572,8 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
<< " for sample " << region->sampleId);
|
||||
}
|
||||
#endif
|
||||
egEnvelope.startRelease(i, true);
|
||||
egEnvelope.setReleaseTime(0.0f);
|
||||
egEnvelope.startRelease(i);
|
||||
fill<int>(indices->subspan(i), sampleEnd);
|
||||
fill<float>(coeffs->subspan(i), 1.0f);
|
||||
break;
|
||||
|
|
@ -695,7 +707,7 @@ bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept
|
|||
return false;
|
||||
|
||||
if (triggerType == TriggerType::NoteOn && region->offBy == group) {
|
||||
release(delay, region->offMode == SfzOffMode::fast);
|
||||
off(delay);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -288,7 +288,15 @@ public:
|
|||
* @param delay
|
||||
* @param fastRelease whether to do a normal release or cut the voice abruptly
|
||||
*/
|
||||
void release(int delay, bool fastRelease = false) noexcept;
|
||||
void release(int delay) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Off the voice (steal). This will respect the off mode of the region
|
||||
* and set the envelopes if necessary.
|
||||
*
|
||||
* @param delay
|
||||
*/
|
||||
void off(int delay) noexcept;
|
||||
|
||||
/**
|
||||
* @brief gets the age of the Voice
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue