ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
micro_wake_word.h
Go to the documentation of this file.
1#pragma once
2
3#ifdef USE_ESP32
4
6#include "streaming_model.h"
7
10
15
16#ifdef USE_OTA_STATE_LISTENER
18#endif
19
20#include <freertos/event_groups.h>
21
22#include <frontend.h>
23#include <frontend_util.h>
24
26
27static constexpr uint16_t DEFAULT_RING_BUFFER_DURATION_MS = 120;
28
35
36class MicroWakeWord final : public Component
37#ifdef USE_OTA_STATE_LISTENER
38 ,
40#endif
41{
42 public:
43 void setup() override;
44 void loop() override;
45 float get_setup_priority() const override;
46 void dump_config() override;
47
48#ifdef USE_OTA_STATE_LISTENER
49 void on_ota_global_state(ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) override;
50#endif
51
52 void start();
53 void stop();
54
55 bool is_running() const { return this->state_ != State::STOPPED; }
56
57 void set_features_step_size(uint8_t step_size) { this->features_step_size_ = step_size; }
58
59 void set_ring_buffer_duration_ms(uint16_t duration_ms) { this->ring_buffer_duration_ms_ = duration_ms; }
60
62 this->microphone_source_ = microphone_source;
63 }
64
65 void set_stop_after_detection(bool stop_after_detection) { this->stop_after_detection_ = stop_after_detection; }
66
67 void set_task_stack_in_psram(bool task_stack_in_psram) { this->task_stack_in_psram_ = task_stack_in_psram; }
68
70
72
81 bool add_runtime_model(std::unique_ptr<WakeWordModel> model);
82
87 bool remove_runtime_model(const std::string &model_id);
88
91 WakeWordModel *get_model_by_id(const std::string &model_id);
92
94 std::vector<std::string> get_runtime_model_ids();
95
97 uint8_t get_features_step_size() const { return this->features_step_size_; }
98
99#ifdef USE_MICRO_WAKE_WORD_VAD
100 void add_vad_model(const uint8_t *model_start, size_t model_size, uint8_t probability_cutoff,
101 size_t sliding_window_size, size_t tensor_arena_size);
102
103 // Intended for the voice assistant component to fetch VAD status
104 bool get_vad_state() { return this->vad_state_; }
105#endif
106
107 // Intended for the voice assistant component to access which wake words are available
108 // Since these are pointers to the WakeWordModel objects, the voice assistant component can enable or disable them
109 std::vector<WakeWordModel *> get_wake_words();
110
111 protected:
115
116 std::weak_ptr<ring_buffer::RingBuffer> ring_buffer_;
117 std::vector<WakeWordModel *> wake_word_models_;
118 std::vector<std::unique_ptr<WakeWordModel>> runtime_models_;
119
120#ifdef USE_MICRO_WAKE_WORD_VAD
121 std::unique_ptr<VADModel> vad_model_;
122 bool vad_state_{false};
123#endif
124
125 bool pending_start_{false};
126 bool pending_stop_{false};
127
129
131
133 uint16_t ring_buffer_duration_ms_{DEFAULT_RING_BUFFER_DURATION_MS}; // at most a second, see the schema
134
135 // Audio frontend handles generating spectrogram features
136 struct FrontendConfig frontend_config_;
137 struct FrontendState frontend_state_;
138
139 // Handles managing the stop/state of the inference task
140 EventGroupHandle_t event_group_;
141
142 // Used to send messages about the models' states to the main loop
143 QueueHandle_t detection_queue_;
144
146
147 static void inference_task(void *params);
148
150 void suspend_task_();
152 void resume_task_();
153
157 bool try_lock_models_();
159 void unlock_models_();
160
161 void set_state_(State state);
162
171 bool generate_features_(const int16_t *audio_buffer, size_t samples_available,
172 int8_t features_buffer[PREPROCESSOR_FEATURE_SIZE], size_t *processed_samples);
173
177
179 void unload_models_();
180
184 bool update_model_probabilities_(const int8_t audio_features[PREPROCESSOR_FEATURE_SIZE]);
185};
186
187} // namespace esphome::micro_wake_word
188
189#endif // USE_ESP32
Helper for FreeRTOS static task management.
Definition static_task.h:18
void resume_task_()
Resumes the inference task.
microphone::MicrophoneSource * microphone_source_
void set_task_stack_in_psram(bool task_stack_in_psram)
void set_ring_buffer_duration_ms(uint16_t duration_ms)
void process_probabilities_()
Processes any new probabilities for each model.
bool remove_runtime_model(const std::string &model_id)
Removes a runtime-downloaded wake word model and frees its interpreter, arenas, and model buffer.
void set_stop_after_detection(bool stop_after_detection)
WakeWordModel * get_model_by_id(const std::string &model_id)
Returns the wake word model with the given id, or nullptr if none matches (compiled or runtime).
std::vector< WakeWordModel * > wake_word_models_
void suspend_task_()
Suspends the inference task.
uint8_t get_features_step_size() const
Returns the feature step size (ms) the frontend is configured for. Runtime models must match it.
std::vector< std::string > get_runtime_model_ids()
Returns the ids of all runtime-downloaded models. Must be called from the main loop.
Trigger< std::string > wake_word_detected_trigger_
void add_wake_word_model(WakeWordModel *model)
bool generate_features_(const int16_t *audio_buffer, size_t samples_available, int8_t features_buffer[PREPROCESSOR_FEATURE_SIZE], size_t *processed_samples)
Generates a spectrogram feature from an input buffer of audio samples.
void add_vad_model(const uint8_t *model_start, size_t model_size, uint8_t probability_cutoff, size_t sliding_window_size, size_t tensor_arena_size)
bool try_lock_models_()
Parks the inference task at a safe point (or verifies it isn't running) so the model lists may be mut...
bool add_runtime_model(std::unique_ptr< WakeWordModel > model)
Adds a runtime-downloaded wake word model.
bool update_model_probabilities_(const int8_t audio_features[PREPROCESSOR_FEATURE_SIZE])
Runs an inference with each model using the new spectrogram features.
std::vector< std::unique_ptr< WakeWordModel > > runtime_models_
std::unique_ptr< VADModel > vad_model_
std::weak_ptr< ring_buffer::RingBuffer > ring_buffer_
void unlock_models_()
Releases the inference task parked by a successful try_lock_models_() call.
void set_features_step_size(uint8_t step_size)
void set_microphone_source(microphone::MicrophoneSource *microphone_source)
void unload_models_()
Deletes each model's TFLite interpreters and frees tensor arena memory.
std::vector< WakeWordModel * > get_wake_words()
void on_ota_global_state(ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) override
Trigger< std::string > * get_wake_word_detected_trigger()
Listener interface for global OTA state changes (includes OTA component pointer).
bool state
Definition fan.h:2