#ifndef AUDIO_MODEL_ESP32_H #define AUDIO_MODEL_ESP32_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include "audio_model_data.h" // ==================== 模型配置参数 ==================== #define SAMPLE_RATE 16000 // 音频采样率 (Hz) #define AUDIO_DURATION_MS 2000 // 音频片段时长 (毫秒) #define N_MELS 32 // Mel频谱图频率bins数量 #define N_FFT 1024 // FFT窗口大小 #define HOP_LENGTH 512 // 跳跃长度 #define NUM_CLASSES 4 // 分类数量 // 计算得出的参数 #define AUDIO_BUFFER_SIZE (SAMPLE_RATE * AUDIO_DURATION_MS / 1000) // 32000 samples #define MEL_FRAMES ((AUDIO_BUFFER_SIZE - N_FFT) / HOP_LENGTH + 1) // 约63帧 #define INPUT_SIZE (MEL_FRAMES * N_MELS) // 输入特征大小 // 预处理参数 #define MEL_FMIN 0.0f // Mel滤波器最低频率 #define MEL_FMAX 8000.0f // Mel滤波器最高频率 #define WINDOW_TYPE_HANN 1 // 汉宁窗 #define ENERGY_THRESHOLD 0.01f // 音频活动检测阈值 #define CONFIDENCE_THRESHOLD 0.6f // 预测置信度阈值 // ==================== 数据结构定义 ==================== // 音频分类枚举 typedef enum { AUDIO_CLASS_PERSON_PRESENT = 0, // 室内有人 AUDIO_CLASS_DOOR_CLOSING = 1, // 关门 AUDIO_CLASS_KEY_JINGLING = 2, // 钥匙弹子声 AUDIO_CLASS_PERSON_ABSENT = 3 // 室内无人 } AudioClassType; // 预测结果结构体 typedef struct { AudioClassType predicted_class; // 预测的类别 float confidence; // 最高置信度 (0.0 - 1.0) float class_probabilities[NUM_CLASSES]; // 各类别概率 bool is_valid; // 预测结果是否有效 uint32_t inference_time_us; // 推理耗时(微秒) } AudioPredictionResult; // 音频预处理状态 typedef struct { float* mel_buffer; // Mel特征缓冲区 float* fft_buffer; // FFT计算缓冲区 float* window_buffer; // 窗函数缓冲区 bool is_initialized; // 是否已初始化 } AudioPreprocessor; // ==================== 核心API函数 ==================== /** * @brief 初始化音频模型 * @return 0: 成功, -1: 失败 * @note 必须在使用其他函数前调用 */ int audio_model_init(void); /** * @brief 清理音频模型资源 * @note 程序结束时调用,释放内存 */ void audio_model_cleanup(void); /** * @brief 音频预测函数(完整版) * @param audio_data 输入音频数据指针 * @param audio_length 音频数据长度(样本数) * @param result 预测结果输出指针 * @return 0: 成功, -1: 失败 * * 音频数据格式要求: * - 数据类型: int16_t (16位有符号整数) * - 采样率: 16000 Hz * - 声道数: 单声道 * - 数据长度: 32000 samples (2秒) * - 数值范围: -32768 到 32767 * - 字节序: 小端序(Little Endian) * * 示例调用: * int16_t audio_buffer[AUDIO_BUFFER_SIZE]; * AudioPredictionResult result; * // ... 填充audio_buffer ... * int ret = audio_model_predict(audio_buffer, AUDIO_BUFFER_SIZE, &result); */ int audio_model_predict(const int16_t* audio_data, int audio_length, AudioPredictionResult* result); /** * @brief 音频预测函数(简化版) * @param audio_data 输入音频数据指针 * @param audio_length 音频数据长度 * @param predicted_class 预测类别输出 * @param confidence 置信度输出 * @return 0: 成功, -1: 失败 */ int audio_model_predict_simple(const int16_t* audio_data, int audio_length, AudioClassType* predicted_class, float* confidence); // ==================== 数据预处理函数 ==================== /** * @brief 音频数据预处理(完整流程) * @param audio_data 原始音频数据 (int16_t格式) * @param audio_length 音频长度 * @param mel_features 输出的Mel特征 (大小为INPUT_SIZE) * @return 0: 成功, -1: 失败 * * 预处理步骤: * 1. 数据类型转换 (int16_t -> float) * 2. 归一化处理 ([-1.0, 1.0]) * 3. 预加重滤波 * 4. 加窗处理 (汉宁窗) * 5. FFT变换 * 6. 功率谱计算 * 7. Mel滤波器组 * 8. 对数变换 * 9. 特征归一化 */ int preprocess_audio_to_mel(const int16_t* audio_data, int audio_length, float* mel_features); /** * @brief 音频数据归一化 * @param audio_data 输入音频数据 * @param length 数据长度 * @param normalized_data 归一化后的数据输出 * @return 0: 成功, -1: 失败 */ int normalize_audio_data(const int16_t* audio_data, int length, float* normalized_data); /** * @brief 计算Mel频谱图 * @param audio_float 浮点音频数据 * @param length 数据长度 * @param mel_spectrogram 输出的Mel频谱图 * @return 0: 成功, -1: 失败 */ int compute_mel_spectrogram(const float* audio_float, int length, float* mel_spectrogram); /** * @brief 应用汉宁窗 * @param data 输入数据 * @param length 数据长度 * @param windowed_data 加窗后的数据 * @return 0: 成功, -1: 失败 */ int apply_hann_window(const float* data, int length, float* windowed_data); // ==================== 辅助函数 ==================== /** * @brief 检测音频活动 * @param audio_data 音频数据 * @param length 数据长度 * @param threshold 能量阈值 * @return true: 检测到音频活动, false: 静音 */ bool detect_audio_activity(const int16_t* audio_data, int length, float threshold); /** * @brief 计算音频RMS能量 * @param audio_data 音频数据 * @param length 数据长度 * @return RMS能量值 */ float calculate_rms_energy(const int16_t* audio_data, int length); /** * @brief 获取类别名称(英文) * @param class_id 类别ID * @return 类别名称字符串 */ const char* get_class_name_en(AudioClassType class_id); /** * @brief 获取类别名称(中文) * @param class_id 类别ID * @return 类别名称字符串 */ const char* get_class_name_cn(AudioClassType class_id); /** * @brief 验证音频数据格式 * @param audio_data 音频数据指针 * @param length 数据长度 * @return true: 格式正确, false: 格式错误 */ bool validate_audio_format(const int16_t* audio_data, int length); /** * @brief 打印预测结果 * @param result 预测结果指针 */ void print_prediction_result(const AudioPredictionResult* result); // ==================== 性能监控函数 ==================== /** * @brief 获取上次推理耗时 * @return 推理时间(微秒) */ uint32_t get_last_inference_time_us(void); /** * @brief 获取模型内存使用情况 * @param model_memory 模型占用内存(字节) * @param buffer_memory 缓冲区占用内存(字节) * @return 0: 成功, -1: 失败 */ int get_memory_usage(size_t* model_memory, size_t* buffer_memory); /** * @brief 获取预测统计信息 * @param total_predictions 总预测次数 * @param successful_predictions 成功预测次数 * @param average_confidence 平均置信度 * @return 0: 成功, -1: 失败 */ int get_prediction_statistics(uint32_t* total_predictions, uint32_t* successful_predictions, float* average_confidence); // ==================== 配置函数 ==================== /** * @brief 设置置信度阈值 * @param threshold 新的阈值 (0.0 - 1.0) * @return 0: 成功, -1: 失败 */ int set_confidence_threshold(float threshold); /** * @brief 获取当前置信度阈值 * @return 当前阈值 */ float get_confidence_threshold(void); /** * @brief 启用/禁用调试模式 * @param enable true: 启用, false: 禁用 */ void set_debug_mode(bool enable); /** * @brief 检查调试模式状态 * @return true: 已启用, false: 已禁用 */ bool is_debug_mode_enabled(void); // ==================== 错误处理 ==================== /** * @brief 获取最后一次错误信息 * @return 错误信息字符串 */ const char* get_last_error_message(void); /** * @brief 清除错误状态 */ void clear_error_status(void); // ==================== 常量定义 ==================== // 类别名称数组(英文) static const char* CLASS_NAMES_EN[NUM_CLASSES] = { "person_present", // 室内有人 "door_closing", // 关门 "key_jingling", // 钥匙弹子声 "person_absent" // 室内无人 }; // 类别名称数组(中文) static const char* CLASS_NAMES_CN[NUM_CLASSES] = { "室内有人", "关门声", "钥匙声", "室内无人" }; // ==================== 模型数据访问函数 ==================== /** * @brief 获取模型数据指针 * @return 模型数据指针 */ const unsigned char* get_audio_model_data(void); /** * @brief 获取模型数据大小 * @return 模型数据大小(字节) */ size_t get_audio_model_size(void); // ==================== 使用示例 ==================== /* 使用示例代码: #include "audio_model_esp32.h" void example_usage() { // 1. 初始化模型 if (audio_model_init() != 0) { printf("模型初始化失败\n"); return; } // 2. 准备音频数据 int16_t audio_buffer[AUDIO_BUFFER_SIZE]; // ... 从麦克风或其他源获取音频数据 ... // 3. 验证音频格式 if (!validate_audio_format(audio_buffer, AUDIO_BUFFER_SIZE)) { printf("音频格式不正确\n"); return; } // 4. 进行预测 AudioPredictionResult result; if (audio_model_predict(audio_buffer, AUDIO_BUFFER_SIZE, &result) == 0) { // 5. 处理预测结果 if (result.is_valid && result.confidence > 0.6f) { printf("预测类别: %s (置信度: %.2f)\n", get_class_name_cn(result.predicted_class), result.confidence); } } // 6. 清理资源 audio_model_cleanup(); } 音频数据获取示例(ESP32 I2S): ```c #include "driver/i2s.h" void get_audio_data(int16_t* buffer, size_t buffer_size) { size_t bytes_read; i2s_read(I2S_NUM_0, buffer, buffer_size * sizeof(int16_t), &bytes_read, portMAX_DELAY); } ``` */ #ifdef __cplusplus } #endif // AUDIO_MODEL_ESP32_H