diff options
Diffstat (limited to 'src/audio/tracker.cc')
| -rw-r--r-- | src/audio/tracker.cc | 37 |
1 files changed, 15 insertions, 22 deletions
diff --git a/src/audio/tracker.cc b/src/audio/tracker.cc index 93a1c49..2bb4159 100644 --- a/src/audio/tracker.cc +++ b/src/audio/tracker.cc @@ -172,8 +172,10 @@ static int get_free_pattern_slot() { } // Helper to trigger a single note event (OPTIMIZED with caching) -// start_offset_samples: How many samples into the future to trigger (for sample-accurate timing) -static void trigger_note_event(const TrackerEvent& event, int start_offset_samples) { +// start_offset_samples: How many samples into the future to trigger (for +// sample-accurate timing) +static void trigger_note_event(const TrackerEvent& event, + int start_offset_samples) { #if defined(DEBUG_LOG_TRACKER) // VALIDATION: Check sample_id bounds if (event.sample_id >= g_tracker_samples_count) { @@ -209,13 +211,15 @@ static void trigger_note_event(const TrackerEvent& event, int start_offset_sampl } // Trigger voice with sample-accurate offset - synth_trigger_voice(cached_synth_id, event.volume, event.pan, start_offset_samples); + synth_trigger_voice(cached_synth_id, event.volume, event.pan, + start_offset_samples); } void tracker_update(float music_time_sec) { // Unit-less timing: 1 unit = 4 beats (by convention) const float BEATS_PER_UNIT = 4.0f; - const float unit_duration_sec = (BEATS_PER_UNIT / g_tracker_score.bpm) * 60.0f; + const float unit_duration_sec = + (BEATS_PER_UNIT / g_tracker_score.bpm) * 60.0f; // Step 1: Process new pattern triggers while (g_last_trigger_idx < g_tracker_score.num_triggers) { @@ -239,9 +243,10 @@ void tracker_update(float music_time_sec) { } // Step 2: Update all active patterns and trigger individual events - // Get current audio playback position for sample-accurate timing - const float current_playback_time = audio_get_playback_time(); - const float SAMPLE_RATE = 32000.0f; // Audio sample rate + // NOTE: We trigger events immediately when their time passes (no sample + // offsets) This gives ~16ms quantization (60fps) which is acceptable Sample + // offsets don't work with tempo scaling because music_time and render_time + // are in different time domains (tempo-scaled vs physical) for (int i = 0; i < MAX_SPECTROGRAMS; ++i) { if (!g_active_patterns[i].active) @@ -261,21 +266,9 @@ void tracker_update(float music_time_sec) { if (event.unit_time > elapsed_units) break; // This event hasn't reached its time yet - // Calculate exact trigger time for this event - const float event_trigger_time = active.start_music_time + - (event.unit_time * unit_duration_sec); - - // Calculate sample-accurate offset from current playback position - const float time_delta = event_trigger_time - current_playback_time; - int sample_offset = (int)(time_delta * SAMPLE_RATE); - - // Clamp to 0 if negative (event is late, play immediately) - if (sample_offset < 0) { - sample_offset = 0; - } - - // Trigger this event as an individual voice with sample-accurate timing - trigger_note_event(event, sample_offset); + // Trigger this event immediately (no sample offset) + // Timing quantization: ~16ms at 60fps, acceptable for rhythm + trigger_note_event(event, 0); active.next_event_idx++; } |
