2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
20 ==============================================================================
26 //==============================================================================
28 This struct represents a playing MPE note.
30 A note is identified by a unique ID, or alternatively, by a MIDI channel
31 and an initial note. It is characterised by five dimensions of continuous
32 expressive control. Their current values are represented as
39 struct JUCE_API MPENote
41 //==============================================================================
42 /** Possible values for the note key state. */
45 off
= 0, /**< The key is up (off). */
46 keyDown
= 1, /**< The note key is currently down (pressed). */
47 sustained
= 2, /**< The note is sustained (by a sustain or sostenuto pedal). */
48 keyDownAndSustained
= 3 /**< The note key is down and sustained (by a sustain or sostenuto pedal). */
51 //==============================================================================
54 @param midiChannel The MIDI channel of the note, between 2 and 15.
55 (Channel 1 and channel 16 can never be note channels in MPE).
57 @param initialNote The MIDI note number, between 0 and 127.
59 @param velocity The note-on velocity of the note.
61 @param pitchbend The initial per-note pitchbend of the note.
63 @param pressure The initial pressure of the note.
65 @param timbre The timbre value of the note.
67 @param keyState The key state of the note (whether the key is down
68 and/or the note is sustained). This value must not
69 be MPENote::off, since you are triggering a new note.
70 (If not specified, the default value will be MPENote::keyDown.)
72 MPENote (int midiChannel
,
78 KeyState keyState
= MPENote::keyDown
) noexcept
;
80 /** Default constructor.
82 Constructs an invalid MPE note (a note with the key state MPENote::off
83 and an invalid MIDI channel. The only allowed use for such a note is to
84 call isValid() on it; everything else is undefined behaviour.
88 /** Checks whether the MPE note is valid. */
89 bool isValid() const noexcept
;
91 //==============================================================================
92 // Invariants that define the note.
94 /** A unique ID. Useful to distinguish the note from other simultaneously
95 sounding notes that may use the same note number or MIDI channel.
96 This should never change during the lifetime of a note object.
100 /** The MIDI channel which this note uses.
101 This should never change during the lifetime of an MPENote object.
103 uint8 midiChannel
= 0;
105 /** The MIDI note number that was sent when the note was triggered.
106 This should never change during the lifetime of an MPENote object.
108 uint8 initialNote
= 0;
110 //==============================================================================
111 // The five dimensions of continuous expressive control
113 /** The velocity ("strike") of the note-on.
114 This dimension will stay constant after the note has been turned on.
116 MPEValue noteOnVelocity
{ MPEValue::minValue() };
118 /** Current per-note pitchbend of the note (in units of MIDI pitchwheel
119 position). This dimension can be modulated while the note sounds.
121 Note: This value is not aware of the currently used pitchbend range,
122 or an additional master pitchbend that may be simultaneously applied.
123 To compute the actual effective pitchbend of an MPENote, you should
124 probably use the member totalPitchbendInSemitones instead.
126 @see totalPitchbendInSemitones, getFrequencyInHertz
128 MPEValue pitchbend
{ MPEValue::centreValue() };
130 /** Current pressure with which the note is held down.
131 This dimension can be modulated while the note sounds.
133 MPEValue pressure
{ MPEValue::centreValue() };
135 /** Initial value of timbre when the note was triggered.
136 This should never change during the lifetime of an MPENote object.
138 MPEValue initialTimbre
{ MPEValue::centreValue() };
140 /** Current value of the note's third expressive dimension, typically
141 encoding some kind of timbre parameter.
142 This dimension can be modulated while the note sounds.
144 MPEValue timbre
{ MPEValue::centreValue() };
146 /** The release velocity ("lift") of the note after a note-off has been
148 This dimension will only have a meaningful value after a note-off has
149 been received for the note (and keyState is set to MPENote::off or
150 MPENote::sustained). Initially, the value is undefined.
152 MPEValue noteOffVelocity
{ MPEValue::minValue() };
154 //==============================================================================
155 /** Current effective pitchbend of the note in units of semitones, relative
156 to initialNote. You should use this to compute the actual effective pitch
157 of the note. This value is computed and set by an MPEInstrument to the
158 sum of the per-note pitchbend value (stored in MPEValue::pitchbend)
159 and the master pitchbend of the MPE zone, weighted with the per-note
160 pitchbend range and master pitchbend range of the zone, respectively.
162 @see getFrequencyInHertz
164 double totalPitchbendInSemitones
;
166 /** Current key state. Indicates whether the note key is currently down (pressed)
167 and/or the note is sustained (by a sustain or sostenuto pedal).
169 KeyState keyState
{ MPENote::off
};
171 //==============================================================================
172 /** Returns the current frequency of the note in Hertz. This is the sum of
173 the initialNote and the totalPitchbendInSemitones, converted to Hertz.
175 double getFrequencyInHertz (double frequencyOfA
= 440.0) const noexcept
;
177 /** Returns true if two notes are the same, determined by their unique ID. */
178 bool operator== (const MPENote
& other
) const noexcept
;
180 /** Returns true if two notes are different notes, determined by their unique ID. */
181 bool operator!= (const MPENote
& other
) const noexcept
;