OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_MidiKeyboardState.cpp
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);
56 jassert (isPositiveAndBelow (midiNoteNumber, 128));
57
58 const ScopedLock sl (lock);
59
60 if (isPositiveAndBelow (midiNoteNumber, 128))
61 {
62 const int timeNow = (int) Time::getMillisecondCounter();
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{
72 if (isPositiveAndBelow (midiNoteNumber, 128))
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 {
85 const int timeNow = (int) Time::getMillisecondCounter();
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
145 if (injectIndirectEvents)
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
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