audio bus crypto display ez global gps keyboard mesh net radio sprite storage synth system wifi

Audio synthesis and playback via I2S DAC

Plays audio through the T-Deck speaker via I2S. Supports multiple formats: WAV files (PCM, 8/16-bit, mono/stereo), MP3 files (decoded with Helix), and raw PCM samples. Also provides tone synthesis for beeps and alerts. Use play() for automatic format detection, or play_wav()/play_mp3() directly. Audio output is mono at 44100Hz with volume control.

Functions

beep() Play a series of beeps (blocking)
ez.audio.beep(count, frequency, on_ms, off_ms)
Plays one or more beeps with configurable timing. This function blocks until all beeps complete. Good for alerts and notifications. Parameters are constrained to safe ranges (count: 1-10, frequency: 100-5000Hz, timing: 10-500ms).
ParameterDescription
countNumber of beeps (default 1)
frequencyTone frequency in Hz (default 1000)
on_msBeep duration in ms (default 100)
off_msPause between beeps in ms (default 50)
ez.audio.beep()           -- Single default beep
ez.audio.beep(2)          -- Two beeps
ez.audio.beep(3, 2000)    -- Three high-pitched beeps
ez.audio.beep(1, 500, 200, 0)  -- One low 200ms beep
get_volume() → integer Get current volume level
ez.audio.get_volume() -> integer
Returns the current master volume setting. Use this to save/restore volume levels or display the current volume in a settings screen.
Returns: Volume level 0-100
local vol = ez.audio.get_volume()
print("Current volume:", vol .. "%")
is_playing() → boolean Check if audio is playing
ez.audio.is_playing() -> boolean
Returns true if a tone or sample is currently playing. Useful for waiting until audio completes before starting another sound.
Returns: true if playing
ez.audio.play_tone(440, 500)
while ez.audio.is_playing() do
ez.system.delay(10)
end
print("Tone finished!")
play() → boolean Play an audio file (auto-detects format)
ez.audio.play(filename) -> boolean
Plays an audio file, automatically detecting the format from the file extension. Supports .wav, .mp3, and .pcm formats. Files are loaded from the /sounds/ directory (LittleFS) by default, or from SD card if the path starts with /sd/. This is the recommended function for playing audio files.
ParameterDescription
filenamePath to audio file (.wav, .mp3, or .pcm)
Returns: true if played successfully, false on error
-- Play different formats
ez.audio.play("click.wav")
ez.audio.play("notify.mp3")
ez.audio.play("beep.pcm")
-- Play from SD card
ez.audio.play("/sd/sounds/music.mp3")
play_mp3() → boolean Play an MP3 audio file
ez.audio.play_mp3(filename) -> boolean
Plays an MP3 file from the /sounds/ directory or SD card. Supports any valid MP3 file (MPEG Layer 3). Audio is decoded in real-time using the Helix decoder. This function blocks until playback completes. MP3 is ideal for longer audio clips and music due to its compression.
ParameterDescription
filenamePath to .mp3 file (relative to /sounds/ for LittleFS, or full path starting with /sd/ for SD card)
Returns: true if played successfully, false on error
-- Play from internal storage
ez.audio.play_mp3("startup.mp3")
-- Play from SD card
ez.audio.play_mp3("/sd/music/song.mp3")
play_preloaded() → boolean Play a preloaded audio sample
ez.audio.play_preloaded(handle) -> boolean
Plays an audio sample that was previously loaded with preload(). This has minimal latency since the audio data is already in memory. The function blocks until playback completes. For non-blocking playback, see start_preloaded().
ParameterDescription
handleHandle returned by preload()
Returns: true if played, false if invalid handle
local click = ez.audio.preload("click.wav")
-- Play instantly when button is pressed
ez.audio.play_preloaded(click)
play_preloaded_async() → boolean Play a preloaded sample without blocking.
ez.audio.play_preloaded_async(handle) -> boolean
Starts playback on the background audio task and returns immediately. Subsequent calls replace the currently-playing sample, which is appropriate for UI click/tap feedback where only the most recent sound needs to complete. Use is_playing() to check whether a sample is still streaming.
ParameterDescription
handleHandle returned by preload()
Returns: true if playback started, false if handle is invalid
local click = ez.audio.preload("tap_01.pcm")
-- Fire and forget — UI stays responsive
ez.audio.play_preloaded_async(click)
play_sample() → boolean Play a PCM sample file from LittleFS
ez.audio.play_sample(filename) -> boolean
Plays a raw PCM audio file from the /sounds/ directory. Files must be 16-bit signed, 22050Hz mono format (.pcm extension). The function blocks until playback completes. Use for sound effects, alerts, or short audio clips. Convert audio files using: ffmpeg -i input.wav -f s16le -ar 22050 -ac 1 output.pcm
ParameterDescription
filenamePath to .pcm file (relative to /sounds/, extension optional)
Returns: true if played successfully, false if file not found
-- Play a notification sound
ez.audio.play_sample("notify")
-- Play with full path
ez.audio.play_sample("alerts/warning.pcm")
play_tone() → boolean Play a tone for specified duration
ez.audio.play_tone(frequency, duration_ms) -> boolean
Plays a sine wave tone at the given frequency. The tone plays in the background and stops automatically after the duration. Non-blocking, so your code continues while the tone plays. Use is_playing() to check status.
ParameterDescription
frequencyFrequency in Hz (20-20000)
duration_msDuration in milliseconds
Returns: true if started successfully
-- Play a 440Hz (A4) beep for half a second
ez.audio.play_tone(440, 500)
-- Play a higher alert tone
ez.audio.play_tone(880, 200)
play_wav() → boolean Play a WAV audio file
ez.audio.play_wav(filename) -> boolean
Plays a WAV file from the /sounds/ directory or SD card. Supports PCM format with 8 or 16 bit samples, mono or stereo, at any sample rate (resampled to 44100Hz). This function blocks until playback completes. WAV is ideal for short sound effects and UI feedback.
ParameterDescription
filenamePath to .wav file (relative to /sounds/ for LittleFS, or full path starting with /sd/ for SD card)
Returns: true if played successfully, false on error
-- Play from internal storage
ez.audio.play_wav("click.wav")
-- Play from SD card
ez.audio.play_wav("/sd/music/song.wav")
preload() → integer | nil Preload an audio file into memory for instant playback
ez.audio.preload(filename) -> integer | nil
Loads a WAV or PCM file entirely into PSRAM for zero-latency playback. Returns a handle (integer) that can be passed to play_preloaded(). Useful for UI feedback sounds and game audio where latency matters. Maximum 8 preloaded sounds at once. Call unload() when the sound is no longer needed.
ParameterDescription
filenamePath to .wav or .pcm file
Returns: Handle (1-8) on success, nil on error (file not found, memory full, or too many preloaded)
-- Preload UI sounds at startup
local click = ez.audio.preload("click.wav")
local beep = ez.audio.preload("beep.wav")
-- Later, play with zero latency
ez.audio.play_preloaded(click)
set_frequency() → boolean Set playback frequency for continuous tones
ez.audio.set_frequency(frequency) -> boolean
Changes the frequency of the tone generator. If a tone is already playing, the frequency changes immediately (smooth transition). Combine with start() and stop() for custom tone patterns.
ParameterDescription
frequencyFrequency in Hz (20-20000)
Returns: true if valid frequency
ez.audio.start()
for freq = 200, 800, 50 do
ez.audio.set_frequency(freq)
ez.system.delay(50)
end
ez.audio.stop()
set_volume() Set audio volume level
ez.audio.set_volume(level)
Sets the master volume for all audio output. Affects both tones and samples. The setting persists until changed. Volume 0 is silent, 100 is max.
ParameterDescription
levelVolume level 0-100
ez.audio.set_volume(50)  -- Half volume
ez.audio.beep()
ez.audio.set_volume(100) -- Full volume
start() Start continuous tone at current frequency
ez.audio.start()
Starts playing a continuous tone at the current frequency (set via set_frequency, default 440Hz). The tone plays until stop() is called. Use this with set_frequency() for custom sound effects like sirens or sweeps.
ez.audio.set_frequency(1000)
ez.audio.start()
-- Tone plays continuously until stopped
ez.system.delay(2000)
ez.audio.stop()
stop() Stop audio playback
ez.audio.stop()
Immediately stops any playing tone or sample. Also clears any pending timed duration, so the audio won't resume.
ez.audio.start()  -- Start continuous tone
ez.system.delay(1000)
ez.audio.stop()   -- Stop after 1 second
unload() Free a preloaded audio sample
ez.audio.unload(handle)
Releases the memory used by a preloaded sample. Call this when the sound is no longer needed to free PSRAM for other uses. After unloading, the handle is invalid and cannot be played.
ParameterDescription
handleHandle returned by preload()
local click = ez.audio.preload("click.wav")
-- ... use it ...
ez.audio.unload(click)  -- Free memory