Skip to content

Measure the VBR target against the nominal rate - #206

Merged
thomas-vilte merged 1 commit into
pion:mainfrom
thomas-vilte:fix/vbr-equiv-rate
Aug 13, 2026
Merged

Measure the VBR target against the nominal rate#206
thomas-vilte merged 1 commit into
pion:mainfrom
thomas-vilte:fix/vbr-equiv-rate

Conversation

@thomas-vilte

Copy link
Copy Markdown
Member

Description

There were two places where the VBR path was using the frame budget while the reference uses the requested bitrate.

1. equiv_rate. This feeds the intensity band, trim, and temporal VBR factor. libopus caps it with the nominal bitrate (celt_encoder.c:1926):

equiv_rate = ((opus_int32)nbCompressedBytes*8*50 << (3-LM)) - (40*C+20)*((400>>LM) - 50);
if (st->bitrate!=OPUS_BITRATE_MAX)
   equiv_rate = IMIN(equiv_rate, st->bitrate - (40*C+20)*((400>>LM) - 50));

In VBR, nbCompressedBytes is the output buffer size, so without that IMIN every rate-dependent decision would see a bitrate corresponding to hundreds of kb/s. pion was always deriving equiv_rate from the frame budget.

Instrumenting the reference at 24 kb/s:

VBR: equiv=24000 with nbComp=1275
CBR: equiv=23600 with nbComp=59

In CBR, st->bitrate is OPUS_BITRATE_MAX, so the cap does not apply.

pion was returning 23600 in both cases. That put VBR 24 kb/s into the previous intensity-table entry: band 9 instead of the reference's band 10.

2. vbr_rate. The base used to calculate the target comes directly from the bitrate (celt_encoder.c:1904):

vbr_rate = bitrate_to_bits(st->bitrate, mode->Fs, frame_size)<<BITRES;
effectiveBytes = vbr_rate>>(3+BITRES);

This is the integer portion of the frame — 60 bytes at 24 kb/s — including the header byte that the CBR payload budget excludes. The reservoir absorbs the difference.

pion was using the 59-byte payload budget instead, one byte less per frame.

For this, the CELT layer needs to know the nominal bitrate, so I added SetBitrate alongside the existing setters.

Measurement

Intensity-band agreement against opus_demo, over 3000 frames:

mode before after
VBR 24 kb/s 0.0% 100%
VBR 96 kb/s 100% 100%
CBR 24 and 96 100% 100%

The 24 kb/s VBR case was a complete mismatch: the reference selected band 10 for all 3000 frames while pion selected band 9.

This also affects the bands that are actually coded:

Packet size and SNR in VBR:

bitrate before after libopus
24000 51.44 B / 6.1840 dB 52.44 B / 6.2953 dB 53.50 B / 6.3764 dB
48000 111.55 B / 9.8859 dB 112.56 B / 9.9074 dB 113.71 B / 10.0016 dB
96000 241.81 B / 14.9433 dB 242.81 B / 14.9785 dB 244.03 B / 15.0810 dB
mode before after
VBR 24 kb/s 90.7% 95.9%
VBR 96 kb/s 99.9% 100%

CBR remains unchanged, verified at 24, 48, and 96 kb/s: 7.0676 / 10.1179 / 15.0721 dB, identical digit for digit.

What remains

In VBR, pion is now within roughly 0.5–2% of libopus in bytes and 0.08–0.10 dB in SNR.

In CBR, it remains essentially matched: +0.014 / +0.015 / −0.002 dB at 24, 48, and 96 kb/s.

The only metric still below 99% is the number of coded bands at 24 kb/s: 95.9% in VBR and 96.9% in CBR. Since it happens in both modes, this is not a VBR-path issue and should be addressed separately.

Reference issue

Part of #34.

@thomas-vilte
thomas-vilte requested a review from FrantaBOT August 12, 2026 20:13
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.11%. Comparing base (00b48f4) to head (0e676e5).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #206      +/-   ##
==========================================
+ Coverage   93.09%   93.11%   +0.01%     
==========================================
  Files          58       58              
  Lines       10389    10407      +18     
==========================================
+ Hits         9672     9690      +18     
  Misses        505      505              
  Partials      212      212              
Flag Coverage Δ
go 93.11% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@thomas-vilte
thomas-vilte merged commit 0a1f437 into pion:main Aug 13, 2026
20 checks passed
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