26MidiKeyboardState::MidiKeyboardState()
28 zerostruct (noteStates);
34 const ScopedLock sl (lock);
35 zerostruct (noteStates);
41 jassert (midiChannel > 0 && midiChannel <= 16);
43 return isPositiveAndBelow (n, 128)
44 && (noteStates[n] & (1 << (midiChannel - 1))) != 0;
49 return isPositiveAndBelow (n, 128)
50 && (noteStates[n] & midiChannelMask) != 0;
55 jassert (midiChannel > 0 && midiChannel <= 16);
56 jassert (isPositiveAndBelow (midiNoteNumber, 128));
58 const ScopedLock sl (lock);
60 if (isPositiveAndBelow (midiNoteNumber, 128))
63 eventsToAdd.addEvent (
MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow);
64 eventsToAdd.clear (0, timeNow - 500);
66 noteOnInternal (midiChannel, midiNoteNumber, velocity);
70void MidiKeyboardState::noteOnInternal (
const int midiChannel,
const int midiNoteNumber,
const float velocity)
72 if (isPositiveAndBelow (midiNoteNumber, 128))
74 noteStates[midiNoteNumber] =
static_cast<uint16
> (noteStates[midiNoteNumber] | (1 << (midiChannel - 1)));
75 listeners.call ([&] (Listener& l) { l.handleNoteOn (
this, midiChannel, midiNoteNumber, velocity); });
81 const ScopedLock sl (lock);
83 if (
isNoteOn (midiChannel, midiNoteNumber))
87 eventsToAdd.clear (0, timeNow - 500);
89 noteOffInternal (midiChannel, midiNoteNumber, velocity);
93void MidiKeyboardState::noteOffInternal (
const int midiChannel,
const int midiNoteNumber,
const float velocity)
95 if (
isNoteOn (midiChannel, midiNoteNumber))
97 noteStates[midiNoteNumber] =
static_cast<uint16
> (noteStates[midiNoteNumber] & ~(1 << (midiChannel - 1)));
98 listeners.call ([&] (Listener& l) { l.handleNoteOff (
this, midiChannel, midiNoteNumber, velocity); });
104 const ScopedLock sl (lock);
106 if (midiChannel <= 0)
108 for (
int i = 1; i <= 16; ++i)
113 for (
int i = 0; i < 128; ++i)
114 noteOff (midiChannel, i, 0.0f);
130 for (
int i = 0; i < 128; ++i)
131 noteOffInternal (message.
getChannel(), i, 0.0f);
136 const int startSample,
137 const int numSamples,
138 const bool injectIndirectEvents)
140 const ScopedLock sl (lock);
142 for (
const auto metadata : buffer)
145 if (injectIndirectEvents)
147 const int firstEventToAdd = eventsToAdd.getFirstEventTime();
148 const double scaleFactor = numSamples / (double) (eventsToAdd.getLastEventTime() + 1 - firstEventToAdd);
150 for (
const auto metadata : eventsToAdd)
152 const auto pos = jlimit (0, numSamples - 1, roundToInt ((metadata.samplePosition - firstEventToAdd) * scaleFactor));
153 buffer.
addEvent (metadata.getMessage(), startSample + pos);
163 const ScopedLock sl (lock);
164 listeners.add (listener);
169 const ScopedLock sl (lock);
170 listeners.remove (listener);
bool addEvent(const MidiMessage &midiMessage, int sampleNumber)
void processNextMidiBuffer(MidiBuffer &buffer, int startSample, int numSamples, bool injectIndirectEvents)
void addListener(Listener *listener)
void noteOff(int midiChannel, int midiNoteNumber, float velocity)
void allNotesOff(int midiChannel)
void processNextMidiEvent(const MidiMessage &message)
void removeListener(Listener *listener)
bool isNoteOn(int midiChannel, int midiNoteNumber) const noexcept
void noteOn(int midiChannel, int midiNoteNumber, float velocity)
bool isNoteOnForChannels(int midiChannelMask, int midiNoteNumber) const noexcept
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
float getFloatVelocity() const noexcept
int getChannel() const noexcept
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
int getNoteNumber() const noexcept
bool isAllNotesOff() const noexcept
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
static uint32 getMillisecondCounter() noexcept