The MIDI-clip-end-grows-too-fast bug was a units confusion: AudioClip.duration is documented "seconds" but MIDI clips store their length in BEATS (they share the AudioClip struct with sampled clips). The timeline's effective_clip_duration read it as raw seconds, so at 120 BPM a MIDI clip rendered ~2x too long. The old backend-snapshot display had hidden this by forcing timeline_duration in beats. Root fix — make the domain explicit and unforgeable: - `duration` is now a private field. Reading it in the wrong unit is impossible because access goes through typed accessors: AudioClip::content_duration() -> ClipDuration (a Seconds|Beats enum tagged by clip_type) and set_content_duration(). serde still serializes the private field, so the .beam format is unchanged (bare number). - ClipDuration::to_seconds(tempo_map) for display/sizing; ::native() for code that already works in the clip's native domain (trim math shares it). - get_clip_duration + the timeline-endpoint calc go through to_seconds, so MIDI is converted correctly; effective_clip_duration delegates to get_clip_duration. - Recording mirrors (audio/MIDI progress + finalize) write via set_content_duration (debug-asserts the value's domain matches the clip type). Every former raw read/write of the field (core actions, timeline, piano roll, infopanel, asset library, recording handlers) now goes through the accessors. Whole workspace compiles; 299 core tests pass. |
||
|---|---|---|
| .. | ||
| beamdsp | ||
| egui_node_graph2 | ||
| gpu-video-encoder | ||
| lightningbeam-core | ||
| lightningbeam-editor | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| GPU_VIDEO_DECODE_PLAN.md | ||
| build-static.sh | ||
| build-windows.bat | ||