JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_MidiKeyboardState.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
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.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26MidiKeyboardState::MidiKeyboardState()
27{
28 zerostruct (noteStates);
29}
30
31//==============================================================================
33{
34 const ScopedLock sl (lock);
35 zerostruct (noteStates);
36 eventsToAdd.clear();
37}
38
39bool MidiKeyboardState::isNoteOn (const int midiChannel, const int n) const noexcept
40{
41 jassert (midiChannel > 0 && midiChannel <= 16);
42
43 return isPositiveAndBelow (n, 128)
44 && (noteStates[n] & (1 << (midiChannel - 1))) != 0;
45}
46
47bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const noexcept
48{
49 return isPositiveAndBelow (n, 128)
50 && (noteStates[n] & midiChannelMask) != 0;
51}
52
53void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, const float velocity)
54{
55 jassert (midiChannel > 0 && midiChannel <= 16);
57
58 const ScopedLock sl (lock);
59
61 {
63 eventsToAdd.addEvent (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow);
64 eventsToAdd.clear (0, timeNow - 500);
65
66 noteOnInternal (midiChannel, midiNoteNumber, velocity);
67 }
68}
69
70void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity)
71{
73 {
74 noteStates[midiNoteNumber] = static_cast<uint16> (noteStates[midiNoteNumber] | (1 << (midiChannel - 1)));
75 listeners.call ([&] (Listener& l) { l.handleNoteOn (this, midiChannel, midiNoteNumber, velocity); });
76 }
77}
78
79void MidiKeyboardState::noteOff (const int midiChannel, const int midiNoteNumber, const float velocity)
80{
81 const ScopedLock sl (lock);
82
83 if (isNoteOn (midiChannel, midiNoteNumber))
84 {
86 eventsToAdd.addEvent (MidiMessage::noteOff (midiChannel, midiNoteNumber), timeNow);
87 eventsToAdd.clear (0, timeNow - 500);
88
89 noteOffInternal (midiChannel, midiNoteNumber, velocity);
90 }
91}
92
93void MidiKeyboardState::noteOffInternal (const int midiChannel, const int midiNoteNumber, const float velocity)
94{
95 if (isNoteOn (midiChannel, midiNoteNumber))
96 {
97 noteStates[midiNoteNumber] = static_cast<uint16> (noteStates[midiNoteNumber] & ~(1 << (midiChannel - 1)));
98 listeners.call ([&] (Listener& l) { l.handleNoteOff (this, midiChannel, midiNoteNumber, velocity); });
99 }
100}
101
102void MidiKeyboardState::allNotesOff (const int midiChannel)
103{
104 const ScopedLock sl (lock);
105
106 if (midiChannel <= 0)
107 {
108 for (int i = 1; i <= 16; ++i)
109 allNotesOff (i);
110 }
111 else
112 {
113 for (int i = 0; i < 128; ++i)
114 noteOff (midiChannel, i, 0.0f);
115 }
116}
117
119{
120 if (message.isNoteOn())
121 {
122 noteOnInternal (message.getChannel(), message.getNoteNumber(), message.getFloatVelocity());
123 }
124 else if (message.isNoteOff())
125 {
126 noteOffInternal (message.getChannel(), message.getNoteNumber(), message.getFloatVelocity());
127 }
128 else if (message.isAllNotesOff())
129 {
130 for (int i = 0; i < 128; ++i)
131 noteOffInternal (message.getChannel(), i, 0.0f);
132 }
133}
134
136 const int startSample,
137 const int numSamples,
138 const bool injectIndirectEvents)
139{
140 const ScopedLock sl (lock);
141
142 for (const auto metadata : buffer)
143 processNextMidiEvent (metadata.getMessage());
144
146 {
147 const int firstEventToAdd = eventsToAdd.getFirstEventTime();
148 const double scaleFactor = numSamples / (double) (eventsToAdd.getLastEventTime() + 1 - firstEventToAdd);
149
150 for (const auto metadata : eventsToAdd)
151 {
152 const auto pos = jlimit (0, numSamples - 1, roundToInt ((metadata.samplePosition - firstEventToAdd) * scaleFactor));
153 buffer.addEvent (metadata.getMessage(), startSample + pos);
154 }
155 }
156
157 eventsToAdd.clear();
158}
159
160//==============================================================================
162{
163 const ScopedLock sl (lock);
164 listeners.add (listener);
165}
166
168{
169 const ScopedLock sl (lock);
170 listeners.remove (listener);
171}
172
173} // namespace juce
Automatically locks and unlocks a mutex object.
Holds a sequence of time-stamped midi events.
int getFirstEventTime() const noexcept
Returns the sample number of the first event in the buffer.
int getLastEventTime() const noexcept
Returns the sample number of the last event in the buffer.
bool addEvent(const MidiMessage &midiMessage, int sampleNumber)
Adds an event to the buffer.
void clear() noexcept
Removes all events from the buffer.
Receives events from a MidiKeyboardState object.
void processNextMidiBuffer(MidiBuffer &buffer, int startSample, int numSamples, bool injectIndirectEvents)
Scans a midi stream for up/down events and adds its own events to it.
void addListener(Listener *listener)
Registers a listener for callbacks when keys go up or down.
void noteOff(int midiChannel, int midiNoteNumber, float velocity)
Turns a specified note off.
void allNotesOff(int midiChannel)
This will turn off any currently-down notes for the given midi channel.
void processNextMidiEvent(const MidiMessage &message)
Looks at a key-up/down event and uses it to update the state of this object.
void removeListener(Listener *listener)
Deregisters a listener.
bool isNoteOn(int midiChannel, int midiNoteNumber) const noexcept
Returns true if the given midi key is currently held down for the given midi channel.
void noteOn(int midiChannel, int midiNoteNumber, float velocity)
Turns a specified note on.
void reset()
Resets the state of the object.
bool isNoteOnForChannels(int midiChannelMask, int midiNoteNumber) const noexcept
Returns true if the given midi key is currently held down on any of a set of midi channels.
Encapsulates a MIDI message.
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Returns true if this message is a 'key-down' event.
float getFloatVelocity() const noexcept
Returns the velocity of a note-on or note-off message.
int getChannel() const noexcept
Returns the midi channel associated with the message.
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Returns true if this message is a 'key-up' event.
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Creates a key-down message (using a floating-point velocity).
int getNoteNumber() const noexcept
Returns the midi note number for note-on and note-off messages.
bool isAllNotesOff() const noexcept
Checks whether this message is an all-notes-off message.
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Creates a key-up message.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
#define jassert(expression)
Platform-independent assertion macro.
typedef int
typedef double
JUCE Namespace.
void zerostruct(Type &structure) noexcept
Overwrites a structure or object with zeros.
Definition juce_Memory.h:32
unsigned short uint16
A platform-independent 16-bit unsigned integer type.
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.