16 static const UBaseType_t RESAMPLER_TASK_PRIORITY = 1;
18 static const uint32_t TRANSFER_BUFFER_DURATION_MS = 50;
20 static const uint32_t TASK_DELAY_MS = 20;
21 static const uint32_t TASK_STACK_SIZE = 3072;
23 static const char *
const TAG =
"resampler_speaker";
41 ESP_LOGE(TAG,
"Failed to create event group");
47 [
this](uint32_t new_playback_ms, uint32_t remainder_us, uint32_t pending_ms, uint32_t write_timestamp) {
50 int32_t adjusted_playback_ms =
static_cast<int32_t
>(new_playback_ms) + adjustment;
56 uint32_t event_group_bits = xEventGroupGetBits(this->
event_group_);
59 ESP_LOGD(TAG,
"Starting resampler task");
60 xEventGroupClearBits(this->
event_group_, ResamplingEventGroupBits::STATE_STARTING);
64 this->
status_set_error(
"Resampler task failed to allocate the internal buffers");
65 xEventGroupClearBits(this->
event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM);
69 this->
status_set_error(
"Cannot resample due to an unsupported audio stream");
70 xEventGroupClearBits(this->
event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED);
75 xEventGroupClearBits(this->
event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL);
80 ESP_LOGD(TAG,
"Started resampler task");
82 xEventGroupClearBits(this->
event_group_, ResamplingEventGroupBits::STATE_RUNNING);
85 ESP_LOGD(TAG,
"Stopping resampler task");
86 xEventGroupClearBits(this->
event_group_, ResamplingEventGroupBits::STATE_STOPPING);
90 ESP_LOGD(TAG,
"Stopped resampler task");
97 esp_err_t err = this->
start_();
103 case ESP_ERR_INVALID_STATE:
104 this->
status_set_error(
"Failed to start resampler: resampler task failed to start");
107 this->
status_set_error(
"Failed to start resampler: not enough memory for task stack");
137 size_t bytes_written = 0;
142 std::shared_ptr<RingBuffer> temp_ring_buffer = this->
ring_buffer_.lock();
143 bytes_written = temp_ring_buffer->write_without_replacement(data, length, ticks_to_wait);
147 return bytes_written;
179 return ESP_ERR_NO_MEM;
188 return ESP_ERR_INVALID_STATE;
222 return ESP_ERR_INVALID_STATE;
228 bool has_ring_buffer_data =
false;
230 has_ring_buffer_data = (this->
ring_buffer_.lock()->available() > 0);
256 std::unique_ptr<audio::AudioResampler> resampler =
264 std::shared_ptr<RingBuffer> temp_ring_buffer =
267 if (temp_ring_buffer.use_count() == 0) {
268 err = ESP_ERR_NO_MEM;
280 }
else if (err == ESP_ERR_NO_MEM) {
282 }
else if (err == ESP_ERR_NOT_SUPPORTED) {
287 while (err == ESP_OK) {
288 uint32_t event_bits = xEventGroupGetBits(this_resampler->
event_group_);
295 int32_t ms_differential = 0;
312 vTaskDelete(
nullptr);
virtual void set_volume(float volume)
uint8_t get_channels() const
void add_audio_output_callback(std::function< void(uint32_t, uint32_t, uint32_t, uint32_t)> &&callback)
Callback function for sending the duration of the audio written to the speaker since the last callbac...
uint8_t get_bits_per_sample() const
void set_volume(float volume) override
Volume state changes are passed to the parent's output speaker.
bool has_buffered_data() const override
uint8_t target_bits_per_sample_
virtual bool has_buffered_data() const =0
esp_err_t start_()
Starts the output speaker after setting the resampled stream info.
bool requires_resampling_() const
CallbackManager< void(uint32_t, uint32_t, uint32_t, uint32_t)> audio_output_callback_
bool task_stack_in_psram_
int32_t playback_differential_ms_
void stop_()
Stops the output speaker. If the resampling task is running, it sends the stop command.
StackType_t * task_stack_buffer_
void set_audio_stream_info(const audio::AudioStreamInfo &audio_stream_info)
void status_set_error(const char *message="unspecified")
static void resample_task(void *params)
EventGroupHandle_t event_group_
uint32_t get_sample_rate() const
size_t ms_to_bytes(uint32_t ms) const
Converts duration to bytes.
esp_err_t delete_task_()
Deallocates the task stack and resets the pointers.
void deallocate(T *p, size_t n)
void set_mute_state(bool mute_state) override
Mute state changes are passed to the parent's output speaker.
void status_clear_error()
uint32_t buffer_duration_ms_
virtual void mark_failed()
Mark this component as failed.
Implementation of SPI Controller mode.
audio::AudioStreamInfo target_stream_info_
uint32_t target_sample_rate_
TaskHandle_t task_handle_
esp_err_t start_task_()
Starts the resampler task after allocating the task stack.
std::weak_ptr< RingBuffer > ring_buffer_
virtual size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait)
Plays the provided audio data.
An STL allocator that uses SPI or internal RAM.
static std::unique_ptr< RingBuffer > create(size_t len)
audio::AudioStreamInfo audio_stream_info_
speaker::Speaker * output_speaker_
virtual void set_mute_state(bool mute_state)
size_t play(const uint8_t *data, size_t length, TickType_t ticks_to_wait) override