Skip to content

audio_wav: 16/24/32-bit PCM read; SFX Lab trimmer + fit-length fix#3236

Merged
borisbat merged 4 commits into
masterfrom
bbatkin/sfx-lab-readwav-trimmer
Jun 21, 2026
Merged

audio_wav: 16/24/32-bit PCM read; SFX Lab trimmer + fit-length fix#3236
borisbat merged 4 commits into
masterfrom
bbatkin/sfx-lab-readwav-trimmer

Conversation

@borisbat

Copy link
Copy Markdown
Collaborator

Three small SFX-Lab / audio improvements (tail of the SFX Lab arc).

audio_wav: 16/24/32-bit integer PCM read

read_wav rejected anything but 16-bit, so 24-bit reference clips (common for hi-res audio) failed to load. It now captures the fmt format code and decodes 16/24/32-bit signed integer PCM (mono or stereo, interleaved); float (format 3) is still rejected. write_wav stays 16-bit.

Adds 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 through the module). Interp green; registered for AOT in tests/aot/CMakeLists.txt.

SFX Lab: silence trimmer

A trim silence button in the reference panel cuts leading + trailing silence from the loaded clip, gated by a trim 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 (matching envelope_fit's existing design; log_spectro already zero-pads past the buffer end). A duration mismatch now costs fit instead of hiding.

🤖 Generated with Claude Code

borisbat and others added 3 commits June 20, 2026 20:59
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>
Copilot AI review requested due to automatic review settings June 21, 2026 04:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_wav now 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.

Comment thread modules/dasAudio/audio/audio_wav.das Outdated
Comment thread modules/dasAudio/audio/audio_wav.das
Comment thread modules/dasAudio/audio/audio_wav.das
Comment thread examples/daStrudel/sfx_lab/main.das
Comment thread tests/audio/test_wav.das Outdated
…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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

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 thread tests/audio/test_wav.das
Comment on lines +77 to +83
var wrote = false
fopen(path, "wb") $(f) {
if (f != null) {
fwrite(f, bytes)
wrote = true
}
}
@borisbat borisbat merged commit bf2fdb2 into master Jun 21, 2026
33 checks passed
@borisbat borisbat deleted the bbatkin/sfx-lab-readwav-trimmer branch June 21, 2026 05:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants