Files
Misaki ba5e47bc77 这是一次长久的提交:
1. 应用界面增加了返回主页的按钮
2. 修复了gif渲染内存泄漏的严重bug
3. 将PetDao当中的cJSON API替换为cpp_json,完美通过测试
4. 整合已经实现的各种上层建筑,实现了一个宠物对话基本业务应用,用于样品测试展示用
5. 重构了音频播放类,使其更modern,更加便于移植和拓展
2025-10-16 11:36:45 +08:00

175 lines
4.6 KiB
C++

//
// Created by misaki on 2025/9/15.
//
#pragma once
#include <functional>
#include <vector>
#include <string>
#include <mutex>
#include <atomic>
#include "esp_afe_sr_iface.h"
#include "model_path.h"
#include "esp_mn_iface.h"
#include "driver/i2s_std.h"
#include "esp_log.h"
#include "ThreadManager.h"
// 前向声明
struct model_iface_data_t;
// 语音命令回调函数类型
using SpeechCommandCallback = std::function<void(int command_id, const std::string& phrase, float probability)>;
// 识别状态回调函数类型
using SpeechStateCallback = std::function<void(const std::string& state)>;
// 识别结果结构体
struct SpeechRecognitionResult {
int command_id;
std::string phrase;
float probability;
int phrase_id;
};
// 配置结构体
struct SpeechRecognizerConfig {
// I2S配置
gpio_num_t bclk_pin = GPIO_NUM_15;
gpio_num_t ws_pin = GPIO_NUM_2;
gpio_num_t din_pin = GPIO_NUM_39;
// 音频处理配置
bool enable_aec = false; // 回声消除
bool enable_se = false; // 降噪
bool enable_vad = false; // 语音活动检测
vad_mode_t vad_mode = VAD_MODE_0; // VAD灵敏度
// 模型路径
std::string model_path = "/sdcard/srmodels";
// 线程配置
ThreadConfig feed_thread_config = {"SR_Feed", 1, 4096, 3, false};
ThreadConfig detect_thread_config = {"SR_Detect", 0, 6 * 1024, 5, false};
// 识别超时时间(ms)
int detection_timeout = 6000;
};
class SpeechRecognizer {
public:
// 获取单例实例
static SpeechRecognizer* getInstance();
// 删除拷贝构造函数和赋值运算符
SpeechRecognizer(const SpeechRecognizer&) = delete;
SpeechRecognizer& operator=(const SpeechRecognizer&) = delete;
// 初始化语音识别系统
bool init(const SpeechRecognizerConfig& config = SpeechRecognizerConfig());
// 重载版本
bool init(const bool enable_vad, const vad_mode_t vad_mode, std::string model_path);
// 反初始化
void deinit();
// 添加自定义语音命令
bool addCommand(int command_id, const std::string& phrase);
// 批量添加语音命令
bool addCommands(const std::vector<std::pair<int, std::string>>& commands);
// 清除所有语音命令
void clearCommands();
// 开始语音识别
bool start();
// 停止语音识别
void stop();
// 是否正在运行
bool isRunning() const;
// 注册命令回调函数
void registerCommandCallback(SpeechCommandCallback callback);
// 注册状态回调函数
void registerStateCallback(SpeechStateCallback callback);
// 获取最后一次识别结果
SpeechRecognitionResult getLastResult() const;
// 获取识别历史
std::vector<SpeechRecognitionResult> getHistory() const;
// 设置VAD灵敏度
// void setVadSensitivity(vad_mode_t mode);
// 启用/禁用语音识别
void setEnabled(bool enabled);
// 获取当前识别状态
std::string getCurrentState() const;
// 获取当前 VAD 识别状态(噪音、静音 or 人声) 需要开启 VAD
afe_vad_state_t getVadState() const;
private:
SpeechRecognizer();
~SpeechRecognizer();
// I2S初始化
bool initI2S();
// ESP-SR初始化
bool initESP_SR();
// 喂数据任务(音频采集)
void feedTask();
// 检测任务(语音识别)
void detectTask();
// 处理识别结果
void handleRecognitionResult(const SpeechRecognitionResult& result);
// 更新识别状态
void updateState(const std::string& state);
// 静态成员函数用于C接口兼容
static void feedTaskWrapper(void* arg);
static void detectTaskWrapper(void* arg);
private:
static SpeechRecognizer* instance;
static std::mutex instanceMutex;
SpeechRecognizerConfig config;
bool initialized;
bool running;
bool enabled;
// I2S相关
i2s_chan_handle_t rx_handle;
// ESP-SR相关
const esp_afe_sr_iface_t* afe_handle;
esp_afe_sr_data_t* afe_data;
srmodel_list_t* models;
esp_mn_iface_t* multinet;
model_iface_data_t* model_data; /// 模型数据
afe_vad_state_t vad_state_; /// 语音活动检测状态
// 命令回调
SpeechCommandCallback commandCallback;
SpeechStateCallback stateCallback;
// 识别结果
SpeechRecognitionResult lastResult;
std::vector<SpeechRecognitionResult> history;
mutable std::mutex historyMutex;
// 任务句柄
std::thread feedThread;
std::thread detectThread;
std::atomic<bool> tasksRunning;
// 当前状态
std::string currentState;
mutable std::mutex stateMutex;
};