Skip to content

Commit

Permalink
initialize data structures for pitchbend and CC support in MidiDrop, …
Browse files Browse the repository at this point in the history
…nothing is handled in the UI yet, but it parses the MidiTrackEvent objects.
  • Loading branch information
smoothdeveloper committed May 10, 2022
1 parent 64bded7 commit b4d9700
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/plugins/score-plugin-midi/Midi/Commands/AddNote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void AddNotes::deserializeImpl(DataStreamOutput& s)

ReplaceNotes::ReplaceNotes(
const ProcessModel& model,
const std::vector<NoteData>& n,
const MidiTrackNotes& n,
int min,
int max,
TimeVal d)
Expand Down
4 changes: 3 additions & 1 deletion src/plugins/score-plugin-midi/Midi/Commands/AddNote.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <Midi/Commands/CommandFactory.hpp>
#include <Midi/MidiNote.hpp>
#include "Midi/MidiDrop.hpp"
#include <Process/TimeValue.hpp>

#include <score/model/path/Path.hpp>
Expand Down Expand Up @@ -52,7 +54,7 @@ class SCORE_PLUGIN_MIDI_EXPORT ReplaceNotes final : public score::Command
public:
ReplaceNotes(
const ProcessModel& model,
const std::vector<NoteData>& note,
const MidiTrackNotes& note,
int min,
int max,
TimeVal dur);
Expand Down
16 changes: 10 additions & 6 deletions src/plugins/score-plugin-midi/Midi/MidiDrop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,8 @@ void DropHandler::dropData(
const double ratio = song_t / actualDuration.msec();
if (ratio != 1.)
{
for (auto& note : track.notes)
{
note.setStart(ratio * note.start());
note.setDuration(ratio * note.duration());
}
track.trackEvents.apply_scale_ratio(ratio);
track.notes.apply_scale_ratio(ratio);
}
disp.submit(new Midi::ReplaceNotes{
midi, track.notes, track.min, track.max, actualDuration});
Expand Down Expand Up @@ -389,6 +386,13 @@ void parseEvent(const libremidi::track_event& ev, MidiTrack& nv, midi_note_map&
nv.notes.push_back(note);
}
notes.erase(ev.m.bytes[1]);

break;
}
case libremidi::message_type::CONTROL_CHANGE:
{
const auto& cc = ControllerData::make_cc(ev.m.get_channel() - 1, ev.m.bytes[1], ev.m.bytes[2]);
nv.trackEvents.push_back(delta, tick, total, cc);
break;
}
default:
Expand Down Expand Up @@ -487,7 +491,7 @@ MidiTrack::parse(const QByteArray& dat, const score::DocumentContext& ctx)
tick += ev.tick;
parseEvent(ev, nv, notes, delta, tick, total);
}
if (nv.notes.size() > 0)
if (nv.notes.size() > 0 || nv.trackEvents.size() > 0)
m.tracks.push_back(std::move(nv));
}
break;
Expand Down
92 changes: 91 additions & 1 deletion src/plugins/score-plugin-midi/Midi/MidiDrop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,101 @@ class DropHandler final : public Process::ProcessDropHandler
const score::DocumentContext& ctx) const noexcept override;
};

struct PitchbendData{
int16_t bend;
};
struct ControllerData {
midi_size_t channel;
midi_size_t number;
midi_size_t value;
static ControllerData make_cc(const midi_size_t channel, const midi_size_t controller, const midi_size_t value)
{
SCORE_ASSERT(channel >= 0 && channel < 16);
return ControllerData{channel, controller, value};
}
};

struct NoteOnData {
midi_size_t channel;
midi_size_t note;
midi_size_t velocity;
};
struct NoteOffData {
midi_size_t channel;
midi_size_t note;
midi_size_t velocity;
};
struct MidiTrackEvent {
static MidiTrackEvent make_note_off(const double start, const midi_size_t ch, const midi_size_t n, const midi_size_t v){
return MidiTrackEvent{m_start: start, m_message: Midi::NoteOffData{channel: ch, note: n, velocity: v}};
}
static MidiTrackEvent make_note_on(const double start, const midi_size_t ch, const midi_size_t n, const midi_size_t v){
return MidiTrackEvent{m_start: start, m_message: Midi::NoteOnData{channel: ch, note: n, velocity: v}};
}
double m_start{};

void setStart(const double start){ m_start = start; }
const double start(){return m_start; }
std::variant<Midi::NoteOnData, Midi::NoteOffData, Midi::ControllerData,Midi::PitchbendData> m_message;
};

struct MidiTrackEvents {
void push_back(double delta, int tick, double total, Midi::ControllerData c){
const double start = delta * (tick / total);
trackEvents.push_back(MidiTrackEvent{m_start:start, m_message: c});
}

void push_back(double delta, int tick, double total, Midi::NoteOnData n){
const double start = delta * (tick / total);
trackEvents.push_back(MidiTrackEvent{m_start:start, m_message: n});
}

void push_back(double delta, int tick, double total, Midi::NoteOffData n){
const double start = delta * (tick / total);
trackEvents.push_back(MidiTrackEvent{m_start:start, m_message: n});
}

void apply_scale_ratio(const double ratio){
for (auto& event : trackEvents)
{
event.setStart(ratio * event.start());
}
}
auto size() const { return trackEvents.size(); }
std::vector<Midi::MidiTrackEvent> trackEvents;
};

struct MidiTrackNotes {
std::vector<Midi::NoteData> notes;
void push_back(Midi::NoteData note){
notes.push_back(note);
}

auto begin() { return notes.begin(); }
auto end() { return notes.end(); }
auto cbegin() const { return notes.begin(); }
auto cend() const { return notes.end(); }
auto begin() const { return notes.begin(); }
auto end() const { return notes.end(); }

auto size() const { return notes.size(); }
auto empty() const { return notes.empty(); }
void apply_scale_ratio(const double ratio){
for (auto& note : notes)
{
note.setStart(ratio * note.start());
note.setDuration(ratio * note.duration());
}
}
};


struct MidiTrack
{
QString name;

std::vector<Midi::NoteData> notes;
MidiTrackNotes notes;
MidiTrackEvents trackEvents;
int min{127}, max{0};

struct MidiSong
Expand Down
7 changes: 2 additions & 5 deletions src/plugins/score-plugin-midi/Midi/MidiPresenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,8 @@ void Presenter::on_drop(const QPointF& pos, const QMimeData& md)
// Scale notes so that the durations are relative to the ratio of the song
// duration & constraint duration
const double ratio = song.durationInMs / model().duration().msec();
for (auto& note : track.notes)
{
note.setStart(ratio * note.start());
note.setDuration(ratio * note.duration());
}
track.notes.apply_scale_ratio(ratio);
track.trackEvents.apply_scale_ratio(ratio);
disp.submit<Midi::ReplaceNotes>(
model(), track.notes, track.min, track.max, model().duration());
}
Expand Down

0 comments on commit b4d9700

Please sign in to comment.