OpenShot Audio Library | OpenShotAudio: juce_MidiKeyboardState.cpp Source File

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//==============================================================================
32 void MidiKeyboardState::reset()
33{
34 const ScopedLock sl (lock);
35 zerostruct (noteStates);
36 eventsToAdd.clear();
37}
38
39 bool 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
47 bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const noexcept
48{
49 return isPositiveAndBelow (n, 128)
50 && (noteStates[n] & midiChannelMask) != 0;
51}
52
53 void 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
79 void 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
102 void 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
118 void MidiKeyboardState::processNextMidiEvent (const MidiMessage& message)
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
135 void MidiKeyboardState::processNextMidiBuffer (MidiBuffer& buffer,
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//==============================================================================
161 void MidiKeyboardState::addListener (Listener* listener)
162{
163 const ScopedLock sl (lock);
164 listeners.add (listener);
165}
166
167 void MidiKeyboardState::removeListener (Listener* listener)
168{
169 const ScopedLock sl (lock);
170 listeners.remove (listener);
171}
172
173} // namespace juce
juce::GenericScopedLock
Definition juce_ScopedLock.h:55
juce::MidiBuffer
Definition juce_MidiBuffer.h:145
juce::MidiBuffer::getFirstEventTime
int getFirstEventTime() const noexcept
Definition juce_MidiBuffer.cpp:180
juce::MidiBuffer::getLastEventTime
int getLastEventTime() const noexcept
Definition juce_MidiBuffer.cpp:185
juce::MidiBuffer::addEvent
bool addEvent(const MidiMessage &midiMessage, int sampleNumber)
Definition juce_MidiBuffer.cpp:122
juce::MidiBuffer::clear
void clear() noexcept
Definition juce_MidiBuffer.cpp:110
juce::MidiKeyboardState::Listener
Definition juce_MidiKeyboardState.h:139
juce::MidiKeyboardState::processNextMidiBuffer
void processNextMidiBuffer(MidiBuffer &buffer, int startSample, int numSamples, bool injectIndirectEvents)
Definition juce_MidiKeyboardState.cpp:135
juce::MidiKeyboardState::addListener
void addListener(Listener *listener)
Definition juce_MidiKeyboardState.cpp:161
juce::MidiKeyboardState::noteOff
void noteOff(int midiChannel, int midiNoteNumber, float velocity)
Definition juce_MidiKeyboardState.cpp:79
juce::MidiKeyboardState::allNotesOff
void allNotesOff(int midiChannel)
Definition juce_MidiKeyboardState.cpp:102
juce::MidiKeyboardState::processNextMidiEvent
void processNextMidiEvent(const MidiMessage &message)
Definition juce_MidiKeyboardState.cpp:118
juce::MidiKeyboardState::removeListener
void removeListener(Listener *listener)
Definition juce_MidiKeyboardState.cpp:167
juce::MidiKeyboardState::isNoteOn
bool isNoteOn(int midiChannel, int midiNoteNumber) const noexcept
Definition juce_MidiKeyboardState.cpp:39
juce::MidiKeyboardState::noteOn
void noteOn(int midiChannel, int midiNoteNumber, float velocity)
Definition juce_MidiKeyboardState.cpp:53
juce::MidiKeyboardState::reset
void reset()
Definition juce_MidiKeyboardState.cpp:32
juce::MidiKeyboardState::isNoteOnForChannels
bool isNoteOnForChannels(int midiChannelMask, int midiNoteNumber) const noexcept
Definition juce_MidiKeyboardState.cpp:47
juce::MidiMessage
Definition juce_MidiMessage.h:35
juce::MidiMessage::isNoteOn
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Definition juce_MidiMessage.cpp:410
juce::MidiMessage::getFloatVelocity
float getFloatVelocity() const noexcept
Definition juce_MidiMessage.cpp:451
juce::MidiMessage::getChannel
int getChannel() const noexcept
Definition juce_MidiMessage.cpp:379
juce::MidiMessage::isNoteOff
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Definition juce_MidiMessage.cpp:418
juce::MidiMessage::noteOn
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Definition juce_MidiMessage.cpp:604
juce::MidiMessage::getNoteNumber
int getNoteNumber() const noexcept
Definition juce_MidiMessage.cpp:432
juce::MidiMessage::isAllNotesOff
bool isAllNotesOff() const noexcept
Definition juce_MidiMessage.cpp:636
juce::MidiMessage::noteOff
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Definition juce_MidiMessage.cpp:618
juce::Time::getMillisecondCounter
static uint32 getMillisecondCounter() noexcept
Definition juce_Time.cpp:241