Baji_Rtc_Toy/main/CMakeLists.txt
Rdzleo c6ecdb124c feat(audio): 同步 Kapi 软件 AEC + NULL crash fix 到数字人项目
来源: Kapi commit 63b21fd (NULL fix) + a369796 (软件 AEC) 完整移植

改动:
- components/common/src/volc_rtc.c
  on_global_error 加 message ? message : "(null)" 防御.
  解决: idle ≥10 分钟后服务端 session 超时 / NAT 表过期触发的
       printf("%s", NULL) → strlen panic → 设备重启.

- main/CMakeLists.txt
  REQUIRES 末尾加 esp-sr (提供 esp_aec.h 同步 API).

- main/application.h
  +7 个 AEC 成员 + 5 个函数声明 (recorder/player pipeline 后).

- main/application.cc
  +InitAec / DeinitAec / AppendRefSamples / GetDelayedRef / ApplyAEC (~170 行).
  OnAudioOutput 三个 codec output 位置都加 AppendRefSamples hook.
  ReadAudio 两条路径 (recorder_pipeline + codec 直读) 加 lazy InitAec
  + ApplyAEC + target_samples = max(samples, chunk_size).
  PHASE8_DIAG_ENABLE 默认 0 (诊断埋点已完成根因定位, 关闭减少日志噪声).

实测效果 (30 分钟设备验证):
  AI 说话:    mic=285 ref=8310 clean=31 (消除 89%)
  AI 说话:    mic=660 ref=7489 clean=57 (消除 91%)
  AI 说话:    mic=156 ref=2748 clean=0  (消除 100%)
  用户说话:   mic=224 ref=8 clean=224   (passthrough 正常)

资源占用:
  Flash       +59 KB (+1.2%)
  Internal SRAM  +35-50 KB (+10-15%)
  PSRAM       +10-15 KB (<0.2%)
  Core 1 CPU  +6-12% @240MHz

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:54:55 +08:00

332 lines
14 KiB
CMake
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

