JUCE  v5.4.1-191-g0ab5e696f
JUCE API
Looking for a senior C++ dev?
I'm looking for work. Hire me!
juce::MPEInstrument Class Reference

This class represents an instrument handling MPE. More...

#include <juce_MPEInstrument.h>

Collaboration diagram for juce::MPEInstrument:

Classes

struct  LegacyMode
 
class  Listener
 Derive from this class to be informed about any changes in the expressive MIDI notes played by this instrument. More...
 
struct  MPEDimension
 

Public Types

enum  TrackingMode {
  lastNotePlayedOnChannel,
  lowestNoteOnChannel,
  highestNoteOnChannel,
  allNotesOnChannel
}
 The MPE note tracking mode. More...
 

Public Member Functions

 MPEInstrument () noexcept
 Constructor. More...
 
virtual ~MPEInstrument ()
 Destructor. More...
 
void addListener (Listener *listenerToAdd)
 Adds a listener. More...
 
void enableLegacyMode (int pitchbendRange=2, Range< int > channelRange=Range< int >(1, 17))
 Puts the instrument into legacy mode. More...
 
Range< intgetLegacyModeChannelRange () const noexcept
 Returns the range of MIDI channels (1-16) to be used for notes when in legacy mode. More...
 
int getLegacyModePitchbendRange () const noexcept
 Returns the pitchbend range in semitones (0-96) to be used for notes when in legacy mode. More...
 
MPENote getMostRecentNote (int midiChannel) const noexcept
 Returns the most recent note that is playing on the given midiChannel (this will be the note which has received the most recent note-on without a corresponding note-off), if there is such a note. More...
 
MPENote getMostRecentNoteOtherThan (MPENote otherThanThisNote) const noexcept
 Returns the most recent note that is not the note passed in. More...
 
MPENote getNote (int index) const noexcept
 Returns the note at the given index. More...
 
MPENote getNote (int midiChannel, int midiNoteNumber) const noexcept
 Returns the note currently playing on the given midiChannel with the specified initial MIDI note number, if there is such a note. More...
 
int getNumPlayingNotes () const noexcept
 Returns the number of MPE notes currently played by the instrument. More...
 
MPEZoneLayout getZoneLayout () const noexcept
 Returns the current zone layout of the instrument. More...
 
bool isLegacyModeEnabled () const noexcept
 Returns true if the instrument is in legacy mode, false otherwise. More...
 
bool isMasterChannel (int midiChannel) const noexcept
 Returns true if the given MIDI channel (1-16) is a master channel (channel 1 or 16). More...
 
bool isMemberChannel (int midiChannel) noexcept
 Returns true if the given MIDI channel (1-16) is a note channel in any of the MPEInstrument's MPE zones; false otherwise. More...
 
virtual void noteOff (int midiChannel, int midiNoteNumber, MPEValue midiNoteOffVelocity)
 Request a note-off. More...
 
virtual void noteOn (int midiChannel, int midiNoteNumber, MPEValue midiNoteOnVelocity)
 Request a note-on on the given channel, with the given initial note number and velocity. More...
 
virtual void pitchbend (int midiChannel, MPEValue pitchbend)
 Request a pitchbend on the given channel with the given value (in units of MIDI pitchwheel position). More...
 
virtual void pressure (int midiChannel, MPEValue value)
 Request a pressure change on the given channel with the given value. More...
 
virtual void processNextMidiEvent (const MidiMessage &message)
 Process a MIDI message and trigger the appropriate method calls (noteOn, noteOff etc.) More...
 
void releaseAllNotes ()
 Discard all currently playing notes. More...
 
void removeListener (Listener *listenerToRemove)
 Removes a listener. More...
 
void setLegacyModeChannelRange (Range< int > channelRange)
 Re-sets the range of MIDI channels (1-16) to be used for notes when in legacy mode. More...
 
