feat: add logging system and debug audio routing

Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-05 13:51:12 +00:00
parent 23fd894efe
commit d1b128f12c
4 changed files with 161 additions and 5 deletions

View File

@@ -1,5 +1,6 @@
#include "engine.h"
#include "carla.h"
#include "logging.h"
#define MAX_NFRAMES 8192
#include <stdio.h>
@@ -47,6 +48,8 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
uint8_t velocity = data[2];
if (status == 0x90 && channel == 0 && velocity > 0) {
LOG_DEBUG("MIDI Note On: note=%d velocity=%d channel=%d", note, velocity, channel);
// Trigger audio clip
Action action = {
.type = ACTION_MIDI_NOTE_ON,
@@ -63,12 +66,8 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
};
engine->dispatch(midi_action);
// Record MIDI event into MIDI clip if recording
// Note: we modify the local copy, not the actual state.
// The actual recording should be done via an action.
// For now, we just dispatch the trigger and let the reducer handle it.
ClipState note_state = (ClipState)atomic_load(&state->clips[note % MAX_CLIPS].state);
LOG_DEBUG("Clip %d state after dispatch: %d", note % MAX_CLIPS, note_state);
uint8_t out_velocity = clip_state_to_velocity(note_state);
uint8_t out_msg[3] = {0x90 | channel, note, out_velocity};
jack_midi_event_write(midi_out_buf, midi_event.time, out_msg, 3);
@@ -88,6 +87,7 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
uint8_t velocity = data[2];
if (status == 0x90 && velocity > 0) {
LOG_DEBUG("MIDI Scene Launch: note=%d", note);
Action action = {
.type = ACTION_MIDI_SCENE_LAUNCH,
.data.midi_scene_launch = { .scene_index = note % MAX_SCENES, .time = midi_event.time }
@@ -137,10 +137,19 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
continue;
}
// Track if any clip is active on this channel
bool any_recording = false;
bool any_looping = false;
for (jack_nframes_t i = 0; i < nframes; i++) {
// Start with live audio input
rack_in[i] = audio_in[ch][i];
// Check if input has signal
if (i == 0 && fabsf(audio_in[ch][i]) > 0.001f) {
LOG_TRACE("Channel %d has audio input at sample %d: %f", ch, i, audio_in[ch][i]);
}
for (int s = 0; s < MAX_SCENES; s++) {
// Iterate over all grids for this scene and channel
for (int g = 0; g < 8; g++) {
@@ -149,6 +158,7 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
ClipState clip_state = (ClipState)atomic_load(&clip->state);
if (clip_state == CLIP_RECORDING) {
any_recording = true;
// Write to lock-free ring buffer instead of clip buffer directly
size_t wp = atomic_load(&state->record_write_pos[ch]);
state->record_buffer[ch][wp % MAX_BUFFER_SIZE] = audio_in[ch][i];
@@ -156,6 +166,7 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
}
if (clip_state == CLIP_LOOPING && clip->buffer_size > 0 && clip->buffer != NULL) {
any_looping = true;
size_t rp = atomic_load(&clip->read_position);
rack_in[i] += clip->buffer[rp];
atomic_store(&clip->read_position, (rp + 1) % clip->buffer_size);
@@ -164,6 +175,13 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
}
}
// Log channel state once per callback
static int log_counter = 0;
if (log_counter++ % 100 == 0) {
LOG_DEBUG("Channel %d: nframes=%d any_recording=%d any_looping=%d rack_in[0]=%f",
ch, nframes, any_recording, any_looping, rack_in[0]);
}
// Process through Carla rack
carla_process(&engine->carla_host, ch, rack_in, rack_out, nframes);