Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

zephyr-cp: audiobusio.I2SOut.playing never becomes False after a non-looping sample finishes

未关闭
#11,084 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
冷清
技术栈
c
领域
embedded-iot

调研方向

Start in ports/zephyr-cp/common-hal/audiobusio/I2SOut.c, tracing fill_buffer(), the audio thread's exit, and common_hal_audiobusio_i2sout_get_playing(). Then investigate how Zephyr reports that I2S draining has completed and how thread/slab resources are safely released. Done means a non-looping sample finishes draining without its tail being dropped, playing becomes false, and resources can be used safely by a subsequent play().

由索引模型根据 Issue 内容生成。

描述

audio bug zephyr

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.

Summary

On the zephyr-cp port, audiobusio.I2SOut has no end-of-playback detection. After a non-looping sample (loop=False) finishes, I2SOut.playing stays True indefinitely — it is only ever cleared by an explicit stop() (or a write error). So the common idiom

i2s.play(sample, loop=False)
while i2s.playing:
    pass

hangs forever.

Where

ports/zephyr-cp/common-hal/audiobusio/I2SOut.c

  • common_hal_audiobusio_i2sout_get_playing() simply returns self->playing.
  • self->playing is set False only in common_hal_audiobusio_i2sout_stop() and on an i2s_write error.
  • When a non-looping sample ends, fill_buffer() sets self->stopping = true and triggers I2S_TRIGGER_DRAIN; the audio thread then exits — but leaves self->playing == true.

Relationship to #10539

The single-buffer loop=False "no sound" bug (the final GET_BUFFER_DONE buffer being dropped before it was copied) was fixed for zephyr-cp as part of the #10539 work. This playing-never-clears problem is a separate, deeper gap and was deliberately scoped out, because a correct fix is non-trivial in the current design:

  • The audio thread cannot clean itself up (it can't k_thread_join/free from within itself, and setting playing = false there would break the next play(), which guards on playing).
  • Clearing it from get_playing() by calling stop() would issue I2S_TRIGGER_DROP, discarding the still-draining tail blocks (the DRAIN just triggered) and cutting off the end of the sample.
  • Doing it cleanly requires waiting until the I2S peripheral has actually finished draining (a driver-state query the code does not currently perform) before finalizing and freeing resources.

Suggested direction

Add drain-aware completion detection: once the sample is exhausted and the queued blocks have fully drained, clear playing and release the thread/slab resources — without dropping the tail. This likely needs a Zephyr I2S state query and/or coordination with the audio thread's exit.

Notes

  • Affects any non-looping sample on zephyr-cp, not just single-buffer RawSample; WaveFile with loop=False would exhibit the same stuck playing.
  • Other ports (espressif, nordic, raspberrypi, atmel-samd, ...) clear playing on completion; this gap is specific to zephyr-cp.
主要语言
C
星标
4.6k
派生
1.4k
平均合并
1 天 8 小时
30 天内合并 PR
153

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

adafruit/circuitpython 的其他 Issue

查看 adafruit/circuitpython 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。