void setLegacyModePitchbendRange (int pitchbendRange)
 Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode. More...
 
void setPitchbendTrackingMode (TrackingMode modeToUse)
 Set the MPE tracking mode for the pitchbend dimension. More...
 
void setPressureTrackingMode (TrackingMode modeToUse)
 Set the MPE tracking mode for the pressure dimension. More...
 
void setTimbreTrackingMode (TrackingMode modeToUse)
 Set the MPE tracking mode for the timbre dimension. More...
 
void setZoneLayout (MPEZoneLayout newLayout)
 Re-sets the zone layout of the instrument to the one passed in. More...
 
virtual void sostenutoPedal (int midiChannel, bool isDown)
 Request a sostenuto pedal press or release. More...
 
virtual void sustainPedal (int midiChannel, bool isDown)
 Request a sustain pedal press or release. More...
 
virtual void timbre (int midiChannel, MPEValue value)
 Request a third dimension (timbre) change on the given channel with the given value. More...
 

Protected Attributes

CriticalSection lock
 

Private Member Functions

void callListenersDimensionChanged (const MPENote &, const MPEDimension &)
 
const MPENotegetHighestNotePtr (int midiChannel) const noexcept
 
MPENotegetHighestNotePtr (int midiChannel) noexcept
 
MPEValue getInitialValueForNewNote (int midiChannel, MPEDimension &) const
 
const MPENotegetLastNotePlayedPtr (int midiChannel) const noexcept
 
MPENotegetLastNotePlayedPtr (int midiChannel) noexcept
 
const MPENotegetLowestNotePtr (int midiChannel) const noexcept
 
MPENotegetLowestNotePtr (int midiChannel) noexcept
 
const MPENotegetNotePtr (int midiChannel, int midiNoteNumber) const noexcept
 
MPENotegetNotePtr (int midiChannel, int midiNoteNumber) noexcept
 
const MPENotegetNotePtr (int midiChannel, TrackingMode) const noexcept
 
MPENotegetNotePtr (int midiChannel, TrackingMode) noexcept
 
void handlePressureLSB (int midiChannel, int value) noexcept
 
void handlePressureMSB (int midiChannel, int value) noexcept
 
void handleSustainOrSostenuto (int midiChannel, bool isDown, bool isSostenuto)
 
void handleTimbreLSB (int midiChannel, int value) noexcept
 
void handleTimbreMSB (int midiChannel, int value) noexcept
 
void processMidiChannelPressureMessage (const MidiMessage &)
 
void processMidiControllerMessage (const MidiMessage &)
 
void processMidiNoteOffMessage (const MidiMessage &)
 
void processMidiNoteOnMessage (const MidiMessage &)
 
void processMidiPitchWheelMessage (const MidiMessage &)
 
void processMidiResetAllControllersMessage (const MidiMessage &)
 
void updateDimension (int midiChannel, MPEDimension &, MPEValue)
 
void updateDimensionForNote (MPENote &, MPEDimension &, MPEValue)
 
void updateDimensionMaster (bool, MPEDimension &, MPEValue)
 
void updateNoteTotalPitchbend (MPENote &)
 

Private Attributes

bool isMemberChannelSustained [16]
 
uint8 lastPressureLowerBitReceivedOnChannel [16]
 
uint8 lastTimbreLowerBitReceivedOnChannel [16]
 
LegacyMode legacyMode
 
ListenerList< Listenerlisteners
 
Array< MPENotenotes
 
MPEDimension pitchbendDimension
 
MPEDimension pressureDimension
 
MPEDimension timbreDimension
 
MPEZoneLayout zoneLayout
 

Detailed Description

This class represents an instrument handling MPE.

It has an MPE zone layout and maintans a state of currently active (playing) notes and the values of their dimensions of expression.

You can trigger and modulate notes:

  • by passing MIDI messages with the method processNextMidiEvent;
  • by directly calling the methods noteOn, noteOff etc.

The class implements the channel and note management logic specified in MPE. If you pass it a message, it will know what notes on what channels (if any) should be affected by that message.

The class has a Listener class with the three callbacks MPENoteAdded, MPENoteChanged, and MPENoteFinished. Implement such a Listener class to react to note changes and trigger some functionality for your application that depends on the MPE note state. For example, you can use this class to write an MPE visualiser.

If you want to write a real-time audio synth with MPE functionality, you should instead use the classes MPESynthesiserBase, which adds the ability to render audio and to manage voices.

See also
MPENote, MPEZoneLayout, MPESynthesiser

{Audio}

Member Enumeration Documentation

◆ TrackingMode

The MPE note tracking mode.

In case there is more than one note playing simultaneously on the same MIDI channel, this determines which of these notes will be modulated by an incoming MPE message on that channel (pressure, pitchbend, or timbre).

The default is lastNotePlayedOnChannel.

Enumerator
lastNotePlayedOnChannel 

The most recent note on the channel that is still played (key down and/or sustained).

lowestNoteOnChannel 

The lowest note (by initialNote) on the channel with the note key still down.

highestNoteOnChannel 

The highest note (by initialNote) on the channel with the note key still down.

allNotesOnChannel 

All notes on the channel (key down and/or sustained).

Constructor & Destructor Documentation

◆ MPEInstrument()

juce::MPEInstrument::MPEInstrument ( )
noexcept

Constructor.

This will construct an MPE instrument with inactive lower and upper zones.

In order to process incoming MIDI, call setZoneLayout, define the layout via MIDI RPN messages, or set the instrument to legacy mode.

◆ ~MPEInstrument()

virtual juce::MPEInstrument::~MPEInstrument ( )
virtual

Destructor.

Member Function Documentation

◆ addListener()

void juce::MPEInstrument::addListener ( Listener listenerToAdd)

Adds a listener.

◆ callListenersDimensionChanged()

void juce::MPEInstrument::callListenersDimensionChanged ( const MPENote ,
const MPEDimension  
)
private

◆ enableLegacyMode()

void juce::MPEInstrument::enableLegacyMode ( int  pitchbendRange = 2,
Range< int channelRange = Rangeint >(1, 17) 
)

Puts the instrument into legacy mode.

As a side effect, this will discard all currently playing notes, and call noteReleased for all of them.

This special zone layout mode is for backwards compatibility with non-MPE MIDI devices. In this mode, the instrument will ignore the current MPE zone layout. It will instead take a range of MIDI channels (default: all channels 1-16) and treat them as note channels, with no master channel. MIDI channels outside of this range will be ignored.

Parameters
pitchbendRangeThe note pitchbend range in semitones to use when in legacy mode. Must be between 0 and 96, otherwise behaviour is undefined. The default pitchbend range in legacy mode is +/- 2 semitones.
channelRangeThe range of MIDI channels to use for notes when in legacy mode. The default is to use all MIDI channels (1-16).

To get out of legacy mode, set a new MPE zone layout using setZoneLayout.

◆ getHighestNotePtr() [1/2]

const MPENote* juce::MPEInstrument::getHighestNotePtr ( int  midiChannel) const
privatenoexcept

◆ getHighestNotePtr() [2/2]

MPENote* juce::MPEInstrument::getHighestNotePtr ( int  midiChannel)
privatenoexcept

◆ getInitialValueForNewNote()

MPEValue juce::MPEInstrument::getInitialValueForNewNote ( int  midiChannel,
MPEDimension  
) const
private

◆ getLastNotePlayedPtr() [1/2]

const MPENote* juce::MPEInstrument::getLastNotePlayedPtr ( int  midiChannel) const
privatenoexcept

◆ getLastNotePlayedPtr() [2/2]

MPENote* juce::MPEInstrument::getLastNotePlayedPtr ( int  midiChannel)
privatenoexcept

◆ getLegacyModeChannelRange()

