distance to closest node displayed, timing problems with midi notes being sent 1 to 3ms too early, or too late

This commit is contained in:
Sebastian
2024-10-28 02:07:47 +01:00
parent 58766cc373
commit 06cb6d8319
11 changed files with 68 additions and 70 deletions
+1
View File
@@ -38,6 +38,7 @@ class Vec2D{
T x = 0;
T y = 0;
T dist(Vec2D* v) { return sqrt(pow((v->x - x), 2) + pow((v->y - y), 2));};
T dist(Vec2D v) { return sqrt(pow((v.x - x), 2) + pow((v.y - y), 2));};
T length() { return (T)sqrt(pow(x, 2) + pow(y, 2));};
+2 -2
View File
@@ -66,8 +66,8 @@ int main(){
app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f);
app.settings.width = monitor_width;
app.settings.height = monitor_height;
app.settings.width = monitor_width - 300;
app.settings.height = monitor_height - 300;
SetTargetFPS(app.settings.fps);
+2 -2
View File
@@ -76,7 +76,7 @@ class Midi {
}
void note(int midi_out, int channel, int note, int velocity, int gate){
if(!midi_outs.empty()){
if(midi_outs.contains(midi_out)){
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);
@@ -88,7 +88,7 @@ class Midi {
float time = GetTime();
for(auto &n : notes){
if(time - n.start >= (float)n.gate / 1000.0f){
midi_outs[n.midi_out]->send_message(libremidi::channel_events::note_off(n.channel, n.note, n.velocity));
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));
n.erase = true;
}
}
+1
View File
@@ -18,6 +18,7 @@ class Movable{
Vec2D<float> direction;
virtual void update(int fps) {};
virtual void update(double frametime) {};
virtual void update() {};
virtual void draw(Vec2D<float> *mouse, Camera2D *cam) {};
+16
View File
@@ -1,6 +1,9 @@
#pragma once
#include "datatypes.h"
#include "node.h"
#include "raylib.h"
#include "raymath.h"
#include <algorithm>
#include <iterator>
#include <random>
@@ -57,7 +60,20 @@ class NodeManager{
}
void drawNodes(Vec2D<float> *mouse_pos, Camera2D *camera){
auto flat_nodes = nodes | std::ranges::views::values | std::ranges::to<std::vector<Node>>();
for(auto& n : nodes | std::ranges::views::values ){
if(n.dragging){
std::sort(flat_nodes.begin(), flat_nodes.end(), [n](Node na, Node nb){ return na.position.dist(n.position) < nb.position.dist(n.position);});
float d = flat_nodes.at(1).position.dist(n.position);
if(d > 0 && d < 240) {
Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f);
Vec2D<float> middle_handle = flat_nodes.at(1).position + (n.position - flat_nodes.at(1).position) * ((d - text_length.x)*0.5f)/d;
Vec2D<float> text_position = middle_handle + (flat_nodes.at(1).position - n.position).norm().orth() * 12.0f;
float rotation = Vector2Angle((Vector2){1,0}, (n.position - flat_nodes.at(1).position)) * RAD2DEG;
DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
DrawLineV(n.position, flat_nodes.at(1).position, VS_COLOR_PINK);
}
}
n.draw(mouse_pos, camera);
}
}
+10 -6
View File
@@ -71,22 +71,24 @@ class SignalManager{
}
void updateSignals(){
auto last = std::chrono::steady_clock::now();
auto last = std::chrono::high_resolution_clock::now();
while(loop){
std::chrono::duration<double, std::micro> diff = std::chrono::steady_clock::now() - last;
if(diff.count() > 500){
std::chrono::duration<double, std::micro> diff = std::chrono::high_resolution_clock::now() - last;
if((int)diff.count() >= 250){
mutex->lock();
if(play){
for(auto& s : signals){
s.direction = (nm->nodes[s.next].position - s.position).norm();
s.update(diff.count());
if(s.position.dist(&nm->nodes[s.next].position) < 1.0f) {
if(s.position.dist(&nm->nodes[s.next].position) < 0.6f) {
int n = cm->next(s.next, s.last);
nm->nodes[s.next].trigger();
if(n != s.next && n != -1) {
for(auto &m : nm->nodes[s.next].midi_outs){
if(m.second.enabled) midi.note(m.second.i, nm->nodes[s.next].midi_channel, nm->nodes[s.next].midi_note, nm->nodes[s.next].midi_velocity, nm->nodes[s.next].midi_gate);
if(m.second.enabled) {
midi.note(m.second.i, nm->nodes[s.next].midi_channel, nm->nodes[s.next].midi_note, nm->nodes[s.next].midi_velocity, nm->nodes[s.next].midi_gate);
}
}
s.last = s.next;
s.next = n;
@@ -96,14 +98,16 @@ class SignalManager{
}
midi.update();
mutex->unlock();
last = std::chrono::steady_clock::now();
last = std::chrono::high_resolution_clock::now();
}
}
}
void drawSignals(Vec2D<float> *mouse_pos, Camera2D *camera){
for(auto& s : signals){
mutex->lock();
s.draw(mouse_pos, camera);
mutex->unlock();
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ class Signal : public Movable{
Color color;
void update(int t_delta){
void update(double t_delta){
// 120px / 16th = 1920px / whole note
// whole note = 2s at 120bpm
// 960px / s
+4 -2
View File
@@ -53,7 +53,9 @@ class AppState{
for(auto &n : copy_nodes_ids){
int old_id = n;
int new_id = nm.copyNode(n, position + nm.nodes[n].drag_offset);
nm.nodes[new_id].copied = false;
nm.nodes[new_id].selected = true;
for(auto &c : copy_connections){
if(c.v1 == old_id) c.v1 = new_id;
if(c.v2 == old_id) c.v2 = new_id;
@@ -121,10 +123,10 @@ class AppState{
void draw(Vec2D<float> *mouse_pos, Camera2D *camera){
mutex.lock();
updateMidiPorts();
mutex.unlock();
nm.drawNodes(mouse_pos, camera);
cm.drawConnections(mouse_pos, camera);
sm.drawSignals(mouse_pos, camera);
mutex.unlock();
}
void drawUI(Vec2D<float> *mouse_pos, Camera2D *camera){
+7 -6
View File
@@ -27,12 +27,13 @@ class AppUI{
void drawSideBar(){
GuiWindowBox((Rectangle){0,0,280,(float)settings->height}, "config");
GuiPanel((Rectangle){-1,-30,280,(float)settings->height + 31}, "");
{
const int s_controls = 55;
if(GuiButton((Rectangle){20, (float)s_controls, 60, 30}, "PLAY")) sm->play ? sm->pause() : sm->start();
if(GuiButton((Rectangle){100, (float)s_controls, 60, 30}, "STOP")) sm->stop();
if(GuiButton((Rectangle){180, (float)s_controls, 60, 30}, "RESET")) sm->reset();
const int s_controls = 20;
//GuiSetStyle(BUTTON, STATE_FOCUSED, 0xFF0000FF);
if(GuiButton((Rectangle){20, (float)s_controls, 80, 30}, "PLAY")) sm->play ? sm->pause() : sm->start();
if(GuiButton((Rectangle){120, (float)s_controls, 60, 30}, "STOP")) sm->stop();
if(GuiButton((Rectangle){200, (float)s_controls, 60, 30}, "RESET")) sm->reset();
const int s_bpm = s_controls + 35;
GuiLabel((Rectangle){20, (float)s_bpm, 120, 20}, "TIMING");
@@ -83,7 +84,7 @@ class AppUI{
if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){
nm->addNode(200.0f, 200.0f);
}
DrawText(std::format("{}", nm->nodes.size()).c_str(), 20, settings->height - 70, 15, VS_COLOR_WHITE);
DrawFPS(20, settings->height - 30);
}
}