Skip to content

DVI audio can play 44.1 kHz and 32 kHz sound too - #11607

Open
mikeysklar wants to merge 7 commits into
adafruit:mainfrom
mikeysklar:dvi-audio-rates
Open

mikeysklar wants to merge 7 commits into
adafruit:mainfrom
mikeysklar:dvi-audio-rates

Conversation

@mikeysklar

Copy link
Copy Markdown
Collaborator

What

DVI audio now plays 32, 44.1 and 48 kHz sound.

Why

Most music files are 44.1 kHz, so they no longer need resampling first.

This matches the rates the Arduino DVI-HSTX library supports.

Builds on #11574, which should merge first. Only the last commit is new here.

Tested

Feather RP2350 (8 MB PSRAM), DVI monitor with speakers, 11.0.0-alpha.1 plus #11574 and this PR.

Test Result
audioout_rates.py, 1 kHz tone at each rate, twice All six play, heard on the monitor
audioout_bad_values.py, 22.05 and 96 kHz ValueError: Invalid sample_rate
board_audio.py Passes
supervisor.runtime.audio at 44.1, 32, then 48 kHz All play
Text to speech demo at 48 kHz Still speaks

Not tested: Fruit Jam, Metro RP2350, other monitors.

Detail
44.1 kHz Usual N of 6272, CTS rounded
RAM About 780 bytes more internal RAM while audio is on
Changing rate The monitor may mute briefly
Idle after 44.1 kHz Silence keeps being written, since frames never repeat exactly
Not from this PR audioout_bad_values.py's 720-wide block hits MemoryError on a Feather with DVI forced on; same on #11574

Written with Claude Code. I reviewed the diff, built it, and ran every test above on the board.

🤖 Generated with Claude Code

mikeysklar and others added 7 commits October 12, 2026 17:49
Fruit Jam now sends sound through the DVI cable of its boot display, as
board.DVI_AUDIO. It is set up in board init, before the VM heap takes
internal RAM, and is skipped quietly if it doesn't fit. Set
CIRCUITPY_PICODVI_AUDIO = false in settings.toml to turn it off.

To make that fit next to the 640x480 8-bit boot display, AudioOut now
sends audio from a pool of 160 encoded packets referenced by 280 slots,
refilled from a 2.5 ms repeating timer, instead of encoding every line.
Audio RAM drops from 118 KB to 37 KB at 640 wide.

Packets are full 4-sample packets, and the ACR N is picked per pixel clock
so frames repeat exactly, so idle frames need no refill. Setup fails
cleanly if the refill timer can't be added, and after a long stall the
refill skips whole frames instead of walking every slot.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Drop CIRCUITPY_BOARD_DVI_AUDIO. Boards that set DEFAULT_DVI_BUS_CLK_DP
now get board.DVI_AUDIO, turned off with CIRCUITPY_PICODVI_AUDIO.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Boards with a default DVI display have no board.DISPLAY, so the audio
output follows supervisor.runtime.display instead of being a board entry.
It is None on ports without DVI audio, when CIRCUITPY_PICODVI_AUDIO is
false, and after displayio.release_displays().

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
play() takes the rate from the sample. The ACR and audio InfoFrame
packets are built once per rate when audio starts, and the refill picks
the set for the current rate, so DMA never reads a packet being
rewritten. Channel status carries the matching IEC 60958 rate code.
At 44.1 kHz the search for an exact CTS finds nothing near 20 ACR
packets a frame, so it uses the usual N of 6272 and rounds CTS.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mikeysklar
mikeysklar marked this pull request as ready for review October 14, 2026 20:43
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.

1 participant