refactor: replace atomic_double with fixed-point BPM and remove circular dependency
Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
25
engine.c
25
engine.c
@@ -157,8 +157,29 @@ static void shutdown_callback(void *arg) {
|
|||||||
|
|
||||||
// Get the next quantization boundary frame
|
// Get the next quantization boundary frame
|
||||||
static jack_nframes_t get_next_quantize_frame(Engine *engine, jack_nframes_t current_frame) {
|
static jack_nframes_t get_next_quantize_frame(Engine *engine, jack_nframes_t current_frame) {
|
||||||
if (!engine->transport) return current_frame;
|
if (!engine->transport || engine->transport->state != TRANSPORT_PLAYING ||
|
||||||
return transport_get_next_quantize_frame(engine->transport, current_frame, engine->quantize_mode);
|
engine->quantize_mode == QUANTIZE_OFF) {
|
||||||
|
return current_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate frames per beat
|
||||||
|
jack_nframes_t frames_per_beat = (jack_nframes_t)engine->transport->samples_per_beat;
|
||||||
|
jack_nframes_t frames_per_bar = frames_per_beat * BEATS_PER_BAR;
|
||||||
|
|
||||||
|
// Current position in frames
|
||||||
|
jack_nframes_t current_pos = engine->transport->sample_position + current_frame;
|
||||||
|
|
||||||
|
if (engine->quantize_mode == QUANTIZE_BEAT) {
|
||||||
|
// Next beat boundary
|
||||||
|
jack_nframes_t beat_frames = frames_per_beat;
|
||||||
|
jack_nframes_t next_beat = ((current_pos / beat_frames) + 1) * beat_frames;
|
||||||
|
return next_beat - engine->transport->sample_position;
|
||||||
|
} else { // QUANTIZE_BAR
|
||||||
|
// Next bar boundary
|
||||||
|
jack_nframes_t bar_frames = frames_per_bar;
|
||||||
|
jack_nframes_t next_bar = ((current_pos / bar_frames) + 1) * bar_frames;
|
||||||
|
return next_bar - engine->transport->sample_position;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Queue a trigger for quantization
|
// Queue a trigger for quantization
|
||||||
|
|||||||
32
transport.c
32
transport.c
@@ -22,7 +22,8 @@ void transport_init(Transport *transport, jack_nframes_t sample_rate) {
|
|||||||
atomic_store(&transport->bar_position_atomic, 0);
|
atomic_store(&transport->bar_position_atomic, 0);
|
||||||
atomic_store(&transport->sample_position_atomic, 0);
|
atomic_store(&transport->sample_position_atomic, 0);
|
||||||
atomic_store(&transport->clock_source_atomic, CLOCK_SOURCE_INTERNAL);
|
atomic_store(&transport->clock_source_atomic, CLOCK_SOURCE_INTERNAL);
|
||||||
atomic_store(&transport->bpm_atomic, DEFAULT_BPM);
|
transport->bpm_atomic = DEFAULT_BPM;
|
||||||
|
atomic_store(&transport->bpm_atomic_raw, (unsigned int)(DEFAULT_BPM * 100.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void transport_cleanup(Transport *transport) {
|
void transport_cleanup(Transport *transport) {
|
||||||
@@ -100,7 +101,8 @@ void transport_set_bpm(Transport *transport, double bpm) {
|
|||||||
|
|
||||||
transport->bpm = bpm;
|
transport->bpm = bpm;
|
||||||
transport->samples_per_beat = (transport->sample_rate * 60.0) / bpm;
|
transport->samples_per_beat = (transport->sample_rate * 60.0) / bpm;
|
||||||
atomic_store(&transport->bpm_atomic, bpm);
|
transport->bpm_atomic = bpm;
|
||||||
|
atomic_store(&transport->bpm_atomic_raw, (unsigned int)(bpm * 100.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
double transport_get_bpm(Transport *transport) {
|
double transport_get_bpm(Transport *transport) {
|
||||||
@@ -221,32 +223,6 @@ void transport_reset(Transport *transport) {
|
|||||||
atomic_store(&transport->sample_position_atomic, 0);
|
atomic_store(&transport->sample_position_atomic, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
jack_nframes_t transport_get_next_quantize_frame(Transport *transport,
|
|
||||||
jack_nframes_t current_frame,
|
|
||||||
QuantizeMode mode) {
|
|
||||||
if (!transport || transport->state != TRANSPORT_PLAYING || mode == QUANTIZE_OFF) {
|
|
||||||
return current_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate frames per beat
|
|
||||||
jack_nframes_t frames_per_beat = (jack_nframes_t)transport->samples_per_beat;
|
|
||||||
jack_nframes_t frames_per_bar = frames_per_beat * BEATS_PER_BAR;
|
|
||||||
|
|
||||||
// Current position in frames
|
|
||||||
jack_nframes_t current_pos = transport->sample_position + current_frame;
|
|
||||||
|
|
||||||
if (mode == QUANTIZE_BEAT) {
|
|
||||||
// Next beat boundary
|
|
||||||
jack_nframes_t beat_frames = frames_per_beat;
|
|
||||||
jack_nframes_t next_beat = ((current_pos / beat_frames) + 1) * beat_frames;
|
|
||||||
return next_beat - transport->sample_position;
|
|
||||||
} else { // QUANTIZE_BAR
|
|
||||||
// Next bar boundary
|
|
||||||
jack_nframes_t bar_frames = frames_per_bar;
|
|
||||||
jack_nframes_t next_bar = ((current_pos / bar_frames) + 1) * bar_frames;
|
|
||||||
return next_bar - transport->sample_position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* transport_state_to_string(TransportState state) {
|
const char* transport_state_to_string(TransportState state) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ typedef struct {
|
|||||||
atomic_uint bar_position_atomic;
|
atomic_uint bar_position_atomic;
|
||||||
atomic_uint sample_position_atomic;
|
atomic_uint sample_position_atomic;
|
||||||
atomic_int clock_source_atomic; // ClockSource
|
atomic_int clock_source_atomic; // ClockSource
|
||||||
atomic_double bpm_atomic;
|
double bpm_atomic; // Direct read for audio thread
|
||||||
|
atomic_uint bpm_atomic_raw; // Fixed-point (BPM * 100) for frontend reads
|
||||||
|
|
||||||
// JACK ports for MIDI clock output (when master)
|
// JACK ports for MIDI clock output (when master)
|
||||||
jack_port_t *midi_clock_out_port;
|
jack_port_t *midi_clock_out_port;
|
||||||
@@ -80,10 +81,6 @@ int transport_process(Transport *transport, jack_nframes_t nframes,
|
|||||||
// Reset position
|
// Reset position
|
||||||
void transport_reset(Transport *transport);
|
void transport_reset(Transport *transport);
|
||||||
|
|
||||||
// Get next quantization boundary (in frames from current position)
|
|
||||||
jack_nframes_t transport_get_next_quantize_frame(Transport *transport,
|
|
||||||
jack_nframes_t current_frame,
|
|
||||||
QuantizeMode mode);
|
|
||||||
|
|
||||||
// Utility
|
// Utility
|
||||||
const char* transport_state_to_string(TransportState state);
|
const char* transport_state_to_string(TransportState state);
|
||||||
|
|||||||
2
tui.c
2
tui.c
@@ -284,7 +284,7 @@ static void draw_grid(void) {
|
|||||||
"Transport: %s | Clock: %s | BPM: %.1f | Quantize: %s | Threshold: %u",
|
"Transport: %s | Clock: %s | BPM: %.1f | Quantize: %s | Threshold: %u",
|
||||||
transport_state_to_string(transport_state),
|
transport_state_to_string(transport_state),
|
||||||
clock_source_to_string(clock_source),
|
clock_source_to_string(clock_source),
|
||||||
atomic_load(&g_engine->transport->bpm_atomic),
|
(double)atomic_load(&g_engine->transport->bpm_atomic_raw) / 100.0,
|
||||||
quantize_mode_to_string((QuantizeMode)atomic_load(&g_engine->quantize_mode_atomic)),
|
quantize_mode_to_string((QuantizeMode)atomic_load(&g_engine->quantize_mode_atomic)),
|
||||||
(unsigned int)atomic_load(&g_engine->quantize_threshold_atomic));
|
(unsigned int)atomic_load(&g_engine->quantize_threshold_atomic));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user