Skip to content

Commit ad22dfa

Browse files
committed
Merge branch 'feature/add_wn_element' into 'main'
gmf_ai_audio: Add wn element See merge request adf/multimedia/esp-gmf!67
2 parents cdc0a17 + 50b275f commit ad22dfa

36 files changed

+1340
-265
lines changed

elements/gmf_ai_audio/CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44

55
### Features
66

7-
- Add API `esp_gmf_afe_set_event_cb` to set AFE element event callback
8-
- Replaced the interface for decoding reconfig
7+
- Added `esp_gmf_afe_set_event_cb` API to register AFE element event callbacks
8+
- Replaced the interface for decoder reconfiguration
9+
- Introduced `esp_gmf_wn` element to support wake word detection
10+
11+
### Bug Fixes
12+
13+
- Fixed an issue where the output attribute of the `esp_gmf_afe` element was not set correctly
14+
- Fixed a build error occurring when SPIRAM is disabled
915

1016
## v0.6.2
1117

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
set(srcs "./src/esp_gmf_wn.c")
2+
3+
if((${IDF_TARGET} STREQUAL "esp32s3") OR (${IDF_TARGET} STREQUAL "esp32p4") OR (${IDF_TARGET} STREQUAL "esp32"))
4+
list(APPEND srcs "./src/esp_gmf_afe_manager.c" "./src/esp_gmf_afe.c" "./src/esp_gmf_aec.c")
5+
endif()
6+
17
idf_component_register(
2-
SRC_DIRS "./src"
8+
SRCS "${srcs}"
39
INCLUDE_DIRS "./include"
10+
PRIV_INCLUDE_DIRS "./private_include"
411
REQUIRES esp-sr esp_timer
512
)