Range<int> juce::MPEInstrument::getLegacyModeChannelRange ( ) const
noexcept

Returns the range of MIDI channels (1-16) to be used for notes when in legacy mode.

◆ getLegacyModePitchbendRange()

int juce::MPEInstrument::getLegacyModePitchbendRange ( ) const
noexcept

Returns the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.

◆ getLowestNotePtr() [1/2]

const MPENote* juce::MPEInstrument::getLowestNotePtr ( int  midiChannel) const
privatenoexcept

◆ getLowestNotePtr() [2/2]

MPENote* juce::MPEInstrument::getLowestNotePtr ( int  midiChannel)
privatenoexcept

◆ getMostRecentNote()

MPENote juce::MPEInstrument::getMostRecentNote ( int  midiChannel) const
noexcept

Returns the most recent note that is playing on the given midiChannel (this will be the note which has received the most recent note-on without a corresponding note-off), if there is such a note.

Otherwise, this returns an invalid MPENote (check with note.isValid() before use!)

◆ getMostRecentNoteOtherThan()

MPENote juce::MPEInstrument::getMostRecentNoteOtherThan ( MPENote  otherThanThisNote) const
noexcept

Returns the most recent note that is not the note passed in.

If there is no such note, this returns an invalid MPENote (check with note.isValid() before use!).

This helper method might be useful for some custom voice handling algorithms.

◆ getNote() [1/2]

MPENote juce::MPEInstrument::getNote ( int  index) const
noexcept

Returns the note at the given index.

If there is no such note, returns an invalid MPENote. The notes are sorted such that the most recently added note is the last element.

◆ getNote() [2/2]

MPENote juce::MPEInstrument::getNote ( int  midiChannel,
int  midiNoteNumber 
) const
noexcept

Returns the note currently playing on the given midiChannel with the specified initial MIDI note number, if there is such a note.

Otherwise, this returns an invalid MPENote (check with note.isValid() before use!)

◆ getNotePtr() [1/4]

const MPENote* juce::MPEInstrument::getNotePtr ( int  midiChannel,
int  midiNoteNumber 
) const
privatenoexcept

◆ getNotePtr() [2/4]

MPENote* juce::MPEInstrument::getNotePtr ( int  midiChannel,
int  midiNoteNumber 
)
privatenoexcept

◆ getNotePtr() [3/4]

const MPENote* juce::MPEInstrument::getNotePtr ( int  midiChannel,
TrackingMode   
) const
privatenoexcept

◆ getNotePtr() [4/4]

MPENote* juce::MPEInstrument::getNotePtr ( int  midiChannel,
TrackingMode   
)
privatenoexcept

◆ getNumPlayingNotes()

int juce::MPEInstrument::getNumPlayingNotes ( ) const
noexcept

Returns the number of MPE notes currently played by the instrument.

◆ getZoneLayout()

MPEZoneLayout juce::MPEInstrument::getZoneLayout ( ) const
noexcept

Returns the current zone layout of the instrument.

This happens by value, to enforce thread-safety and class invariants.

Note: If the instrument is in legacy mode, the return value of this method is unspecified.

◆ handlePressureLSB()

void juce::MPEInstrument::handlePressureLSB ( int  midiChannel,
int  value 
)
privatenoexcept

◆ handlePressureMSB()

void juce::MPEInstrument::handlePressureMSB ( int  midiChannel,
int  value 
)
privatenoexcept

◆ handleSustainOrSostenuto()

void juce::MPEInstrument::handleSustainOrSostenuto ( int  midiChannel,
bool  isDown,
bool  isSostenuto 
)
private

◆ handleTimbreLSB()

void juce::MPEInstrument::handleTimbreLSB ( int  midiChannel,
int  value 
)
privatenoexcept

◆ handleTimbreMSB()

void juce::MPEInstrument::handleTimbreMSB ( int  midiChannel,
int  value 
)
privatenoexcept

