diff --git a/transport.h b/transport.h new file mode 100644 index 0000000..b0d6a7a --- /dev/null +++ b/transport.h @@ -0,0 +1,92 @@ +#ifndef TRANSPORT_H +#define TRANSPORT_H + +#include +#include +#include +#include +#include + +#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