Merge pull request #321 from paulfd/readable-active-voices

Readable active voices
This commit is contained in:
Paul Ferrand 2020-07-26 21:00:22 +02:00 committed by GitHub
commit 8b9affad0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 101 additions and 72 deletions

View file

@ -60,14 +60,14 @@
#define SFIZZ_URI "http://sfztools.github.io/sfizz"
#define SFIZZ_PREFIX SFIZZ_URI "#"
#define SFIZZ__sfzFile "http://sfztools.github.io/sfizz:sfzfile"
#define SFIZZ__tuningfile "http://sfztools.github.io/sfizz:tuningfile"
#define SFIZZ__numVoices "http://sfztools.github.io/sfizz:numvoices"
#define SFIZZ__preloadSize "http://sfztools.github.io/sfizz:preload_size"
#define SFIZZ__oversampling "http://sfztools.github.io/sfizz:oversampling"
#define SFIZZ__sfzFile SFIZZ_URI ":" "sfzfile"
#define SFIZZ__tuningfile SFIZZ_URI ":" "tuningfile"
#define SFIZZ__numVoices SFIZZ_URI ":" "numvoices"
#define SFIZZ__preloadSize SFIZZ_URI ":" "preload_size"
#define SFIZZ__oversampling SFIZZ_URI ":" "oversampling"
// These ones are just for the worker
#define SFIZZ__logStatus "http://sfztools.github.io/sfizz:log_status"
#define SFIZZ__checkModification "http://sfztools.github.io/sfizz:check_modification"
#define SFIZZ__logStatus SFIZZ_URI ":" "log_status"
#define SFIZZ__checkModification SFIZZ_URI ":" "check_modification"
#define CHANNEL_MASK 0x0F
#define MIDI_CHANNEL(byte) (byte & CHANNEL_MASK)
@ -114,6 +114,7 @@ typedef struct
const float *scala_root_key_port;
const float *tuning_frequency_port;
const float *stretch_tuning_port;
float *active_voices_port;
// Atom forge
LV2_Atom_Forge forge; ///< Forge for writing atoms in run thread
@ -147,6 +148,7 @@ typedef struct
LV2_URID sfizz_oversampling_uri;
LV2_URID sfizz_log_status_uri;
LV2_URID sfizz_check_modification_uri;
LV2_URID sfizz_active_voices_uri;
LV2_URID time_position_uri;
// Sfizz related data
@ -182,6 +184,7 @@ enum
SFIZZ_SCALA_ROOT_KEY = 9,
SFIZZ_TUNING_FREQUENCY = 10,
SFIZZ_STRETCH_TUNING = 11,
SFIZZ_ACTIVE_VOICES = 12,
};
static void
@ -224,6 +227,7 @@ sfizz_lv2_map_required_uris(sfizz_plugin_t *self)
self->sfizz_preload_size_uri = map->map(map->handle, SFIZZ__preloadSize);
self->sfizz_oversampling_uri = map->map(map->handle, SFIZZ__oversampling);
self->sfizz_log_status_uri = map->map(map->handle, SFIZZ__logStatus);
self->sfizz_log_status_uri = map->map(map->handle, SFIZZ__logStatus);
self->sfizz_check_modification_uri = map->map(map->handle, SFIZZ__checkModification);
self->time_position_uri = map->map(map->handle, LV2_TIME__Position);
}
@ -272,6 +276,9 @@ connect_port(LV2_Handle instance,
case SFIZZ_STRETCH_TUNING:
self->stretch_tuning_port = (const float *)data;
break;
case SFIZZ_ACTIVE_VOICES:
self->active_voices_port = (float *)data;
break;
default:
break;
}
@ -509,7 +516,6 @@ sfizz_lv2_send_file_path(sfizz_plugin_t *self, LV2_URID urid, const char *path)
lv2_atom_forge_pop(&self->forge, &frame);
}
static void
sfizz_lv2_handle_atom_object(sfizz_plugin_t *self, const LV2_Atom_Object *obj)
{
@ -802,6 +808,7 @@ run(LV2_Handle instance, uint32_t sample_count)
sfizz_lv2_check_preload_size(self);
sfizz_lv2_check_oversampling(self);
sfizz_lv2_check_num_voices(self);
*(self->active_voices_port) = sfizz_get_num_active_voices(self->synth);
// Log the buffer usage
self->sample_counter += (int)sample_count;

View file

@ -35,6 +35,12 @@ midnam:update a lv2:Feature .
"Accordage"@fr ,
"Accordatura"@it .
<@LV2PLUGIN_URI@#status>
a pg:Group ;
lv2:symbol "status" ;
lv2:name "status",
"Status"@fr .
<@LV2PLUGIN_URI@:sfzfile>
a lv2:Parameter ;
rdfs:label "SFZ file",
@ -77,8 +83,8 @@ midnam:update a lv2:Feature .
opts:supportedOption param:sampleRate ;
opts:supportedOption bufsize:maxBlockLength, bufsize:nominalBlockLength ;
patch:writable <@LV2PLUGIN_URI@:sfzfile> ;
patch:writable <@LV2PLUGIN_URI@:tuningfile> ;
patch:writable <@LV2PLUGIN_URI@:sfzfile> ,
<@LV2PLUGIN_URI@:tuningfile> ;
lv2:port [
a lv2:InputPort, atom:AtomPort ;
@ -291,4 +297,15 @@ midnam:update a lv2:Feature .
lv2:minimum 0.0 ;
lv2:maximum 1.0 ;
units:unit units:coef
] , [
a lv2:OutputPort, lv2:ControlPort ;
lv2:index 12 ;
lv2:symbol "active_voices" ;
lv2:name "Active voices",
"Voix utilisées"@fr ;
pg:group <@LV2PLUGIN_URI@#status> ;
lv2:portProperty lv2:integer ;
lv2:default 0 ;
lv2:minimum 0 ;
lv2:maximum 256 ;
] .

View file

@ -625,14 +625,18 @@ sfz::Voice* sfz::Synth::findFreeVoice() noexcept
return {};
}
int sfz::Synth::getNumActiveVoices() const noexcept
int sfz::Synth::getNumActiveVoices(bool recompute) const noexcept
{
auto activeVoices = 0;
for (const auto& voice : voices) {
if (!recompute)
return activeVoices;
int active { 0 };
for (auto& voice: voices) {
if (!voice->isFree())
activeVoices++;
active++;
}
return activeVoices;
return active;
}
void sfz::Synth::garbageCollect() noexcept
@ -711,7 +715,7 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
return;
}
int numActiveVoices { 0 };
activeVoices = 0;
{ // Main render block
ScopedTiming logger { callbackBreakdown.renderMethod, ScopedTiming::Operation::addToDuration };
tempSpan->fill(0.0f);
@ -730,7 +734,7 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
if (voice->isFree())
continue;
numActiveVoices++;
activeVoices++;
renderVoiceToOutputs(*voice, *tempSpan);
callbackBreakdown.data += voice->getLastDataDuration();
callbackBreakdown.amplitude += voice->getLastAmplitudeDuration();
@ -770,7 +774,7 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
}
callbackBreakdown.dispatch = dispatchDuration;
resources.logger.logCallbackTime(callbackBreakdown, numActiveVoices, numFrames);
resources.logger.logCallbackTime(callbackBreakdown, activeVoices, numFrames);
// Reset the dispatch counter
dispatchDuration = Duration(0);

View file

@ -396,7 +396,7 @@ public:
*
* @return int
*/
int getNumActiveVoices() const noexcept;
int getNumActiveVoices(bool recompute = false) const noexcept;
/**
* @brief Get the total number of voices in the synth (the polyphony)
*
@ -731,6 +731,7 @@ private:
float sampleRate { config::defaultSampleRate };
float volume { Default::globalVolume };
int numVoices { config::numVoices };
int activeVoices { 0 };
Oversampling oversamplingFactor { config::defaultOversamplingFactor };
// Distribution used to generate random value for the *rand opcodes

View file

@ -474,7 +474,7 @@ TEST_CASE("[Files] Off by with different delays")
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_by.sfz");
REQUIRE( synth.getNumRegions() == 4 );
synth.noteOn(0, 63, 63);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
auto group1Voice = synth.getVoiceView(0);
REQUIRE( group1Voice->getRegion()->group == 1ul );
REQUIRE( group1Voice->getRegion()->offBy == 2ul );
@ -490,7 +490,7 @@ TEST_CASE("[Files] Off by with the same delays")
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_by.sfz");
REQUIRE( synth.getNumRegions() == 4 );
synth.noteOn(0, 63, 63);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
auto group1Voice = synth.getVoiceView(0);
REQUIRE( group1Voice->getRegion()->group == 1ul );
REQUIRE( group1Voice->getRegion()->offBy == 2ul );
@ -505,14 +505,14 @@ TEST_CASE("[Files] Off by with the same notes at the same time")
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_by.sfz");
REQUIRE( synth.getNumRegions() == 4 );
synth.noteOn(0, 65, 63);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
synth.noteOn(0, 65, 63);
REQUIRE( synth.getNumActiveVoices() == 4 );
REQUIRE( synth.getNumActiveVoices(true) == 4 );
AudioBuffer<float> buffer { 2, 256 };
synth.renderBlock(buffer);
synth.noteOn(0, 65, 63);
synth.renderBlock(buffer);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
}
TEST_CASE("[Files] Off modes")
@ -522,7 +522,7 @@ TEST_CASE("[Files] Off modes")
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_mode.sfz");
REQUIRE( synth.getNumRegions() == 3 );
synth.noteOn(0, 64, 63);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
const auto* fastVoice =
synth.getVoiceView(0)->getRegion()->offMode == SfzOffMode::fast ?
synth.getVoiceView(0) :
@ -532,10 +532,10 @@ TEST_CASE("[Files] Off modes")
synth.getVoiceView(1) :
synth.getVoiceView(0) ;
synth.noteOn(100, 63, 63);
REQUIRE( synth.getNumActiveVoices() == 3 );
REQUIRE( synth.getNumActiveVoices(true) == 3 );
AudioBuffer<float> buffer { 2, 256 };
synth.renderBlock(buffer);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
REQUIRE( fastVoice->isFree() );
REQUIRE( !normalVoice->isFree() );
}

View file

@ -78,7 +78,7 @@ TEST_CASE("[Polyphony] group polyphony limits")
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note
REQUIRE(synth.getNumActiveVoices(true) == 2); // group polyphony should block the last note
}
TEST_CASE("[Polyphony] Hierarchy polyphony limits")
@ -91,7 +91,7 @@ TEST_CASE("[Polyphony] Hierarchy polyphony limits")
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
}
TEST_CASE("[Polyphony] Hierarchy polyphony limits (group)")
@ -104,7 +104,7 @@ TEST_CASE("[Polyphony] Hierarchy polyphony limits (group)")
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
}
TEST_CASE("[Polyphony] Hierarchy polyphony limits (master)")
@ -118,7 +118,7 @@ TEST_CASE("[Polyphony] Hierarchy polyphony limits (master)")
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
}
TEST_CASE("[Polyphony] Hierarchy polyphony limits (limit in another master)")
@ -137,7 +137,7 @@ TEST_CASE("[Polyphony] Hierarchy polyphony limits (limit in another master)")
synth.noteOn(0, 66, 64);
synth.noteOn(0, 66, 64);
synth.noteOn(0, 66, 64);
REQUIRE(synth.getNumActiveVoices() == 5);
REQUIRE(synth.getNumActiveVoices(true) == 5);
}
TEST_CASE("[Polyphony] Hierarchy polyphony limits (global)")
@ -151,7 +151,7 @@ TEST_CASE("[Polyphony] Hierarchy polyphony limits (global)")
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
}
TEST_CASE("[Polyphony] Polyphony in master")
@ -171,21 +171,21 @@ TEST_CASE("[Polyphony] Polyphony in master")
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
synth.noteOn(0, 65, 64);
REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note
REQUIRE(synth.getNumActiveVoices(true) == 2); // group polyphony should block the last note
synth.allSoundOff();
synth.renderBlock(buffer);
REQUIRE(synth.getNumActiveVoices() == 0);
REQUIRE(synth.getNumActiveVoices(true) == 0);
synth.noteOn(0, 63, 64);
synth.noteOn(0, 63, 64);
synth.noteOn(0, 63, 64);
REQUIRE(synth.getNumActiveVoices() == 2); // group polyphony should block the last note
REQUIRE(synth.getNumActiveVoices(true) == 2); // group polyphony should block the last note
synth.allSoundOff();
synth.renderBlock(buffer);
REQUIRE(synth.getNumActiveVoices() == 0);
REQUIRE(synth.getNumActiveVoices(true) == 0);
synth.noteOn(0, 61, 64);
synth.noteOn(0, 61, 64);
synth.noteOn(0, 61, 64);
REQUIRE(synth.getNumActiveVoices() == 3);
REQUIRE(synth.getNumActiveVoices(true) == 3);
}
@ -198,7 +198,7 @@ TEST_CASE("[Polyphony] Self-masking")
synth.noteOn(0, 64, 63);
synth.noteOn(0, 64, 62);
synth.noteOn(0, 64, 64);
REQUIRE(synth.getNumActiveVoices() == 3); // One of these is releasing
REQUIRE(synth.getNumActiveVoices(true) == 3); // One of these is releasing
REQUIRE(synth.getVoiceView(0)->getTriggerValue() == 63_norm);
REQUIRE(!synth.getVoiceView(0)->releasedOrFree());
REQUIRE(synth.getVoiceView(1)->getTriggerValue() == 62_norm);
@ -216,7 +216,7 @@ TEST_CASE("[Polyphony] Not self-masking")
synth.noteOn(0, 66, 63);
synth.noteOn(0, 66, 62);
synth.noteOn(0, 66, 64);
REQUIRE(synth.getNumActiveVoices() == 3); // One of these is releasing
REQUIRE(synth.getNumActiveVoices(true) == 3); // One of these is releasing
REQUIRE(synth.getVoiceView(0)->getTriggerValue() == 63_norm);
REQUIRE(synth.getVoiceView(0)->releasedOrFree()); // The first encountered voice is the masking candidate
REQUIRE(synth.getVoiceView(1)->getTriggerValue() == 62_norm);

View file

@ -23,11 +23,11 @@ TEST_CASE("[Synth] Play and check active voices")
synth.noteOn(0, 36, 24);
synth.noteOn(0, 36, 89);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
// Render for a while
for (int i = 0; i < 200; ++i)
synth.renderBlock(buffer);
REQUIRE(synth.getNumActiveVoices() == 0);
REQUIRE(synth.getNumActiveVoices(true) == 0);
}
TEST_CASE("[Synth] All sound off")
@ -36,9 +36,9 @@ TEST_CASE("[Synth] All sound off")
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz");
synth.noteOn(0, 36, 24);
synth.noteOn(0, 36, 89);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
synth.allSoundOff();
REQUIRE(synth.getNumActiveVoices() == 0);
REQUIRE(synth.getNumActiveVoices(true) == 0);
}
TEST_CASE("[Synth] Change the number of voice while playing")
@ -51,9 +51,9 @@ TEST_CASE("[Synth] Change the number of voice while playing")
synth.noteOn(0, 36, 24);
synth.noteOn(0, 36, 89);
synth.renderBlock(buffer);
REQUIRE(synth.getNumActiveVoices() == 2);
REQUIRE(synth.getNumActiveVoices(true) == 2);
synth.setNumVoices(8);
REQUIRE(synth.getNumActiveVoices() == 0);
REQUIRE(synth.getNumActiveVoices(true) == 0);
REQUIRE(synth.getNumVoices() == 8);
}
@ -131,15 +131,15 @@ TEST_CASE("[Synth] All notes offs/all sounds off")
)");
synth.noteOn(0, 60, 63);
synth.noteOn(0, 62, 63);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
synth.cc(0, 120, 63);
REQUIRE( synth.getNumActiveVoices() == 0 );
REQUIRE( synth.getNumActiveVoices(true) == 0 );
synth.noteOn(0, 62, 63);
synth.noteOn(0, 60, 63);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
synth.cc(0, 123, 63);
REQUIRE( synth.getNumActiveVoices() == 0 );
REQUIRE( synth.getNumActiveVoices(true) == 0 );
}
TEST_CASE("[Synth] Reset all controllers")
@ -491,14 +491,14 @@ TEST_CASE("[Synth] sample quality")
// default sample quality
synth.noteOn(0, 60, 100);
REQUIRE(synth.getNumActiveVoices() == 1);
REQUIRE(synth.getNumActiveVoices(true) == 1);
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == sfz::Default::sampleQuality);
synth.allSoundOff();
// default sample quality, freewheeling
synth.enableFreeWheeling();
synth.noteOn(0, 60, 100);
REQUIRE(synth.getNumActiveVoices() == 1);
REQUIRE(synth.getNumActiveVoices(true) == 1);
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == sfz::Default::sampleQualityInFreewheelingMode);
synth.allSoundOff();
synth.disableFreeWheeling();
@ -506,7 +506,7 @@ TEST_CASE("[Synth] sample quality")
// user-defined sample quality
synth.setSampleQuality(sfz::Synth::ProcessLive, 3);
synth.noteOn(0, 60, 100);
REQUIRE(synth.getNumActiveVoices() == 1);
REQUIRE(synth.getNumActiveVoices(true) == 1);
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == 3);
synth.allSoundOff();
@ -514,21 +514,21 @@ TEST_CASE("[Synth] sample quality")
synth.enableFreeWheeling();
synth.setSampleQuality(sfz::Synth::ProcessFreewheeling, 8);
synth.noteOn(0, 60, 100);
REQUIRE(synth.getNumActiveVoices() == 1);
REQUIRE(synth.getNumActiveVoices(true) == 1);
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == 8);
synth.allSoundOff();
synth.disableFreeWheeling();
// region sample quality
synth.noteOn(0, 61, 100);
REQUIRE(synth.getNumActiveVoices() == 1);
REQUIRE(synth.getNumActiveVoices(true) == 1);
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == 5);
synth.allSoundOff();
// region sample quality, freewheeling
synth.enableFreeWheeling();
synth.noteOn(0, 61, 100);
REQUIRE(synth.getNumActiveVoices() == 1);
REQUIRE(synth.getNumActiveVoices(true) == 1);
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == 5);
synth.allSoundOff();
synth.disableFreeWheeling();
@ -551,7 +551,7 @@ TEST_CASE("[Synth] Sister voices")
REQUIRE( synth.getVoiceView(0)->getNextSisterVoice() == synth.getVoiceView(0) );
REQUIRE( synth.getVoiceView(0)->getPreviousSisterVoice() == synth.getVoiceView(0) );
synth.noteOn(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 3 );
REQUIRE( synth.getNumActiveVoices(true) == 3 );
REQUIRE( sfz::SisterVoiceRing::countSisterVoices(synth.getVoiceView(1)) == 2 );
REQUIRE( synth.getVoiceView(1)->getNextSisterVoice() == synth.getVoiceView(2) );
REQUIRE( synth.getVoiceView(1)->getPreviousSisterVoice() == synth.getVoiceView(2) );
@ -559,7 +559,7 @@ TEST_CASE("[Synth] Sister voices")
REQUIRE( synth.getVoiceView(2)->getNextSisterVoice() == synth.getVoiceView(1) );
REQUIRE( synth.getVoiceView(2)->getPreviousSisterVoice() == synth.getVoiceView(1) );
synth.noteOn(0, 63, 85);
REQUIRE( synth.getNumActiveVoices() == 6 );
REQUIRE( synth.getNumActiveVoices(true) == 6 );
REQUIRE( sfz::SisterVoiceRing::countSisterVoices(synth.getVoiceView(3)) == 3 );
REQUIRE( synth.getVoiceView(3)->getNextSisterVoice() == synth.getVoiceView(4) );
REQUIRE( synth.getVoiceView(3)->getPreviousSisterVoice() == synth.getVoiceView(5) );
@ -599,14 +599,14 @@ TEST_CASE("[Synth] Sisters and off-by")
<group> group=2 <region> key=63 sample=*saw
)");
synth.noteOn(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
REQUIRE( sfz::SisterVoiceRing::countSisterVoices(synth.getVoiceView(0)) == 2 );
synth.renderBlock(buffer);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
synth.noteOn(0, 63, 85);
REQUIRE( synth.getNumActiveVoices() == 3 );
REQUIRE( synth.getNumActiveVoices(true) == 3 );
synth.renderBlock(buffer);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
REQUIRE( sfz::SisterVoiceRing::countSisterVoices(synth.getVoiceView(0)) == 1 );
}
@ -619,7 +619,7 @@ TEST_CASE("[Synth] Release key")
synth.noteOn(0, 62, 85);
synth.cc(0, 64, 127);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
}
TEST_CASE("[Synth] Release")
@ -631,9 +631,9 @@ TEST_CASE("[Synth] Release")
synth.noteOn(0, 62, 85);
synth.cc(0, 64, 127);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 0 );
REQUIRE( synth.getNumActiveVoices(true) == 0 );
synth.cc(0, 64, 0);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
}
TEST_CASE("[Synth] Release key (Different sustain CC)")
@ -646,7 +646,7 @@ TEST_CASE("[Synth] Release key (Different sustain CC)")
synth.noteOn(0, 62, 85);
synth.cc(0, 54, 127);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
}
TEST_CASE("[Synth] Release (Different sustain CC)")
@ -659,9 +659,9 @@ TEST_CASE("[Synth] Release (Different sustain CC)")
synth.noteOn(0, 62, 85);
synth.cc(0, 54, 127);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 0 );
REQUIRE( synth.getNumActiveVoices(true) == 0 );
synth.cc(0, 54, 0);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
}
TEST_CASE("[Synth] Sustain threshold default")
@ -673,7 +673,7 @@ TEST_CASE("[Synth] Sustain threshold default")
synth.noteOn(0, 62, 85);
synth.cc(0, 64, 1);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 0 );
REQUIRE( synth.getNumActiveVoices(true) == 0 );
}
TEST_CASE("[Synth] Sustain threshold")
@ -686,12 +686,12 @@ TEST_CASE("[Synth] Sustain threshold")
synth.noteOn(0, 62, 85);
synth.cc(0, 64, 1);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 1 );
REQUIRE( synth.getNumActiveVoices(true) == 1 );
synth.noteOn(0, 62, 85);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
synth.noteOn(0, 62, 85);
synth.cc(0, 64, 64);
synth.noteOff(0, 62, 85);
REQUIRE( synth.getNumActiveVoices() == 2 );
REQUIRE( synth.getNumActiveVoices(true) == 2 );
}