File audio_driver.h¶
File List > espos_audio > include > espos_audio > audio_driver.h
Go to the documentation of this file
/* SPDX-FileCopyrightText: 2026 Dirk Wahrheit */
/* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include <cstddef>
#include <cstdint>
namespace espos_audio {
class AudioDriver {
public:
virtual ~AudioDriver() = default;
virtual void init() = 0;
virtual bool ready() const = 0;
virtual uint32_t sample_rate() const = 0;
virtual void play_pcm(const int16_t* samples, size_t frames) = 0;
virtual void play_cue(const int16_t* samples, size_t frames) {
play_pcm(samples, frames);
}
virtual void set_volume(uint8_t /*pct*/) {}
virtual void set_enabled(bool /*on*/) {}
// --- Streaming playback (voice / TTS) -----------------------------------
//
// A continuous stream, unlike play_pcm()'s disposable fixed clips: no
// length cap, no per-chunk silence tail (that would gap the audio), and
// write_stream() BLOCKS to apply backpressure instead of dropping. The
// three calls bracket one audio-start / audio-chunk* / audio-stop span.
//
// Default no-ops so speaker-less boards still compile.
virtual bool begin_stream(uint32_t /*rate*/, uint8_t /*bits*/,
uint8_t /*channels*/) {
return false;
}
virtual size_t write_stream(const int16_t* /*samples*/, size_t /*frames*/) {
return 0;
}
virtual void end_stream() {}
// --- Microphone capture (voice-in) --------------------------------------
//
// Default: no capture. A board with a wired mic overrides these.
virtual bool can_capture() const { return false; }
virtual uint32_t capture_rate() const { return 16000; }
virtual size_t record_pcm(int16_t* /*out*/, size_t /*max_frames*/) {
return 0;
}
virtual void start_capture() {}
virtual void stop_capture() {}
// --- Dual-mic capture (on-device wake feed only) ------------------------
//
// The Waveshare panel has TWO live mics (ES7210 MIC1 + MIC2). The mono
// record_pcm() path above feeds STT/PTT one mic; esp-sr's AFE can take BOTH
// (format "MM") for noise suppression / beamforming, which lifts far-field
// wake SNR. These give the wake engine a SEPARATE 2-channel capture handle so
// the mono STT path stays byte-identical. The two handles open the SAME I2S
// RX, so they must never be open at once — the wake engine pauses (releasing
// the 2ch handle) before the STT pipeline runs, so they don't overlap.
//
// Default: unsupported (single-mic boards keep the mono "M" AFE).
virtual bool supports_dual_mic() const { return false; }
virtual void start_capture2() {}
virtual void stop_capture2() {}
virtual size_t record_pcm2(int16_t* /*out*/, size_t /*max_frames*/) {
return 0;
}
virtual void set_mic_gain_db(float /*db*/) {}
virtual float mic_gain_db() const { return 0.0f; }
// --- Diagnostic: per-input mic level probe --------------------------------
//
// Which physical ADC input each mic is wired to isn't documented for this
// board, so this measures all four ES7210 inputs to find the live mic(s).
// Levels for MIC1..MIC4 (index 0..3): RMS and peak magnitude of a short
// capture. A live mic tracks speech; an unpopulated input flatlines near the
// noise floor. Returns false if the board has no probe path. Must NOT be
// called while normal capture is running (it re-opens the ADC).
struct MicLevels {
uint16_t rms[4] = {0, 0, 0, 0};
uint16_t peak[4] = {0, 0, 0, 0};
};
virtual bool probe_mic_channels(MicLevels& /*out*/) { return false; }
};
} // namespace espos_audio