Skip to content

FLAC PCM: declare sampleRate in kHz - #1036

Open
paulorichards wants to merge 2 commits into
GLinnik21:mainfrom
paulorichards:flac-pcm-khz
Open

paulorichards wants to merge 2 commits into
GLinnik21:mainfrom
paulorichards:flac-pcm-khz

Conversation

@paulorichards

@paulorichards paulorichards commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

The FLAC path in #950 declared pcmInfo.sampleRate in the wrong unit, so the TV played every FLAC at 44.1 kHz. This PR declares it in kHz, and a measured test tone now comes back at the right pitch at every rate I tried.

When I tested #950, I checked 48 kHz by ear and by comparing the feed timestamps against the wall clock. Both looked fine, but neither could catch this: the timestamps follow the clock the input keeps, not the pitch, and 919 Hz instead of 1000 Hz is hard to hear without something to compare it to.

@tiper then noticed in #917 that on a C1 every FLAC played at 44.1 kHz, whatever rate was declared. So I tested again on my B8 (OLED55B8, webOS 4.4.3), this time measuring instead of listening. I made FLAC clips at each rate with a 1 kHz tone, then 440 Hz + 5 kHz, then a 2 kHz beep every 10 s, played them on the TV, recorded the room with a laptop mic, and measured the tone's frequency. A wrong rate shifts the tone by the ratio between the file's rate and the one played. To check the method, an AAC 48 kHz clip decoded by the TV came back at 999.98 Hz, and a 48 kHz file relabelled as 44.1 kHz came back at 918.74 Hz, as it should. The B8 did the same as the C1: 918.8 Hz from 48 kHz, 1377.9 Hz from 32 kHz and about 2006 Hz from 22.05 kHz, which is exactly 1000 × 44.1 / the file's rate.

The reason was already in #805: @dimitrije83 found there that libpf matches sampleRate against a kilohertz table (48, 44.1, 32, ...) and falls back to 44.1 for a value it can't match. The speed path declares 48. The FLAC path declared 48000, which matches nothing, so 44.1 kHz files sounded right by accident and every other rate didn't.

With the rate declared in kHz, the same clips measured:

FLAC file Declared in Hz (before) Declared in kHz (this PR) Rate the TV reported (this PR)
48 kHz, 24-bit 918.8 Hz 999.98 Hz 48.000000
44.1 kHz 999.99 Hz 999.99 Hz 44.099998
32 kHz 1377.9 Hz 999.96 Hz 32.000000
22.05 kHz about 2006 Hz 999.99 Hz 22.049999

The 440 Hz and 5 kHz tones measured 440.0 and 4999.9 Hz, and all 8 beeps were 10.000 s apart on every file. The last column comes from the pipeline's audio-info callback (smp_cb type=8). For the relabelled control it said 44.099998, so it shows the rate the TV really used.

I also checked whether the 48 kHz ceiling was the same unit problem. It isn't. A test build that admitted 88.2, 96, 176.4 and 192 kHz and declared them in kHz still played all four at 44.1: the tone came back at about 504, 457, 246 and 234 Hz, against 500, 459, 250 and 230 predicted by the fallback, and for 192 kHz the TV reported 44.099998. libpf's table stops at 48, so PCM_SAMPLE_RATES stays as it is and faster files stay a server conversion.

Change

  • with_pcm_info states the rate in kHz, the same unit the speed path uses. pcm_rate_khz converts it (48000 → 48, 44100 → 44.1, 22050 → 22.05).
  • New test the_sample_rate_is_declared_in_kilohertz checks every rate in PCM_SAMPLE_RATES. The two payload tests that expected 48000 and 44100 now expect 48 and 44.1.
  • The PCM_SAMPLE_RATES doc in devcaps.rs no longer says 48 kHz played right on the B8.

Nothing is resampled, so this adds no CPU.

Tests

  • make test-crate C=plx-media T=player::engine (51 passed)
  • make test-crate C=plx-platform T=pcm
  • make FLAVOR=stable RELEASE=1 ipk
  • make check
  • make check-nodef

Not verified

  • webOS 4.5 and other firmware.
  • Rates in the table other than 48, 44.1, 32 and 22.05 kHz.
  • The rate the TV reported for 88.2, 96 and 176.4 kHz. Only the recordings show those; the log kept only the last run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BNxR112kqmb5uZjUzXgND1

@paulorichards
paulorichards marked this pull request as draft October 25, 2026 12:47
@paulorichards
paulorichards marked this pull request as ready for review October 25, 2026 12:59
@tiper

tiper commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Nice, same conclusion here! #1032 is the same change (with the C1 / webOS 6.5.3 results: 48, 32 and 22.05 kHz now on time). Between the two we've got it confirmed on webOS 4.4 and 6. Happy for @GLinnik21 to take whichever he prefers and close the other.

@tiper

tiper commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Had a closer look and this PR does the same thing in fewer files and works the kHz out from any rate, so it's the better one. Closing #1032

@paulorichards

Copy link
Copy Markdown
Contributor Author

Closing as a duplicate of #1032, which @tiper opened first with the same fix. The B8 measurements from here are posted there.

@tiper

tiper commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

@paulorichards please keep this one. Its a better approach 😄

@paulorichards paulorichards reopened this Oct 25, 2026
libpf matches pcmInfo.sampleRate against a kilohertz table (GLinnik21#805). The
FLAC node stated hertz, so every FLAC played at the 44.1 kHz fallback:
on an OLED55B8 (webOS 4.4.3) a 1 kHz tone came back at 918.8 Hz from a
48 kHz file, 1378 Hz from 32 kHz and about 2006 Hz from 22.05 kHz.
Declared in kHz, all four rates play at 1000 Hz and the pipeline reports
the declared rate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BNxR112kqmb5uZjUzXgND1
Signed-off-by: Paulo Richards <paulo.richards@gmail.com>
@paulorichards

Copy link
Copy Markdown
Contributor Author

Our comments crossed, sorry about that. Reopening as you suggest, thanks! With your C1 results we have it confirmed on webOS 4.4 and 6.5.

…innik21#1032)

The rate doc, the track gate and the planner's refusal said the PCM input
plays some rates "at their own speed". What decides it is whether
pcmInfo.sampleRate names a rate in libpf's kilohertz table, so they say
that now, and the comments carry the C1 (webOS 6.5.3) results next to
the B8 ones.

Co-authored-by: Tiago Pereira <1698241+tiper@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BNxR112kqmb5uZjUzXgND1
Signed-off-by: Paulo Richards <paulo.richards@gmail.com>
@paulorichards

Copy link
Copy Markdown
Contributor Author

I've also brought over your wording from #1032: the rate doc, the gate and error messages now say a rate is one the table "names" instead of one that plays "at its own speed", and the comments include your C1 results (GStreamer caps rate=44100, 48 kHz 9% slow, 32/22.05 kHz stuttering). That covers devcaps.rs, decision.rs, transcoder.rs and plan_track_selection_tests.rs. The kHz conversion stays as it was here.

This branch has not been deployed

No deployments
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