target_os=none only.Expand description
A device abstraction for playing audio clips over I²S hardware, with runtime sequencing and volume control.
This page provides the primary documentation for generated audio player types and clip utilities.
Audio clip sample data is defined at compile time as static values. At runtime, you select which clips to play and in what order. Playback runs in the background while the application does other work. Volume can be adjusted on the fly, and playback can be stopped or interrupted mid-clip. Audio samples are stored in flash. Only a small DMA buffer is used at runtime.
Supported audio formats
- Any sample rate
- 16-bit signed little-endian PCM audio data (
s16le) - Mono input audio (duplicated to left/right on I²S output)
After reading the examples below, see also:
audio_player!- Macro to generate an audio player struct type (includes syntax details). SeeAudioPlayerGeneratedfor a sample of a generated type.AudioPlayerGenerated- Sample struct type showing methods and associated constants generated byaudio_player!.audio_clip!- Macro to “compile in” an audio clip from an external file (includes syntax details). SeeAudioClipGeneratedfor a sample of a generated items.AudioClipGenerated- Sample module showingAudioClipandaudio_clip()generated byaudio_clip!.AudioClipBuf- Sized, const-friendly storage for static audio clip data. You can write your own compile-time (const fn) clip transforms usingAudioClipBuf::newandAudioClipBuf::samples.AudioClip- Unsized view of static audio clip data.&AudioClip(of varying lengths) can be sequenced together.
§Example: Play “Mary Had a Little Lamb” (Phrase) Once
This example plays the opening phrase (E D C D E E E) and then stops.
use device_envoy::{Result, audio_player::{AtEnd, Volume, audio_player, samples_ms, VOICE_22050_HZ}};
// Generate `AudioPlayer8`, a struct type with the specified configuration.
audio_player! {
AudioPlayer8 {
data_pin: PIN_8,
bit_clock_pin: PIN_9,
word_select_pin: PIN_10,
sample_rate_hz: VOICE_22050_HZ, // Convenience constant for this example; any hardware-supported sample rate can be used.
max_volume: Volume::percent(50),
}
}
async fn example(spawner: embassy_executor::Spawner) -> Result<Infallible> {
// Define REST_MS as a static clip of silence, 80 milliseconds long.
static REST_MS: samples_ms! { AudioPlayer8, 80 } = AudioPlayer8::silence();
// Define each note as a static clip of a sine wave at the appropriate frequency, 220 ms long.
static NOTE_E4: samples_ms! { AudioPlayer8, 220 } = AudioPlayer8::tone(330);
static NOTE_D4: samples_ms! { AudioPlayer8, 220 } = AudioPlayer8::tone(294);
static NOTE_C4: samples_ms! { AudioPlayer8, 220 } = AudioPlayer8::tone(262);
let p = embassy_rp::init(Default::default());
// Create an `AudioPlayer8` instance with the specified pins and resources.
let audio_player8 = AudioPlayer8::new(p.PIN_8, p.PIN_9, p.PIN_10, p.PIO0, p.DMA_CH0, spawner)?;
audio_player8.play(
[
&NOTE_E4, &REST_MS,
&NOTE_D4, &REST_MS,
&NOTE_C4, &REST_MS,
&NOTE_D4, &REST_MS,
&NOTE_E4, &REST_MS,
&NOTE_E4, &REST_MS,
&NOTE_E4,
],
AtEnd::Stop,
);
// Audio plays in the background while we can do other things here, like blink an LED or read a button.
core::future::pending().await // run forever
}§Example: Compiling in an External Audio Clip and Runtime Volume Changes
This example shows how to “compile in” an audio clip from an external file, adjust its loudness at compile time, and then play it in a loop while changing the volume while it plays. This also demonstrates how to stop playback and reset the volume.
use device_envoy::{
Result,
audio_player::{
AtEnd, Gain, Volume, audio_clip, audio_player, samples_ms, VOICE_22050_HZ,
},
button::{Button, PressedTo},
};
use embassy_futures::select::{Either, select};
use embassy_time::{Duration, Timer};
audio_player! {
AudioPlayer10 {
data_pin: PIN_8,
bit_clock_pin: PIN_9,
word_select_pin: PIN_10,
sample_rate_hz: VOICE_22050_HZ,
pio: PIO0, // optional, defaults to PIO0
dma: DMA_CH1, // optional, defaults to DMA_CH0
max_clips: 8, // optional, defaults to 16
max_volume: Volume::spinal_tap(11), // optional, defaults to Volume::MAX
initial_volume: Volume::spinal_tap(5), // optional, defaults to Volume::MAX
}
}
// Define a `const` function that, if called, will return the audio from this file.
audio_clip! {
Nasa {
sample_rate_hz: VOICE_22050_HZ, // To avoid a compiler error, this must match the player sample rate.
file: concat!(env!("CARGO_MANIFEST_DIR"), "/examples/data/audio/nasa_22k.s16"),
}
}
async fn example(spawner: embassy_executor::Spawner) -> Result<Infallible> {
// After lower its loudness (at compile time), materialize the clip as a static value.
static NASA: Nasa::AudioClip = Nasa::audio_clip().with_gain(Gain::percent(25));
static GAP: samples_ms! { AudioPlayer10, 80 } = AudioPlayer10::silence();
let p = embassy_rp::init(Default::default());
let mut button = Button::new(p.PIN_13, PressedTo::Ground);
let audio_player10 =
AudioPlayer10::new(p.PIN_8, p.PIN_9, p.PIN_10, p.PIO0, p.DMA_CH1, spawner)?;
const VOLUME_STEPS_PERCENT: [u8; 7] = [50, 25, 12, 6, 3, 1, 0];
loop {
// Wait for user input before starting.
button.wait_for_press().await;
// Start playing the NASA clip, over and over.
audio_player10.play([&NASA, &GAP], AtEnd::Loop);
// Lower runtime volume over time, unless the button is pressed.
for volume_percent in VOLUME_STEPS_PERCENT {
match select(
button.wait_for_press(),
Timer::after(Duration::from_secs(1)),
)
.await
{
Either::First(()) => {
// Button pressed: leave inner loop.
break;
}
Either::Second(()) => {
// Timer elapsed: lower volume and keep looping.
audio_player10.set_volume(Volume::percent(volume_percent));
}
}
}
audio_player10.stop();
audio_player10.set_volume(AudioPlayer10::INITIAL_VOLUME);
}
core::future::pending().await // run forever
}Modules§
- audio_
clip_ generated - Module containing
AudioClipGenerated, the sample module generated by theaudio_clip!macro. - audio_
player_ generated - Module containing
AudioPlayerGenerated, the sample struct type generated by theaudio_player!macro.
Macros§
- audio_
clip - Macro to “compile in” an audio clip from an external file (includes syntax details). See
AudioClipGeneratedfor a sample of generated items. - audio_
player - Macro to generate an audio player struct type (includes syntax details). See
AudioPlayerGeneratedfor a sample of a generated type. - samples_
ms - Macro that expands to an
AudioClipBuftype sized from a player type and milliseconds.
Structs§
- Audio
Clip - Unsized view of static audio clip data.
&AudioClipvalues of different lengths can be sequenced together. - Gain
- Relative loudness adjustment for audio clips.
- Volume
- Absolute playback loudness setting for the whole player.
Enums§
- AtEnd
- End-of-sequence behavior for playback.
- Audio
Format - Audio clip source formats for
audio_clip!. Currently, only one format is supported.
Constants§
- CD_
44100_ HZ - Compact-disc sample rate.
- NARROWBAND_
8000_ HZ - Common audio sample-rate constants in hertz. Narrowband telephony sample rate.
- PRO_
48000_ HZ - Pro-audio sample rate.
- VOICE_
16000_ HZ - Wideband voice sample rate.
- VOICE_
22050_ HZ - Common low-memory voice/music sample rate.
Type Aliases§
- Audio
Clip Buf - Sized, const-friendly storage for static audio clip data.