audio_wav: 16/24/32-bit PCM read; SFX Lab trimmer + fit-length fix#3236
Merged
Conversation
A 'trim silence' button in the reference panel cuts leading AND trailing silence from the loaded reference clip, gated by a 'trim gate (dB below peak)' slider (default -24 dB). Trimming is button-triggered, not on load, so the user controls when and how aggressively. Reports the ms trimmed off each end (g_trim_info). refresh_reference() extracts the post-load recompute (downsample / spectrum / spectrogram / fit / levels) so trim can reuse it. Also fixes a pre-existing LINT003 (var doc -> let doc) in two spots. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
read_wav rejected anything but 16-bit, so 24-bit reference clips (common for hi-res game audio) failed to load. Capture the fmt format code and decode 16/24/32-bit signed integer PCM (mono or stereo, interleaved); reject float (format 3) for now. write_wav stays 16-bit. Add tests/audio/test_wav.das: hand-builds a minimal mono WAV at each depth in memory, writes it, and asserts read_wav reconstructs the samples/rate/channels (write_wav only emits 16-bit, so the wider depths can't round-trip via the module). Interp green; registered for AOT. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The spectral fit/evo windows used min(len_a, len_b) — truncating the comparison to the shorter clip. So trimming the reference shrank the fit window to it, and a generated sound longer than the reference had its extra tail ignored rather than penalized. Switch to max(len) (matching envelope_fit's existing design): span the longer duration and zero-pad the shorter's tail (log_spectro already zero-pads past the buffer end). A duration mismatch now costs fit instead of hiding, and trimming no longer destabilizes the score. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR extends the audio_wav module and SFX Lab tooling to better handle real-world reference clips and improve fit scoring behavior across duration mismatches.
Changes:
audio_wav.read_wavnow decodes 16/24/32-bit integer PCM WAVs (mono/stereo interleaved), and a new unit test builds minimal WAVs in-memory to validate decoding.- SFX Lab adds a “trim silence” action for the loaded reference clip and refactors reference-derived recomputation into a shared helper.
- SFX analysis fit windows now span the longer clip duration (with zero-padding) so duration mismatch is penalized instead of truncated away.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/audio/test_wav.das | Adds coverage for 16/24/32-bit integer PCM decoding using a hand-built WAV buffer written to disk. |
| tests/aot/CMakeLists.txt | Registers the new WAV test for AOT runs when audio is enabled. |
| modules/dasAudio/audio/audio_wav.das | Adds integer PCM decoding for 24/32-bit and captures WAV fmt format code. |
| examples/daStrudel/sfx_lab/sfx_analysis.das | Updates fit window selection to use the longer buffer length (zero-padding shorter tails). |
| examples/daStrudel/sfx_lab/main.das | Adds reference silence trimming UI/logic and refactors reference refresh logic into refresh_reference(). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…t: temp file Copilot review (#3236): only accept format-1 integer PCM — accepting extensible (0xFFFE) without parsing the sub-format GUID risked silently mis-decoding an extensible-float WAV as int. Guard the fmt-chunk skip against a backward cursor (malformed < 16 size) and clamp data_size to the available bytes, so a truncated / over-claimed chunk can't hang or read past the buffer. The read_wav test now uses create_temp_file_result for a unique writable path instead of a cwd-relative name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment on lines
35
to
39
| let chunk_id = read_wav_tag(raw, cursor) | ||
| let chunk_size = read_wav_u32(raw, cursor) | ||
| if (chunk_id == "fmt ") { | ||
| cursor += 2 | ||
| fmt_format = read_wav_u16(raw, cursor) | ||
| fmt_channels = read_wav_u16(raw, cursor) |
Comment on lines
+59
to
+60
| let bytes_per = fmt_bits / 8 | ||
| return false if (bytes_per != 2 && bytes_per != 3 && bytes_per != 4) // 16 / 24 / 32-bit PCM |
Comment on lines
+77
to
+83
| var wrote = false | ||
| fopen(path, "wb") $(f) { | ||
| if (f != null) { | ||
| fwrite(f, bytes) | ||
| wrote = true | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three small SFX-Lab / audio improvements (tail of the SFX Lab arc).
audio_wav: 16/24/32-bit integer PCM read
read_wavrejected anything but 16-bit, so 24-bit reference clips (common for hi-res audio) failed to load. It now captures thefmtformat code and decodes 16/24/32-bit signed integer PCM (mono or stereo, interleaved); float (format 3) is still rejected.write_wavstays 16-bit.Adds
tests/audio/test_wav.das: hand-builds a minimal mono WAV at each depth in memory, writes it, and assertsread_wavreconstructs the samples / rate / channels (write_wav only emits 16-bit, so the wider depths can't round-trip through the module). Interp green; registered for AOT intests/aot/CMakeLists.txt.SFX Lab: silence trimmer
A
trim silencebutton in the reference panel cuts leading + trailing silence from the loaded clip, gated by atrim gate (dB below peak)slider (default -24 dB). Button-triggered (not on load), and reports the ms trimmed off each end.sfx_analysis: fit spans the longer duration (zero-pad), not the shorter
The spectral fit / evo windows used
min(len_a, len_b)— truncating the comparison to the shorter clip. So trimming the reference shrank the fit window, and a generated sound longer than the reference had its extra tail ignored rather than penalized. Switched to the longer duration with the shorter zero-padded (matchingenvelope_fit's existing design;log_spectroalready zero-pads past the buffer end). A duration mismatch now costs fit instead of hiding.🤖 Generated with Claude Code