Added proper support for off_modes

This commit is contained in:
Paul Ferrand 2019-12-21 21:24:49 +01:00
parent ed7d5369a7
commit 92aaa2a17e
6 changed files with 45 additions and 9 deletions

View file

@ -224,10 +224,13 @@ int ADSREnvelope<Type>::getRemainingDelay() const noexcept
} }
template <class Type> template <class Type>
void ADSREnvelope<Type>::startRelease(int releaseDelay) noexcept void ADSREnvelope<Type>::startRelease(int releaseDelay, bool fastRelease) noexcept
{ {
shouldRelease = true; shouldRelease = true;
this->releaseDelay = releaseDelay; this->releaseDelay = releaseDelay;
if (fastRelease)
this->release = 0;
} }
} }

View file

@ -66,8 +66,11 @@ public:
* @brief Start the envelope release after a delay. * @brief Start the envelope release after a delay.
* *
* @param releaseDelay the delay before releasing in samples * @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) noexcept; void startRelease(int releaseDelay, bool fastRelease = false) noexcept;
/** /**
* @brief Is the envelope smoothing? * @brief Is the envelope smoothing?
* *

View file

@ -130,7 +130,7 @@ bool sfz::Voice::isFree() const noexcept
return (state == State::idle); return (state == State::idle);
} }
void sfz::Voice::release(int delay) noexcept void sfz::Voice::release(int delay, bool fastRelease) noexcept
{ {
if (state != State::playing) if (state != State::playing)
return; return;
@ -139,7 +139,7 @@ void sfz::Voice::release(int delay) noexcept
reset(); reset();
} else { } else {
state = State::release; state = State::release;
egEnvelope.startRelease(delay); egEnvelope.startRelease(delay, fastRelease);
} }
} }
@ -499,8 +499,11 @@ void sfz::Voice::fillWithGenerator(AudioSpan<float> buffer) noexcept
bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept
{ {
if (region != nullptr && triggerType == TriggerType::NoteOn && region->offBy && *region->offBy == group) { if (region == nullptr)
release(delay); return false;
if (triggerType == TriggerType::NoteOn && region->offBy && *region->offBy == group) {
release(delay, region->offMode == SfzOffMode::fast);
return true; return true;
} }

View file

@ -264,8 +264,9 @@ private:
* @brief Release the voice after a given delay * @brief Release the voice after a given delay
* *
* @param delay * @param delay
* @param fastRelease whether to do a normal release or cut the voice abruptly
*/ */
void release(int delay) noexcept; void release(int delay, bool fastRelease = false) noexcept;
Region* region { nullptr }; Region* region { nullptr };
enum class State { enum class State {

View file

@ -355,7 +355,6 @@ TEST_CASE("[Files] Default path is ignored for generators")
REQUIRE(synth.getRegionView(0)->sample == R"(*sine)"); REQUIRE(synth.getRegionView(0)->sample == R"(*sine)");
} }
TEST_CASE("[Files] Set CC applies properly to all channels") TEST_CASE("[Files] Set CC applies properly to all channels")
{ {
sfz::Synth synth; sfz::Synth synth;
@ -366,7 +365,6 @@ TEST_CASE("[Files] Set CC applies properly to all channels")
} }
} }
TEST_CASE("[Files] Note and octave offsets") TEST_CASE("[Files] Note and octave offsets")
{ {
sfz::Synth synth; sfz::Synth synth;
@ -408,3 +406,28 @@ TEST_CASE("[Files] Note and octave offsets")
REQUIRE( synth.getRegionView(6)->pitchKeycenter == 50 ); REQUIRE( synth.getRegionView(6)->pitchKeycenter == 50 );
} }
TEST_CASE("[Files] Off modes")
{
sfz::Synth synth;
synth.setSamplesPerBlock(256);
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_mode.sfz");
REQUIRE( synth.getNumRegions() == 3 );
synth.noteOn(0, 0, 64, 63);
REQUIRE( synth.getNumActiveVoices() == 2 );
const auto* fastVoice =
synth.getVoiceView(0)->getRegion()->offMode == SfzOffMode::fast ?
synth.getVoiceView(0) :
synth.getVoiceView(1) ;
const auto* normalVoice =
synth.getVoiceView(0)->getRegion()->offMode == SfzOffMode::fast ?
synth.getVoiceView(1) :
synth.getVoiceView(0) ;
synth.noteOn(100, 0, 63, 63);
REQUIRE( synth.getNumActiveVoices() == 3 );
sfz::AudioBuffer<float> buffer { 2, 256 };
synth.renderBlock(buffer);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( fastVoice->isFree() );
REQUIRE( !normalVoice->isFree() );
}

View file

@ -0,0 +1,3 @@
<region> group=1 off_by=2 key=64 off_mode=fast ampeg_release=0.1 sample=mono_sample.wav
<region> group=1 off_by=2 key=64 off_mode=normal ampeg_release=0.1 sample=mono_sample.wav
<region> group=2 key=63 off_mode=normal ampeg_release=0.1 sample=mono_sample.wav