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

请问下BOX3的IIS端口1要怎么才能用? (AEGHB-938) #176

Open
3 tasks done
PoohWoah opened this issue Jan 6, 2025 · 12 comments
Open
3 tasks done

请问下BOX3的IIS端口1要怎么才能用? (AEGHB-938) #176

PoohWoah opened this issue Jan 6, 2025 · 12 comments

Comments

@PoohWoah
Copy link

PoohWoah commented Jan 6, 2025

Checklist

  • Checked the issue tracker for similar issues to ensure this is not a duplicate.
  • Provided a clear description of your suggestion.
  • Included any relevant context or examples.

Issue or Suggestion Description

我使用ADF进行语音的录音播放 怎么做到用不同的IIS端口?用了IIS端口一报错了

@github-actions github-actions bot changed the title 请问下BOX3的IIS端口1要怎么才能用? 请问下BOX3的IIS端口1要怎么才能用? (AEGHB-938) Jan 6, 2025
@PoohWoah
Copy link
Author

PoohWoah commented Jan 6, 2025

因为我目前再跑唤醒和服务器的语音识别,但是用了唤醒后 再用语音识别貌似不可行 需要两个端口分着来

@espressif2022
Copy link
Collaborator

因为我目前再跑唤醒和服务器的语音识别,但是用了唤醒后 再用语音识别貌似不可行 需要两个端口分着来

正常不会这个问题,我们也是这么使用的。你唤醒后,是不是改了 I2S 的 clk 等配置了?唤醒后的录音文件有确认下是否正常

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

因为我目前再跑唤醒和服务器的语音识别,但是用了唤醒后 再用语音识别貌似不可行 需要两个端口分着来

正常不会这个问题,我们也是这么使用的。你唤醒后,是不是改了 I2S 的 clk 等配置了?唤醒后的录音文件有确认下是否正常

唤醒的是需要源I2S数据吧 我传给服务器的需要做G711A数据处理,所以管道只能满足一个 (唤醒或者G711A编码)

@espressif2022
Copy link
Collaborator

espressif2022 commented Jan 8, 2025

因为我目前再跑唤醒和服务器的语音识别,但是用了唤醒后 再用语音识别貌似不可行 需要两个端口分着来

正常不会这个问题,我们也是这么使用的。你唤醒后,是不是改了 I2S 的 clk 等配置了?唤醒后的录音文件有确认下是否正常

唤醒的是需要源I2S数据吧 我传给服务器的需要做G711A数据处理,所以管道只能满足一个 (唤醒或者G711A编码)

了解,所以你是加了改了 clk, 16k 改成 8k。你这边可以加一个 resample 处理将 16K PCM 音频转为 8K,这样 I2S 一直工作在 16K
我前两天接了一个 openai 的工程也是这么处理的,这样你还能在播报时打断他
参考 component rate conversion

    esp_ae_rate_cvt_cfg_t config;
    config.src_rate = 16000;
    config.dest_rate = 8000;
    config.channel = 1;
    config.bits_per_sample = 16;
    config.complexity = 2;

    ret = esp_ae_rate_cvt_open(&config, &rsp_handle);
    ESP_LOGI(TAG, "esp_ae_rate_cvt_open:%d, %p", ret, rsp_handle);
char *audio_pcm16_to_g711A(uint32_t *g711_len)
{
    .........................
    int ret = esp_ae_rate_cvt_process(rsp_handle, aenc_in_frame.buffer, record_total_len, out_samples, &out_num);
    .........................
}

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

因为我目前再跑唤醒和服务器的语音识别,但是用了唤醒后 再用语音识别貌似不可行 需要两个端口分着来

正常不会这个问题,我们也是这么使用的。你唤醒后,是不是改了 I2S 的 clk 等配置了?唤醒后的录音文件有确认下是否正常

唤醒的是需要源I2S数据吧 我传给服务器的需要做G711A数据处理,所以管道只能满足一个 (唤醒或者G711A编码)

