3 次代码提交 e7e1df5afb ... 3061dac07b

作者 SHA1 备注 提交日期
  Kathy Zhu 3061dac07b aec with dual mic and volume buttons 2 周之前
  Kathy Zhu d570339243 aec with dual mic and volume buttons 2 周之前
  Kathy Zhu 2da33ece94 aec and volume buttons implemented 2 周之前
共有 5 个文件被更改,包括 405 次插入100 次删除
  1. 77 14
      dependencies.lock
  2. 123 23
      main/hardeware_driver/bsp_board.c
  3. 10 3
      main/hardeware_driver/bsp_board.h
  4. 170 60
      main/sip/sip.c
  5. 25 0
      sdkconfig

+ 77 - 14
dependencies.lock

@@ -6,7 +6,7 @@ dependencies:
       require: private
       version: '>=5.0'
     source:
-      registry_url: https://components.espressif.com/
+      registry_url: https://components.espressif.com
       type: service
     version: 1.7.19~2
   espressif/dl_fft:
@@ -16,9 +16,37 @@ dependencies:
       require: private
       version: '>=5.0'
     source:
-      registry_url: https://components.espressif.com/
+      registry_url: https://components.espressif.com
       type: service
     version: 0.6.0
+  espressif/esp-dl:
+    component_hash: 0d5dd7fadd04854a82e1404f871e16980002a46dfe9796e52626d3c8d6566ad2
+    dependencies:
+    - name: espressif/dl_fft
+      registry_url: https://components.espressif.com
+      require: private
+      version: '>=0.6.0'
+    - name: espressif/esp_new_jpeg
+      registry_url: https://components.espressif.com
+      require: private
+      version: ^1
+    - name: idf
+      require: private
+      version: '*'
+    source:
+      registry_url: https://components.espressif.com
+      type: service
+    targets:
+    - esp32
+    - esp32c2
+    - esp32c3
+    - esp32c5
+    - esp32c6
+    - esp32p4
+    - esp32s2
+    - esp32s3
+    - esp32s31
+    version: 3.3.9
   espressif/esp-dsp:
     component_hash: 12e44db246517a627bc0fe2b255b8335410c0215c98bfba2df5a8e3edea839ef
     dependencies:
@@ -26,17 +54,37 @@ dependencies:
       require: private
       version: '>=4.2'
     source:
-      registry_url: https://components.espressif.com/
+      registry_url: https://components.espressif.com
       type: service
     version: 1.8.0
   espressif/esp-sr:
-    dependencies: []
+    component_hash: 803a3e2917f5100f6ce5766373d29c269ce32b9c6b33ca948548bc94ad752ef1
+    dependencies:
+    - name: espressif/cjson
+      registry_url: https://components.espressif.com
+      require: private
+      version: ^1.7.19
+    - name: espressif/dl_fft
+      registry_url: https://components.espressif.com
+      require: private
+      version: '>=0.6.0'
+    - name: espressif/esp-dl
+      registry_url: https://components.espressif.com
+      require: private
+      version: '>=3.3.9'
+    - name: espressif/esp-dsp
+      registry_url: https://components.espressif.com
+      require: private
+      version: 1.8.0
+    - name: idf
+      require: private
+      version: '>=5.0'
     source:
-      path: C:\Users\doop3\OneDrive\Documents\espidfprojects\SIP_test2_1\SIP_test2\components\espressif__esp-sr
-      type: local
-    version: 2.4.6
+      registry_url: https://components.espressif.com/
+      type: service
+    version: 2.5.0
   espressif/esp_codec_dev:
-    component_hash: 8a58569aed3c6e8d858da5419eba4d54ee905d7709cdbe01c42101c1ed0c5319
+    component_hash: 4779f31a3ba3f9b38aee1afe6ccb9ba8f6108dc3a6e77d39d7d714e9a215371b
     dependencies:
     - name: idf
       require: private
@@ -44,7 +92,7 @@ dependencies:
     source:
       registry_url: https://components.espressif.com/
       type: service
-    version: 1.6.1
+    version: 1.6.2
   espressif/esp_io_expander:
     component_hash: 7b7f91270172e46ca4597e3874f48d8412e280e8c295559f5922ec38656e3e5f
     dependencies:
@@ -69,6 +117,25 @@ dependencies:
       registry_url: https://components.espressif.com/
       type: service
     version: 2.0.2
+  espressif/esp_new_jpeg:
+    component_hash: e1e7e6991193c41ed6c9fc386702aa7821433319e7aa9c3147cd3236310cd69c
+    dependencies: []
+    source:
+      registry_url: https://components.espressif.com
+      type: service
+    targets:
+    - esp32
+    - esp32s2
+    - esp32s3
+    - esp32s31
+    - esp32p4
+    - esp32c2
+    - esp32c3
+    - esp32c5
+    - esp32c6
+    - esp32c61
+    - esp32h4
+    version: 1.0.2
   espressif/led_strip:
     component_hash: 28621486f77229aaf81c71f5e15d6fbf36c2949cf11094e07090593e659e7639
     dependencies:
@@ -84,14 +151,10 @@ dependencies:
       type: idf
     version: 5.3.5
 direct_dependencies:
-- espressif/cjson
-- espressif/dl_fft
-- espressif/esp-dsp
 - espressif/esp-sr
 - espressif/esp_codec_dev
 - espressif/esp_io_expander_tca95xx_16bit
 - espressif/led_strip
-- idf
-manifest_hash: 2e8c992a35dd97ed7aa093a6dede2214b63671f1dbf36fba70a42539f89df49a
+manifest_hash: cc6725c3be0ea7fd83b3ab5f9e00bbc374e48bbe22994003311ddb44aa92bcbe
 target: esp32s3
 version: 2.0.0

+ 123 - 23
main/hardeware_driver/bsp_board.c

@@ -24,6 +24,9 @@
 #include "driver/sdmmc_host.h"
 #include <errno.h>
 
+#include "esp_aec.h"
+#include "tca9555_driver.h"
+
 #if ((SOC_SDMMC_HOST_SUPPORTED) && (FUNC_SDMMC_EN))
 #include "driver/sdmmc_host.h"
 #endif /* ((SOC_SDMMC_HOST_SUPPORTED) && (FUNC_SDMMC_EN)) */
@@ -56,6 +59,95 @@ static i2c_master_bus_handle_t i2c_bus_handle = NULL;
 static uint32_t SDCard_Size  = 0;
 static bool s_volume_buttons_task_started = false;
 
+static aec_handle_t *aec = NULL;
+static int frame_size = 0;
+static int16_t *mic = NULL;
+static int16_t *ref = NULL;
+static int16_t *out = NULL;
+
+static esp_err_t bsp_aec_init(void)
+{
+    /* Espressif's direct AEC flow: create, query the algorithm frame size,
+     * then allocate aligned signed-16-bit audio buffers for each frame.
+     * aec_create_from_config() is used instead of aec_create() so the NLP
+     * (residual echo suppression) level can be pushed to its strongest
+     * setting; a longer filter_length also helps cancel longer echo tails. */
+    aec_config_t aec_cfg = {
+        .mic_num       = 1,
+        .ref_num       = 1,
+        .out_num       = 1,
+        .filter_length = 6,
+        .sample_rate   = 16000,
+        .caps          = MALLOC_CAP_8BIT,
+        .mode          = AEC_MODE_VOIP_HIGH_PERF,
+        .nlp_level     = AEC_NLP_LEVEL_AGGR,
+    };
+    aec = aec_create_from_config(&aec_cfg);
+    if (aec == NULL) {
+        ESP_LOGE(TAG, "AEC create failed");
+        return ESP_ERR_NO_MEM;
+    }
+
+    frame_size = aec_get_chunksize(aec);
+    mic = heap_caps_aligned_alloc(16, frame_size * sizeof(int16_t), MALLOC_CAP_8BIT);
+    ref = heap_caps_aligned_alloc(16, frame_size * sizeof(int16_t), MALLOC_CAP_8BIT);
+    out = heap_caps_aligned_alloc(16, frame_size * sizeof(int16_t), MALLOC_CAP_8BIT);
+    if (mic == NULL || ref == NULL || out == NULL) {
+        ESP_LOGE(TAG, "AEC buffer allocation failed for %d samples", frame_size);
+        free(mic);
+        free(ref);
+        free(out);
+        mic = NULL;
+        ref = NULL;
+        out = NULL;
+        aec_destroy(aec);
+        aec = NULL;
+        frame_size = 0;
+        return ESP_ERR_NO_MEM;
+    }
+
+    ESP_LOGI(TAG, "AEC ready: %d samples/frame at 16 kHz", frame_size);
+    return ESP_OK;
+}
+
+static esp_err_t bsp_codec_deinit(void);
+
+static void bsp_aec_deinit(void)
+{
+    if (aec != NULL) {
+        aec_destroy(aec);
+        aec = NULL;
+    }
+    free(mic);
+    free(ref);
+    free(out);
+    mic = NULL;
+    ref = NULL;
+    out = NULL;
+    frame_size = 0;
+}
+
+int bsp_aec_get_frame_size(void)
+{
+    return frame_size;
+}
+
+esp_err_t bsp_aec_process_frame(const int16_t *near_end,
+                                const int16_t *far_end,
+                                int16_t *processed)
+{
+    if (aec == NULL || mic == NULL || ref == NULL || out == NULL ||
+        near_end == NULL || far_end == NULL || processed == NULL) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    memcpy(mic, near_end, frame_size * sizeof(int16_t));
+    memcpy(ref, far_end, frame_size * sizeof(int16_t));
+    aec_process(aec, mic, ref, out);
+    memcpy(processed, out, frame_size * sizeof(int16_t));
+    return ESP_OK;
+}
+
 int mic_level = 0;
 esp_codec_dev_handle_t esp_ret_play_dev(void)
 {
@@ -431,6 +523,12 @@ static esp_err_t bsp_codec_init(
     }
 
 
+    ret = bsp_aec_init();
+    if (ret != ESP_OK) {
+        bsp_codec_deinit();
+        return ret;
+    }
+
     return ret;
 }
 
@@ -440,6 +538,7 @@ static esp_err_t bsp_codec_deinit()
 
     ret_val |= bsp_codec_adc_deinit();
     ret_val |= bsp_codec_dac_deinit();
+    bsp_aec_deinit();
     return ret_val;
 }
 
@@ -510,7 +609,7 @@ esp_err_t esp_get_feed_data(
         int buffer_len)
 {
 
-    ESP_LOGE(TAG, "NEW esp_get_feed_data CALLED");
+    // ESP_LOGE(TAG, "NEW esp_get_feed_data CALLED");
 
     if(record_dev == NULL)
     {
@@ -519,10 +618,10 @@ esp_err_t esp_get_feed_data(
     }
 
 
-    ESP_LOGI(TAG,
-             "read buffer=%p size=%d",
-             buffer,
-             buffer_len);
+    // ESP_LOGI(TAG,
+    //          "read buffer=%p size=%d",
+    //          buffer,
+    //          buffer_len);
 
 
     esp_err_t ret;
@@ -533,9 +632,9 @@ esp_err_t esp_get_feed_data(
             buffer_len);
 
 
-    ESP_LOGI(TAG,
-             "codec read ret=%s",
-             esp_err_to_name(ret));
+    // ESP_LOGI(TAG,
+    //          "codec read ret=%s",
+    //          esp_err_to_name(ret));
 
 
     if(ret != ESP_OK)
@@ -574,12 +673,24 @@ char* esp_get_input_format(void)
 
 static void bsp_volume_buttons_task(void *arg)
 {
+    /* K1/K3 are wired through the TCA9555 IO expander, not raw ESP32 GPIOs
+     * (GPIO0 is the BOOT/RESET strapping pin, so it must not be used here). */
     int last_key1 = 1;
     int last_key3 = 1;
 
+    while (io_expander == NULL) {
+        vTaskDelay(pdMS_TO_TICKS(VOLUME_BUTTON_POLL_MS));
+    }
+
     while (1) {
-        int key1 = gpio_get_level(GPIO_KEY1_PIN);
-        int key3 = gpio_get_level(GPIO_KEY3_PIN);
+        uint32_t mask = 0;
+        if (esp_io_expander_get_level(io_expander, KEY_VOLUME_UP_PIN | KEY_VOLUME_DOWN_PIN, &mask) != ESP_OK) {
+            vTaskDelay(pdMS_TO_TICKS(VOLUME_BUTTON_POLL_MS));
+            continue;
+        }
+
+        int key1 = (mask & KEY_VOLUME_UP_PIN) ? 1 : 0;
+        int key3 = (mask & KEY_VOLUME_DOWN_PIN) ? 1 : 0;
 
         if (key1 == 0 && last_key1 != 0) {
             int current_vol = 0;
@@ -619,19 +730,8 @@ static esp_err_t bsp_volume_buttons_init(void)
         return ESP_OK;
     }
 
-    gpio_config_t io_conf = {
-        .pin_bit_mask = (1ULL << GPIO_KEY1_PIN) | (1ULL << GPIO_KEY3_PIN),
-        .mode = GPIO_MODE_INPUT,
-        .pull_up_en = GPIO_PULLUP_ENABLE,
-        .pull_down_en = GPIO_PULLDOWN_DISABLE,
-        .intr_type = GPIO_INTR_DISABLE,
-    };
-
-    esp_err_t ret = gpio_config(&io_conf);
-    if (ret != ESP_OK) {
-        return ret;
-    }
-
+    /* K1/K3 input direction is already configured on the TCA9555 expander by
+     * tca9555_driver_init(); no direct GPIO configuration is needed here. */
     BaseType_t task_created = xTaskCreate(bsp_volume_buttons_task, "vol_btns", 4096, NULL, 5, NULL);
     if (task_created != pdPASS) {
         return ESP_FAIL;

+ 10 - 3
main/hardeware_driver/bsp_board.h

@@ -98,9 +98,12 @@ extern "C" {
 #define GPIO_PWR_CTRL       (-1)
 #define GPIO_PWR_ON_LEVEL   (1)
 
-/* Waveshare ESP32-S3 audio board button mapping */
-#define GPIO_KEY1_PIN       (GPIO_NUM_0)
-#define GPIO_KEY3_PIN       (GPIO_NUM_18)
+/* Waveshare ESP32-S3 audio board button mapping.
+ * K1/K2/K3 are wired through the TCA9555 IO expander (not raw ESP32 GPIOs) -
+ * GPIO0 must not be used here since it is the BOOT/RESET strapping pin.
+ * K1 = volume up, K3 = volume down (matches the official Waveshare factory demo). */
+#define KEY_VOLUME_UP_PIN   (1ULL << 9)   /* K1, TCA9555 expander pin 9 */
+#define KEY_VOLUME_DOWN_PIN (1ULL << 11)  /* K3, TCA9555 expander pin 11 */
 #define VOLUME_BUTTON_POLL_MS (50)
 #define VOLUME_STEP         (2)
 #define VOLUME_MIN_LEVEL    (0)
@@ -193,6 +196,10 @@ esp_err_t esp_sdcard_init(char *mount_point, size_t max_files);
 esp_err_t esp_sdcard_deinit(char *mount_point);
 
 esp_err_t esp_audio_play(const int16_t* data, int length, uint32_t ticks_to_wait);
+int bsp_aec_get_frame_size(void);
+esp_err_t bsp_aec_process_frame(const int16_t *near_end,
+                                const int16_t *far_end,
+                                int16_t *processed);
 
 esp_err_t esp_get_feed_data(bool is_get_raw_channel, int16_t *buffer, int buffer_len);
 int esp_get_feed_channel(void);

+ 170 - 60
main/sip/sip.c

@@ -29,7 +29,7 @@
 #include "esp_g711_enc.h"
 #include "esp_g711_dec.h"*/
 
-#define ESP32_IP ""
+#define ESP32_IP "192.168.68.67"
 #define RTP_PORT 4000
 
 #define WIFI_SSID ""
@@ -47,11 +47,13 @@
 #define TONE_FREQ 1000
 
 
-#define MIC_FRAME_SAMPLES 160
+#define MIC_FRAME_SAMPLES 320
+#define AEC_MAX_FRAME_SAMPLES 512
+#define FAR_END_FIFO_SAMPLES 2048
 
 static int32_t mic_buffer[320];
-static int16_t mic_pcm16[MIC_FRAME_SAMPLES];
-static uint8_t payload[MIC_FRAME_SAMPLES];
+static int16_t mic_pcm16[SAMPLES_PER_PACKET];
+static uint8_t payload[SAMPLES_PER_PACKET];
 
 static uint8_t rx_packet[172];
 static int16_t speaker_pcm[160];
@@ -65,6 +67,16 @@ static uint16_t s_rtp_peer_port = 0;
 static volatile bool call_active = false;
 static volatile bool s_audio_hw_ready = false;
 
+static int16_t far_end_fifo[FAR_END_FIFO_SAMPLES];
+static size_t far_end_read = 0;
+static size_t far_end_write = 0;
+static portMUX_TYPE far_end_mux = portMUX_INITIALIZER_UNLOCKED;
+static int16_t aec_mic_pending[AEC_MAX_FRAME_SAMPLES];
+static int16_t aec_ref_pending[AEC_MAX_FRAME_SAMPLES];
+static size_t aec_pending_samples = 0;
+static int16_t aec_output_fifo[FAR_END_FIFO_SAMPLES];
+static size_t aec_output_samples = 0;
+
 esp_err_t esp_get_feed_data(
     bool is_get_raw_channel,
     int16_t *buffer,
@@ -78,6 +90,86 @@ esp_err_t sip_media_init(void);
 static void rtp_tx_task(void *pvParameters);
 static void rtp_rx_task(void *pvParameters);
 
+static void far_end_push(const int16_t *samples, size_t count)
+{
+    portENTER_CRITICAL(&far_end_mux);
+    for (size_t i = 0; i < count; ++i) {
+        size_t next = (far_end_write + 1) % FAR_END_FIFO_SAMPLES;
+        if (next == far_end_read) {
+            far_end_read = (far_end_read + 1) % FAR_END_FIFO_SAMPLES;
+        }
+        far_end_fifo[far_end_write] = samples[i];
+        far_end_write = next;
+    }
+    portEXIT_CRITICAL(&far_end_mux);
+}
+
+static void far_end_pop(int16_t *samples, size_t count)
+{
+    portENTER_CRITICAL(&far_end_mux);
+    for (size_t i = 0; i < count; ++i) {
+        if (far_end_read == far_end_write) {
+            samples[i] = 0;
+        } else {
+            samples[i] = far_end_fifo[far_end_read];
+            far_end_read = (far_end_read + 1) % FAR_END_FIFO_SAMPLES;
+        }
+    }
+    portEXIT_CRITICAL(&far_end_mux);
+}
+
+static bool aec_process_capture(const int16_t *near_end,
+                                const int16_t *far_end,
+                                size_t sample_count)
+{
+    int frame_size = bsp_aec_get_frame_size();
+    if (frame_size <= 0 || frame_size > AEC_MAX_FRAME_SAMPLES) {
+        return false;
+    }
+
+    for (size_t i = 0; i < sample_count; ++i) {
+        if (aec_pending_samples == AEC_MAX_FRAME_SAMPLES) {
+            return false;
+        }
+        aec_mic_pending[aec_pending_samples] = near_end[i];
+        aec_ref_pending[aec_pending_samples] = far_end[i];
+        ++aec_pending_samples;
+
+        if (aec_pending_samples == (size_t)frame_size) {
+            int16_t processed[AEC_MAX_FRAME_SAMPLES];
+            if (bsp_aec_process_frame(aec_mic_pending,
+                                      aec_ref_pending,
+                                      processed) != ESP_OK) {
+                return false;
+            }
+
+            /* AEC runs at 16 kHz. The negotiated PCMU stream is 8 kHz,
+             * so retain every second cleaned sample for RTP encoding. */
+            for (int sample = 0; sample < frame_size; sample += 2) {
+                if (aec_output_samples < FAR_END_FIFO_SAMPLES) {
+                    aec_output_fifo[aec_output_samples++] = processed[sample];
+                }
+            }
+
+            aec_pending_samples = 0;
+        }
+    }
+    return true;
+}
+
+static bool aec_output_pop(int16_t *samples, size_t count)
+{
+    if (aec_output_samples < count) {
+        return false;
+    }
+    memcpy(samples, aec_output_fifo, count * sizeof(int16_t));
+    memmove(aec_output_fifo,
+            aec_output_fifo + count,
+            (aec_output_samples - count) * sizeof(int16_t));
+    aec_output_samples -= count;
+    return true;
+}
+
 /* ================= WIFI ================= */
 
 static void wifi_event_handler(void *arg, esp_event_base_t event_base,
@@ -306,16 +398,13 @@ static bool sip_extract_rtp_port(const char *msg, uint16_t *out_port)
 
 static bool microphone_read(int16_t *samples, size_t count)
 {
-    ESP_LOGI(TAG,
-             "mic ptr=%p samples=%d bytes=%d",
-             samples,
-             count,
-             count * sizeof(int16_t));
+    // ESP_LOGI(TAG,
+    //          "mic ptr=%p samples=%d bytes=%d",
+    //          samples,
+    //          count,
+    //          count * sizeof(int16_t));
 
-    esp_err_t ret = esp_get_feed_data(
-        false,
-        (int16_t *)mic_buffer,
-    sizeof(mic_buffer));
+    esp_err_t ret = esp_get_feed_data(false, samples, count);
 
 
 
@@ -430,7 +519,6 @@ ESP_LOGI(TAG,
     return;
 }
 
-
     if(s_rtp_sock < 0)
     {
         s_rtp_sock = socket(AF_INET,
@@ -472,33 +560,26 @@ else
     uint8_t payload[SAMPLES_PER_PACKET];
 
 
-// Read microphone data
-if(!microphone_read(
-        (int16_t *)mic_buffer,
-        sizeof(mic_buffer)))
+    // Read one 20 ms stereo capture block (320 mono samples at 16 kHz).
+    if (!microphone_read((int16_t *)mic_buffer, sizeof(mic_buffer)))
 {
     return;
 }
-int16_t *mic16 = (int16_t *)mic_buffer;
-/*
-ESP_LOGI("MIC",
-"pcm16=%d %d %d %d",
-mic16[0],
-mic16[1],
-mic16[2],
-mic16[3]);*/
-
-// Convert 32-bit audio to PCM16
-for(int i = 0; i < SAMPLES_PER_PACKET; i++)
-{
-    // Take microphone channel
-int32_t s = mic_buffer[i * 2];
+    int16_t *mic16 = (int16_t *)mic_buffer;
+    int16_t near_end[MIC_FRAME_SAMPLES];
+    int16_t far_end[MIC_FRAME_SAMPLES];
+
+    for (int i = 0; i < MIC_FRAME_SAMPLES; ++i) {
+        int32_t left = mic16[i * 2];
+        int32_t right = mic16[i * 2 + 1];
+        near_end[i] = (int16_t)((left + right) / 2);
+    }
 
-// Trying these one at a time
-//mic_pcm16[i] = s >> 16;
- //mic_pcm16[i] = s >> 15;
- mic_pcm16[i] = s >> 14;
-}
+    far_end_pop(far_end, MIC_FRAME_SAMPLES);
+    if (!aec_process_capture(near_end, far_end, MIC_FRAME_SAMPLES) ||
+        !aec_output_pop(mic_pcm16, SAMPLES_PER_PACKET)) {
+        return;
+    }
 
 
 // Debug microphone level
@@ -745,7 +826,28 @@ static void rtp_rx_task(void *pvParameters)
     continue;
 }
 
-ESP_LOGI(TAG, "Received RTP packet (%d bytes)", n);
+if (s_rtp_peer_port != 0 &&
+    (src.sin_port != htons(s_rtp_peer_port) ||
+     src.sin_addr.s_addr != s_rtp_peer.sin_addr.s_addr))
+{
+    ESP_LOGW(TAG,
+             "Ignoring RTP from unexpected peer %s:%d",
+             inet_ntoa(src.sin_addr),
+             ntohs(src.sin_port));
+    continue;
+}
+
+/* Ignore packets that are clearly looped back to the local device. */
+esp_netif_ip_info_t local_ip;
+esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
+esp_netif_get_ip_info(netif, &local_ip);
+if (src.sin_addr.s_addr == local_ip.ip.addr)
+{
+    ESP_LOGW(TAG, "Ignoring looped RTP packet from local IP");
+    continue;
+}
+
+// ESP_LOGI(TAG, "Received RTP packet (%d bytes)", n);
 
 if (n <= 12)
 {
@@ -753,23 +855,23 @@ if (n <= 12)
     continue;
 }
 
-ESP_LOGI(TAG,
-         "RTP Header: %02X %02X %02X %02X",
-         rx_packet[0],
-         rx_packet[1],
-         rx_packet[2],
-         rx_packet[3]);
-
-         ESP_LOGI(TAG,
-         "RTP Payload: %02X %02X %02X %02X %02X %02X %02X %02X",
-         rx_packet[12],
-         rx_packet[13],
-         rx_packet[14],
-         rx_packet[15],
-         rx_packet[16],
-         rx_packet[17],
-         rx_packet[18],
-         rx_packet[19]);
+// ESP_LOGI(TAG,
+//          "RTP Header: %02X %02X %02X %02X",
+//          rx_packet[0],
+//          rx_packet[1],
+//          rx_packet[2],
+//          rx_packet[3]);
+
+//          ESP_LOGI(TAG,
+//          "RTP Payload: %02X %02X %02X %02X %02X %02X %02X %02X",
+//          rx_packet[12],
+//          rx_packet[13],
+//          rx_packet[14],
+//          rx_packet[15],
+//          rx_packet[16],
+//          rx_packet[17],
+//          rx_packet[18],
+//          rx_packet[19]);
 
 
 int payload_size = n - 12;
@@ -781,6 +883,7 @@ if (payload_size > SAMPLES_PER_PACKET)
 
 
 int16_t play_buf[640];
+int16_t far_end_ref[320];
 
 for (int i = 0; i < payload_size; i++)
 {
@@ -801,20 +904,27 @@ for (int i = 0; i < payload_size; i++)
     // interpolated sample
     play_buf[4*i + 2] = s2; // Left
     play_buf[4*i + 3] = s2; // Right
+
+    far_end_ref[2 * i] = s1;
+    far_end_ref[2 * i + 1] = s2;
 }
 
+    // The reference must be the mono 16 kHz signal sent to the speaker,
+    // before it is duplicated into the codec's stereo output.
+    far_end_push(far_end_ref, payload_size * 2);
+
 esp_err_t ret = esp_audio_play(
     play_buf,
     payload_size * 4 * sizeof(int16_t),
     portMAX_DELAY);
 
 
-ESP_LOGI(TAG,
-         "esp_audio_play() = %s",
-         esp_err_to_name(ret));
+// ESP_LOGI(TAG,
+//          "esp_audio_play() = %s",
+//          esp_err_to_name(ret));
 
-            ESP_LOGI(TAG, "esp_audio_play() returned %s",
-             esp_err_to_name(ret));
+//             ESP_LOGI(TAG, "esp_audio_play() returned %s",
+//              esp_err_to_name(ret));
 }
 
     ESP_LOGI(TAG, "RTP RX stopped");

+ 25 - 0
sdkconfig

@@ -2411,6 +2411,31 @@ CONFIG_CJSON_CIRCULAR_LIMIT=10000
 # end of cJSON
 
 #
+# ESP-DL Configuration
+#
+
+#
+# Vision/Image: Pixel Convert Support
+#
+CONFIG_PIX_CVT_RGB565_TO_RGB565_SUPPORT=y
+CONFIG_PIX_CVT_RGB565_TO_RGB888_SUPPORT=y
+CONFIG_PIX_CVT_RGB565_TO_GRAY_SUPPORT=y
+CONFIG_PIX_CVT_RGB565_TO_HSV_SUPPORT=y
+CONFIG_PIX_CVT_RGB888_TO_RGB888_SUPPORT=y
+CONFIG_PIX_CVT_RGB888_TO_RGB565_SUPPORT=y
+CONFIG_PIX_CVT_RGB888_TO_GRAY_SUPPORT=y
+CONFIG_PIX_CVT_RGB888_TO_HSV_SUPPORT=y
+CONFIG_PIX_CVT_GRAY_TO_GRAY_SUPPORT=y
+CONFIG_PIX_CVT_HSV_TO_HSV_MASK_SUPPORT=y
+CONFIG_PIX_CVT_YUV_TO_RGB888_SUPPORT=y
+CONFIG_PIX_CVT_YUV_TO_RGB565_SUPPORT=y
+CONFIG_PIX_CVT_YUV_TO_GRAY_SUPPORT=y
+CONFIG_PIX_CVT_YUV_TO_HSV_SUPPORT=y
+CONFIG_PIX_CVT_YUV_TO_YUV_SUPPORT=y
+# end of Vision/Image: Pixel Convert Support
+# end of ESP-DL Configuration
+
+#
 # DSP Library
 #
 CONFIG_DSP_OPTIMIZATIONS_SUPPORTED=y