模型上线
This commit is contained in:
355
audio_model_esp32.h
Normal file
355
audio_model_esp32.h
Normal file
@@ -0,0 +1,355 @@
|
||||
#ifndef AUDIO_MODEL_ESP32_H
|
||||
#define AUDIO_MODEL_ESP32_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#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
|
||||
Reference in New Issue
Block a user