13 using IntervalType = std::pair<int64_t, int64_t>;
17 event_sequences_.clear ();
18 merged_events_.clear ();
21 void remove_sequences_matching_interval (IntervalType interval)
23 const auto [target_start, target_end] = interval;
25 std::erase_if (event_sequences_, [&] (
const auto &entry) {
26 const auto &[existing_interval, seq] = entry;
27 const auto [existing_start, existing_end] = existing_interval;
29 return !(existing_end < target_start || existing_start > target_end);
34 add_sequence (IntervalType interval,
const juce::MidiMessageSequence &sequence)
36 const auto [start_time, end_time] = interval;
39 for (
const auto * event : sequence)
41 const double event_time =
event->message.getTimeStamp ();
43 event_time <
static_cast<double> (start_time)
44 || event_time >
static_cast<double> (end_time))
46 throw std::invalid_argument (
47 "MIDI sequence contains events outside the specified interval");
52 juce::MidiMessageSequence validated_sequence (sequence);
53 validated_sequence.updateMatchedPairs ();
56 for (
const auto * event : validated_sequence)
58 if (event->message.isNoteOn () && event->noteOffObject ==
nullptr)
61 validated_sequence.addEvent (
62 juce::MidiMessage::noteOff (
63 event->message.getChannel (), event->message.getNoteNumber ()),
64 static_cast<double> (end_time));
68 validated_sequence.updateMatchedPairs ();
69 event_sequences_[interval] = validated_sequence;
72 void finalize_changes ()
74 merged_events_.clear ();
75 for (
const auto &[interval, seq] : event_sequences_)
77 merged_events_.addSequence (seq, 0);
78 merged_events_.updateMatchedPairs ();
82 const auto &cached_events ()
const {
return merged_events_; }
88 std::map<IntervalType, juce::MidiMessageSequence> event_sequences_;
89 juce::MidiMessageSequence merged_events_;