Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
gtk2k opened this issue Dec 25, 2024 · 0 comments
Open

Comments

@gtk2k
Copy link

gtk2k commented Dec 25, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant