libpeer icon indicating copy to clipboard operation
libpeer copied to clipboard

I would like an Audio 2 Way example using the OPUS encoder and decoder.

Open gtk2k opened this issue 1 year ago • 1 comments

I just started using ESP-IDF. I'm trying it myself, but I get an error.

#include "driver/i2s_pdm.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_audio_enc.h"
#include "esp_audio_enc_default.h"
#include "esp_audio_enc_reg.h"
#include "esp_g711_enc.h"
#include "esp_opus_enc.h"

#include "peer_connection.h"

#define I2S_CLK_GPIO 42
#define I2S_DATA_GPIO 41

static const char* TAG = "AUDIO";

extern PeerConnection* g_pc;
extern PeerConnectionState eState;
extern int get_timestamp();

i2s_chan_handle_t rx_handle = NULL;

esp_audio_enc_handle_t enc_handle = NULL;
esp_audio_enc_in_frame_t aenc_in_frame = {0};
esp_audio_enc_out_frame_t aenc_out_frame = {0};
// esp_g711_enc_config_t g711_cfg;
esp_opus_enc_config_t opus_cfg;
esp_audio_enc_config_t enc_cfg;

esp_err_t audio_codec_init() {
  uint8_t* read_buf = NULL;
  uint8_t* write_buf = NULL;
  int read_size = 0;
  int out_size = 0;

  esp_audio_err_t ret = ESP_AUDIO_ERR_OK;

  esp_audio_enc_register_default();

  // g711_cfg.sample_rate = ESP_AUDIO_SAMPLE_RATE_8K;
  // g711_cfg.channel = ESP_AUDIO_MONO;
  // g711_cfg.bits_per_sample = ESP_AUDIO_BIT16;

  // enc_cfg.type = ESP_AUDIO_TYPE_G711A;
  // enc_cfg.cfg = &g711_cfg;
  // enc_cfg.cfg_sz = sizeof(g711_cfg);

  // ret = esp_audio_enc_open(&enc_cfg, &enc_handle);
  // if (ret != ESP_AUDIO_ERR_OK) {
  //   ESP_LOGE(TAG, "audio encoder open failed");
  //   return ESP_FAIL;
  // }

  // int frame_size = (g711_cfg.bits_per_sample * g711_cfg.channel) >> 3;

  opus_cfg.sample_rate = ESP_AUDIO_SAMPLE_RATE_8K;
  opus_cfg.channel = ESP_AUDIO_DUAL;
  opus_cfg.bits_per_sample = ESP_AUDIO_BIT16;
  opus_cfg.bitrate = 256;
  opus_cfg.frame_duration = ESP_OPUS_ENC_FRAME_DURATION_20_MS;
  opus_cfg.application_mode = ESP_OPUS_ENC_APPLICATION_VOIP;
  opus_cfg.complexity = 0;
  opus_cfg.enable_fec = false;
  opus_cfg.enable_dtx = false;

  enc_cfg.type = ESP_AUDIO_TYPE_OPUS;
  enc_cfg.cfg = &opus_cfg;
  enc_cfg.cfg_sz = sizeof(opus_cfg);
  ret = esp_opus_enc_open(&opus_cfg, sizeof(esp_opus_enc_config_t), &enc_handle);
  if (ret != ESP_AUDIO_ERR_OK) {
    ESP_LOGE(TAG, "audio encoder open failed");
    return ESP_FAIL;
  }

  int frame_size = (opus_cfg.bits_per_sample * opus_cfg.channel) >> 3;
  ret = esp_opus_enc_get_frame_size(enc_handle, &read_size, &out_size);
  if (frame_size == read_size) {
    read_size *= 256;
    out_size *= 256;
  }

  if (ret != ESP_AUDIO_ERR_OK) {
    ESP_LOGE(TAG, "audio encoder get frame size failed");
    return ESP_FAIL;
  }

  read_buf = malloc(read_size);
  if (!read_buf) {
    ESP_LOGE(TAG, "read_buf malloc failed");
    return ESP_FAIL;
  }

  write_buf = malloc(out_size);
  if (!write_buf) {
    ESP_LOGE(TAG, "write_buf malloc failed");
    return ESP_FAIL;
  }

  aenc_in_frame.buffer = read_buf;
  aenc_in_frame.len = read_size;
  aenc_out_frame.buffer = write_buf;
  aenc_out_frame.len = out_size;
  ESP_LOGI(TAG, "audio codec init done. in buffer size: %d, out buffer size: %d", read_size, out_size);

  return 0;
}

