Skip to content

Commit 10848bf

Browse files
authored
Merge pull request #37 from Cycling74/develop
Develop to main
2 parents 83e476f + de4f557 commit 10848bf

File tree

8 files changed

+946
-194
lines changed

8 files changed

+946
-194
lines changed

Source/RNBOMetasound/Private/RNBOMIDI.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ void FMIDIPacket::Advance(int32 InNumFrames)
8181
mFrame -= InNumFrames;
8282
}
8383

84+
bool FMIDIPacket::IsNoteOff(uint8_t chan, uint8_t num) const
85+
{
86+
return mLength == 3 && mData[0] == (chan | 0x80) && mData[1] == num;
87+
}
88+
89+
bool FMIDIPacket::IsNoteOn(uint8_t chan, uint8_t num) const
90+
{
91+
return mLength == 3 && mData[0] == (chan | 0x90) && mData[1] == num;
92+
}
93+
94+
FMIDIPacket FMIDIPacket::CloneTo(int32 frame) const
95+
{
96+
FMIDIPacket r = *this;
97+
r.mFrame = frame;
98+
return r;
99+
}
100+
84101
FMIDIBuffer::FMIDIBuffer(const Metasound::FOperatorSettings& InSettings)
85102
: NumFramesPerBlock(InSettings.GetNumFramesPerBlock())
86103
{
@@ -142,6 +159,70 @@ void FMIDIBuffer::Push(FMIDIPacket packet)
142159
}
143160
}
144161

162+
void FMIDIBuffer::PushNote(int32 start, int32 dur, uint8_t chan, uint8_t note, uint8_t onvel, uint8_t offvel)
163+
{
164+
/* situations where we have to move an OFF
165+
* 1. Our new note happens inside another scheduled duration
166+
* * off after our off without an on after our off, move old off right before our new on
167+
* 2. Our new note spans the off of another note
168+
* * off between our on and our off, move old off to right before our new on
169+
* 3. Our new note spans the an entire note
170+
* * on and off come between our new on and off, move old off right before our new on
171+
*
172+
*/
173+
const auto count = Packets.Num();
174+
const auto end = start + dur;
175+
for (auto i = 0; i < count; i++) {
176+
auto& p = Packets[i];
177+
const auto f = p.Frame();
178+
if (f < start) {
179+
continue;
180+
}
181+
// in range
182+
if (p.IsNoteOn(chan, note)) {
183+
// existing note starts before our note ends, we need to shorten our note
184+
if (f < end) {
185+
// insert our Off before the existing On, updated time
186+
Packets.Insert(FMIDIPacket::NoteOff(f, note, offvel, chan), i);
187+
// adjust count
188+
if (f < NumFramesPerBlock) {
189+
CountInBlock++;
190+
}
191+
// push our on after so we don't screw up above index
192+
Push(FMIDIPacket::NoteOn(start, note, onvel, chan));
193+
return;
194+
}
195+
else {
196+
break;
197+
}
198+
}
199+
else if (p.IsNoteOff(chan, note) && f > start) {
200+
// should only hit this case if a note on isn't found either within the new note bounds or after it.
201+
// our new note either spans the off of an existing on note or is contained within an existing note
202+
// move the off just before our on
203+
auto off = p.CloneTo(start);
204+
Packets.RemoveAt(i);
205+
206+
// adjust count
207+
if (f < NumFramesPerBlock) {
208+
CountInBlock--; // will get incremented in the Push below
209+
}
210+
// adjust last frame
211+
if (Packets.Num() > 0) {
212+
LastFrame = Packets.Last(0).Frame();
213+
}
214+
else {
215+
LastFrame = -1;
216+
}
217+
Push(off); // XXX assumes there isn't another matching On at the exact time
218+
break;
219+
}
220+
}
221+
222+
Push(FMIDIPacket::NoteOn(start, note, onvel, chan));
223+
Push(FMIDIPacket::NoteOff(end, note, offvel, chan));
224+
}
225+
145226
void FMIDIBuffer::Reset()
146227
{
147228
Packets.Reset();

Source/RNBOMetasound/Private/RNBOMakeNote.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,11 @@ class FMakeNoteOperator : public TExecutableOperator<FMakeNoteOperator>
129129
const auto vel = static_cast<uint8_t>(std::clamp(*NoteVel, 1, 127));
130130
const auto offvel = static_cast<uint8_t>(std::clamp(*NoteOffVel, 0, 127));
131131
const auto chan = static_cast<uint8_t>(std::clamp(*NoteChan, 0, 15));
132-
const int32 frames = std::max(static_cast<int32>(ceil(SampleRate.GetSeconds() * NoteDur->GetSeconds())), 1);
132+
const int32 dur = std::max(static_cast<int32>(ceil(SampleRate.GetSeconds() * NoteDur->GetSeconds())), 1);
133133

134134
for (auto i = 0; i < num; i++) {
135135
auto start = (*Trigger)[i];
136-
auto end = start + frames;
137-
138-
MIDIOut->Push(FMIDIPacket::NoteOn(start, note, vel, chan));
139-
MIDIOut->Push(FMIDIPacket::NoteOff(end, note, offvel, chan));
136+
MIDIOut->PushNote(start, dur, chan, note, vel, offvel);
140137
}
141138
}
142139
}

0 commit comments

Comments
 (0)