◆ isLegacyModeEnabled()

bool juce::MPEInstrument::isLegacyModeEnabled ( ) const
noexcept

Returns true if the instrument is in legacy mode, false otherwise.

◆ isMasterChannel()

bool juce::MPEInstrument::isMasterChannel ( int  midiChannel) const
noexcept

Returns true if the given MIDI channel (1-16) is a master channel (channel 1 or 16).

In legacy mode, this will always return false.

◆ isMemberChannel()

bool juce::MPEInstrument::isMemberChannel ( int  midiChannel)
noexcept

Returns true if the given MIDI channel (1-16) is a note channel in any of the MPEInstrument's MPE zones; false otherwise.

When in legacy mode, this will return true if the given channel is contained in the current legacy mode channel range; false otherwise.

◆ noteOff()

virtual void juce::MPEInstrument::noteOff ( int  midiChannel,
int  midiNoteNumber,
MPEValue  midiNoteOffVelocity 
)
virtual

Request a note-off.

If there is a matching playing note, this will release the note (except if it is sustained by a sustain or sostenuto pedal) and call the noteReleased callback.

◆ noteOn()

virtual void juce::MPEInstrument::noteOn ( int  midiChannel,
int  midiNoteNumber,
MPEValue  midiNoteOnVelocity 
)
virtual

Request a note-on on the given channel, with the given initial note number and velocity.

If the message arrives on a valid note channel, this will create a new MPENote and call the noteAdded callback.

◆ pitchbend()

virtual void juce::MPEInstrument::pitchbend ( int  midiChannel,
MPEValue  pitchbend 
)
virtual

Request a pitchbend on the given channel with the given value (in units of MIDI pitchwheel position).

Internally, this will determine whether the pitchwheel move is a per-note pitchbend or a master pitchbend (depending on midiChannel), take the correct per-note or master pitchbend range of the affected MPE zone, and apply the resulting pitchbend to the affected note(s) (if any).

◆ pressure()

virtual void juce::MPEInstrument::pressure ( int  midiChannel,
MPEValue  value 
)
virtual

Request a pressure change on the given channel with the given value.

This will modify the pressure dimension of the note currently held down on this channel (if any). If the channel is a zone master channel, the pressure change will be broadcast to all notes in this zone.

◆ processMidiChannelPressureMessage()

void juce::MPEInstrument::processMidiChannelPressureMessage ( const MidiMessage )
private

◆ processMidiControllerMessage()

void juce::MPEInstrument::processMidiControllerMessage ( const MidiMessage )
private

◆ processMidiNoteOffMessage()

void juce::MPEInstrument::processMidiNoteOffMessage ( const MidiMessage )
private

◆ processMidiNoteOnMessage()

void juce::MPEInstrument::processMidiNoteOnMessage ( const MidiMessage )
private

◆ processMidiPitchWheelMessage()

void juce::MPEInstrument::processMidiPitchWheelMessage ( const MidiMessage )
private

◆ processMidiResetAllControllersMessage()

void juce::MPEInstrument::processMidiResetAllControllersMessage ( const MidiMessage )
private

◆ processNextMidiEvent()

virtual void juce::MPEInstrument::processNextMidiEvent ( const MidiMessage message)
virtual

Process a MIDI message and trigger the appropriate method calls (noteOn, noteOff etc.)

You can override this method if you need some special MIDI message treatment on top of the standard MPE logic implemented here.

◆ releaseAllNotes()

void juce::MPEInstrument::releaseAllNotes ( )

Discard all currently playing notes.

This will also call the noteReleased listener callback for all of them.

◆ removeListener()

void juce::MPEInstrument::removeListener ( Listener listenerToRemove)

Removes a listener.

◆ setLegacyModeChannelRange()

void juce::MPEInstrument::setLegacyModeChannelRange ( Range< int channelRange)