了解,所以你是加了改了 clk, 16k 改成 8k。你这边可以加一个 resample 处理将 16K PCM 音频转为 8K,这样 I2S 一直工作在 16K 我前两天接了一个 openai 的工程也是这么处理的,这样你还能在播报时打断他 参考 component rate conversion

    esp_ae_rate_cvt_cfg_t config;
    config.src_rate = 16000;
    config.dest_rate = 8000;
    config.channel = 1;
    config.bits_per_sample = 16;
    config.complexity = 2;

    ret = esp_ae_rate_cvt_open(&config, &rsp_handle);
    ESP_LOGI(TAG, "esp_ae_rate_cvt_open:%d, %p", ret, rsp_handle);
char *audio_pcm16_to_g711A(uint32_t *g711_len)
{
    .........................
    int ret = esp_ae_rate_cvt_process(rsp_handle, aenc_in_frame.buffer, record_total_len, out_samples, &out_num);
    .........................
}

你好,你说的好像和我说的不一样,我是唤醒用的是iis->filter->raw,读取的是raw这里的数据用于唤醒词识别
但是我现在还有一条管道需要直接输出G711A编码后的数据,这样我如果去获取呢,如你所说,我需要raw读取出来然后自己用G711A库编解码么?
提出这个issue我的期望是偷个懒,哈哈。想能不能两条管道(wakeup,g711a)同时去工作呢?这样我可以省掉很多工作,提高开发效率。

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

`static void app_record_playback_init()
{
audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG();
pipeline_wakeup = audio_pipeline_init(&pipeline_cfg);
if (NULL == pipeline_wakeup)
{
return;
}
i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT_WITH_PARA(CODEC_ADC_I2S_PORT, 48000, CODEC_ADC_BITS_PER_SAMPLE, AUDIO_STREAM_READER);
// i2s_cfg.i2s_config.channel_num = 2;
audio_element_handle_t i2s_reader = i2s_stream_init(&i2s_cfg);

audio_element_handle_t filter = NULL;
rsp_filter_cfg_t rsp_cfg = DEFAULT_RESAMPLE_FILTER_CONFIG();
rsp_cfg.src_rate = 48000;
rsp_cfg.dest_rate = 16000;
// rsp_cfg.src_ch = 1;  // 源通道数改为 1
// rsp_cfg.dest_ch = 1; // 目标通道数改为 1
filter = rsp_filter_init(&rsp_cfg);

raw_stream_cfg_t raw_cfg = RAW_STREAM_CFG_DEFAULT();
raw_cfg.type = AUDIO_STREAM_READER;
raw_read = raw_stream_init(&raw_cfg);

audio_pipeline_register(pipeline_wakeup, i2s_reader, "i2s");
audio_pipeline_register(pipeline_wakeup, raw_read, "raw");

if (filter)
{
    audio_pipeline_register(pipeline_wakeup, filter, "filter");
    const char *link_tag[3] = {"i2s", "filter", "raw"};
    audio_pipeline_link(pipeline_wakeup, &link_tag[0], 3);
}
else
{
    const char *link_tag[2] = {"i2s", "raw"};
    audio_pipeline_link(pipeline_wakeup, &link_tag[0], 2);
}

audio_pipeline_run(pipeline_wakeup);

recorder_sr_cfg_t recorder_sr_cfg = DEFAULT_RECORDER_SR_CFG();
recorder_sr_cfg.afe_cfg.memory_alloc_mode = AFE_MEMORY_ALLOC_MORE_PSRAM;
recorder_sr_cfg.afe_cfg.wakenet_init = WAKENET_ENABLE;
recorder_sr_cfg.afe_cfg.aec_init = RECORD_HARDWARE_AEC;
recorder_sr_cfg.afe_cfg.agc_mode = AFE_MN_PEAK_NO_AGC;
recorder_sr_cfg.afe_cfg.vad_init = VAD_ENBLE;
recorder_sr_cfg.afe_cfg.vad_mode = VAD_MODE_4;
recorder_sr_cfg.multinet_init = MULTINET_ENABLE;
recorder_sr_cfg.mn_language = ESP_MN_CHINESE;

audio_rec_cfg_t cfg = AUDIO_RECORDER_DEFAULT_CFG();
cfg.read = (recorder_data_read_t)&input_cb_for_afe;
cfg.sr_handle = recorder_sr_create(&recorder_sr_cfg, &cfg.sr_iface);

cfg.vad_start = 50;
cfg.event_cb = rec_engine_cb;
cfg.vad_off = 600;
recorder = audio_recorder_create(&cfg);

}`

我如果还需要一个管道去进行G711A编码 const char *link_tag[4] = {"i2s", "algo", "g711a", "raw"};这样的连接方式,可行吗?我参阅了所有的例子 好像都没这样的使用方式?

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

正因为如此 我才想到我能不能用两个端口去进行两条录音管道的创建,这就是我的初衷。或者你有什么好的解决方式吗?

@espressif2022
Copy link
Collaborator

正因为如此 我才想到我能不能用两个端口去进行两条录音管道的创建,这就是我的初衷。或者你有什么好的解决方式吗?

抱歉,ADF 框架那不太熟悉,可能导致我不是很理解你问题难点。
你用 16k pcm 音频 feed 给本地 SR 做唤醒,唤醒后将 pcm16 音频,reample 降到 8K + G711 编码上报就行了吧,如下就可以得到 录音数据后 G711A 编码音频

char *audio_pcm16_to_g711A(char *pcm16_data, uint32_t pcm16_len, uint32_t *g711_len)
{
    uint32_t pcm8k_sample_num = 0;
    uint32_t pcm16k_sample_num = pcm16_len / 2;

    esp_ae_rate_cvt_get_max_out_sample_num(rsp_16_to_8K, pcm16k_sample_num, &pcm8k_sample_num);

    char *out_8K_samples = heap_caps_malloc(pcm8k_sample_num * 2, MALLOC_CAP_SPIRAM);
    assert(out_8K_samples);

    int ret = esp_ae_rate_cvt_process(rsp_16_to_8K, pcm16_data, pcm16k_sample_num, out_8K_samples, &pcm8k_sample_num);

    esp_audio_enc_in_frame_t pcm16_8K_frame = {
        .buffer = (uint32_t *)out_8K_samples,
        .len = pcm8k_sample_num * 2,
    };
    g711_out_frame.len = pcm16_8K_frame.len / 2;

    if (esp_audio_enc_process(g711_enc_handle, &pcm16_8K_frame, &g711_out_frame) == ESP_AUDIO_ERR_OK) {
        // ESP_LOGI(TAG, "enc_process ok, in: %d out: %d", pcm16_8K_frame.len, g711_out_frame.len);
    }
    *g711_len = g711_out_frame.len;
    free(out_8K_samples);
    return (char *)g711_out_frame.buffer;
}

你的两个端口是指 两个 I2S 硬件描述符么?

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

正因为如此 我才想到我能不能用两个端口去进行两条录音管道的创建,这就是我的初衷。或者你有什么好的解决方式吗?

抱歉,ADF 框架那不太熟悉,可能导致我不是很理解你问题难点。 你用 16k pcm 音频 feed 给本地 SR 做唤醒,唤醒后将 pcm16 音频,reample 降到 8K + G711 编码上报就行了吧,如下就可以得到 录音数据后 G711A 编码音频

char *audio_pcm16_to_g711A(char *pcm16_data, uint32_t pcm16_len, uint32_t *g711_len)
{
    uint32_t pcm8k_sample_num = 0;
    uint32_t pcm16k_sample_num = pcm16_len / 2;

    esp_ae_rate_cvt_get_max_out_sample_num(rsp_16_to_8K, pcm16k_sample_num, &pcm8k_sample_num);

    char *out_8K_samples = heap_caps_malloc(pcm8k_sample_num * 2, MALLOC_CAP_SPIRAM);
    assert(out_8K_samples);

    int ret = esp_ae_rate_cvt_process(rsp_16_to_8K, pcm16_data, pcm16k_sample_num, out_8K_samples, &pcm8k_sample_num);

    esp_audio_enc_in_frame_t pcm16_8K_frame = {
        .buffer = (uint32_t *)out_8K_samples,
        .len = pcm8k_sample_num * 2,
    };
    g711_out_frame.len = pcm16_8K_frame.len / 2;

    if (esp_audio_enc_process(g711_enc_handle, &pcm16_8K_frame, &g711_out_frame) == ESP_AUDIO_ERR_OK) {
        // ESP_LOGI(TAG, "enc_process ok, in: %d out: %d", pcm16_8K_frame.len, g711_out_frame.len);
    }
    *g711_len = g711_out_frame.len;
    free(out_8K_samples);
    return (char *)g711_out_frame.buffer;
}

你的两个端口是指 两个 I2S 硬件描述符么?

两个端口I2S_NUM0 I2S_NUM1

正因为如此 我才想到我能不能用两个端口去进行两条录音管道的创建,这就是我的初衷。或者你有什么好的解决方式吗?

抱歉,ADF 框架那不太熟悉,可能导致我不是很理解你问题难点。 你用 16k pcm 音频 feed 给本地 SR 做唤醒,唤醒后将 pcm16 音频,reample 降到 8K + G711 编码上报就行了吧,如下就可以得到 录音数据后 G711A 编码音频

所以还是需要我自己去找一个G711编码库才下行吧?

@espressif2022
Copy link
Collaborator

两个端口I2S_NUM0 I2S_NUM1

这个不行

所以还是需要我自己去找一个G711编码库才下行吧?

ADF 内部有, 他们也封装了 组件 给别的工程用,用法可以参考 test_app, 上面 esp_audio_enc_process 就是 G711 编码,可注册初始化如下

    esp_audio_enc_register_default();

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

    esp_audio_enc_config_t g711_enc_cfg;
    g711_enc_cfg.type = ESP_AUDIO_TYPE_G711A;
    g711_enc_cfg.cfg = &g711_cfg;
    g711_enc_cfg.cfg_sz = sizeof(g711_cfg);

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

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

两个端口I2S_NUM0 I2S_NUM1

这个不行

所以还是需要我自己去找一个G711编码库才下行吧?

ADF 内部有, 他们也封装了 组件 给别的工程用,用法可以参考 test_app, 上面 esp_audio_enc_process 就是 G711 编码,可注册初始化如下

    esp_audio_enc_register_default();

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

    esp_audio_enc_config_t g711_enc_cfg;
    g711_enc_cfg.type = ESP_AUDIO_TYPE_G711A;
    g711_enc_cfg.cfg = &g711_cfg;
    g711_enc_cfg.cfg_sz = sizeof(g711_cfg);

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

我是唤醒也想用ADF,我现在有两个工程一个是ADF的唤醒,调试好了。另一个是G711A编码 和服务器交互也调试好了。合并再一起就都不能用了。你的意思是我唤醒用SR库?G711用ADF封装的?

@PoohWoah
Copy link
Author

PoohWoah commented Jan 8, 2025

两个端口I2S_NUM0 I2S_NUM1

这个不行

所以还是需要我自己去找一个G711编码库才下行吧?

ADF 内部有, 他们也封装了 组件 给别的工程用,用法可以参考 test_app, 上面 esp_audio_enc_process 就是 G711 编码,可注册初始化如下

    esp_audio_enc_register_default();

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

    esp_audio_enc_config_t g711_enc_cfg;
    g711_enc_cfg.type = ESP_AUDIO_TYPE_G711A;
    g711_enc_cfg.cfg = &g711_cfg;
    g711_enc_cfg.cfg_sz = sizeof(g711_cfg);

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

我是唤醒也想用ADF,我现在有两个工程一个是ADF的唤醒,调试好了。另一个是G711A编码 和服务器交互也调试好了。合并再一起就都不能用了。你的意思是我唤醒用SR库?G711用ADF封装的?

谢谢 我大概知道你的意思了 感谢!

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

2 participants