esp_err_t audio_init(void) {
  i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
  ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &rx_handle));

  i2s_pdm_rx_config_t pdm_rx_cfg = {
      .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(8000),
      .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
      .gpio_cfg = {
          .clk = I2S_CLK_GPIO,
          .din = I2S_DATA_GPIO,
          .invert_flags = {
              .clk_inv = false,
          },
      },
  };

  ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_handle, &pdm_rx_cfg));
  ESP_ERROR_CHECK(i2s_channel_enable(rx_handle));

  return audio_codec_init();
}

void audio_deinit(void) {
  ESP_ERROR_CHECK(i2s_channel_disable(rx_handle));
  ESP_ERROR_CHECK(i2s_del_channel(rx_handle));
}

int32_t audio_get_samples(uint8_t* buf, size_t size) {
  size_t bytes_read;

  if (i2s_channel_read(rx_handle, (char*)buf, size, &bytes_read, 1000) != ESP_OK) {
    ESP_LOGE(TAG, "i2s read error");
  }

  return bytes_read;
}

void audio_task(void* arg) {
  int ret;
  static int64_t last_time;
  int64_t curr_time;
  float bytes = 0;

  last_time = get_timestamp();
  ESP_LOGI(TAG, "audio task started");

  for (;;) {
    if (eState == PEER_CONNECTION_COMPLETED) {
      ret = audio_get_samples(aenc_in_frame.buffer, aenc_in_frame.len);

      if (ret == aenc_in_frame.len) {
        if (esp_audio_enc_process(enc_handle, &aenc_in_frame, &aenc_out_frame) == ESP_AUDIO_ERR_OK) {
          peer_connection_send_audio(g_pc, aenc_out_frame.buffer, aenc_out_frame.encoded_bytes);

          bytes += aenc_out_frame.encoded_bytes;
          // if (bytes > 50000) {
          //   curr_time = get_timestamp();
          //   ESP_LOGI(TAG, "audio bitrate: %.1f bps", 1000.0 * (bytes * 8.0 / (float)(curr_time - last_time)));
          //   last_time = curr_time;
          //   bytes = 0;
          // }
        } else {
          ESP_LOGI(TAG, "esp_audio_enc_process error");
        }
      }
      vTaskDelay(pdMS_TO_TICKS(5));

    } else {
      vTaskDelay(pdMS_TO_TICKS(100));
    }
  }
}
--- 0x4200b485: esp_audio_enc_process at /builds/adf/esp-adf-libs-source/esp_audio_codec/codec-interface/src/esp_audio_enc.c:110

A2      : 0x3fcdc9ec  A3      : 0x3fca15e8  A4      : 0x3fca15d0  A5      : 0x00001d29  
A6      : 0x3c0f5e04  A7      : 0x00000000  A8      : 0x00001f40  A9      : 0x3c1520a0  
A10     : 0x3c140e0c  A11     : 0x3fca15e8  A12     : 0x3fca15d0  A13     : 0x3c1520d0  
A14     : 0x00000280  A15     : 0x3c140c30  SAR     : 0x00000004  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00001f4c  LBEG    : 0x40056f5c  LEND    : 0x40056f72  LCOUNT  : 0x00000000  
--- 0x40056f5c: memcpy in ROM
0x40056f72: memcpy in ROM

gtk2k avatar Dec 25 '24 06:12 gtk2k

hello, can you try to allocate more stack size for audio_task?

sepfy avatar Jan 26 '25 13:01 sepfy