Skip to content

Audio-reactive components read scene-local time against a scenario-time analysis #201

Description

@LeadcodeDev

Symptom

A waveform in a scene that starts at t=73 s draws the analysis at 73 s into the scene, not into the scenario. With a uniform track nobody notices; with any track whose level varies over the timeline the visualisation is simply wrong, and it goes flat when the scene's own local window falls in a silent region of the analysis.

Evidence

Same scene, same track, same build — only the scene's position in the scenario differs:

scene position trace height
first scene (local ≈ scenario time) 42 px
starting at t≈73 s in the full scenario 0 px (flat)

Cause

PaintCtx carries no scenario-global time:

pub struct PaintFrame {
    pub time: f64,        // scene time
    pub frame_index: u32, // "frames elapsed since this scene started"
    ...
}

waveform.rs and audio_spectrum.rs call analysis.amplitude_at(ctx.time), and the audio-reactive binding in box_builder.rs calls amplitude_smoothed(actx.time, …) — all scene-local. AudioAnalysis is indexed from the file's own start, i.e. scenario time once track.start is applied (#190/#198).

So the two only agree for a track placed at 0 and a scene starting at 0.

Why it stayed hidden

The analysis was uniform enough that any offset looked plausible: a periodic track shows peaks whatever the phase. I "verified" the alignment earlier by observing peaks, which proves nothing about the offset — the test above is the one that discriminates.

Proposed fix

Thread scenario time into the paint context:

  1. Add scenario_time: f64 (or a global frame index) to PaintFrame/PaintCtx. The FrameTask layer already knows it — tasks are a flat list over the whole render.
  2. Use it in waveform, audio_spectrum and the audio-reactive binding; every other consumer keeps time (scene-local), which is correct for animation progress.
  3. Define it for world views as the view timeline's own time, which is what WorldTimeline already computes.

A test asserting that the same scene renders the same waveform whether it is first or last in the scenario pins the property; that is the discriminating case above.

Blocks

The switch to a mix-following analysis (option A on #190's open question) is implemented but cannot land before this: it makes level variation visible, so the misalignment stops being harmless and turns into a flat trace.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions