Double-buffer RawSample (single_buffer=False) played with loop=False hangs; playing never clears
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
- Tipo di issue
- Bug
- Chiarezza
- Da chiarire
- Stato di attività
- Tranquilla
- Stack tecnologico
- c
- Ambito
- embedded-iot
Direzione di ricerca
Start by reading the RawSample documentation and shared-module/audiocore/RawSample.c, then trace the rp2 behavior in ports/raspberrypi/audio_dma.c. Reproduce the hang and check the listed audio ports. Done means the intended double-buffer plus loop=False semantics are decided and implemented, with behavior verified across ports.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Note: This issue was written by Claude (via Claude Code), not by a human. It was filed at the request of @dhalbert while working on the fixes for #10539 (PR #11085).
@dhalbert says: This is kind of an edge case; no one has reported it as a bug; I discovered it while testing audio PR's.
Summary
A RawSample constructed with single_buffer=False and played with loop=False plays a short burst and then hangs: audio stops, but .playing never becomes False. Observed on raspberrypi; likely affects other ports (needs verification — see below).
sample = audiocore.RawSample(sine_wave, sample_rate=8000, single_buffer=False)
i2s.play(sample, loop=False)
while i2s.playing: # never exits
pass
Root cause (raspberrypi)
A double-buffer RawSample's get_buffer (shared-module/audiocore/RawSample.c) returns half the buffer with GET_BUFFER_DONE and alternates halves forever — it never signals true end-of-data.
On rp2 (ports/raspberrypi/audio_dma.c), audio_dma_load_next_block treats GET_BUFFER_DONE && !loop by pointing the DMA channel's chain at itself to stop. With both channels chained to themselves, the ping-pong breaks: channel[0] plays its half and stops, and dma_callback_fun never re-triggers (channels_to_load_mask == 0, filled_count == 1). Audio halts after one half, and playing_in_progress is never cleared. The proper end-of-sample detection (output_length_used == 0) never fires because RawSample always returns nonzero halves.
WaveFile in double-buffer mode is unaffected: it returns GET_BUFFER_MORE_DATA for intermediate reads and a truly-empty GET_BUFFER_DONE at EOF, so playback terminates cleanly.
Why this is tricky (semantics)
Per the RawSample docstring, single_buffer=False (double-buffered) is intended for continuous, live-update playback — updating the buffer while it plays — and its examples all use loop=True. single_buffer=False + loop=False on a static buffer is effectively ill-defined: the sample has no natural end, so "play once and stop" has no clear meaning.
A fix probably needs a decision at the RawSample/shared layer about what this combination should do (e.g. play the whole buffer through once then stop, treat it as looping, or reject the combination), rather than a per-port patch.
TODO
- Reproduce on other audio ports (espressif, nordic, atmel-samd, mimxrt10xx, stm, zephyr-cp) and note behavior per port.
- Decide the intended semantics for double-buffer +
loop=False. - Implement, likely at the
RawSample/shared-module layer.
Context
Discovered while fixing the single-buffer loop=False "no sound" / stuck-playing bugs in #10539 (PR #11085). This double-buffer case was deliberately scoped out of that PR.
- Lingua principale
- C
- Stelle
- 4.6k
- Fork
- 1.4k
- Merge medio
- 1g 7h
- PR unite (30g)
- 166
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di adafruit/circuitpython
-
board breaks api
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
adafruit/circuitpython#11099 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
storage usb zephyr
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
adafruit/circuitpython#11531 ·
I maintainer di solito rispondono entro 1 giorno
-
Move silabs to ZephyrApertasilabs
Difficoltà 5/5 Più di una settimana Idoneità per principianti 20/100
adafruit/circuitpython#11507 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Feature/API request: portable camera capture across ESP-IDF, Zephyr, and parallel interfacesForse già presa @tannewt l’ha presa 1 giorno fa. Apertacircuitpython api displayio enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
adafruit/circuitpython#11505 · 5 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 38/100
adafruit/circuitpython#11472 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di adafruit/circuitpython
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
severity: low
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
luainkernel/lunatik#1853 ·
I maintainer di solito rispondono entro 1 giorno
-
encoding.binary: bounds check guard is compiled away, so decode functions read past the sliceAperta
Difficoltà 2/5 Mezza giornata Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
resetes12/pokeemerald#204 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 6 giorni