audiobusio
– Support for audio input and output over digital buses
The audiobusio
module contains classes to provide access to audio IO
over digital buses. These protocols are used to communicate audio to other
chips in the same circuit. It doesn’t include audio interconnect protocols
such as S/PDIF.
All classes change hardware state and should be deinitialized when they
are no longer needed. To do so, either call deinit()
or use a
context manager.
Available on these boards
- class audiobusio.I2SOut(bit_clock: microcontroller.Pin, word_select: microcontroller.Pin, data: microcontroller.Pin, *, main_clock: microcontroller.Pin | None = None, left_justified: bool = False)
Output an I2S audio signal
Create a I2SOut object associated with the given pins.
- Parameters:
bit_clock (Pin) – The bit clock (or serial clock) pin
word_select (Pin) – The word select (or left/right clock) pin
data (Pin) – The data pin
main_clock (Pin) – The main clock pin
left_justified (bool) – True when data bits are aligned with the word select clock. False when they are shifted by one to match classic I2S protocol.
Simple 8ksps 440 Hz sine wave on Metro M0 Express using UDA1334 Breakout:
import audiobusio import audiocore import board import array import time import math # Generate one period of sine wave. length = 8000 // 440 sine_wave = array.array("H", [0] * length) for i in range(length): sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15) sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000) i2s = audiobusio.I2SOut(board.D1, board.D0, board.D9) i2s.play(sine_wave, loop=True) time.sleep(1) i2s.stop()
Playing a wave file from flash:
import board import audiocore import audiobusio import digitalio f = open("cplay-5.1-16bit-16khz.wav", "rb") wav = audiocore.WaveFile(f) a = audiobusio.I2SOut(board.D1, board.D0, board.D9) print("playing") a.play(wav) while a.playing: pass print("stopped")
- __exit__() None
Automatically deinitializes the hardware when exiting a context. See Lifetime and ContextManagers for more info.
- play(sample: circuitpython_typing.AudioSample, *, loop: bool = False) None
Plays the sample once when loop=False and continuously when loop=True. Does not block. Use
playing
to block.Sample must be an
audiocore.WaveFile
,audiocore.RawSample
,audiomixer.Mixer
oraudiomp3.MP3Decoder
.The sample itself should consist of 8 bit or 16 bit samples.
- class audiobusio.PDMIn(clock_pin: microcontroller.Pin, data_pin: microcontroller.Pin, *, sample_rate: int = 16000, bit_depth: int = 8, mono: bool = True, oversample: int = 64, startup_delay: float = 0.11)
Record an input PDM audio stream
Create a PDMIn object associated with the given pins. This allows you to record audio signals from the given pins. Individual ports may put further restrictions on the recording parameters. The overall sample rate is determined by
sample_rate
xoversample
, and the total must be 1MHz or higher, sosample_rate
must be a minimum of 16000.- Parameters:
clock_pin (Pin) – The pin to output the clock to
data_pin (Pin) – The pin to read the data from
sample_rate (int) – Target sample_rate of the resulting samples. Check
sample_rate
for actual value. Minimum sample_rate is about 16000 Hz.bit_depth (int) – Final number of bits per sample. Must be divisible by 8
mono (bool) – True when capturing a single channel of audio, captures two channels otherwise
oversample (int) – Number of single bit samples to decimate into a final sample. Must be divisible by 8
startup_delay (float) – seconds to wait after starting microphone clock to allow microphone to turn on. Most require only 0.01s; some require 0.1s. Longer is safer. Must be in range 0.0-1.0 seconds.
Limitations: On SAMD and RP2040, supports only 8 or 16 bit mono input, with 64x oversampling. On nRF52840, supports only 16 bit mono input at 16 kHz; oversampling is fixed at 64x. Not provided on nRF52833 for space reasons. Not available on Espressif.
For example, to record 8-bit unsigned samples to a buffer:
import audiobusio import board # Prep a buffer to record into b = bytearray(200) with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000) as mic: mic.record(b, len(b))
To record 16-bit unsigned samples to a buffer:
import audiobusio import board # Prep a buffer to record into. b = array.array("H", [0] * 200) with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16) as mic: mic.record(b, len(b))
- record(destination: circuitpython_typing.WriteableBuffer, destination_length: int) None
Records destination_length bytes of samples to destination. This is blocking.
An IOError may be raised when the destination is too slow to record the audio at the given rate. For internal flash, writing all 1s to the file before recording is recommended to speed up writes.
- Returns:
The number of samples recorded. If this is less than
destination_length
, some samples were missed due to processing time.