19 Commits
Author SHA1 Message Date
BFlat 4a060dbb5a Merge pull request #2402 from vangel76/opusenc-pvq-search
opusenc: vectorisable candidate filter for the greedy PVQ pulse search
2026-10-30 01:17:19 +07:00
BFlat c357d2901a Merge pull request #2398 from vangel76/opusenc-nlsf-grid
opusenc: tabulate the a2nlsf cosine grid, halve its bisection, memoise pitch contour correlations
2026-10-30 01:13:05 +07:00
BFlat 5feecb679f Merge pull request #2403 from vangel76/opusenc-fft-radix
opusenc: radix-2/3/4 FFT kernels for the MDCT
2026-10-30 00:10:45 +07:00
BFlat 2ad5a5d124 Merge pull request #2404 from vangel76/opusenc-decimator-sums
opusenc: eight partial sums in the 48 kHz decimator
2026-10-30 00:09:12 +07:00
Dylan M. Taylor 7c27d88030 Refactor opusenc for strict Clippy checks 2026-10-28 06:09:21 +00:00
aiongg be942e5776 refactor(opusenc): move src/silk/mod.rs to src/silk.rs 2026-10-26 21:49:10 +00:00
vangel76andClaude Sonnet 5.5 611ffcb841 opusenc: eight partial sums in the 48 kHz decimator
The decimator computed each output as one sequential f32 dot product over
167 taps, which is bound by the 4-cycle latency of the float addition. Use
eight independent partial sums (combined pairwise) so the compiler can
vectorise the loop.

This changes the input of the SILK encoder at rounding level, so the
bitstream differs from before; decoded quality and size are unchanged to
within noise (see the PR for SNR, segmental SNR and size at several
bitrates). A test checks the dot product against an f64 reference.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:24:45 +01:00
vangel76andClaude Sonnet 5.5 63c9ac8941 opusenc: vectorisable candidate filter for the greedy PVQ pulse search
pvq_search scored every coefficient in a serial compare-and-select chain per
pulse. Score all coefficients branch-free in 8-lane chunks instead (square
over energy, one division), take the maximum, and run the original exact
cross-multiplied test only on the entries within 1e-5 of it, which is
normally a single entry whose index comes from a lane-wise count. The chosen
pulse, and with it the bitstream, is unchanged; a test compares the result
with the old scalar search on 6000 random, sparse, tied and extreme-scale
vectors. The pre-projection also uses the truncating cast instead of a floor
libm call (the value is non-negative).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:18:35 +01:00
vangel76andClaude Sonnet 5.5 9c1f8bfa41 opusenc: radix-2/3/4 FFT kernels for the MDCT
Every FFT stage was a generic DFT butterfly: p * p complex multiplications
per butterfly (16 for radix 4) and a modulo on every twiddle index. Add
kiss_fft-style kernels for radix 2, 3 and 4 (three twiddle multiplications
and eight additions for radix 4, a sqrt(3)/2 constant for radix 3, +-j done
by swapping parts). The generic butterfly stays for radix 5, which occurs
once per transform, with its roots precomputed. The modulo is dropped: the
twiddle index q * k * tw_stride is always below n.

The results differ from before at f32 rounding level, so a few packets
change on speech and hybrid input (CELT music stays byte-identical). A new
test checks the FFT against a direct DFT for every radix combination up to
the 480-point frame size.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:14:10 +01:00
vangel76andClaude Sonnet 5.5 9a0e19aae7 opusenc: memoise the pitch contour correlations
The contour search tries 5 base lags times 34 codebook contours times 4
subframes, 680 normalised correlations, but only about 4 x 30 distinct
(subframe, lag) pairs occur. Cache them per call. The values are the same
f64 results as before, so the bitstream does not change (cmp on 24 SILK and
hybrid configurations of 90 s, mono and stereo, speech and music).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:05:19 +01:00
vangel76andClaude Sonnet 5.5 fd84350122 opusenc: halve the a2nlsf bisection steps
Each root was refined with 40 bisection steps, which shrinks the bracket to
about 3e-15 rad. A Q15 NLSF step is 9.6e-5 rad, so 20 steps (3e-9 rad) are
far more than the quantiser can see. The saved cos calls are the remaining
bulk of the root search after the grid table.

