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"
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
2024-10-19 17:41:31 +02:00
|
|
|
#include <map>
|
2024-10-19 04:08:46 +02:00
|
|
|
#include <memory>
|
|
|
|
|
#include <ostream>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
|
2024-10-19 17:41:31 +02:00
|
|
|
struct MidiOutPort{
|
|
|
|
|
libremidi::output_port port;
|
|
|
|
|
int number;
|
|
|
|
|
bool enabled;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct MidiOut{
|
|
|
|
|
libremidi::midi_out out;
|
|
|
|
|
|
|
|
|
|
};
|
2024-10-19 04:08:46 +02:00
|
|
|
|
|
|
|
|
class Midi {
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Midi() {
|
2024-10-19 17:41:31 +02:00
|
|
|
int i = 0;
|
2024-10-19 04:08:46 +02:00
|
|
|
for(const libremidi::output_port& port : obs.get_output_ports()){
|
2024-10-19 17:41:31 +02:00
|
|
|
midi_out_ports.push_back({port, i, false});
|
|
|
|
|
i++;
|
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
|
|
|
|
|
|
|
|
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-19 17:41:31 +02:00
|
|
|
void note(int midi_out, int channel, int note, int velocity, int gate){
|
|
|
|
|
if(!midi_outs.empty()){
|
|
|
|
|
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 04:08:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void update(){
|
|
|
|
|
float time = GetTime();
|
2024-10-19 17:41:31 +02:00
|
|
|
for(auto it = notes.begin(); it != notes.end(); ++it){
|
|
|
|
|
if(time - it->start >= (float)it->gate / 1000.0f){
|
2024-10-19 04:08:46 +02:00
|
|
|
midi_outs[it->midi_out]->send_message(libremidi::channel_events::note_off(it->channel, it->note, it->velocity));
|
2024-10-19 17:41:31 +02:00
|
|
|
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);
|
2024-10-19 04:08:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|