set(SOURCES "audio_codecs/audio_codec.cc"
"audio_codecs/no_audio_codec.cc"
"audio_codecs/box_audio_codec.cc"
"audio_codecs/es8311_audio_codec.cc"
"audio_codecs/es8388_audio_codec.cc"
"audio/simple_pipeline.cc"
"led/single_led.cc"
"led/circular_strip.cc"
"led/gpio_led.cc"
"display/display.cc"
"display/ai_chat_display.cc" # AI 对话模式专用显示
#"display/lcd_display.cc" # 移除LCD显示器支持
#"display/oled_display.cc" # 移除OLED显示器支持
"protocols/protocol.cc"
"iot/thing.cc"
"iot/thing_manager.cc"
"system_info.cc"
"application.cc"
"ota.cc"
"settings.cc"
"background_task.cc"
"bluetooth_provisioning.cc" # 蓝牙配网实现
#"ble_service.cc" # BLE JSON 通讯服务(暂不使用,保留代码)
"weather_api.cc"
"main.cc"
# dzbj 公共显示驱动AI 模式也使用)
"dzbj/lcd.c"
"dzbj/pages_pwm.c"
"dzbj/dzbj_init.c" # 含 dzbj_hw_display_init公共硬件初始化dzbj_display_init 函数体内部 #ifdef 包裹
"dzbj/fatfs.c" # DecodeImg 公共AI 模式 BG GIF PoC 也用);吧唧专用函数 fatfs_init/list 等无副作用
# Phase 10: ai_chat_ui 双轨编译
# CONFIG_BAJI_BADGE_MODE=y → ai_chat_ui.c (LVGL 版)
# CONFIG_BAJI_BADGE_MODE=n → ai_chat_ui_eaf.c (esp_emote_gfx 版)
# 这两个在下方 if(CONFIG_BAJI_BADGE_MODE) 块中条件编译
"fonts/font_puhui_20_4.c" # 阿里巴巴普惠体 20px 4bppGB2312 简体中文)
# SquareLine Studio UI 公共文件AI 模式也使用)
"ui/ui.c"
"ui/ui_helpers.c"
"ui/components/ui_comp_hook.c"
"ui/battery_ui.c"
# UI 图片资源
"ui/images/ui_img_airhub_png.c"
"ui/images/ui_img_peiwang_new2_png.c"
"ui/images/ui_img_image_shar_png.c"
"ui/images/ui_img_image_reception_png.c"
"ui/images/ui_img_sharing_png.c"
"ui/images/ui_img_receiving_png.c"
"ui/images/Gengxin.c"
"ui/images/Update_GIF.c"
"ui/images/ui_img_s1_png.c"
"ui/images/ui_img_s6_png.c"
"ui/images/ui_img_s8_png.c"
"ui/images/ui_img_s9_png.c"
"ui/images/ui_img_s10_png.c"
"ui/images/ui_img_s11_png.c"
"ui/images/ui_img_s12_png.c"
"ui/images/ui_img_s13_png.c"
"ui/images/ui_img_s14_png.c"
# emoji 表情图片资源(旧 PNG 静态表情,保留备用)
"ui/images/ui_img_neutral_png.c"
"ui/images/ui_img_happy_png.c"
"ui/images/ui_img_sad_png.c"
"ui/images/ui_img_angry_png.c"
"ui/images/ui_img_crying_png.c"
"ui/images/ui_img_funny_png.c"
"ui/images/ui_img_laughing_png.c"
# GIF 动画表情资源压缩优化200x89
"ui/images/my_emotion/emotion_angry_200_89.c"
"ui/images/my_emotion/emotion_blink1_200_89.c"
"ui/images/my_emotion/emotion_blink_fast_200_89.c"
"ui/images/my_emotion/emotion_blink_slow_200_89.c"
"ui/images/my_emotion/emotion_dizzy_200_89.c"
"ui/images/my_emotion/emotion_happy_200_89.c"
"ui/images/my_emotion/emotion_sad_200_89.c"
"ui/images/my_emotion/emotion_sleep_200_89.c"
# GIF 动画图标资源压缩优化45x45叠加在表情上
"ui/images/my_icon/icon_emotion_confused_45.c"
"ui/images/my_icon/icon_emotion_sleep_45.c"
"ui/images/my_icon/icon_emotion_thinking_45.c"
)
set(INCLUDE_DIRS "." "display" "audio_codecs" "protocols" "audio_processing" "audio" "dzbj" "ui")
# 添加 IOT 相关文件
file(GLOB IOT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/iot/things/*.cc)
# 排除 screen.cc 文件,因为这个板子没有显示器
list(REMOVE_ITEM IOT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/iot/things/screen.cc)
list(APPEND SOURCES ${IOT_SOURCES})
# 添加板级公共文件
file(GLOB BOARD_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/common/*.cc)
# Exclude ml307_board.cc by default, only include it when ML307 board is selected
list(FILTER BOARD_COMMON_SOURCES EXCLUDE REGEX ".*ml307_board\.cc$")
list(APPEND SOURCES ${BOARD_COMMON_SOURCES})
list(APPEND INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/boards/common)
# Include ml307_board.cc only when ML307 board is selected
if(CONFIG_BOARD_TYPE_BREAD_COMPACT_ML307 OR CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_ML307 OR CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_ML307 OR CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_ML307)
list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/common/ml307_board.cc)
endif()
# 根据 BOARD_TYPE 配置添加对应的板级文件
if(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI)
set(BOARD_TYPE "bread-compact-wifi")
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ML307)
set(BOARD_TYPE "bread-compact-ml307")
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32)
set(BOARD_TYPE "bread-compact-esp32")
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32_LCD)
set(BOARD_TYPE "bread-compact-esp32-lcd")
elseif(CONFIG_BOARD_TYPE_DF_K10)
set(BOARD_TYPE "df-k10")
elseif(CONFIG_BOARD_TYPE_ESP_BOX_3)
set(BOARD_TYPE "esp-box-3")
elseif(CONFIG_BOARD_TYPE_ESP_BOX)
set(BOARD_TYPE "esp-box")
elseif(CONFIG_BOARD_TYPE_ESP_BOX_LITE)
set(BOARD_TYPE "esp-box-lite")
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_1)
set(BOARD_TYPE "kevin-box-1")
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_2)
set(BOARD_TYPE "kevin-box-2")
elseif(CONFIG_BOARD_TYPE_KEVIN_C3)
set(BOARD_TYPE "kevin-c3")
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V3_DEV)
set(BOARD_TYPE "kevin-sp-v3-dev")
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V4_DEV)
set(BOARD_TYPE "kevin-sp-v4-dev")
elseif(CONFIG_BOARD_TYPE_KEVIN_YUYING_313LCD)
set(BOARD_TYPE "kevin-yuying-313lcd")
elseif(CONFIG_BOARD_TYPE_LICHUANG_DEV)
set(BOARD_TYPE "lichuang-dev")
elseif(CONFIG_BOARD_TYPE_LICHUANG_C3_DEV)
set(BOARD_TYPE "lichuang-c3-dev")
elseif(CONFIG_BOARD_TYPE_MAGICLICK_2P4)
set(BOARD_TYPE "magiclick-2p4")
elseif(CONFIG_BOARD_TYPE_MAGICLICK_2P5)
set(BOARD_TYPE "magiclick-2p5")
elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3)
set(BOARD_TYPE "magiclick-c3")
elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3_V2)
set(BOARD_TYPE "magiclick-c3-v2")
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_S3)
set(BOARD_TYPE "m5stack-core-s3")
elseif(CONFIG_BOARD_TYPE_ATOMS3_ECHO_BASE)
set(BOARD_TYPE "atoms3-echo-base")
elseif(CONFIG_BOARD_TYPE_ATOMS3R_ECHO_BASE)
set(BOARD_TYPE "atoms3r-echo-base")
elseif(CONFIG_BOARD_TYPE_ATOMS3R_CAM_M12_ECHO_BASE)
set(BOARD_TYPE "atoms3r-cam-m12-echo-base")
elseif(CONFIG_BOARD_TYPE_ATOMMATRIX_ECHO_BASE)
set(BOARD_TYPE "atommatrix-echo-base")
elseif(CONFIG_BOARD_TYPE_XMINI_C3)
set(BOARD_TYPE "xmini-c3")
elseif(CONFIG_BOARD_TYPE_ESP32S3_KORVO2_V3)
set(BOARD_TYPE "esp32s3-korvo2-v3")
elseif(CONFIG_BOARD_TYPE_ESP_SPARKBOT)
set(BOARD_TYPE "esp-sparkbot")
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_1_8)
set(BOARD_TYPE "esp32-s3-touch-amoled-1.8")
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85C)
set(BOARD_TYPE "esp32-s3-touch-lcd-1.85c")
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85)
set(BOARD_TYPE "esp32-s3-touch-lcd-1.85")
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_46)
set(BOARD_TYPE "esp32-s3-touch-lcd-1.46")
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_3_5)
set(BOARD_TYPE "esp32-s3-touch-lcd-3.5")
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_LCD)
set(BOARD_TYPE "bread-compact-wifi-lcd")
elseif(CONFIG_BOARD_TYPE_TUDOUZI)
set(BOARD_TYPE "tudouzi")
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CIRCLE_S3)
set(BOARD_TYPE "lilygo-t-circle-s3")
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3)
set(BOARD_TYPE "lilygo-t-cameraplus-s3")
elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3)
set(BOARD_TYPE "movecall-moji-esp32s3")
elseif(CONFIG_BOARD_TYPE_MOVECALL_CUICAN_ESP32S3)
set(BOARD_TYPE "movecall-cuican-esp32s3")
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3)
set(BOARD_TYPE "atk-dnesp32s3")
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX)
set(BOARD_TYPE "atk-dnesp32s3-box")
elseif(CONFIG_BOARD_TYPE_DU_CHATX)
set(BOARD_TYPE "du-chatx")
elseif(CONFIG_BOARD_TYPE_ESP32S3_Taiji_Pi)
set(BOARD_TYPE "taiji-pi-s3")
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_WIFI)
set(BOARD_TYPE "xingzhi-cube-0.85tft-wifi")
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_ML307)
set(BOARD_TYPE "xingzhi-cube-0.85tft-ml307")
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_WIFI)
set(BOARD_TYPE "xingzhi-cube-0.96oled-wifi")
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_ML307)
set(BOARD_TYPE "xingzhi-cube-0.96oled-ml307")
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_WIFI)
set(BOARD_TYPE "xingzhi-cube-1.54tft-wifi")
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_ML307)
set(BOARD_TYPE "xingzhi-cube-1.54tft-ml307")
elseif(CONFIG_BOARD_TYPE_SENSECAP_WATCHER)
set(BOARD_TYPE "sensecap-watcher")
elseif(CONFIG_BOARD_TYPE_ESP32_CGC)
set(BOARD_TYPE "esp32-cgc")
endif()
file(GLOB BOARD_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc
${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.c
)
list(APPEND SOURCES ${BOARD_SOURCES})
# === 电子吧唧专属 srcs条件编译CONFIG_BAJI_BADGE_MODE=n 时不参与编译)===
# 源代码文件全部保留在仓库中,仅通过 Kconfig 开关控制是否进入编译队列
if(CONFIG_BAJI_BADGE_MODE)
list(APPEND SOURCES
# dzbj 吧唧专属模块
"dzbj/device_mode.c"
"dzbj/pages.c"
"dzbj/dzbj_ble.c"
"dzbj/sleep_mgr.c"
"dzbj/dzbj_button.c"
"dzbj/dzbj_battery.c"
"dzbj/ble_transfer.c"
# 吧唧模式 LVGL UIAI 对话屏幕 + 各种 PoC
"dzbj/ai_chat_ui.c"
"dzbj/sprite_demo.c"
"dzbj/dual_gif_demo.c"
"dzbj/bg_gif_demo.c"
# SquareLine Studio 吧唧专属 UI 屏幕9 个)
"ui/screens/ui_ScreenHome.c"
"ui/screens/ui_ScreenImg.c"
"ui/screens/ui_ScreenSet.c"
"ui/screens/ui_ScreenPeiwang.c"
"ui/screens/ui_ScreenUpdate.c"
"ui/screens/ui_ScreenImageShar.c"
"ui/screens/ui_ScreenImageReception.c"
"ui/screens/ui_ScreenSharing.c"
"ui/screens/ui_ScreenReceiving.c"
)
else()
# Phase 10: 数字人模式 EAF UI替代 LVGL 版 ai_chat_ui.c + bg_gif_demo.c
list(APPEND SOURCES
"dzbj/ai_chat_ui_eaf.c"
)
endif()
if(CONFIG_CONNECTION_TYPE_MQTT_UDP)
list(APPEND SOURCES "protocols/mqtt_protocol.cc")
endif()
if(CONFIG_CONNECTION_TYPE_WEBSOCKET)
list(APPEND SOURCES "protocols/websocket_protocol.cc")
endif()
if(CONFIG_CONNECTION_TYPE_VOLC_RTC)
list(APPEND SOURCES "protocols/volc_rtc_protocol.cc")
endif()
if(CONFIG_USE_AUDIO_PROCESSOR)
list(APPEND SOURCES "audio_processing/audio_processor.cc")
endif()
if(CONFIG_USE_WAKE_WORD_DETECT)
list(APPEND SOURCES "audio_processing/wake_word_detect.cc")
elseif(CONFIG_USE_CUSTOM_WAKE_WORD)
list(APPEND SOURCES "audio_processing/custom_wake_word.cc")
endif()
# 根据Kconfig选择语言目录
if(CONFIG_LANGUAGE_ZH_CN)
set(LANG_DIR "zh-CN")
elseif(CONFIG_LANGUAGE_ZH_TW)
set(LANG_DIR "zh-TW")
elseif(CONFIG_LANGUAGE_EN_US)
set(LANG_DIR "en-US")
elseif(CONFIG_LANGUAGE_JA_JP)
set(LANG_DIR "ja-JP")
endif()
# 定义生成路径
set(LANG_JSON "${CMAKE_CURRENT_SOURCE_DIR}/assets/${LANG_DIR}/language.json")
set(LANG_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/assets/lang_config.h")
file(GLOB LANG_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/${LANG_DIR}/*.p3)
file(GLOB COMMON_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/common/*.p3)
# 如果目标芯片是 ESP32则排除特定文件
if(CONFIG_IDF_TARGET_ESP32)
list(REMOVE_ITEM SOURCES "audio_codecs/box_audio_codec.cc"
"audio_codecs/es8388_audio_codec.cc"
"led/gpio_led.cc"
)
endif()
idf_component_register(SRCS ${SOURCES}
EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS}
INCLUDE_DIRS ${INCLUDE_DIRS}
# 路径 D'' AEC: esp-sr 提供 esp_aec.h 底层同步 API (aec_create/aec_process/aec_destroy)
# 配合软件 loopback ref (DAC PCM copy 到 ring buffer) 实现设备端 AEC
REQUIRES esp_wifi esp_netif esp_event nvs_flash bt spi_flash app_update efuse volc_engine_rtc_lite common zlib esp_lcd driver esp-sr
WHOLE_ARCHIVE
)
# 使用 target_compile_definitions 来定义 BOARD_TYPE, BOARD_NAME
# 如果 BOARD_NAME 为空,则使用 BOARD_TYPE
if(NOT BOARD_NAME)
set(BOARD_NAME ${BOARD_TYPE})
endif()
target_compile_definitions(${COMPONENT_LIB}
PRIVATE BOARD_TYPE=\"${BOARD_TYPE}\" BOARD_NAME=\"${BOARD_NAME}\"
)
# 添加生成规则
add_custom_command(
OUTPUT ${LANG_HEADER}
COMMAND python ${PROJECT_DIR}/scripts/gen_lang.py
--input "${LANG_JSON}"
--output "${LANG_HEADER}"
DEPENDS
${LANG_JSON}
${PROJECT_DIR}/scripts/gen_lang.py
COMMENT "Generating ${LANG_DIR} language config"
)
# 强制建立生成依赖
add_custom_target(lang_header ALL
DEPENDS ${LANG_HEADER}
)
# Add ENABLE_RTC_MODE definition if VOLC_RTC connection type is selected
if(CONFIG_CONNECTION_TYPE_VOLC_RTC)
target_compile_definitions(${COMPONENT_LIB} PRIVATE ENABLE_RTC_MODE)
# Link against zlib library directly
target_link_libraries(${COMPONENT_LIB} PRIVATE ${CMAKE_BINARY_DIR}/esp-idf/zlib/libzlib.a)
endif()