#pragma once #include "libremidi/libremidi.hpp" #include "libremidi/message.hpp" #include "libremidi/observer_configuration.hpp" #include "raylib.h" #include #include #include "datatypes.h" struct NoteTimer{ int midi_out; int channel; int note; int velocity; float start; int gate; bool erase = false; }; class Midi { public: Midi() { int i = 0; for(const libremidi::output_port& port : obs.get_output_ports()){ midi_out_ports.push_back({port, i, false}); i++; } } std::vector midiNotes = { "C-1", "C#-1", "D-1", "D#-1", "E-1", "F-1", "F#-1", "G-1", "G#-1", "A-1", "A#-1", "B-1", "C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0", "C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1", "C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2", "C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3", "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", "C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5", "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6", "C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7", "C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8", "G#8", "A8", "A#8", "B8", "C9", "C#9", "D9", "D#9", "E9", "F9", "F#9", "G9", "G#9", "A9", "A#9", "B9", "C10" }; libremidi::observer obs; std::map> midi_outs; std::vector midi_in_ports; std::vector midi_out_ports; std::vector notes; float timer; void open_midi_out(MidiOutPort *out_port){ if(!midi_outs.contains(out_port->number)){ auto out = std::make_shared(); out->open_port(out_port->port); midi_outs[out_port->number] = out; } } void note(int midi_out, int channel, int note, int velocity, int gate){ if(!midi_outs.empty()){ if(midi_outs[midi_out]->is_port_open()){ midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity)); notes.emplace_back(midi_out, channel, note, velocity, GetTime(), gate); } } } void update(){ float time = GetTime(); for(auto it = notes.begin(); it != notes.end(); ++it){ if(time - it->start >= (float)it->gate / 1000.0f){ midi_outs[it->midi_out]->send_message(libremidi::channel_events::note_off(it->channel, it->note, it->velocity)); it->erase = true; } } std::erase_if(notes, [](const auto& item){return item.erase;}); for(auto& p : midi_out_ports){ if(p.enabled) { open_midi_out(&p); } } } };