Streaming I2S mic audio from ESP32 (PowerFeather)

j0shmillar
Posts: 2
Joined: Sun Jun 09, 2024 11:33 am

Streaming I2S mic audio from ESP32 (PowerFeather)

Postby j0shmillar » Sun Jun 09, 2024 12:33 pm

Hi!

Firstly, I'm completely new to embedded development so apologies in advance if this is obvious!

I'm trying to stream I2S mic audio from my ESP32 (I'm using the PowerFeather board and INMP441 mic). I receive audio at my server (currently just as .raw, playing using audacity), but it's not continuous - there are "jumps" or discontinuities and parts of it seem sped up. I think it may be a timing issue?

Please see my code below - if anyone out there could offer some guidance or suggestions, it would be much appreciated!
  1. main.cpp
  2.  
  3. #include "Wifi.h"
  4. #include "I2S.h"
  5. #include "Http.h"
  6.  
  7. #include <PowerFeather.h>
  8. #include <freertos/FreeRTOS.h>
  9.  
  10. #include <esp_log.h>
  11. #include <esp_sleep.h>
  12.  
  13. #define BATTERY_CAPACITY 0
  14.  
  15. using namespace PowerFeather;
  16. static const char* TAG = "esp32-test";
  17.  
  18. bool inited = false;
  19.  
  20. void data_loop() {
  21.     int16_t* samples = (int16_t*) malloc(sizeof(uint16_t) * I2S_SAMPLE_COUNT);
  22.     http_init();
  23.     esp_err_t error;
  24.     while (true) {
  25.         gpio_set_level(Mainboard::Pin::LED, !gpio_get_level(Mainboard::Pin::LED));
  26.  
  27.         Board.enableBatteryCharging(gpio_get_level(Mainboard::Pin::BTN) == 0);
  28.  
  29.         /*mic read*/
  30.         size_t sample_read = mic_read(samples);
  31.         if (sample_read == 0) {
  32.             ESP_LOGE(TAG, "No data available");
  33.             mic_deinit();
  34.             mic_init();
  35.             continue;
  36.         }
  37.        
  38.         /*send mic data*/
  39.         ESP_LOGI(TAG, "Send: %u", sample_read);
  40.         error = http_send(samples, sample_read);
  41.         if (error != ESP_OK) {
  42.             ESP_LOGE(TAG, "Sending has failed: %s", esp_err_to_name(error));
  43.         }
  44.     }
  45. }
  46.  
  47. extern "C" void app_main() {
  48.     gpio_reset_pin(Mainboard::Pin::BTN);
  49.     gpio_set_direction(Mainboard::Pin::BTN, GPIO_MODE_INPUT);
  50.  
  51.     gpio_reset_pin(Mainboard::Pin::LED);
  52.     gpio_set_direction(Mainboard::Pin::LED, GPIO_MODE_INPUT_OUTPUT);
  53.  
  54.     if (Board.init(BATTERY_CAPACITY) == Result::Ok) {
  55.         printf("Board initialized successfully\n\n");
  56.         Board.setBatteryChargingMaxCurrent(100);
  57.         inited = true;
  58.     }
  59.  
  60.     wifi_init();
  61.     mic_init();
  62.     if (inited) {
  63.         data_loop();
  64.     } else {
  65.         printf("Board not initialized\n");
  66.     }
  67. }
  1. #include "Wifi.h"
  2.  
  3. #include <freertos/task.h>
  4. #include <esp_log.h>
  5. #include <esp_wifi.h>
  6. #include <nvs_flash.h>
  7.  
  8. static const char* TAG = "wifi";
  9. EventGroupHandle_t s_wifi_event_group;
  10. static int s_wifi_retry_num = 0;
  11.  
  12. void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
  13.     if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
  14.         esp_wifi_connect();
  15.     } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
  16.         if (s_wifi_retry_num < WIFI_MAX_RETRY) {
  17.             esp_wifi_connect();
  18.             s_wifi_retry_num++;
  19.             ESP_LOGI(TAG, "Retry to connect to the WiFi");
  20.         } else {
  21.             xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
  22.         }
  23.         ESP_LOGI(TAG, "Connecting to the WiFi failed");
  24.     } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
  25.         ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
  26.         ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
  27.         s_wifi_retry_num = 0;
  28.         xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
  29.     }
  30. }
  31.  
  32. void wifi_init() {
  33.     esp_err_t rv = nvs_flash_init();
  34.     if (rv == ESP_ERR_NVS_NO_FREE_PAGES || rv == ESP_ERR_NVS_NEW_VERSION_FOUND) {
  35.         ESP_ERROR_CHECK(nvs_flash_erase());
  36.         rv = nvs_flash_init();
  37.     }
  38.     ESP_ERROR_CHECK(rv);
  39.  
  40.     s_wifi_event_group = xEventGroupCreate();
  41.     ESP_ERROR_CHECK(esp_netif_init());
  42.  
  43.     ESP_ERROR_CHECK(esp_event_loop_create_default());
  44.     esp_netif_create_default_wifi_sta();
  45.  
  46.     wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  47.     ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  48.  
  49.     esp_event_handler_instance_t instance_any_id;
  50.     esp_event_handler_instance_t instance_got_ip;
  51.     ESP_ERROR_CHECK(esp_event_handler_instance_register(
  52.         WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id));
  53.     ESP_ERROR_CHECK(esp_event_handler_instance_register(
  54.         IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip));
  55.  
  56.     wifi_config_t wifi_config = {
  57.         .sta = {
  58.             .ssid = WIFI_SSID,
  59.             .password = WIFI_PASS,
  60.             .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
  61.         },
  62.     };
  63.     ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  64.     ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
  65.     ESP_ERROR_CHECK(esp_wifi_start());
  66.  
  67.     EventBits_t bits = xEventGroupWaitBits(
  68.         s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
  69.  
  70.     if (bits & WIFI_CONNECTED_BIT) {
  71.         ESP_LOGI(TAG, "Connected to WiFi SSID: <%s>", WIFI_SSID);
  72.     } else if (bits & WIFI_FAIL_BIT) {
  73.         ESP_LOGI(TAG, "Unable to connect to SSID: <%s>", WIFI_SSID);
  74.     } else {
  75.         ESP_LOGE(TAG, "Unexpected event");
  76.     }
  77. }
  1. #include <freertos/FreeRTOS.h>
  2. #include "I2S.h"
  3.  
  4. #include <esp_log.h>
  5.  
  6. static const char* TAG = "i2s";
  7. i2s_chan_handle_t s_rx_handle;
  8.  
  9. void mic_init() {
  10.     i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
  11.     ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &s_rx_handle));
  12.  
  13.     i2s_std_config_t std_cfg = {
  14.         .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(I2S_SAMPLE_RATE),
  15.         .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
  16.         .gpio_cfg = {
  17.             .mclk = I2S_GPIO_UNUSED,
  18.             .bclk = I2S_INMP441_SCK,
  19.             .ws = I2S_INMP441_WS,
  20.             .dout = I2S_GPIO_UNUSED,
  21.             .din = I2S_INMP441_SD,
  22.             .invert_flags = {
  23.                 .mclk_inv = false,
  24.                 .bclk_inv = false,
  25.                 .ws_inv = false,
  26.             },
  27.         },
  28.     };
  29.     ESP_ERROR_CHECK(i2s_channel_init_std_mode(s_rx_handle, &std_cfg));
  30.     ESP_ERROR_CHECK(i2s_channel_enable(s_rx_handle));
  31. }
  32.  
  33. void mic_deinit() {
  34.     i2s_channel_disable(s_rx_handle);
  35.     i2s_del_channel(s_rx_handle);
  36. }
  37.  
  38. size_t mic_read(int16_t* samples) {
  39.     static const size_t s_buffer_size = 1024U;
  40.     static int32_t s_buffer[1024U];
  41.  
  42.     size_t count = I2S_SAMPLE_COUNT;
  43.     size_t sample_index = 0;
  44.     while (count > 0) {
  45.         size_t bytes_read = 0;
  46.         if (i2s_channel_read(s_rx_handle, (char*) s_buffer, s_buffer_size * I2S_SAMPLE_BYTES, &bytes_read, portMAX_DELAY) != ESP_OK) {
  47.             ESP_LOGE(TAG, "Unable to read from audio channel");
  48.             return 0;
  49.         }
  50.  
  51.         size_t samples_read = bytes_read / I2S_SAMPLE_BYTES;
  52.         for (int i = 0; i < samples_read; ++i) {
  53.             samples[sample_index++] = s_buffer[i] >> 8;
  54.             count--;
  55.         }
  56.     }
  57.     return I2S_SAMPLE_COUNT;
  58. }
  1. #include "Http.h"
  2.  
  3. static esp_http_client_handle_t s_http_client;
  4.  
  5. void http_init() {
  6.     esp_http_client_config_t config = {
  7.         .host = "192.168.1.144",
  8.         .port = 5003,
  9.         .auth_type = HTTP_AUTH_TYPE_NONE,
  10.         .path = CONFIG_ESP_HTTP_SERVER_PATH,
  11.         .disable_auto_redirect = true,
  12.         .transport_type = HTTP_TRANSPORT_OVER_TCP,
  13.     };
  14.     s_http_client = esp_http_client_init(&config);
  15.  
  16.     ESP_ERROR_CHECK(esp_http_client_set_method(s_http_client, HTTP_METHOD_POST));
  17.     ESP_ERROR_CHECK(esp_http_client_set_header(s_http_client, "Content-Type", "application/octet-stream"));
  18. }
  19.  
  20. esp_err_t http_send(const int16_t* const samples, size_t count) {
  21.     ESP_ERROR_CHECK(esp_http_client_set_post_field(s_http_client, (const char*) samples, sizeof(uint16_t) * count));
  22.     return esp_http_client_perform(s_http_client);
  23. }

Who is online

Users browsing this forum: Google [Bot], snutw_ and 100 guests