2024-10-19 04:08:46 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "libremidi/libremidi.hpp"
|
|
|
|
|
#include "libremidi/message.hpp"
|
|
|
|
|
#include "libremidi/observer_configuration.hpp"
|
|
|
|
|
#include "raylib.h"
|
|
|
|
|
|
2024-10-28 19:24:18 +01:00
|
|
|
#include <iostream>
|
2024-10-19 17:41:31 +02:00
|
|
|
#include <map>
|
2024-10-19 04:08:46 +02:00
|
|
|
#include <memory>
|
2024-10-20 01:17:18 +02:00
|
|
|
#include "datatypes.h"
|
2024-10-19 04:08:46 +02:00
|
|
|
|
|
|
|
|
struct NoteTimer{
|
|
|
|
|
int midi_out;
|
|
|
|
|
int channel;
|
|
|
|
|
int note;
|
|
|
|
|
int velocity;
|
2024-10-19 17:41:31 +02:00
|
|
|
float start;
|
|
|
|
|
int gate;
|
|
|
|
|
bool erase = false;
|
2024-10-19 04:08:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Midi {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Midi() {
|
2024-10-28 19:24:18 +01:00
|
|
|
enumerate();
|
2024-10-19 04:08:46 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-20 02:01:30 +02:00
|
|
|
std::vector<std::string> 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"
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-19 04:08:46 +02:00
|
|
|
libremidi::observer obs;
|
|
|
|
|
|
2024-10-19 17:41:31 +02:00
|
|
|
std::map<int, std::shared_ptr<libremidi::midi_out>> midi_outs;
|
2024-10-19 04:08:46 +02:00
|
|
|
std::vector<libremidi::input_port> midi_in_ports;
|
2024-10-19 17:41:31 +02:00
|
|
|
std::vector<MidiOutPort> midi_out_ports;
|
2024-10-19 04:08:46 +02:00
|
|
|
|
|
|
|
|
std::vector<NoteTimer> notes;
|
|
|
|
|
|
|
|
|
|
float timer;
|
2024-10-19 17:41:31 +02:00
|
|
|
|
2024-10-28 19:24:18 +01:00
|
|
|
void enumerate(){
|
|
|
|
|
std::cout << (int)obs.get_current_api() << std::endl;
|
|
|
|
|
int i = 0;
|
|
|
|
|
for(const libremidi::output_port& port : obs.get_output_ports()){
|
|
|
|
|
midi_out_ports.push_back({port, i, false});
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-19 17:41:31 +02:00
|
|
|
void open_midi_out(MidiOutPort *out_port){
|
|
|
|
|
if(!midi_outs.contains(out_port->number)){
|
|
|
|
|
auto out = std::make_shared<libremidi::midi_out>();
|
|
|
|
|
out->open_port(out_port->port);
|
|
|
|
|
midi_outs[out_port->number] = out;
|
|
|
|
|
}
|
2024-10-19 04:08:46 +02:00
|
|
|
}
|
2024-10-20 23:42:38 +02:00
|
|
|
|
|
|
|
|
void close_midi_out(MidiOutPort *out_port){
|
|
|
|
|
if(midi_outs.contains(out_port->number)){
|
|
|
|
|
midi_outs[out_port->number]->close_port();
|
|
|
|
|
midi_outs.erase(out_port->number);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-19 04:08:46 +02:00
|
|
|
|
2024-10-19 17:41:31 +02:00
|
|
|
void note(int midi_out, int channel, int note, int velocity, int gate){
|
2024-10-28 02:07:47 +01:00
|
|
|
if(midi_outs.contains(midi_out)){
|
2024-10-20 01:17:18 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2024-10-19 17:41:31 +02:00
|
|
|
}
|
2024-10-19 04:08:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void update(){
|
|
|
|
|
float time = GetTime();
|
2024-10-27 00:40:57 +02:00
|
|
|
for(auto &n : notes){
|
|
|
|
|
if(time - n.start >= (float)n.gate / 1000.0f){
|
2024-10-28 02:07:47 +01:00
|
|
|
if(midi_outs.contains(n.midi_out) && midi_outs[n.midi_out]->is_port_open()) midi_outs[n.midi_out]->send_message(libremidi::channel_events::note_off(n.channel, n.note, n.velocity));
|
2024-10-27 00:40:57 +02:00
|
|
|
n.erase = true;
|
2024-10-19 17:41:31 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
std::erase_if(notes, [](const auto& item){return item.erase;});
|
2024-10-27 00:40:57 +02:00
|
|
|
|
2024-10-19 17:41:31 +02:00
|
|
|
for(auto& p : midi_out_ports){
|
|
|
|
|
if(p.enabled) {
|
|
|
|
|
open_midi_out(&p);
|
2024-10-20 23:42:38 +02:00
|
|
|
} else if(!p.enabled) {
|
|
|
|
|
close_midi_out(&p);
|
2024-10-19 04:08:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|