Audio Playback
When an alarm fires, the alarm audio file is streamed from LittleFS (flash storage) through the MAX98357A amplifier.
This page covers the higher-level playback orchestration. The low-level I2S streaming is in the audio driver doc.
Audio Commands
typedef enum {
AUDIO_CMD_PLAY,
AUDIO_CMD_STOP,
AUDIO_CMD_SET_VOLUME,
} audio_cmd_type_t;
typedef struct {
audio_cmd_type_t type;
char path[64]; // for PLAY
uint8_t volume; // for SET_VOLUME (0–100)
} audio_cmd_t;
extern QueueHandle_t audio_cmd_queue;
Starting and Stopping Playback
From the main task, when an alarm fires:
audio_cmd_t cmd = {
.type = AUDIO_CMD_PLAY,
};
strncpy(cmd.path, fired_alarm.audio_file, sizeof(cmd.path));
xQueueSend(audio_cmd_queue, &cmd, 0);
When the user presses SNOOZE or DISMISS:
audio_cmd_t stop = { .type = AUDIO_CMD_STOP };
xQueueSend(audio_cmd_queue, &stop, 0);
Fade-In Behaviour
The alarm starts at zero volume and ramps to full over 30 seconds. This is kinder for waking up than an immediate full-volume burst.
The fade is applied in the audio driver's playback loop (see audio driver).
To adjust the fade duration, expose it as an sdkconfig item:
config ALARM_FADE_SECONDS
int "Alarm volume fade-in duration (seconds)"
default 30
range 0 120
Looping
The alarm should play on repeat until dismissed or snoozed. After the WAV file ends, restart it:
// In the audio task playback loop:
do {
fseek(f, info.data_offset, SEEK_SET); // rewind to start of PCM data
// stream file...
} while (!audio_stop_requested);
File Selection
Each alarm stores the path to its audio file (alarm.audio_file). The web interface
allows uploading custom WAV files to /lfs/alarms/ and selecting them per alarm.
A fallback: if the file in the alarm does not exist, fall back to
/lfs/alarms/alarm.wav. Log an error so the issue is visible in the serial monitor.
FILE *f = fopen(alarm.audio_file, "rb");
if (!f) {
ESP_LOGW("audio", "File not found: %s, using default", alarm.audio_file);
f = fopen("/lfs/alarms/alarm.wav", "rb");
}
if (!f) {
ESP_LOGE("audio", "No alarm audio available");
return;
}
Volume Control
The MAX98357A hardware gain is fixed by the GAIN resistor. Software volume is applied by
scaling PCM samples in the driver. Expose a volume setting (0–100%) stored in NVS.
At volume 100%, the scale factor is 1.0 (no scaling). At 50%, it is 0.5. At 0% it is 0.0 (silence — but you still need to drain the I2S buffer to prevent the amp from outputting a DC offset hum).