I'm trying to write my own audio element. The board I'm using is LyraT v4.3. I created a pipeline i2s_stream_reader -> my_element -> i2s_stream_writer. In the process function of 'my_element', if I forward the samples without doing anything with them, I can hear my voice from the headphones without a problem. If I multiply the samples with 0.5 before forwarding them to i2s_stream_writer, all I hear is very loud noise. Aren't the samples provided to my process function raw audio samples? Should I add some kind of decode element between i2s_stream_reader and my_element?
Here is my code for reference:
- #include <string.h>
- #include "board.h"
- #include "esp_log.h"
- #include "audio_pipeline.h"
- #include "audio_element.h"
- #include "i2s_stream.h"
- static const char *TAG = "ELEMENTEXAMPLE";
- static esp_err_t el_open(audio_element_handle_t self) {
- ESP_LOGI(TAG, "open");
- return ESP_OK;
- }
- static int el_process(audio_element_handle_t self, char *buf, int len) {
- int rsize = audio_element_input(self, buf, len);
- for (int i =0; i<rsize; i+=4) {
- // convert bytes to samples
- uint16_t lSample = ((((uint16_t) buf[i]) << 8) & 0xFF00) + buf[i+1];
- uint16_t rSample = ((((uint16_t) buf[i+2]) << 8) & 0xFF00) + buf[i+3];
- // if i comment out these two lines it works as expected
- lSample *= 0.5;
- rSample *= 0.5;
- // convert samples to byte
- buf[i] = (char) (((lSample & 0xFF00) >> 8) & 0xFF);
- buf[i+1] = (char) (lSample & 0xFF);
- buf[i+2] = (char) (((rSample & 0xFF00) >> 8) & 0xFF);
- buf[i+3] = (char) (rSample & 0xFF);
- }
- rsize = audio_element_output(self, buf, rsize);
- return rsize;
- }
- void app_main() {
- audio_pipeline_handle_t pipeline;
- audio_element_handle_t i2s_stream_reader, i2s_stream_writer, my_el;
- esp_log_level_set("*", ESP_LOG_INFO);
- ESP_LOGI(TAG, "[1.0] Start codec chip");
- audio_board_handle_t board_handle = audio_board_init();
- audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START);
- audio_hal_set_volume(board_handle->audio_hal, 100);
- ESP_LOGI(TAG, "[2.0] Create i2s stream to read audio data from codec chip");
- i2s_stream_cfg_t i2sr_cfg = I2S_STREAM_CFG_DEFAULT();
- i2sr_cfg.type = AUDIO_STREAM_READER;
- i2s_stream_reader = i2s_stream_init(&i2sr_cfg);
- ESP_LOGI(TAG, "[3.0] Create i2s stream to write audio data to codec chip");
- i2s_stream_cfg_t i2sw_cfg = I2S_STREAM_CFG_DEFAULT();
- i2sw_cfg.type = AUDIO_STREAM_WRITER;
- i2s_stream_writer = i2s_stream_init(&i2sw_cfg);
- ESP_LOGI(TAG, "[4.0] Init Element");
- audio_element_cfg_t cfg = DEFAULT_AUDIO_ELEMENT_CONFIG();
- cfg.open = el_open;
- cfg.process = el_process;
- cfg.tag = "my_el";
- my_el = audio_element_init(&cfg);
- ESP_LOGI(TAG, "[5.0] Create pipeline");
- audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
- pipeline = audio_pipeline_init(&pipeline_cfg);
- mem_assert(pipeline);
- audio_pipeline_register(pipeline, my_el, "my_el");
- audio_pipeline_register(pipeline, i2s_stream_reader, "i2sr");
- audio_pipeline_register(pipeline, i2s_stream_writer, "i2sw");
- const char *link_tag[3] = {"i2sr", "my_el", "i2sw"};
- audio_pipeline_link(pipeline, link_tag, 3);
- ESP_LOGI(TAG, "[6.0] Run pipeline");
- audio_pipeline_run(pipeline);
- ESP_LOGI(TAG, "[ * ] Starting ...");
- while (1) {
- vTaskDelay(2000);
- }
- }