mirror of
https://github.com/esphome/esphome.git
synced 2026-09-18 10:38:38 +00:00
[audio][media_player][speaker] WAV decoding is no longer always built (#16244)
This commit is contained in:
@@ -64,8 +64,7 @@ class AudioData:
|
||||
flac_support: bool = False
|
||||
mp3_support: bool = False
|
||||
opus_support: bool = False
|
||||
# WAV defaults to True for backward compatibility; will become opt-in in a future release
|
||||
wav_support: bool = True
|
||||
wav_support: bool = False
|
||||
micro_decoder_support: bool = False
|
||||
flac: FlacOptions = field(default_factory=FlacOptions)
|
||||
mp3: Mp3Options = field(default_factory=Mp3Options)
|
||||
@@ -428,3 +427,5 @@ async def to_code(config):
|
||||
add_idf_sdkconfig_option(
|
||||
"CONFIG_OPUS_PSEUDOSTACK_SIZE", data.opus.pseudostack.size
|
||||
)
|
||||
if data.wav_support:
|
||||
cg.add_define("USE_AUDIO_WAV_SUPPORT")
|
||||
|
||||
@@ -55,8 +55,10 @@ const char *audio_file_type_to_string(AudioFileType file_type) {
|
||||
case AudioFileType::OPUS:
|
||||
return "OPUS";
|
||||
#endif
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
case AudioFileType::WAV:
|
||||
return "WAV";
|
||||
#endif
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
@@ -71,9 +73,11 @@ AudioFileType detect_audio_file_type(const char *content_type, const char *url)
|
||||
return AudioFileType::MP3;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
if (strcasecmp(content_type, "audio/wav") == 0) {
|
||||
return AudioFileType::WAV;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AUDIO_FLAC_SUPPORT
|
||||
if (strcasecmp(content_type, "audio/flac") == 0 || strcasecmp(content_type, "audio/x-flac") == 0) {
|
||||
return AudioFileType::FLAC;
|
||||
@@ -91,9 +95,11 @@ AudioFileType detect_audio_file_type(const char *content_type, const char *url)
|
||||
|
||||
// Fallback to URL extension
|
||||
if (url != nullptr && url[0] != '\0') {
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
if (str_endswith_ignore_case(url, ".wav")) {
|
||||
return AudioFileType::WAV;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AUDIO_MP3_SUPPORT
|
||||
if (str_endswith_ignore_case(url, ".mp3")) {
|
||||
return AudioFileType::MP3;
|
||||
|
||||
@@ -116,7 +116,9 @@ enum class AudioFileType : uint8_t {
|
||||
#ifdef USE_AUDIO_OPUS_SUPPORT
|
||||
OPUS,
|
||||
#endif
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
WAV,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct AudioFile {
|
||||
|
||||
@@ -98,6 +98,7 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) {
|
||||
this->decoder_buffers_internally_ = true;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
case AudioFileType::WAV:
|
||||
this->wav_decoder_ = make_unique<esp_audio_libs::wav_decoder::WAVDecoder>();
|
||||
this->wav_decoder_->reset();
|
||||
@@ -109,6 +110,7 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) {
|
||||
this->output_transfer_buffer_->reallocate(this->free_buffer_required_);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case AudioFileType::NONE:
|
||||
default:
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
@@ -226,9 +228,11 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) {
|
||||
state = this->decode_opus_();
|
||||
break;
|
||||
#endif
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
case AudioFileType::WAV:
|
||||
state = this->decode_wav_();
|
||||
break;
|
||||
#endif
|
||||
case AudioFileType::NONE:
|
||||
default:
|
||||
state = FileDecoderState::IDLE;
|
||||
@@ -395,6 +399,7 @@ FileDecoderState AudioDecoder::decode_opus_() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
FileDecoderState AudioDecoder::decode_wav_() {
|
||||
if (!this->audio_stream_info_.has_value()) {
|
||||
// Header hasn't been processed
|
||||
@@ -441,6 +446,7 @@ FileDecoderState AudioDecoder::decode_wav_() {
|
||||
|
||||
return FileDecoderState::END_OF_FILE;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace audio
|
||||
} // namespace esphome
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
// esp-audio-libs
|
||||
#include <wav_decoder.h>
|
||||
|
||||
// micro-flac
|
||||
#ifdef USE_AUDIO_FLAC_SUPPORT
|
||||
#include <micro_flac/flac_decoder.h>
|
||||
@@ -33,6 +30,11 @@
|
||||
#include <micro_opus/ogg_opus_decoder.h>
|
||||
#endif
|
||||
|
||||
// esp-audio-libs
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
#include <wav_decoder.h>
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace audio {
|
||||
|
||||
@@ -56,7 +58,7 @@ class AudioDecoder {
|
||||
* @brief Class that facilitates decoding an audio file.
|
||||
* The audio file is read from a source (ring buffer or const data pointer), decoded, and sent to an audio sink
|
||||
* (ring buffer, speaker component, or callback).
|
||||
* Supports wav, flac, mp3, and ogg opus formats.
|
||||
* Supports flac, mp3, ogg opus, and wav formats (each enabled independently at compile time).
|
||||
*/
|
||||
public:
|
||||
/// @brief Allocates the output transfer buffer and stores the input buffer size for later use by add_source()
|
||||
@@ -119,7 +121,6 @@ class AudioDecoder {
|
||||
void set_pause_output_state(bool pause_state) { this->pause_output_ = pause_state; }
|
||||
|
||||
protected:
|
||||
std::unique_ptr<esp_audio_libs::wav_decoder::WAVDecoder> wav_decoder_;
|
||||
#ifdef USE_AUDIO_FLAC_SUPPORT
|
||||
FileDecoderState decode_flac_();
|
||||
std::unique_ptr<micro_flac::FLACDecoder> flac_decoder_;
|
||||
@@ -132,7 +133,10 @@ class AudioDecoder {
|
||||
FileDecoderState decode_opus_();
|
||||
std::unique_ptr<micro_opus::OggOpusDecoder> opus_decoder_;
|
||||
#endif
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
FileDecoderState decode_wav_();
|
||||
std::unique_ptr<esp_audio_libs::wav_decoder::WAVDecoder> wav_decoder_;
|
||||
#endif
|
||||
|
||||
std::unique_ptr<AudioReadableBuffer> input_buffer_;
|
||||
std::unique_ptr<AudioSinkTransferBuffer> output_transfer_buffer_;
|
||||
@@ -142,14 +146,18 @@ class AudioDecoder {
|
||||
|
||||
size_t input_buffer_size_{0};
|
||||
size_t free_buffer_required_{0};
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
size_t wav_bytes_left_{0};
|
||||
#endif
|
||||
|
||||
uint32_t potentially_failed_count_{0};
|
||||
uint32_t accumulated_frames_written_{0};
|
||||
uint32_t playback_ms_{0};
|
||||
|
||||
bool end_of_file_{false};
|
||||
#ifdef USE_AUDIO_WAV_SUPPORT
|
||||
bool wav_has_known_end_{false};
|
||||
#endif
|
||||
|
||||
bool decoder_buffers_internally_{false};
|
||||
|
||||
|
||||
@@ -193,6 +193,8 @@ def _validate_supported_local_file(config: list[ConfigType]) -> list[ConfigType]
|
||||
audio.request_mp3_support()
|
||||
elif media_file_type_str == str(audio.AUDIO_FILE_TYPE_ENUM["OPUS"]):
|
||||
audio.request_opus_support()
|
||||
elif media_file_type_str == str(audio.AUDIO_FILE_TYPE_ENUM["WAV"]):
|
||||
audio.request_wav_support()
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ def request_codecs_for_format_configs(
|
||||
audio.request_flac_support()
|
||||
audio.request_mp3_support()
|
||||
audio.request_opus_support()
|
||||
audio.request_wav_support()
|
||||
else:
|
||||
if "FLAC" in needed_formats:
|
||||
audio.request_flac_support()
|
||||
@@ -140,6 +141,8 @@ def request_codecs_for_format_configs(
|
||||
audio.request_mp3_support()
|
||||
if "OPUS" in needed_formats:
|
||||
audio.request_opus_support()
|
||||
if "WAV" in needed_formats:
|
||||
audio.request_wav_support()
|
||||
|
||||
|
||||
# Local config key constants
|
||||
|
||||
@@ -210,6 +210,8 @@ def _final_validate(config):
|
||||
audio.request_mp3_support()
|
||||
elif fmt_name == "OPUS":
|
||||
audio.request_opus_support()
|
||||
elif fmt_name == "WAV":
|
||||
audio.request_wav_support()
|
||||
break
|
||||
|
||||
return config
|
||||
|
||||
@@ -17,9 +17,12 @@ namespace speaker {
|
||||
// - Each stream has an individual speaker component for output
|
||||
// - Each stream is handled by an ``AudioPipeline`` object with two parts/tasks
|
||||
// - ``AudioReader`` handles reading from an HTTP source or from a PROGMEM flash set at compile time
|
||||
// - ``AudioDecoder`` handles decoding the audio file. All formats are limited to two channels and 16 bits per sample
|
||||
// - ``AudioDecoder`` handles decoding the audio file. All formats are limited to two channels and 16 bits per
|
||||
// sample.
|
||||
// Each format is enabled independently at compile time:
|
||||
// - FLAC
|
||||
// - MP3 (based on the libhelix decoder)
|
||||
// - Ogg Opus
|
||||
// - WAV
|
||||
// - Each task runs until it is done processing the file or it receives a stop command
|
||||
// - Inter-task communication uses a FreeRTOS Event Group
|
||||
|
||||
@@ -180,6 +180,7 @@
|
||||
#define USE_AUDIO_FLAC_SUPPORT
|
||||
#define USE_AUDIO_MP3_SUPPORT
|
||||
#define USE_AUDIO_OPUS_SUPPORT
|
||||
#define USE_AUDIO_WAV_SUPPORT
|
||||
#define USE_API
|
||||
#define USE_API_CLIENT_CONNECTED_TRIGGER
|
||||
#define USE_API_CLIENT_DISCONNECTED_TRIGGER
|
||||
|
||||
Reference in New Issue
Block a user