feat: add transport.h header with transport state machine and MIDI clock support
Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
92
transport.h
Normal file
92
transport.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef TRANSPORT_H
|
||||
#define TRANSPORT_H
|
||||
|
||||
#include <jack/jack.h>
|
||||
#include <jack/midiport.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#define MIDI_CLOCKS_PER_BEAT 24
|
||||
#define BEATS_PER_BAR 4
|
||||
#define DEFAULT_BPM 120.0
|
||||
|
||||
typedef enum {
|
||||
TRANSPORT_STOPPED,
|
||||
TRANSPORT_PLAYING,
|
||||
TRANSPORT_PAUSED
|
||||
} TransportState;
|
||||
|
||||
typedef enum {
|
||||
CLOCK_SOURCE_INTERNAL, // Master clock
|
||||
CLOCK_SOURCE_MIDI // Slave to external MIDI clock
|
||||
} ClockSource;
|
||||
|
||||
typedef struct {
|
||||
// State
|
||||
TransportState state;
|
||||
ClockSource clock_source;
|
||||
|
||||
// Position
|
||||
uint32_t clock_count;
|
||||
uint32_t beat_position; // 0-3
|
||||
uint32_t bar_position;
|
||||
uint32_t sample_position; // derived from clock at current sample rate
|
||||
|
||||
// Internal clock generation
|
||||
double bpm;
|
||||
double samples_per_beat;
|
||||
double sample_accumulator; // For precise BPM timing
|
||||
|
||||
// Atomic mirrors for frontend reads
|
||||
atomic_int state_atomic; // TransportState
|
||||
atomic_uint clock_count_atomic;
|
||||
atomic_uint beat_position_atomic;
|
||||
atomic_uint bar_position_atomic;
|
||||
atomic_uint sample_position_atomic;
|
||||
atomic_int clock_source_atomic; // ClockSource
|
||||
atomic_double bpm_atomic;
|
||||
|
||||
// JACK ports for MIDI clock output (when master)
|
||||
jack_port_t *midi_clock_out_port;
|
||||
|
||||
// Reference to engine for sample rate
|
||||
jack_nframes_t sample_rate;
|
||||
} Transport;
|
||||
|
||||
// Lifecycle
|
||||
void transport_init(Transport *transport, jack_nframes_t sample_rate);
|
||||
void transport_cleanup(Transport *transport);
|
||||
|
||||
// Control
|
||||
void transport_play(Transport *transport);
|
||||
void transport_pause(Transport *transport);
|
||||
void transport_stop(Transport *transport);
|
||||
void transport_toggle_play(Transport *transport);
|
||||
|
||||
// Clock source
|
||||
void transport_set_clock_source(Transport *transport, ClockSource source);
|
||||
ClockSource transport_get_clock_source(Transport *transport);
|
||||
|
||||
// BPM (only relevant for internal clock)
|
||||
void transport_set_bpm(Transport *transport, double bpm);
|
||||
double transport_get_bpm(Transport *transport);
|
||||
|
||||
// Process function called from audio thread
|
||||
// Returns number of MIDI clock ticks generated (for master mode)
|
||||
int transport_process(Transport *transport, jack_nframes_t nframes,
|
||||
void *midi_clock_in_buf, void *midi_clock_out_buf);
|
||||
|
||||
// Reset position
|
||||
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
|
||||
const char* transport_state_to_string(TransportState state);
|
||||
const char* clock_source_to_string(ClockSource source);
|
||||
|
||||
#endif // TRANSPORT_H
|
||||
Reference in New Issue
Block a user