3 #include <Engine/Node/SimpleApi.hpp>
14 static const constexpr
auto prettyName =
"Chord";
15 static const constexpr
auto objectKey =
"Chord";
16 static const constexpr
auto category =
"Midi";
17 static const constexpr
auto author =
"ossia score";
18 static const constexpr
auto tags = std::array<const char*, 0>{};
19 static const constexpr
auto kind = Process::ProcessCategory::Mapping;
20 static const constexpr
auto description =
"Generate a chord from a single note";
21 static const uuid_constexpr
auto uuid
22 = make_uuid(
"F0904279-EA26-48DB-B0DF-F68FE3091DA1");
24 static const constexpr midi_in midi_ins[]{
"in"};
25 static const constexpr midi_out midi_outs[]{
"out"};
26 static const constexpr
auto controls = tuplet::make_tuple(
29 "Chord", 0U, ossia::make_array(
"Maj",
"Min",
"Sus2",
"Sus4",
"Dim",
"Aug")));
39 ossia::flat_map<uint8_t, std::vector<chord>> chords;
53 using control_policy = ossia::safe_nodes::default_tick_controls;
56 static const constexpr std::array<int, 5> major7{0, 4, 7, 11, 12};
57 static const constexpr std::array<int, 5> minor7{0, 3, 7, 10, 12};
58 static const constexpr std::array<int, 5> sus2{0, 2, 7, 9, 12};
59 static const constexpr std::array<int, 5> sus4{0, 5, 7, 9, 12};
60 static const constexpr std::array<int, 5> dim{0, 3, 6, 9, 12};
61 static const constexpr std::array<int, 5> aug{0, 4, 8, 10, 12};
64 static void startChord(
65 const T& chord,
const libremidi::message& m,
const std::size_t num,
68 for(std::size_t i = 0; i < std::min(num, chord.size()); i++)
70 auto new_note = m.bytes[1] + chord[i];
75 = libremidi::channel_events::note_on(m.get_channel(), new_note, m.bytes[2]);
76 non.timestamp = m.timestamp;
77 op.messages.push_back(non);
82 static void stopChord(
83 const T& chord,
const libremidi::message& m,
const std::size_t num,
86 for(std::size_t i = 0; i < std::min(num, chord.size()); i++)
88 auto new_note = m.bytes[1] + chord[i];
93 = libremidi::channel_events::note_off(m.get_channel(), new_note, m.bytes[2]);
94 noff.timestamp = m.timestamp;
95 op.messages.push_back(noff);
100 static void dispatchChord(
101 std::string_view chord,
const libremidi::message& m,
int num, ossia::midi_port& op,
104 static const ossia::string_view_map<std::array<int, 5>> chords{
105 {
"Maj", major7}, {
"Min", minor7}, {
"Sus2", sus2},
106 {
"Sus4", sus4}, {
"Dim", dim}, {
"Aug", aug}};
107 auto it = chords.find(chord);
108 if(it != chords.end())
109 f(it->second, m, num, op);
112 run(
const ossia::midi_port& ip,
const ossia::timed_vec<int>& num,
113 const ossia::timed_vec<std::string>& chord, ossia::midi_port& op,
114 ossia::token_request tk, ossia::exec_state_facade st,
State&
self)
116 for(
const libremidi::message& m : ip.messages)
118 auto lastNum = num.rbegin()->second;
119 const auto& lastCh = chord.rbegin()->second;
121 if(m.get_message_type() == libremidi::message_type::NOTE_ON)
123 auto cur = m.bytes[1];
124 self.chords[cur].push_back({lastCh, lastNum});
126 lastCh, m, lastNum, op, [](
auto&&... args) { startChord(args...); });
128 else if(m.get_message_type() == libremidi::message_type::NOTE_OFF)
130 auto it =
self.chords.find(m.bytes[1]);
131 if(it !=
self.chords.end())
133 for(
const State::chord& chord : it->second)
135 dispatchChord(chord.ch, m, chord.notes, op, [](
auto&&... args) {
139 const_cast<std::vector<State::chord>&
>(it->second).clear();
145 op.messages.push_back(m);
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: score-lib-process/Control/Widgets.hpp:178