Skip to content

Commit

Permalink
Merge pull request #43 from gnumpi/finish_on_timeout
Browse files Browse the repository at this point in the history
Finish on timeout
  • Loading branch information
gnumpi authored Jun 17, 2024
2 parents a8f66cb + 8926065 commit ac25907
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 21 deletions.
2 changes: 2 additions & 0 deletions esphome/components/adf_pipeline/adf_audio_element.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class AudioPipelineSettingsRequest {
int final_number_of_channels{-1};
float final_volume{-1.};

int finish_on_timeout{0};

bool failed{false};
int error_code{0};
ADFPipelineElement *requested_by{nullptr};
Expand Down
10 changes: 7 additions & 3 deletions esphome/components/adf_pipeline/adf_audio_sources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,12 @@ bool PCMSource::init_adf_elements_() {
}

int PCMSource::stream_write(char *buffer, int len) {
if( !this->adf_raw_stream_writer_ ){
ESP_LOGE(TAG, "Attempt writing to PCM stream buffer which has not been created.");
return 0;
}
int ret = audio_element_output(this->adf_raw_stream_writer_, buffer, len);
if (ret == AEL_IO_TIMEOUT) {
audio_element_report_status(this->adf_raw_stream_writer_, AEL_STATUS_STATE_FINISHED);
} else if (ret < 0) {
if (ret < 0) {
return 0;
}
return ret;
Expand All @@ -320,6 +322,8 @@ bool PCMSource::has_buffered_data() const {
return rb_bytes_filled(rb) > 0;
}



} // namespace esp_adf
} // namespace esphome

Expand Down
1 change: 1 addition & 0 deletions esphome/components/adf_pipeline/adf_audio_sources.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class PCMSource : public ADFPipelineSourceElement {
const std::string get_name() override { return "PCMSource"; }
int stream_write(char *buffer, int len);
bool has_buffered_data() const;
bool elements_have_stopped() override { return true; }

protected:
bool init_adf_elements_() override;
Expand Down
2 changes: 1 addition & 1 deletion esphome/components/adf_pipeline/adf_pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ void ADFPipeline::watch_() {
if(this->requested_ == PipelineRequest::STOPPED){
set_state_(PipelineState::STOPPED);
}
else if ( millis() - this->finish_timeout_invoke_ > 16000){
else if ( millis() - this->finish_timeout_invoke_ > this->wait_for_finish_timeout_ms_){
this->requested_ = PipelineRequest::STOPPED;
set_state_(PipelineState::ABORTING);
}
Expand Down
4 changes: 4 additions & 0 deletions esphome/components/adf_pipeline/adf_pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class ADFPipeline {
void loop() { this->watch_(); }

void set_destroy_on_stop(bool value){ this->destroy_on_stop_ = value; }
void set_finish_timeout_ms(int timeout){ this->wait_for_finish_timeout_ms_ = timeout; }

void append_element(ADFPipelineElement *element);
int get_number_of_elements() { return pipeline_elements_.size(); }
Expand All @@ -99,6 +100,7 @@ class ADFPipeline {
bool check_all_finished_();
bool check_all_destroyed_();
uint32_t finish_timeout_invoke_{0};
int wait_for_finish_timeout_ms_{16000};

enum CheckState { CHECK_PREPARED, CHECK_PAUSED, CHECK_RESUMED, CHECK_STOPPED, NUM_STATE_CHECKS };
std::vector<std::string> check_state_name = {"PREPARING", "PAUSING", "RESUMING", "STOPPING","WRONG_IDX"};
Expand All @@ -116,6 +118,8 @@ class ADFPipeline {
bool build_adf_pipeline_();
void deinit_all_();



audio_pipeline_handle_t adf_pipeline_{};
audio_event_iface_handle_t adf_pipeline_event_{};

Expand Down
12 changes: 8 additions & 4 deletions esphome/components/adf_pipeline/speaker/esp_adf_speaker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ static const char *const TAG = "esp_adf.speaker";

void ADFSpeaker::setup() {
ESP_LOGCONFIG(TAG, "Setting up ESP ADF Speaker...");
pipeline.set_finish_timeout_ms(10000);
}

void ADFSpeaker::dump_config() {
Expand Down Expand Up @@ -67,11 +68,12 @@ size_t ADFSpeaker::play(const uint8_t *data, size_t length) {
ESP_LOGE(TAG, "Failed to play audio, speaker is in failed state.");
return 0;
}
/*
if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) {
this->start();

if (this->state_ != speaker::STATE_RUNNING) {
ESP_LOGV(TAG, "Trying to play audio while speaker not running.");
return 0;
}
*/

size_t remaining = length;
size_t index = 0;
while (remaining > 0) {
Expand All @@ -92,6 +94,8 @@ void ADFSpeaker::request_pipeline_settings_(){
request.sampling_rate = 16000;
request.bit_depth = 16;
request.number_of_channels = 1;
request.finish_on_timeout = 1000; //ms
request.target_volume = 1.;
if (!this->pipeline.request_settings(request)) {
esph_log_e(TAG, "Requested audio settings, didn't get accepted");
this->pipeline.on_settings_request_failed(request);
Expand Down
1 change: 1 addition & 0 deletions esphome/components/i2s_audio/adf_pipeline/adf_i2s_in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ bool ADFElementI2SIn::init_adf_elements_() {
.uninstall_drv = false,
.need_expand = false,
.expand_src_bits = I2S_BITS_PER_SAMPLE_16BIT,
.finish_on_timeout = false,
};

this->adf_i2s_stream_reader_ = i2s_stream_init(&i2s_stream_cfg);
Expand Down
16 changes: 15 additions & 1 deletion esphome/components/i2s_audio/adf_pipeline/adf_i2s_out.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ bool ADFElementI2SOut::init_adf_elements_() {
.i2s_port = this->parent_->get_port(),
.use_alc = this->use_adf_alc_,
.volume = 0,
.out_rb_size = (4 * 1024),
.out_rb_size = (20 * 1024),
.task_stack = I2S_STREAM_TASK_STACK,
.task_core = I2S_STREAM_TASK_CORE,
.task_prio = I2S_STREAM_TASK_PRIO,
Expand All @@ -49,12 +49,15 @@ bool ADFElementI2SOut::init_adf_elements_() {
.uninstall_drv = false,
.need_expand = i2s_config.bits_per_sample != I2S_BITS_PER_SAMPLE_16BIT,
.expand_src_bits = I2S_BITS_PER_SAMPLE_16BIT,
.finish_on_timeout = false, //don't set it yet, set it in the preparation phase instead
};

this->adf_i2s_stream_writer_ = i2s_stream_init(&i2s_cfg);
this->adf_i2s_stream_writer_->buf_size = 1 * 1024;

this->install_i2s_driver(i2s_config);
audio_element_set_input_timeout(this->adf_i2s_stream_writer_, 1000 / portTICK_PERIOD_MS);
this->finish_on_timeout_ms_ = 0;

#ifdef I2S_EXTERNAL_DAC
if (this->external_dac_ != nullptr){
Expand Down Expand Up @@ -112,6 +115,8 @@ void ADFElementI2SOut::on_settings_request(AudioPipelineSettingsRequest &request
audio_element_set_music_info(this->adf_i2s_stream_writer_,this->sample_rate_, this->num_of_channels(), this->bits_per_sample_ );

esph_log_d(TAG, "update i2s clk settings: rate:%d bits:%d ch:%d",this->sample_rate_, this->bits_per_sample_, this->num_of_channels());
i2s_stream_t *i2s = (i2s_stream_t *)audio_element_getdata(this->adf_i2s_stream_writer_);
i2s->config.i2s_config.bits_per_sample = this->bits_per_sample_;
if (i2s_stream_set_clk(this->adf_i2s_stream_writer_, this->sample_rate_, this->bits_per_sample_,
this->num_of_channels()) != ESP_OK) {
esph_log_e(TAG, "error while setting sample rate and bit depth,");
Expand All @@ -122,6 +127,15 @@ void ADFElementI2SOut::on_settings_request(AudioPipelineSettingsRequest &request
}
}

if ( request.finish_on_timeout != this->finish_on_timeout_ms_ ){
esph_log_d(TAG, "Setting finish_on_timout to (ms): %d", request.finish_on_timeout);
this->finish_on_timeout_ms_ = request.finish_on_timeout;
i2s_stream_t *i2s = (i2s_stream_t *) audio_element_getdata(this->adf_i2s_stream_writer_);
esph_log_d(TAG, "finish on timeout was: %s",i2s->finish_on_timeout ? "true":"false");
i2s->finish_on_timeout = this->finish_on_timeout_ms_ > 0;
audio_element_set_input_timeout(this->adf_i2s_stream_writer_, this->finish_on_timeout_ms_ / portTICK_PERIOD_MS);
}

// final pipeline settings are unset
if (request.final_sampling_rate == -1) {
esph_log_d(TAG, "Set final i2s settings: %d", this->sample_rate_);
Expand Down
4 changes: 3 additions & 1 deletion esphome/components/i2s_audio/adf_pipeline/adf_i2s_out.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ class ADFElementI2SOut : public I2SWriter, public ADFPipelineSinkElement, public

void set_use_adf_alc(bool use_alc){ this->use_adf_alc_ = use_alc; }
void set_alc_max_val(float max_val){ this->max_alc_val_ = max_val;}

void set_finish_on_timeout_ms(int timeout){this->finish_on_timeout_ms_ = timeout;}
protected:
void on_settings_request(AudioPipelineSettingsRequest &request) override;
bool use_adf_alc_{false};
float max_alc_val_{1.};
bool adjustable_{false};
int finish_on_timeout_ms_{0};

bool init_adf_elements_() override;
void clear_adf_elements_() override;

audio_element_handle_t adf_i2s_stream_writer_;
};

Expand Down
23 changes: 12 additions & 11 deletions esphome/components/i2s_audio/adf_pipeline/i2s_stream_mod.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#include "audio_common.h"
#include "audio_mem.h"
#include "audio_element.h"
#include "i2s_stream.h"
#include "i2s_stream_mod.h"
#include "esp_alc.h"
#include "board_pins_config.h"
#include "audio_idf_version.h"
Expand All @@ -53,15 +53,6 @@ static const char *TAG = "I2S_STREAM";
#endif
#endif

typedef struct i2s_stream {
audio_stream_type_t type;
i2s_stream_cfg_t config;
bool is_open;
bool use_alc;
void *volume_handle;
int volume;
bool uninstall_drv;
} i2s_stream_t;
#ifdef SOC_I2S_SUPPORTS_ADC_DAC
static esp_err_t i2s_mono_fix(int bits, uint8_t *sbuff, uint32_t len)
{
Expand Down Expand Up @@ -161,10 +152,12 @@ static esp_err_t _i2s_open(audio_element_handle_t self)
return ESP_OK;
}

/*
if (i2s->type == AUDIO_STREAM_WRITER) {
audio_element_set_input_timeout(self, 10 / portTICK_RATE_MS);
ESP_LOGI(TAG, "AUDIO_STREAM_WRITER");
}
*/
i2s->is_open = true;
if (i2s->use_alc) {
i2s->volume_handle = alc_volume_setup_open();
Expand Down Expand Up @@ -283,7 +276,14 @@ static int _i2s_process(audio_element_handle_t self, char *in_buffer, int in_len
} else
#endif
{
memset(in_buffer, 0x00, in_len);
if( i2s->finish_on_timeout ){
ESP_LOGI(TAG, "Sending finish status after time out occurred." );
audio_element_report_status(self, AEL_STATUS_STATE_FINISHED);
return 0;
}
else {
memset(in_buffer, 0x00, in_len);
}
}
r_size = in_len;
audio_element_multi_output(self, in_buffer, r_size, 0);
Expand Down Expand Up @@ -375,6 +375,7 @@ audio_element_handle_t i2s_stream_init(i2s_stream_cfg_t *config)
i2s->use_alc = config->use_alc;
i2s->volume = config->volume;
i2s->uninstall_drv = config->uninstall_drv;
i2s->finish_on_timeout = config->finish_on_timeout;

if (config->type == AUDIO_STREAM_READER) {
cfg.read = _i2s_read;
Expand Down
13 changes: 13 additions & 0 deletions esphome/components/i2s_audio/adf_pipeline/i2s_stream_mod.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,21 @@ typedef struct {
bool uninstall_drv; /*!< whether uninstall the i2s driver when stream destroyed*/
bool need_expand; /*!< whether to expand i2s data */
i2s_bits_per_sample_t expand_src_bits; /*!< The source bits per sample when data expand */
bool finish_on_timeout; /*!< send finish message when input data timeout occurs */
} i2s_stream_cfg_t;

typedef struct i2s_stream {
audio_stream_type_t type;
i2s_stream_cfg_t config;
bool is_open;
bool use_alc;
void *volume_handle;
int volume;
bool uninstall_drv;
bool finish_on_timeout;
} i2s_stream_t;


#define I2S_STREAM_TASK_STACK (3072+512)
#define I2S_STREAM_BUF_SIZE (2048)
#define I2S_STREAM_TASK_PRIO (23)
Expand Down
7 changes: 7 additions & 0 deletions examples/m5stack-atom-echo-adf-spk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ esp32:
logger:
api:
ota:
platform: esphome

packages:
wifi: !include common/wifi.yaml
Expand All @@ -49,6 +50,12 @@ adf_pipeline:
id: adf_i2s_out
i2s_audio_id: i2s_dplx
i2s_dout_pin: GPIO22
adf_alc: true
alc_max: 0.6

sample_rate: 16000
bits_per_sample: 16bit
channel: right
fixed_settings: false

- platform: i2s_audio
Expand Down

0 comments on commit ac25907

Please sign in to comment.