elements/gmf_ai_audio/README.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
`GMF AI Audio` is an artificial intelligence audio processing module that provides users with convenient and easy-to-use intelligent audio processing algorithms at the [GMF](https://github.com/espressif/esp-gmf) framework, such as voice wake-up, command word recognition, and echo cancellation. Currently, it offers the following modules based on `esp-sr`:
66

7-
* [esp_gmf_afe_manager](./src/esp_gmf_afe_manager.c): `audio front end(afe)` manager
8-
* [esp_gmf_aec](./src/esp_gmf_aec.c): Echo Cancellation
9-
* [esp_gmf_afe](./src/esp_gmf_afe.c): An easy-to-use interface based on the `audio front end (afe)` from `esp-sr`, providing functionalities such as voice wake-up, command word recognition, and speech detection
7+
- [esp_gmf_afe_manager](./src/esp_gmf_afe_manager.c): `audio front end(afe)` manager
8+
- [esp_gmf_aec](./src/esp_gmf_aec.c): Echo Cancellation
9+
- [esp_gmf_wn](./src/esp_gmf_wn.c): A standalone wake word detection module that can be used independently
10+
- [esp_gmf_afe](./src/esp_gmf_afe.c): An easy-to-use interface based on the `audio front end (afe)` from `esp-sr`, providing functionalities such as voice wake-up, command word recognition, and speech detection
1011

1112
## AFE Manager `esp_gmf_afe_manager`
1213

@@ -53,7 +54,27 @@
5354

5455
### Technical Specifications
5556

56-
- Supported Hardware: `ESP32`, `ESP32-S3`, `ESP32-C5`, and `ESP32-P4`
57+
- Supported Hardware: `ESP32`, `ESP32-S3`, and `ESP32-P4`
58+
- Input Format
59+
- Sampling Rate: 8 kHz and 16 kHz
60+
- Bit Width: 16-bit PCM
61+
- Channel Configuration: String identifiers (e.g., `MMNR`)
62+
- `M`: Microphone Channel
63+
- `R`: Reference Signal Channel
64+
- `N`: Invalid Signal
65+
- Output Format: 16-bit single-channel PCM
66+
67+
## Wake Word Detection `esp_gmf_wn`
68+
69+
### Features
70+
71+
- Runs independently without AFE dependency, low resource usage
72+
- Supports multi-channel input and single-channel output
73+
- Notifies wake word detection results via callback function
74+
75+
### Technical Specifications
76+
77+
- Supported Hardware: `ESP32`, `ESP32-S3`, `ESP32-C3`, `ESP32-C5` and `ESP32-P4`
5778
- Input Format
5879
- Sampling Rate: 16 kHz
5980
- Bit Width: 16-bit PCM
@@ -165,7 +186,7 @@ The following illustrates state transitions when features are enabled. The `/` c
165186

166187
- **Enable Both Wake Word Detection and VAD**
167188

168-
This scenario combines command word detection with voice activity detection to avoid frequent voice activity events outside the wake word interval
189+
This scenario combines wake word detection with voice activity detection to avoid frequent voice activity events outside the wake word interval
169190

170191
Modify the configuration in the example [wwe](./examples/wwe/main/main.c) to use this scenario
171192

@@ -193,8 +214,8 @@ The following illustrates state transitions when features are enabled. The `/` c
193214

194215
Users need to decide when to start command word detection. A typical use case is to enable detection after the state machine pushes a (WAKEUP_START) event and determine the next operation based on the detected command word index in the callback function
195216

196-
* Command word detection is independent of the wake word state machine
197-
* Command word detection supports continuous detection until timeout
217+
- Command word detection is independent of the wake word state machine
218+
- Command word detection supports continuous detection until timeout
198219

199220
## Usage
200221

elements/gmf_ai_audio/README_CN.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
`GMF AI Audio` 是一个人工智能语音处理模块,它在 [GMF](https://github.com/espressif/esp-gmf) 层面为用户提供方便、易用的语音唤醒、命令词识别和回声消除等常用智能语音处理算法。目前基于 `esp-sr` 提供以下模块:
66

7-
* [esp_gmf_afe_manager](./src/esp_gmf_afe_manager.c): `audio front end(afe)` 管理器
8-
* [esp_gmf_aec](./src/esp_gmf_aec.c): 回声消除
9-
* [esp_gmf_afe](./src/esp_gmf_afe.c): 基于 `esp-sr``audio front end (afe)` 实现的易用接口,提供了语音唤醒,命令词识别,人声检测等语音识别的功能
7+
- [esp_gmf_afe_manager](./src/esp_gmf_afe_manager.c): `audio front end(afe)` 管理器
8+
- [esp_gmf_aec](./src/esp_gmf_aec.c): 回声消除
9+
- [esp_gmf_wn](./src/esp_gmf_wn.c): 独立的唤醒词检测模块,不依赖AFE
10+
- [esp_gmf_afe](./src/esp_gmf_afe.c): 基于 `esp-sr``audio front end (afe)` 实现的易用接口,提供了语音唤醒,命令词识别,人声检测等语音识别的功能
1011

1112
## AFE 管理器 `esp_gmf_afe_manager`
1213

@@ -53,7 +54,7 @@
5354

5455
### 技术规格
5556

56-
- 支持硬件:`ESP32``ESP32-S3``ESP32-C5``ESP32-P4`
57+
- 支持硬件:`ESP32``ESP32-S3``ESP32-P4`
5758
- 输入格式
5859
- 采样率:16 kHz
5960
- 位宽:16-bit PCM
@@ -63,6 +64,26 @@
6364
- `N`:无效信号
6465
- 输出格式:16-bit 单通道 PCM
6566

67+
## 唤醒词检测 `esp_gmf_wn`
68+
69+
### 功能
70+
71+
- 独立运行,不依赖AFE,资源占用小
72+
- 支持多通道输入,单通道输出
73+
- 通过回调函数通知唤醒词检测结果
74+
75+
### 技术规格
76+
77+
- 支持硬件:`ESP32``ESP32-S3``ESP32-C3``ESP32-C5``ESP32-P4`
78+
- 输入格式
79+
- 采样率:8 kHz, 16 kHz
80+
- 位宽:16-bit PCM
81+
- 通道配置:字符串标识(如 `MMNR`
82+
- `M`:麦克风通道
83+
- `R`:回采信号通道
84+
- `N`:无效信号
85+
- 输出格式:16-bit 单通道 PCM
86+
6687
## 语音识别 `esp_gmf_afe`
6788

6889
### 功能
@@ -165,7 +186,7 @@
165186

166187
- **使能唤醒和VAD**
167188

168-
该场景结合命令词与人声检测,避免在唤醒间隔之外频繁触发人声检测事件
189+
该场景结合唤醒词与人声检测,避免在唤醒间隔之外频繁触发人声检测事件
169190

170191
修改示例 [wwe](./examples/wwe/main/main.c) 中的配置,从而使用该场景
171192

@@ -193,8 +214,8 @@
193214

194215
用户需决定何时开始检测命令词,如典型的使用场景:在状态机推送(WAKEUP_START)事件之后,开启检测,并在回调函数中根据检测到的命令词序号决定下一步操作
195216

196-
* 命令词检测与唤醒状态机独立
197-
* 命令词支持连续检测,直到超时
217+
- 命令词检测与唤醒状态机独立
218+
- 命令词支持连续检测,直到超时
198219

199220
## 示例
200221

elements/gmf_ai_audio/examples/common/gmf_setup/esp_gmf_gpio_config.h

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ extern "C" {
4848
#define ESP_GMF_AMP_IO_NUM (GPIO_NUM_21)
4949

5050
#elif CONFIG_IDF_TARGET_ESP32C3
51-
// ESP32c3-Lyra
51+
// XD_AIOT_C3
5252
// Sdmmc
5353
#define ESP_GMF_SD_CLK_IO_NUM (GPIO_NUM_NC)
5454
#define ESP_GMF_SD_CMD_IO_NUM (GPIO_NUM_NC)
@@ -65,25 +65,61 @@ extern "C" {
6565
#define ESP_GMF_SD_WIDTH (1)
6666

6767
// I2C
68-
#define ESP_GMF_I2C_SDA_IO_NUM (GPIO_NUM_9)
69-
#define ESP_GMF_I2C_SCL_IO_NUM (GPIO_NUM_8)
68+
#define ESP_GMF_I2C_SDA_IO_NUM (GPIO_NUM_0)
69+
#define ESP_GMF_I2C_SCL_IO_NUM (GPIO_NUM_1)
70+
71+
// I2S
72+
#define ESP_GMF_I2S_DAC_MCLK_IO_NUM (GPIO_NUM_10)
73+
#define ESP_GMF_I2S_DAC_BCLK_IO_NUM (GPIO_NUM_8)
74+
#define ESP_GMF_I2S_DAC_WS_IO_NUM (GPIO_NUM_12)
75+
#define ESP_GMF_I2S_DAC_DO_IO_NUM (GPIO_NUM_11)
76+
#define ESP_GMF_I2S_DAC_DI_IO_NUM (GPIO_NUM_7)
77+
78+
#define ESP_GMF_I2S_ADC_MCLK_IO_NUM (GPIO_NUM_10)
79+
#define ESP_GMF_I2S_ADC_BCLK_IO_NUM (GPIO_NUM_8)
80+
#define ESP_GMF_I2S_ADC_WS_IO_NUM (GPIO_NUM_12)
81+
#define ESP_GMF_I2S_ADC_DO_IO_NUM (GPIO_NUM_11)
82+
#define ESP_GMF_I2S_ADC_DI_IO_NUM (GPIO_NUM_7)
83+
84+
// PA
85+
#define ESP_GMF_AMP_IO_NUM (GPIO_NUM_13)
86+
#elif CONFIG_IDF_TARGET_ESP32C5
87+
// ESP-SPOT
88+
// Sdmmc
89+
#define ESP_GMF_SD_CLK_IO_NUM (GPIO_NUM_NC)
90+
#define ESP_GMF_SD_CMD_IO_NUM (GPIO_NUM_NC)
91+
#define ESP_GMF_SD_D0_IO_NUM (GPIO_NUM_NC)
92+
#define ESP_GMF_SD_D1_IO_NUM (GPIO_NUM_NC)
93+
#define ESP_GMF_SD_D2_IO_NUM (GPIO_NUM_NC)
94+
#define ESP_GMF_SD_D3_IO_NUM (GPIO_NUM_NC)
95+
#define ESP_GMF_SD_D4_IO_NUM (GPIO_NUM_NC)
96+
#define ESP_GMF_SD_D5_IO_NUM (GPIO_NUM_NC)
97+
#define ESP_GMF_SD_D6_IO_NUM (GPIO_NUM_NC)
98+
#define ESP_GMF_SD_D7_IO_NUM (GPIO_NUM_NC)
99+
#define ESP_GMF_SD_CD_IO_NUM (GPIO_NUM_NC)
100+
#define ESP_GMF_SD_WP_IO_NUM (GPIO_NUM_NC)
101+
#define ESP_GMF_SD_WIDTH (1)
102+
103+
// I2C
104+
#define ESP_GMF_I2C_SDA_IO_NUM (GPIO_NUM_25)
105+
#define ESP_GMF_I2C_SCL_IO_NUM (GPIO_NUM_26)
106+
#define ESP_SPOT_ES8311_I2C_ADDR (0x18)
70107

71108
// I2S
72109
#define ESP_GMF_I2S_DAC_MCLK_IO_NUM (GPIO_NUM_NC)
73-
#define ESP_GMF_I2S_DAC_BCLK_IO_NUM (GPIO_NUM_NC)
74-
#define ESP_GMF_I2S_DAC_WS_IO_NUM (GPIO_NUM_NC)
75-
#define ESP_GMF_I2S_DAC_DO_IO_NUM (GPIO_NUM_3)
76-
#define ESP_GMF_I2S_DAC_DI_IO_NUM (GPIO_NUM_NC)
110+
#define ESP_GMF_I2S_DAC_BCLK_IO_NUM (GPIO_NUM_7)
111+
#define ESP_GMF_I2S_DAC_WS_IO_NUM (GPIO_NUM_8)
112+
#define ESP_GMF_I2S_DAC_DO_IO_NUM (GPIO_NUM_9)
113+
#define ESP_GMF_I2S_DAC_DI_IO_NUM (GPIO_NUM_6)
77114

78115
#define ESP_GMF_I2S_ADC_MCLK_IO_NUM (GPIO_NUM_NC)
79-
#define ESP_GMF_I2S_ADC_BCLK_IO_NUM (GPIO_NUM_NC)
80-
#define ESP_GMF_I2S_ADC_WS_IO_NUM (GPIO_NUM_NC)
81-
#define ESP_GMF_I2S_ADC_DO_IO_NUM (GPIO_NUM_3)
82-
#define ESP_GMF_I2S_ADC_DI_IO_NUM (GPIO_NUM_NC)
116+
#define ESP_GMF_I2S_ADC_BCLK_IO_NUM (GPIO_NUM_7)
117+
#define ESP_GMF_I2S_ADC_WS_IO_NUM (GPIO_NUM_8)
118+
#define ESP_GMF_I2S_ADC_DO_IO_NUM (GPIO_NUM_9)
119+
#define ESP_GMF_I2S_ADC_DI_IO_NUM (GPIO_NUM_6)
83120

84121
// PA
85-
#define ESP_GMF_AMP_IO_NUM (GPIO_NUM_1)
86-
122+
#define ESP_GMF_AMP_IO_NUM (GPIO_NUM_23)
87123
#elif CONFIG_IDF_TARGET_ESP32S3
88124
// ESP32s3_Korvo_2
89125
// Sdmmc

elements/gmf_ai_audio/examples/common/gmf_setup/esp_gmf_setup_peripheral.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#include "driver/i2c.h"
1515
#include "esp_gmf_gpio_config.h"
1616
#include "esp_gmf_setup_peripheral.h"
17+
#if SOC_SDMMC_IO_POWER_EXTERNAL
1718
#include "sd_pwr_ctrl_by_on_chip_ldo.h"
19+
#endif /* SOC_SDMMC_IO_POWER_EXTERNAL */
1820
#ifdef USE_ESP_GMF_ESP_CODEC_DEV_IO
1921
#include "esp_gmf_io_codec_dev.h"
2022
#include "esp_gmf_io_i2s_pdm.h"
@@ -136,11 +138,6 @@ static const audio_codec_data_if_t *setup_periph_new_i2s_data(void *tx_hd, void
136138

137139
static void setup_periph_new_play_codec()
138140
{
139-
#ifdef CONFIG_IDF_TARGET_ESP32C3
140-
gpio_if = audio_codec_new_gpio();
141-
gpio_if->setup(ESP_GMF_AMP_IO_NUM, AUDIO_GPIO_DIR_OUT, AUDIO_GPIO_MODE_PULL_DOWN);
142-
gpio_if->set(ESP_GMF_AMP_IO_NUM, 1);
143-
#else
144141
audio_codec_i2c_cfg_t i2c_ctrl_cfg = {.addr = ES8311_CODEC_DEFAULT_ADDR, .port = 0, .bus_handle = i2c_handle};
145142
out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_ctrl_cfg);
146143
gpio_if = audio_codec_new_gpio();
@@ -153,13 +150,15 @@ static void setup_periph_new_play_codec()
153150
.use_mclk = true,
154151
};
155152
out_codec_if = es8311_codec_new(&es8311_cfg);
156-
#endif /* CONFIG_IDF_TARGET_ESP32C3 */
157153
}
158154

159155
static void setup_periph_new_record_codec(void)
160156
{
161-
#if defined CONFIG_IDF_TARGET_ESP32P4
157+
#if defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C5)
162158
audio_codec_i2c_cfg_t i2c_ctrl_cfg = {.addr = ES8311_CODEC_DEFAULT_ADDR, .port = 0, .bus_handle = i2c_handle};
159+
#if defined(CONFIG_IDF_TARGET_ESP32C5)
160+
i2c_ctrl_cfg.addr = ESP_SPOT_ES8311_I2C_ADDR;
161+
#endif
163162
in_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_ctrl_cfg);
164163
gpio_if = audio_codec_new_gpio();
165164
// New output codec interface
@@ -266,12 +265,13 @@ void teardown_periph_record_codec(void *record_dev)
266265
}
267266
#endif /* USE_ESP_GMF_ESP_CODEC_DEV_IO */
268267

268+
#if SOC_SDMMC_HOST_SUPPORTED
269269
void esp_gmf_setup_periph_sdmmc(void **out_card)
270270
{
271271
sdmmc_card_t *card = NULL;
272272
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
273273
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
274-
#if defined CONFIG_IDF_TARGET_ESP32P4
274+
#if SOC_SDMMC_IO_POWER_EXTERNAL
275275
host.slot = SDMMC_HOST_SLOT_0;
276276
host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
277277
sd_pwr_ctrl_ldo_config_t ldo_config = {
@@ -284,7 +284,7 @@ void esp_gmf_setup_periph_sdmmc(void **out_card)
284284
return;
285285
}
286286
host.pwr_ctrl_handle = pwr_ctrl_handle;
287-
#endif /* defined CONFIG_IDF_TARGET_ESP32P4 */
287+
#endif /* SOC_SDMMC_IO_POWER_EXTERNAL */
288288

289289
#if defined CONFIG_IDF_TARGET_ESP32
290290
gpio_config_t sdcard_pwr_pin_cfg = {
@@ -326,8 +326,26 @@ void esp_gmf_setup_periph_sdmmc(void **out_card)
326326

327327
void esp_gmf_teardown_periph_sdmmc(void *card)
328328
{
329-
esp_vfs_fat_sdcard_unmount("/sdcard", card);
329+
sdmmc_card_t *sd_card = card;
330+
esp_vfs_fat_sdcard_unmount("/sdcard", sd_card);
331+
#if SOC_SDMMC_IO_POWER_EXTERNAL
332+
int ret = sd_pwr_ctrl_del_on_chip_ldo(sd_card->host.pwr_ctrl_handle);
333+
if (ret != ESP_OK) {
334+
ESP_LOGE(TAG, "Failed to delete the on-chip LDO power control driver");
335+
}
336+
#endif /* SOC_SDMMC_IO_POWER_EXTERNAL */
337+
}
338+
#else
339+
void esp_gmf_setup_periph_sdmmc(void **out_card)
340+
{
341+
// TODO nothing
342+
}
343+
344+
void esp_gmf_teardown_periph_sdmmc(void *card)
345+
{
346+
// TODO nothing
330347
}
348+
#endif // SOC_SDMMC_HOST_SUPPORTED
331349

332350
void esp_gmf_setup_periph_i2c(int port)
333351
{

0 commit comments

Comments
 (0)