Files
looper/src/midi.c
Loic Coenen 5a2414b4c3 feat: add WAV load/save and ring buffer implementation
Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
2026-05-11 21:15:12 +00:00

120 lines
3.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// cppcheck-suppress missingIncludeSystem
#include "midi.h"
#include "channel.h"
#include <jack/jack.h>
#include <jack/midiport.h>
#include <stdatomic.h>
extern atomic_int control_key_active;
extern atomic_int cmd_add;
extern atomic_int cmd_remove;
extern atomic_int cmd_load;
extern atomic_int cmd_save;
extern atomic_int bind_channel;
void midi_handle_events(void *port_buffer, jack_nframes_t nframes) {
(void)nframes;
jack_nframes_t nevents = jack_midi_get_event_count(port_buffer);
jack_midi_event_t ev;
for (jack_nframes_t i = 0; i < nevents; i++) {
if (jack_midi_event_get(&ev, port_buffer, i) != 0)
continue;
if (ev.size < 3)
continue;
unsigned char status = ev.buffer[0];
unsigned char note = ev.buffer[1];
unsigned char vel = ev.buffer[2];
/* noteon */
if ((status & 0xf0) == 0x90 && vel > 0) {
if (note == 64) {
atomic_store(&control_key_active, 1);
} else {
int ck = atomic_load(&control_key_active);
if (ck) {
atomic_store(&control_key_active, 0);
if (note < 16) {
atomic_store(&bind_channel, note);
} else {
switch (note) {
case 60:
atomic_store(&cmd_add, 1);
break;
case 61:
atomic_store(&cmd_remove, 1);
break;
case 62: /* trigger looper channel via bind_channel */
{
int bch = atomic_load(&bind_channel);
if (bch >= 0 && bch < MAX_CHANNELS) {
int cur = atomic_load(&channels[bch].state);
switch (cur) {
case STATE_IDLE:
atomic_store(&channels[bch].state, STATE_RECORD);
break;
case STATE_RECORD:
atomic_store(&channels[bch].state, STATE_LOOPING);
break;
case STATE_LOOPING:
atomic_store(&channels[bch].state, STATE_PAUSED);
break;
case STATE_PAUSED:
atomic_store(&channels[bch].state, STATE_LOOPING);
break;
}
}
} break;
case 63: /* unbind reset bind to channel 0 */
atomic_store(&bind_channel, 0);
break;
case 70: /* load WAV into channel 0 */
atomic_store(&cmd_load, 1);
break;
case 71: /* save WAV of channel 0 */
atomic_store(&cmd_save, 1);
break;
default:
break;
}
}
} else {
/* direct mapping */
switch (note) {
case 1: /* toggle channel 0 */
{
int cur0 = atomic_load(&channels[0].state);
switch (cur0) {
case STATE_IDLE:
atomic_store(&channels[0].state, STATE_RECORD);
break;
case STATE_RECORD:
atomic_store(&channels[0].state, STATE_LOOPING);
break;
case STATE_LOOPING:
atomic_store(&channels[0].state, STATE_PAUSED);
break;
case STATE_PAUSED:
atomic_store(&channels[0].state, STATE_LOOPING);
break;
}
} break;
case 60:
atomic_store(&cmd_add, 1);
break;
case 61:
atomic_store(&cmd_remove, 1);
break;
default:
break;
}
}
}
} else if ((status & 0xf0) == 0x80 ||
((status & 0xf0) == 0x90 && vel == 0)) {
atomic_store(&control_key_active, 0);
}
}
}