Repository navigation
Conversation
…ives Ogg Vorbis, Opus and WMA were recognised as files no player opens and then left alone, because nothing in the build decoded them, and a file above 96 kHz was reported and refused by the drive writer, because nothing here resampled. All four are now decoded, offered a conversion to FLAC at import, and carried onto a drive as a 320 kbps mp3 like a FLAC bound for a nexus deck. Decoding, each measured on a 30-second CC record against a reference: - Vorbis, through symphonia's own Ogg demuxer and Vorbis decoder: 137.9 dB from ffmpeg's decode, which is rounding. - Opus, through rusty-opus, because symphonia demuxes Opus and has no decoder: 83.1 dB from libopus's float decode, where ffmpeg's built-in Opus decoder is 70.2 dB from it, in 96 ms for the 30 seconds. The other pure-Rust decoder, opus-decoder, was 87.0 dB and took 12.6 s. Symphonia leaves the 312-sample pre-skip on the first packet, which would put every cue on an Opus file 6.5 ms late; it is taken off. - WMA, through ffmpeg when it is installed, since nothing in Rust decodes it: on PATH, in Homebrew's two folders, or BOOTH_FFMPEG. A WMA without ffmpeg is reported with the command to install it, and is not offered a conversion that would fail. Their tags are read too, so a file arrives with its name and a conversion keeps it: Vorbis comments as symphonia finds them in the Ogg, under the keys a FLAC's use, and ASF through ffmpeg's metadata listing. They are read and not written. Resampling for the library goes through rubato's FFT resampler, already compiled in by rusty-chromaprint, to 88.2 or 96 kHz so it is a halving or a quartering. Halving a 192 kHz signal it keeps 40 kHz flat to 0.0001 dB and folds ultrasonic tones back at -149 to -158 dB, where the quick resampler the models are fed by gets -111 dB and is 0.34 dB down at 40 kHz; it is also twice as fast. The quick one is left alone. The drive writer refused anything above 96 kHz outright, though LAME takes 176.4, 192 and 384 kHz input and writes 44.1 or 48 kHz from it, measured with the same encoder settings. It now carries those as mp3s and takes any format something here decodes; what nothing decodes is still refused, and the preflight says "skipped" only about that. A conversion is 24-bit FLAC from a float WAV or a hi-res file and 16-bit with dither from a lossy one. Every conversion was 16-bit until now, though the float WAV's fix has always said 24. The library takes the new formats on import; the command-line pipelines do not, because normalize writes its output in the format it was given and has no Ogg, Opus or WMA writer. flacenc refuses to write FLAC above 96 kHz, which conversions never need, so the test's 192 kHz input is a WAV. CI installs ffmpeg so the WMA tests decode a file; without it they check the absence is explained. The fixtures are synthetic and made with ffmpeg, with the commands beside them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019tjgDHGCsZrZcZPVL4Dmon
This branch has not been deployed
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.
Closes the TODO entry "Formats nothing here converts". Ogg Vorbis, Opus and WMA used to be recognised as unplayable and then left alone, because nothing in the build decoded them. A file above 96 kHz was reported, and refused by the drive writer, because nothing here resampled.
All four are now decoded, and all four get the same treatment. At import they are offered a conversion to FLAC. On a drive they are carried as a 320 kbps MP3, the same way a FLAC bound for a nexus deck already is.
What changed
Decoding (
booth-cli,audio::decode):audio::ffmpegmodule. Nothing in Rust decodes WMA. Booth looks for ffmpeg onPATH, then in Homebrew's two folders (an app started from the Finder doesn't get the shell's PATH), or whereverBOOTH_FFMPEGpoints. Without ffmpeg, a WMA is reported with the command to install it and is not offered a conversion.Tags: Ogg, Opus and WMA files now arrive with their names, and a conversion keeps them.
TagKind::writable()keeps the three callers that only ruled out WAV from trying to write them.Resampling for the library: a new
resample::for_library, built on rubato's FFT resampler (already compiled in, via rusty-chromaprint). It converts to 88.2 or 96 kHz (compat::library_rate), so the conversion is a halving or a quartering. The quick resampler that feeds the speech and genre models is unchanged.Conversions (the app's Convert job):
for_library.Drive writer:
Import: the app now imports the new formats (
discover::LIBRARY,collect_library), and so does the library-folder orphan check. The booth-cli pipelines keep the old list, becausenormalizewrites its output in the input's format and has no Ogg, Opus or WMA writer, so one such file in a folder would stop the whole command.Why it's right
Everything below is measured: each decoder against a reference decode of the same file, each resampler on test tones.
Decoding, on a 30-second CC record:
Both Rust Opus decoders are closer to libopus than ffmpeg's own decoder is. opus-decoder is 130 times slower than rusty-opus, which would mean about two and a half minutes to decode one six-minute track, so rusty-opus it is. Without the pre-skip trim the decode is exactly 312 samples late. A test holds both the frame count and the phase of a tone that starts at zero.
Resampling, halving tones at 192 kHz:
resampleA test holds the audible band within 0.001 dB and every folded tone below −120 dB. Another holds a click in the same place after resampling, so cues still land on the same beat.
LAME at hi-res rates: I gave it 176.4, 192, 384 and 96 kHz, with the encoder settings the writer uses. It accepted all four and wrote 44.1 or 48 kHz MP3s of the right length. So the writer's refusal above 96 kHz had no technical cause.
Fixtures: six small synthetic files, made with ffmpeg; the commands are in their README.
tones.*: a different tone in each channel, which catches a swapped or mixed-down decode.beat.*: 128 BPM, because writing a drive means finding a grid, and a pure tone has none.The new
formatstest decodes all of them, reads their tags, and writes a drive carrying Ogg, Opus, WMA and a 192 kHz file. All four land as MP3s at 44.1 or 48 kHz.The other ways, and why they lost
symphonia-adapter-libopus. That is the reference decoder, but it means building C with cmake, including inside the universal macOS build. rusty-opus has no build step and no dependencies, and it is closer to libopus than ffmpeg is.normalizeon any folder containing one of these files.Worth a second opinion
unsafeonly in its documented SIMD kernels. The code looks fine, but the advert is a reason to keep an eye on who maintains it..mp3on the end, and nothing checks the name is free. I saw it happen with three fixtures calledbeat.ogg,beat.opusandbeat.wmaby the same artist. It was already true for a FLAC and an MP3 of the same name going to a nexus deck. This PR makes it likelier, so it's now in the README's "not done yet" list and in TODO.md.Gates pass:
cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings, andenv -u BOOTH_WHISPER_MODEL -u BOOTH_WHISPER_BIN -u BOOTH_GENRE_MODEL cargo test --workspace, which runs 32 test binaries, including the newformats.Generated by Claude Code