Repository navigation
Releases: PyDevices/audioif
Releases · PyDevices/audioif
Release list
v0.1.2
- Record while you play, on one I2S port.
_audioif.rx_open()reads the RX
half of the channel pair whileaudiobusio.I2SOutplays on the TX half, so a
board whose speaker codec and microphone share a port (the ESP32-P4 boards)
can do both at once. The output and the recorder each hold the channel and it
closes when the last one lets go.I2SOuttakesdata_in=to open the pair,
keeps the channel stereo while it can carry a recording, and refuses a sample
at another rate while a recorder is open instead of retuning the bus under
it.retarget()now also refuses a tail with another channel count, which
used to play at twice or half speed.
(#25) audiobusio.I2SOut.starved()reads 0 through a clean playback. It was
the wire's position minus what the pump had fed, and that difference also
carries how full the DMA ring is, so a clean playback on the ESP32-P4 read
tens to thousands of bytes, agc.collect()made it fall, and a real
underrun read low by the ring's depth. It now counts two events in the DMA's
interrupt: a descriptor started with nothing written into it (the ring ran
dry), and a gap of more than two descriptor periods between finished
descriptors (the DMA itself stood still, as a flash erase does on the
ESP32-S3). Counting starts at the pump's first write afterplay()or
resume(), stops atpause(), and onlyplay()clears it, so the number
never goes down and a pause is not counted.
(#26)audiobusio.I2SOut(bit_clock, word_select, data)withoutport=opens. The
default used to reach the driver as port -1 and fail withEIO; it now lets
the driver choose the port, as on CircuitPython.
(#27)
v0.1.1
audiobusio.I2SOut.starved()reports silence on the wire, in bytes. It
used to return the engine's sink-refusal count, which needs the pump running
and the DMA full -- the one case that is not an underrun -- so it read 0
through a stall that plainly starved the wire, on both chips. It now reports
audio that should have played and did not, taking whichever of two witnesses
is further on: the DMA's own byte count, which is right when the ring runs
dry andauto_clearclocks zeros, and the wall clock, which is right when
the DMA itself stops -- which is what a flash erase does on the ESP32-S3,
measured at 1.14 seconds of audio lost from one 32 kB write with the pump
sitting level with the DMA throughout. Neither witness alone sees both. The
old number keeps its meaning under its real name,sink_timeouts(), and
_audioifgainsi2s_sink_bytes()andi2s_starved_bytes()so the
subtraction is checkable from Python. Silence that was asked for -- a
stopped or paused output -- is not charged: the count restarts wherever
feeding legitimately begins, and arms for one ring period so the wait for
the pump's first block reads as the latency it is.
(#8)_audioif.lock_probe()asks FreeRTOS whether it refuses a give of the
pump mutex from a task that does not own it, and one with nobody holding it.
ESP32 only; nothing in the audio path calls it.
(#14)__revision__says which audioif a firmware was built from: a
git describeof this repository, orunknownwithout git.
(#17)- One
include()line adds this module to your own MicroPython 1.29 build.
manifest.pynames the C module withc_module(), and the README shows the
line. (#19) micropython.cmakeskips the driver on CMake ports other than esp32, so an
rp2 build that includes it no longer fails on ESP-IDF's I2S header.
(#15)tests/run_probes.shruns CI's probes against a desktop interpreter, and
refuses one that was not built from this checkout's HEAD. CI builds against
audiodsp v0.5.1 rather than its default branch.
(#6)- A newcomer's guide in
docs/newcomers.md.
Add it to your own MicroPython build beside audiodsp with one include() line; the README shows it. It is a firmware C module, so there is nothing on PyPI or MIP to install.
v0.1.0
- This repository is
audioif, the audio hardware layer, and public. It was
the privateaudiopumpdriver repo until today; the name belonged to the DSP
repository, which is audiodsp now. - First public shape. The audio pump's platform driver: the
_audioifC
module (i2s_startwith a one-port and a two-port form,i2s_stop,
i2s_dma_bytes,i2s_rx_bytes,Input,rt_probe) and a
CircuitPython-shapedaudiobusio.I2SOut(play,stop,pause,resume,
playing,paused,deinit, plusretarget(),.statusandstarved()).
Drivers for ESP32 (a pinned FreeRTOS task and the I2S peripheral), unix
(pthread) and Windows (_beginthreadex); WebAssembly and any port without
threads run the engine throughaudiopump.service()and need nothing from
here. - The portable half — the pull loop, the ring, the event queue, the tap and the
lock as port hooks — lives in
audiodsp. This repository binds to
it by definingaudiodsp_port_driver(). - Proved on an ESP32-P4 (ES8311 codec) and an ESP32-S3 (MAX98357A amplifier),
on unix and on Windows. What is open is in the issues.
Build it beside audiodsp in a cmods workspace; the README has the two links and the command. It is a firmware C module, so there is nothing on PyPI or MIP to install.