Re-sets the range of MIDI channels (1-16) to be used for notes when in legacy mode.

◆ setLegacyModePitchbendRange()

void juce::MPEInstrument::setLegacyModePitchbendRange ( int  pitchbendRange)

Re-sets the pitchbend range in semitones (0-96) to be used for notes when in legacy mode.

◆ setPitchbendTrackingMode()

void juce::MPEInstrument::setPitchbendTrackingMode ( TrackingMode  modeToUse)

Set the MPE tracking mode for the pitchbend dimension.

◆ setPressureTrackingMode()

void juce::MPEInstrument::setPressureTrackingMode ( TrackingMode  modeToUse)

Set the MPE tracking mode for the pressure dimension.

◆ setTimbreTrackingMode()

void juce::MPEInstrument::setTimbreTrackingMode ( TrackingMode  modeToUse)

Set the MPE tracking mode for the timbre dimension.

◆ setZoneLayout()

void juce::MPEInstrument::setZoneLayout ( MPEZoneLayout  newLayout)

Re-sets the zone layout of the instrument to the one passed in.

As a side effect, this will discard all currently playing notes, and call noteReleased for all of them.

This will also disable legacy mode in case it was enabled previously.

◆ sostenutoPedal()

virtual void juce::MPEInstrument::sostenutoPedal ( int  midiChannel,
bool  isDown 
)
virtual

Request a sostenuto pedal press or release.

If midiChannel is a zone's master channel, this will act on all notes in that zone; otherwise, nothing will happen.

◆ sustainPedal()

virtual void juce::MPEInstrument::sustainPedal ( int  midiChannel,
bool  isDown 
)
virtual

Request a sustain pedal press or release.

If midiChannel is a zone's master channel, this will act on all notes in that zone; otherwise, nothing will happen.

◆ timbre()

virtual void juce::MPEInstrument::timbre ( int  midiChannel,
MPEValue  value 
)
virtual

Request a third dimension (timbre) change on the given channel with the given value.

This will modify the timbre dimension of the note currently held down on this channel (if any). If the channel is a zone master channel, the timbre change will be broadcast to all notes in this zone.

◆ updateDimension()

void juce::MPEInstrument::updateDimension ( int  midiChannel,
MPEDimension ,
MPEValue   
)
private

◆ updateDimensionForNote()

void juce::MPEInstrument::updateDimensionForNote ( MPENote ,
MPEDimension ,
MPEValue   
)
private

◆ updateDimensionMaster()

void juce::MPEInstrument::updateDimensionMaster ( bool  ,
MPEDimension ,
MPEValue   
)
private

◆ updateNoteTotalPitchbend()

void juce::MPEInstrument::updateNoteTotalPitchbend ( MPENote )
private

Member Data Documentation

◆ isMemberChannelSustained

bool juce::MPEInstrument::isMemberChannelSustained[16]
private

◆ lastPressureLowerBitReceivedOnChannel

uint8 juce::MPEInstrument::lastPressureLowerBitReceivedOnChannel[16]
private

◆ lastTimbreLowerBitReceivedOnChannel

uint8 juce::MPEInstrument::lastTimbreLowerBitReceivedOnChannel[16]
private

◆ legacyMode

LegacyMode juce::MPEInstrument::legacyMode
private

◆ listeners

ListenerList<Listener> juce::MPEInstrument::listeners
private

◆ lock

CriticalSection juce::MPEInstrument::lock
protected

◆ notes

Array<MPENote> juce::MPEInstrument::notes
private

◆ pitchbendDimension

MPEDimension juce::MPEInstrument::pitchbendDimension
private

◆ pressureDimension

MPEDimension juce::MPEInstrument::pressureDimension
private

◆ timbreDimension

MPEDimension juce::MPEInstrument::timbreDimension
private

◆ zoneLayout

MPEZoneLayout juce::MPEInstrument::zoneLayout
private

The documentation for this class was generated from the following file: