feat: refactor transport into separate module with master/slave clock support

Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-01 21:08:38 +00:00
parent c2ad0e874c
commit a47598df8c
6 changed files with 490 additions and 229 deletions

View File

@@ -20,20 +20,13 @@ static Engine *create_test_engine(void) {
command_queue_init(&engine->command_queue);
// Initialize atomic state mirrors
atomic_store(&engine->transport_rolling, 0);
atomic_store(&engine->transport_clock_count, 0);
atomic_store(&engine->transport_beat_position, 0);
atomic_store(&engine->transport_bar_position, 0);
atomic_store(&engine->transport_sample_position, 0);
atomic_store(&engine->quantize_mode_atomic, (int)QUANTIZE_OFF);
atomic_store(&engine->quantize_threshold_atomic, 0);
// Initialize transport
engine->transport.rolling = false;
engine->transport.clock_count = 0;
engine->transport.beat_position = 0;
engine->transport.bar_position = 0;
engine->transport.sample_position = 0;
engine->transport = (Transport *)calloc(1, sizeof(Transport));
assert(engine->transport != NULL);
transport_init(engine->transport, 48000);
for (int i = 0; i < MAX_CLIPS; i++) {
engine->clips[i].state = CLIP_EMPTY;
@@ -57,6 +50,10 @@ static void destroy_test_engine(Engine *engine) {
qt = next;
}
if (engine->transport) {
transport_cleanup(engine->transport);
free(engine->transport);
}
for (int i = 0; i < MAX_CLIPS; i++) {
free(engine->clips[i].buffer);
}
@@ -309,7 +306,7 @@ void test_transport_initial_state(void) {
printf("Test 13: Transport initial state... ");
Engine *engine = create_test_engine();
assert(engine->transport.rolling == false);
assert(engine->transport->state == TRANSPORT_STOPPED);
assert(engine->transport.clock_count == 0);
assert(engine->transport.beat_position == 0);
assert(engine->transport.bar_position == 0);
@@ -325,16 +322,16 @@ void test_transport_reset(void) {
Engine *engine = create_test_engine();
// Simulate some transport state
engine->transport.rolling = true;
engine->transport.clock_count = 100;
engine->transport.beat_position = 2;
engine->transport.bar_position = 5;
engine->transport.sample_position = 10000;
engine->transport->state = TRANSPORT_PLAYING;
engine->transport->clock_count = 100;
engine->transport->beat_position = 2;
engine->transport->bar_position = 5;
engine->transport->sample_position = 10000;
engine_reset_transport(engine);
engine_process_commands(engine);
assert(engine->transport.rolling == false);
assert(engine->transport->state == TRANSPORT_STOPPED);
assert(engine->transport.clock_count == 0);
assert(engine->transport.beat_position == 0);
assert(engine->transport.bar_position == 0);
@@ -444,10 +441,10 @@ void test_midi_clock_start(void) {
engine->transport.sample_position = 5000;
// Process start message (simplified - just call the logic directly)
engine->transport.rolling = true;
engine->transport.clock_count = 0;
engine->transport.beat_position = 0;
engine->transport.bar_position = 0;
engine->transport->state = TRANSPORT_PLAYING;
engine->transport->clock_count = 0;
engine->transport->beat_position = 0;
engine->transport->bar_position = 0;
engine->transport.sample_position = 0;
assert(engine->transport.rolling == true);
@@ -465,14 +462,14 @@ void test_midi_clock_stop(void) {
printf("Test 20: MIDI clock stop message... ");
Engine *engine = create_test_engine();
engine->transport.rolling = true;
engine->transport.clock_count = 100;
engine->transport->state = TRANSPORT_PLAYING;
engine->transport->clock_count = 100;
// Process stop message
engine->transport.rolling = false;
engine->transport->state = TRANSPORT_STOPPED;
assert(engine->transport.rolling == false);
assert(engine->transport.clock_count == 100); // Keep position
assert(engine->transport->state == TRANSPORT_STOPPED);
assert(engine->transport->clock_count == 100); // Keep position
destroy_test_engine(engine);
printf("PASSED\n");
@@ -483,14 +480,14 @@ void test_midi_clock_continue(void) {
printf("Test 21: MIDI clock continue message... ");
Engine *engine = create_test_engine();
engine->transport.rolling = false;
engine->transport.clock_count = 100;
engine->transport->state = TRANSPORT_STOPPED;
engine->transport->clock_count = 100;
// Process continue message
engine->transport.rolling = true;
engine->transport->state = TRANSPORT_PLAYING;
assert(engine->transport.rolling == true);
assert(engine->transport.clock_count == 100); // Keep position
assert(engine->transport->state == TRANSPORT_PLAYING);
assert(engine->transport->clock_count == 100); // Keep position
destroy_test_engine(engine);
printf("PASSED\n");
@@ -574,9 +571,9 @@ void test_quantization_with_transport(void) {
printf("Test 24: Quantization with transport rolling... ");
Engine *engine = create_test_engine();
engine->sample_rate = 48000;
engine->transport.rolling = true;
engine->transport.clock_count = MIDI_CLOCKS_PER_BEAT * 2; // 2 beats in
engine->transport.sample_position = engine->sample_rate * 2; // 2 beats in samples
engine->transport->state = TRANSPORT_PLAYING;
engine->transport->clock_count = MIDI_CLOCKS_PER_BEAT * 2; // 2 beats in
engine->transport->sample_position = engine->sample_rate * 2; // 2 beats in samples
// Set quantize to beat
engine_set_quantize_mode(engine, QUANTIZE_BEAT);
@@ -608,9 +605,9 @@ void test_quantization_off_with_transport(void) {
printf("Test 25: Quantization off with transport rolling... ");
Engine *engine = create_test_engine();
engine->sample_rate = 48000;
engine->transport.rolling = true;
engine->transport.clock_count = MIDI_CLOCKS_PER_BEAT * 2;
engine->transport.sample_position = engine->sample_rate * 2;
engine->transport->state = TRANSPORT_PLAYING;
engine->transport->clock_count = MIDI_CLOCKS_PER_BEAT * 2;
engine->transport->sample_position = engine->sample_rate * 2;
engine_set_quantize_mode(engine, QUANTIZE_OFF);
@@ -629,7 +626,7 @@ void test_quantization_without_transport(void) {
printf("Test 26: Quantization without transport rolling... ");
Engine *engine = create_test_engine();
engine->sample_rate = 48000;
engine->transport.rolling = false;
engine->transport->state = TRANSPORT_STOPPED;
engine_set_quantize_mode(engine, QUANTIZE_BEAT);