30 int trimIndex,
int channel)
32 jassert (trimIndex < data.getNumEvents());
34 const int lastNoteOnIndex = searchBackForNoteOn (data, trimIndex, channel);
36 if (! wasFound (lastNoteOnIndex))
39 const auto& noteOn = data.getEventPointer (lastNoteOnIndex)->message;
40 const auto initial = searchBackForExpression (data, lastNoteOnIndex, channel, MessageToStopAt::noteOff);
41 const auto mostRecent = searchBackForExpression (data, trimIndex, channel, MessageToStopAt::noteOn);
50 if (wasFound (mostRecent.timbre))
53 if (wasFound (mostRecent.pressure))
56 if (wasFound (mostRecent.pitchBend))
65 const choc::midi::Sequence& data,
66 size_t trimIndex,
int channel1to16)
68 jassert (trimIndex < data.events.size());
70 const int lastNoteOnIndex = searchBackForNoteOn (data, (
int) trimIndex, (
uint8_t) channel1to16);
72 if (! wasFound (lastNoteOnIndex))
75 const auto& noteOn = data.events[(
size_t) lastNoteOnIndex].message;
76 const auto initial = searchBackForExpression (data, lastNoteOnIndex, (
uint8_t) channel1to16, MessageToStopAt::noteOff);
77 const auto mostRecent = searchBackForExpression (data, (
int) trimIndex, (
uint8_t) channel1to16, MessageToStopAt::noteOn);
86 if (wasFound (mostRecent.timbre))
89 if (wasFound (mostRecent.pressure))
92 if (wasFound (mostRecent.pitchBend))
99 while (--startIndex >= 0)
101 const auto& m = data.getEventPointer (startIndex)->message;
103 if (m.getChannel() == channel)
105 if (m.isNoteOn (
true))
108 if (m.isNoteOff (
true))
116 static int searchBackForNoteOn (
const choc::midi::Sequence& data,
int startIndex, uint8_t channel1to16)
118 while (--startIndex >= 0)
120 const auto& e =
data.events[(
size_t) startIndex];
122 const auto& m = e.message;
124 if (! m.isShortMessage())
127 if (m.getChannel1to16() == channel1to16)
140 struct ExpressionData
154 int startIndex,
int channel, MessageToStopAt stopAt)
156 int timbre = notFound;
157 int pressure = notFound;
158 int pitchBend = notFound;
160 for (
int i = startIndex; --i >= 0;)
162 const auto& m =
data.getEventPointer (i)->message;
164 if (m.getChannel() != channel)
167 if ((stopAt == noteOn ? m.isNoteOn (
true) : m.isNoteOff (true))
168 || (wasFound (timbre) && wasFound (pressure) && wasFound (pitchBend)))
171 if (m.isController() && m.getControllerNumber() == 74 && ! wasFound (timbre))
172 timbre = m.getControllerValue();
174 else if (m.isChannelPressure() && ! wasFound (pressure))
175 pressure = m.getChannelPressureValue();
177 else if (m.isPitchWheel() && ! wasFound (pitchBend))
178 pitchBend = m.getPitchWheelValue();
181 return { timbre, pressure, pitchBend };
184 static ExpressionData searchBackForExpression (
const choc::midi::Sequence& data,
185 int startIndex, uint8_t channel, MessageToStopAt stopAt)
187 int timbre = notFound;
188 int pressure = notFound;
189 int pitchBend = notFound;
191 for (
int i = startIndex; --i >= 0;)
193 const auto& m =
data.events[(
size_t) startIndex].message;
195 if (! m.isShortMessage())
198 if (m.getChannel1to16() != channel)
201 if ((stopAt == noteOn ? m.isNoteOn() : m.isNoteOff())
202 || (wasFound (timbre) && wasFound (pressure) && wasFound (pitchBend)))
205 if (m.isController() && m.getControllerNumber() == 74 && ! wasFound (timbre))
206 timbre = m.getControllerValue();
207 else if (m.isChannelPressure() && ! wasFound (pressure))
208 pressure = m.getChannelPressureValue();
209 else if (m.isPitchWheel() && ! wasFound (pitchBend))
210 pitchBend = (
int) m.getPitchWheelValue();
213 return { timbre, pressure, pitchBend };
216 static constexpr int notFound = -1;
217 static bool wasFound (
int v) {
return v != notFound; }
static void reconstructExpression(juce::Array< juce::MidiMessage > &mpeMessagesToAddAtStart, const choc::midi::Sequence &data, size_t trimIndex, int channel1to16)
Reconstruct note expression for a particular channel.
static void reconstructExpression(juce::Array< juce::MidiMessage > &mpeMessagesToAddAtStart, const juce::MidiMessageSequence &data, int trimIndex, int channel)
Reconstruct note expression for a particular channel.