44 jassert (voice !=
nullptr);
46 voice->currentlyPlayingNote = noteToStart;
53 jassert (voice !=
nullptr);
55 voice->currentlyPlayingNote = noteToStop;
72 for (
auto* voice : voices)
74 if (voice->isCurrentlyPlayingNote (changedNote))
76 voice->currentlyPlayingNote = changedNote;
77 voice->notePressureChanged();
86 for (
auto* voice : voices)
88 if (voice->isCurrentlyPlayingNote (changedNote))
90 voice->currentlyPlayingNote = changedNote;
91 voice->notePitchbendChanged();
100 for (
auto* voice : voices)
102 if (voice->isCurrentlyPlayingNote (changedNote))
104 voice->currentlyPlayingNote = changedNote;
105 voice->noteTimbreChanged();
114 for (
auto* voice : voices)
116 if (voice->isCurrentlyPlayingNote (changedNote))
118 voice->currentlyPlayingNote = changedNote;
119 voice->noteKeyStateChanged();
128 for (
auto i = voices.size(); --i >= 0;)
130 auto* voice = voices.getUnchecked (i);
132 if (voice->isCurrentlyPlayingNote(finishedNote))
145 for (
auto i = voices.size(); --i >= 0;)
146 voices.getUnchecked (i)->setCurrentSampleRate (newRate);
163 for (
auto* voice : voices)
165 if (! voice->isActive())
169 if (stealIfNoneAvailable)
183 jassert (voices.size() > 0);
193 for (
auto* voice : voices)
195 jassert (voice->isActive());
197 usableVoices.
add (voice);
206 std::sort (usableVoices.
begin(), usableVoices.
end(), Sorter());
208 if (! voice->isPlayingButReleased())
210 auto noteNumber = voice->getCurrentlyPlayingNote().initialNote;
212 if (low ==
nullptr || noteNumber < low->getCurrentlyPlayingNote().initialNote)
226 if (noteToStealVoiceFor.
isValid())
227 for (
auto* voice : usableVoices)
228 if (voice->getCurrentlyPlayingNote().initialNote == noteToStealVoiceFor.
initialNote)
232 for (
auto* voice : usableVoices)
237 for (
auto* voice : usableVoices)
238 if (voice != low && voice != top
244 for (
auto* voice : usableVoices)
245 if (voice != low && voice != top)
249 jassert (low !=
nullptr);
263 voices.add (newVoice);
275 return voices [index];
281 voices.remove (index);
287 jassert (newNumVoices >= 0);
291 while (voices.size() > newNumVoices)
294 voices.removeObject (voice);
304 for (
auto* voice : voices)
305 voice->noteStopped (allowTailOff);
314 for (
auto* voice : voices)
316 if (voice->isActive())
317 voice->renderNextBlock (buffer, startSample, numSamples);
323 for (
auto* voice : voices)
325 if (voice->isActive())
326 voice->renderNextBlock (buffer, startSample, numSamples);
ElementType * begin() const noexcept
Returns a pointer to the first element in the array.
void noteReleased(MPENote finishedNote) override
Stops playing a note.
void stopVoice(MPESynthesiserVoice *voice, MPENote noteToStop, bool allowTailOff)
Stops a given voice and tells it to stop playing a particular MPENote (which should be the same note ...
This class represents the current MPE zone layout of a device capable of handling MPE...
void setZoneLayout(MPEZoneLayout newLayout)
Re-sets the synthesiser's internal MPE zone layout to the one passed in.
Encapsulates a MIDI message.
KeyState keyState
Current key state.
void setCurrentPlaybackSampleRate(double newRate) override
Tells the synthesiser what the sample rate is for the audio it's being used to render.
virtual MPESynthesiserVoice * findFreeVoice(MPENote noteToFindVoiceFor, bool stealIfNoneAvailable) const
Searches through the voices to find one that's not currently playing, and which can play the given MP...
virtual void setCurrentSampleRate(double newRate)
Changes the voice's reference sample rate.
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
virtual void handleMidiEvent(const MidiMessage &)
Handle incoming MIDI events (called from renderNextBlock).
void removeVoice(int index)
Deletes one of the voices.
bool isPlayingButReleased() const noexcept
Returns true if a voice is sounding in its release phase.
void startVoice(MPESynthesiserVoice *voice, MPENote noteToStart)
Starts a specified voice and tells it to play a particular MPENote.
bool isValid() const noexcept
Checks whether the MPE note is valid.
virtual void turnOffAllVoices(bool allowTailOff)
Release all MPE notes and turn off all voices.
void noteTimbreChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note...
void notePitchbendChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note...
void reduceNumVoices(int newNumVoices)
Reduces the number of voices to newNumVoices.
std::unique_ptr< MPEInstrument > instrument
bool isProgramChange() const noexcept
Returns true if the message is a program (patch) change message.
void noteAdded(MPENote newNote) override
Attempts to start playing a new note.
int getControllerNumber() const noexcept
Returns the controller number of a controller message.
uint8 initialNote
The MIDI note number that was sent when the note was triggered.
uint32 noteOnTime
This will be set to an incrementing counter value in MPESynthesiser::startVoice() and can be used to ...
int getChannel() const noexcept
Returns the midi channel associated with the message.
bool isController() const noexcept
Returns true if this is a midi controller message.
virtual void noteStopped(bool allowTailOff)=0
Called by the MPESynthesiser to let the voice know that its currently playing note has stopped...
void noteKeyStateChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note...
ElementType * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
The note key is down and sustained (by a sustain or sostenuto pedal).
The note key is currently down (pressed).
int getProgramChangeNumber() const noexcept
Returns the new program number of a program change message.
Holds a resizable array of primitive or copy-by-value objects.
MPESynthesiserVoice * getVoice(int index) const
Returns one of the voices that have been added.
virtual void noteStarted()=0
Called by the MPESynthesiser to let the voice know that a new note has started on it...
Represents an MPE voice that an MPESynthesiser can use to play a sound.
virtual void setCurrentPlaybackSampleRate(double sampleRate)
Tells the synthesiser what the sample rate is for the audio it's being used to render.
MPENote getCurrentlyPlayingNote() const noexcept
Returns the MPENote that this voice is currently playing.
Derive from this class to create a basic audio generator capable of MPE.
This struct represents a playing MPE note.
virtual void handleController(int, int, int)
Callback for MIDI controller messages.
double getSampleRate() const noexcept
Returns the current target sample rate at which rendering is being done.
void handleMidiEvent(const MidiMessage &) override
Handle incoming MIDI events.
virtual void handleProgramChange(int, int)
Callback for MIDI program change messages.
int getControllerValue() const noexcept
Returns the controller value from a controller message.
void clearVoices()
Deletes all voices.
~MPESynthesiser() override
Destructor.
void notePressureChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note...
This class represents an instrument handling MPE.
void renderNextSubBlock(AudioBuffer< float > &outputAudio, int startSample, int numSamples) override
This will simply call renderNextBlock for each currently active voice and fill the buffer with the su...
Automatically locks and unlocks a mutex object.
MPESynthesiser()
Constructor.
void addVoice(MPESynthesiserVoice *newVoice)
Adds a new voice to the synth.
virtual MPESynthesiserVoice * findVoiceToSteal(MPENote noteToStealVoiceFor=MPENote()) const
Chooses a voice that is most suitable for being re-used to play a new note, or for being deleted by r...
void setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
Sets the lower zone of this layout.