diff --git a/examples/MPETest/Source/MPESetupComponent.h b/examples/MPETest/Source/MPESetupComponent.h index 31d8548f44..04e2d02027 100644 --- a/examples/MPETest/Source/MPESetupComponent.h +++ b/examples/MPETest/Source/MPESetupComponent.h @@ -65,7 +65,6 @@ public: initialiseComboBoxWithConsecutiveIntegers (noteChannels, noteChannelsLabel, 1, 15, defaultNoteChannels); initialiseComboBoxWithConsecutiveIntegers (masterPitchbendRange, masterPitchbendRangeLabel, 0, 96, defaultMasterPitchbendRange); initialiseComboBoxWithConsecutiveIntegers (notePitchbendRange, notePitchbendRangeLabel, 0, 96, defaultNotePitchbendRange); - notePitchbendRange.addListener (this); initialiseButton (addZoneButton); @@ -73,7 +72,8 @@ public: initialiseButton (omniModeEnabledToggle); initialiseButton (voiceStealingEnabledToggle); - initialiseComboBoxWithConsecutiveIntegers (numberOfVoices, numberOfVoicesLabel, 0, 21, 15); + initialiseComboBoxWithConsecutiveIntegers (numberOfVoices, numberOfVoicesLabel, 1, 20, 15); + numberOfVoices.addListener (this); } //========================================================================== diff --git a/modules/juce_audio_basics/mpe/juce_MPESynthesiser.cpp b/modules/juce_audio_basics/mpe/juce_MPESynthesiser.cpp index a8680bdb6c..58c85c3b6a 100644 --- a/modules/juce_audio_basics/mpe/juce_MPESynthesiser.cpp +++ b/modules/juce_audio_basics/mpe/juce_MPESynthesiser.cpp @@ -189,6 +189,10 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF // - Re-use the oldest notes first // - Protect the lowest & topmost notes, even if sustained, but not if they've been released. + + // apparently you are trying to render audio without having any voices... + jassert (voices.size() > 0); + // These are the voices we want to protect (ie: only steal if unavoidable) MPESynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase MPESynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase @@ -279,6 +283,7 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF void MPESynthesiser::addVoice (MPESynthesiserVoice* const newVoice) { const ScopedLock sl (voicesLock); + newVoice->setCurrentSampleRate (getSampleRate()); voices.add (newVoice); } @@ -309,7 +314,7 @@ void MPESynthesiser::reduceNumVoices (const int newNumVoices) while (voices.size() > newNumVoices) { - if (MPESynthesiserVoice* voice = findVoiceToSteal()) + if (MPESynthesiserVoice* voice = findFreeVoice (MPENote(), true)) voices.removeObject (voice); else voices.remove (0); // if there's no voice to steal, kill the oldest voice diff --git a/modules/juce_audio_basics/mpe/juce_MPESynthesiser.h b/modules/juce_audio_basics/mpe/juce_MPESynthesiser.h index 6069e28017..cbca499e8b 100644 --- a/modules/juce_audio_basics/mpe/juce_MPESynthesiser.h +++ b/modules/juce_audio_basics/mpe/juce_MPESynthesiser.h @@ -259,10 +259,12 @@ protected: /** Searches through the voices to find one that's not currently playing, and which can play the given MPE note. - Returns nullptr if all voices are busy and stealing isn't enabled. + If all voices are active and stealIfNoneAvailable is false, this returns + a nullptr. If all voices are active and stealIfNoneAvailable is true, + this will call findVoiceToSteal() to find a voice. - To implement a custom note-stealing algorithm, you can either override this - method, or (preferably) override findVoiceToSteal(). + If you need to find a free voice for something else than playing a note + (e.g. for deleting it), you can pass an invalid (default-constructed) MPENote. */ virtual MPESynthesiserVoice* findFreeVoice (MPENote noteToFindVoiceFor, bool stealIfNoneAvailable) const; @@ -276,7 +278,8 @@ protected: If you pass a valid MPENote for the optional argument, then the note number of that note will be taken into account for finding the ideal voice to steal. - Otherwise, this part of the algorithm will be ignored. + If you pass an invalid (default-constructed) MPENote instead, this part of + the algorithm will be ignored. */ virtual MPESynthesiserVoice* findVoiceToSteal (MPENote noteToStealVoiceFor = MPENote()) const; diff --git a/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp b/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp index 2aa10fb7ce..3433428bc9 100644 --- a/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp +++ b/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp @@ -114,6 +114,7 @@ void Synthesiser::clearVoices() SynthesiserVoice* Synthesiser::addVoice (SynthesiserVoice* const newVoice) { const ScopedLock sl (lock); + newVoice->setCurrentPlaybackSampleRate (sampleRate); return voices.add (newVoice); } @@ -557,6 +558,9 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay, // - Re-use the oldest notes first // - Protect the lowest & topmost notes, even if sustained, but not if they've been released. + // apparently you are trying to render audio without having any voices... + jassert (voices.size() > 0); + // These are the voices we want to protect (ie: only steal if unavoidable) SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase