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);
307 for (
auto* voice : voices)
308 voice->noteStopped (allowTailOff);
320 for (
auto* voice : voices)
322 if (voice->isActive())
323 voice->renderNextBlock (buffer, startSample, numSamples);
331 for (
auto* voice : voices)
333 if (voice->isActive())
334 voice->renderNextBlock (buffer, startSample, numSamples);
Holds a resizable array of primitive or copy-by-value objects.
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
ElementType * end() noexcept
Returns a pointer to the element which follows the last element in the array.
ElementType * begin() noexcept
Returns a pointer to the first element in the array.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Automatically locks and unlocks a mutex object.
This class represents an instrument handling MPE.
Represents an MPE voice that an MPESynthesiser can use to play a sound.
virtual void setCurrentSampleRate(double newRate)
Changes the voice's reference sample rate.
MPENote getCurrentlyPlayingNote() const noexcept
Returns the MPENote that this voice is currently playing.
virtual void noteStarted()=0
Called by the MPESynthesiser to let the voice know that a new note has started on it.
uint32 noteOnTime
This will be set to an incrementing counter value in MPESynthesiser::startVoice() and can be used to ...
virtual void noteStopped(bool allowTailOff)=0
Called by the MPESynthesiser to let the voice know that its currently playing note has stopped.
bool isPlayingButReleased() const noexcept
Returns true if a voice is sounding in its release phase.
void removeVoice(int index)
Deletes one of the voices.
void reduceNumVoices(int newNumVoices)
Reduces the number of voices to newNumVoices.
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...
MPESynthesiser()
Constructor.
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 ...
void setCurrentPlaybackSampleRate(double newRate) override
Tells the synthesiser what the sample rate is for the audio it's being used to render.
void startVoice(MPESynthesiserVoice *voice, MPENote noteToStart)
Starts a specified voice and tells it to play a particular MPENote.
void notePressureChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note,...
void noteReleased(MPENote finishedNote) override
Stops playing a note.
void clearVoices()
Deletes all voices.
void addVoice(MPESynthesiserVoice *newVoice)
Adds a new voice to the synth.
~MPESynthesiser() override
Destructor.
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 noteTimbreChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note,...
void noteAdded(MPENote newNote) override
Attempts to start playing a new note.
MPESynthesiserVoice * getVoice(int index) const
Returns one of the voices that have been added.
void noteKeyStateChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note,...
virtual void turnOffAllVoices(bool allowTailOff)
Release all MPE notes and turn off all voices.
virtual void handleProgramChange(int, int)
Callback for MIDI program change messages.
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...
void notePitchbendChanged(MPENote changedNote) override
Will find any voice that is currently playing changedNote, update its currently playing note,...
void handleMidiEvent(const MidiMessage &) override
Handle incoming MIDI events.
virtual void handleController(int, int, int)
Callback for MIDI controller messages.
This class represents the current MPE zone layout of a device capable of handling MPE.
void setLowerZone(int numMemberChannels=0, int perNotePitchbendRange=48, int masterPitchbendRange=2) noexcept
Sets the lower zone of this layout.
Encapsulates a MIDI message.
int getChannel() const noexcept
Returns the midi channel associated with the message.
bool isProgramChange() const noexcept
Returns true if the message is a program (patch) change message.
bool isController() const noexcept
Returns true if this is a midi controller message.
int getControllerNumber() const noexcept
Returns the controller number of a controller message.
int getProgramChangeNumber() const noexcept
Returns the new program number of a program change message.
int getControllerValue() const noexcept
Returns the controller value from a controller message.
This struct represents a playing MPE note.
@ keyDown
The note key is currently down (pressed).
@ keyDownAndSustained
The note key is down and sustained (by a sustain or sostenuto pedal).
uint8 initialNote
The MIDI note number that was sent when the note was triggered.
KeyState keyState
Current key state.
bool isValid() const noexcept
Checks whether the MPE note is valid.
Derive from this class to create a basic audio generator capable of MPE.
virtual void handleMidiEvent(const MidiMessage &)
Handle incoming MIDI events (called from renderNextBlock).
void setZoneLayout(MPEZoneLayout newLayout)
Re-sets the synthesiser's internal MPE zone layout to the one passed in.
std::unique_ptr< MPEInstrument > instrument
virtual void setCurrentPlaybackSampleRate(double sampleRate)
Tells the synthesiser what the sample rate is for the audio it's being used to render.
double getSampleRate() const noexcept
Returns the current target sample rate at which rendering is being done.