The coded packet streams are byte-identical to the 40-step search on 24
configurations of 90 s: speech-like and music-like input, mono and stereo,
SILK NB 8k, MB 12k, WB 16k and 32k, hybrid SWB 32k and FB 64k.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:04:03 +01:00
vangel76andClaude Sonnet 5.5 587d8bdf5b opusenc: tabulate the cosine grid of the a2nlsf root search
The LPC to LSF conversion scans a 1024-point grid for sign changes of two
cosine series and called libm cos for every series term, about 21,000 calls
per channel and frame (30-40 % of SILK and hybrid encode time). Compute
cos(m * w) for every grid point and multiple once, with the same expression
as before, so the values are bit-identical and the bitstream does not change.
Only the bisection steps still call cos.

A test compares the new root search against the previous one bit for bit on
random symmetric polynomials; a2nlsf rejects orders beyond the table.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:02:37 +01:00
vangel76andClaude Sonnet 5.5 e3593d608a opusenc: build the PVQ V table once for encode_pulses
encode_pulses rebuilt the full V(n, k) table with saturating u64 adds for
every coded band and summed the prefixes through a closure. Build the table
once (n <= 176, k <= 128, saturated at u32::MAX, 91 KB) and sum the prefixes
over a contiguous row slice. Shapes outside that range, which the band
layout never produces, fall back to a local table. The unused scratch Vec
is gone from BandEnc.

The bitstream is unchanged; a test keeps the old per-call encoder and
compares the coded bytes on random codewords over the whole (n, k) range.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-25 12:01:39 +01:00
aiongg 0173abde8c CI: dev-profile gate, one test binary per crate, nextest, line tables only (#2235)
* Dev profile: line tables only for workspace crates, no debug info for dependencies

* xtask ci: dev-profile gate, nextest, tests without examples, wasm --keep-going

* One integration-test binary per crate

* xtask ci: run effectcraft-gpu's shared-device tests in one cargo test process

* xtask ci: run every stage and report all failures

* xtask ci: name the stage type (clippy type_complexity)

* xtask ci: run every test pass and report all failures

* cargo fmt
2026-10-23 12:59:51 -04:00
Dexter 39e6907b5f G2: improve editing reliability and Windows rendering fidelity 2026-10-06 00:00:31 -05:00
Brandon ThomasandClaude Opus 5.5 5cc376a818 Never crash: Opus and VP9 encoders without expect()
opusenc: the SILK state is used through if-let / let-else instead of expect("SILK state").
vp9enc: the motion-search SAD and inter prediction return early without a reference frame
instead of expect("reference"). Denies the panic lints in both crates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 13:23:06 -04:00
Brandon ThomasandClaude Opus 5.5 374d21e6a5 M13.4: opus extreme-input tests, SILK doc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:23:03 -04:00
Brandon ThomasandClaude Opus 5.5 3eeba31c43 M13.4: opus SILK (NB/MB/WB, mid/side stereo) and hybrid (SWB/FB) modes
Application/Mode/Bandwidth API with OpusEncoder::with_application and
with_mode; SILK analysis-by-synthesis encoder mirroring the decoder's
fixed-point reconstruction with noise feedback, LTP, NLSF quantisation and
per-frame rate control; hybrid CELT from band 17 in the shared range coder;
pre-skip 120 in every mode. Oracle tests against filmcraft-opus and ffmpeg
(native opus + libopus).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:16:07 -04:00
Brandon ThomasandClaude Opus 5.5 b936ed0055 OUT-2: Opus (CELT) encoder (effectcraft-opusenc)
New L0 crate effectcraft-opusenc: clean-room RFC 6716 CELT-only encoder
(fullband 48 kHz, 20 ms packets, mono/stereo as dual L/R stereo, constant
packet size from the bitrate) with the RFC 7845 OpusHead and pre-skip.
Forward low-overlap MDCT, inter/intra coarse energy, fine/final energy,
the decoder's exact allocation, recursive band splitting, PVQ search and
codeword indexing, silence frames.

crates/export depends on it; filmcraft-opus (dev) is the round-trip oracle
in tests/opus_roundtrip.rs, with ffmpeg reading an in-test Ogg Opus file
as a second oracle when installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 21:41:29 -04:00