当前位置: 首页 > news >正文

音频识别优化(FFT)

整合多频段检测、动态阈值调整和持续时长验证的完整代码实现,包含详细注释:

#include "esp_dsp.h"
#include "driver/i2s.h"
#include "esp_log.h"
#include "math.h"

static const char* TAG = "ADV_FREQ_DETECT";

/*======= 系统配置 =======*/
#define FFT_SIZE        1024          // FFT点数
#define SAMPLE_RATE     16000         // 采样率
#define NOISE_BINS      50            // 噪声基底计算区间
#define MIN_DURATION    5             // 最小持续帧数(50ms/帧)
#define THRESHOLD_OFFSET 20.0         // 阈值相对噪声基底的偏移量

/*======= 多频段配置 =======*/
typedef struct {
    int target_freq;    // 目标频率(Hz)
    float threshold_db; // 检测阈值(dB)
    int sustain_count;  // 持续计数
    bool triggered;     // 触发状态
} freq_band_t;

// 配置需要检测的三个频段
freq_band_t freq_bands[] = {
    {1000, 0, 0, false},  // 初始阈值设为0,实际运行时动态计算
    {2000, 0, 0, false},
    {3000, 0, 0, false}
};
const int BAND_COUNT = sizeof(freq_bands)/sizeof(freq_band_t);

/*======= 硬件配置 =======*/
__attribute__((aligned(16)))
float fft_input[FFT_SIZE*2];       // FFT输入缓冲
__attribute__((aligned(16)))
float fft_mag[FFT_SIZE/2];         // 幅度谱
__attribute__((aligned(16)))
float window[FFT_SIZE];            // 汉宁窗系数

// I2S配置(根据硬件调整)
#define I2S_CHANNEL     I2S_NUM_0
#define I2S_BUF_SIZE    1024
#define I2S_BCK_PIN     32
#define I2S_WS_PIN      25
#define I2S_DATA_PIN    33

/*======= 核心算法函数 =======*/

// 计算噪声基底(使用前NOISE_BINS个bin)
float calculate_noise_floor(float *spectrum) {
    float sum = 0;
    for(int i=1; i<=NOISE_BINS; i++) { // 从1开始避免DC分量
        sum += spectrum[i];
    }
    return 20 * log10f(sum / NOISE_BINS); // 转换为dB
}

// 检测指定频段是否激活
void check_frequency_band(freq_band_t *band, float *spectrum, float noise_floor) {
    const float freq_res = (float)SAMPLE_RATE / FFT_SIZE;
    const int target_bin = band->target_freq / freq_res;
    const int bin_range = (FREQ_TOLERANCE / freq_res) + 1;

    // 搜索目标区间峰值
    float peak_mag = 0;
    int start_bin = target_bin - bin_range;
    int end_bin = target_bin + bin_range;
    start_bin = start_bin < 1 ? 1 : start_bin; // 跳过DC
    end_bin = end_bin >= FFT_SIZE/2 ? FFT_SIZE/2-1 : end_bin;

    for(int i=start_bin; i<=end_bin; i++) {
        if(spectrum[i] > peak_mag) {
            peak_mag = spectrum[i];
        }
    }

    // 计算实际dB值
    float peak_db = 20 * log10f(peak_mag);
    bool current_detect = (peak_db > (noise_floor + THRESHOLD_OFFSET));

    // 持续时间验证
    if(current_detect) {
        if(++band->sustain_count >= MIN_DURATION) {
            if(!band->triggered) {
                band->triggered = true;
                ESP_LOGI(TAG, "频段%dHz触发! 强度:%.1fdB", 
                        band->target_freq, peak_db);
            }
        }
    } else {
        band->sustain_count = 0;
        if(band->triggered) {
            band->triggered = false;
            ESP_LOGI(TAG, "频段%dHz释放", band->target_freq);
        }
    }
}

/*======= 信号处理流水线 =======*/
void audio_processing_task(void *arg) {
    int16_t raw_data[FFT_SIZE]; // 原始采样缓冲

    while(1) {
        // 1. 采集音频数据
        size_t bytes_read = 0;
        i2s_read(I2S_CHANNEL, raw_data, sizeof(raw_data), &bytes_read, portMAX_DELAY);

        // 2. 预处理:加窗转换
        for(int i=0; i<FFT_SIZE; i++) {
            fft_input[i*2] = (float)raw_data[i] * window[i]; // 实部
            fft_input[i*2+1] = 0;                            // 虚部
        }

        // 3. 执行FFT
        dsps_fft2r_fc32(fft_input, FFT_SIZE);
        dsps_bit_rev_fc32(fft_input, FFT_SIZE);
        dsps_cplx2real_fc32(fft_input, FFT_SIZE);

        // 4. 计算幅度谱
        for(int i=0; i<FFT_SIZE/2; i++) {
            float real = fft_input[i*2];
            float imag = fft_input[i*2+1];
            fft_mag[i] = sqrtf(real*real + imag*imag);
        }

        // 5. 动态阈值计算
        float noise_floor = calculate_noise_floor(fft_mag);

        // 6. 多频段检测
        for(int i=0; i<BAND_COUNT; i++) {
            check_frequency_band(&freq_bands[i], fft_mag, noise_floor);
        }

        vTaskDelay(pdMS_TO_TICKS(10)); // 10ms周期
    }
}

/*======= 初始化函数 =======*/
void init_system() {
    // 初始化I2S
    i2s_config_t i2s_cfg = {
        .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM,
        .sample_rate = SAMPLE_RATE,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .dma_buf_count = 4,
        .dma_buf_len = I2S_BUF_SIZE,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
    };
    i2s_pin_config_t pin_cfg = {
        .bck_io_num = I2S_BCK_PIN,
        .ws_io_num = I2S_WS_PIN,
        .data_in_num = I2S_DATA_PIN,
        .data_out_num = -1
    };
    i2s_driver_install(I2S_CHANNEL, &i2s_cfg, 0, NULL);
    i2s_set_pin(I2S_CHANNEL, &pin_cfg);

    // 初始化FFT
    dsps_fft2r_init_fc32(NULL, FFT_SIZE);
    dsps_wind_hann_f32(window, FFT_SIZE); // 生成窗函数

    ESP_LOGI(TAG, "系统初始化完成,开始运行...");
}

void app_main() {
    init_system();
    xTaskCreate(audio_processing_task, "audio_proc", 4096, NULL, 5, NULL);
}

关键增强功能说明

  1. 多频段独立检测

    • 使用freq_band_t结构体管理每个频段的参数

    • 并行检测多个频段,各频段独立维护触发状态

    • 示例配置检测1000Hz、2000Hz、3000Hz三个频段

  2. 自适应噪声基底

    // 噪声基底计算(排除直流分量)
    |[1-50] bins| --> 平均值 --> dB转换 --> 噪声基底
    // 动态阈值 = 噪声基底 + 固定偏移(20dB)
  3. 持续时长验证机制

    graph LR
    A[当前检测到信号] --> B{持续计数 >=5?}
    B -->|是| C[标记触发]
    B -->|否| D[计数+1]
    E[未检测到信号] --> F[复位计数器]
  4. 状态管理优化

    • 触发时记录时间戳,避免重复报警

    • 释放时明确状态变更

    • 提供完整的触发-保持-释放状态周期

相关文章:

  • 认识Vue
  • Java锁的分类与解析
  • QT6 源(34):随机数生成器类 QRandomGenerator 的源码阅读
  • 科学护理进行性核上性麻痹,缓解病痛提升生活质量
  • 用cython将python程序打包成C++动态库(windows+Vistual Studio2017平台)
  • Lombok @Builder 注解的进阶玩法:自定义 Getter/Setter 方法全攻略
  • 在没有第三方库的情况下使用 Python 自带函数解码
  • 3.串口通信之SPI
  • Java学习手册:Java内存模型
  • 22、字节与字符的概念以及二者有什么区别?
  • 【Python爬虫基础篇】--1.基础概念
  • MCP Server和Client的基本使用方法
  • halcon模板匹配(八)alignment_for_ocr_in_semiconductor
  • OCR:开启文档抽取的智能变革之门
  • 4.16 AT好题选做
  • 探索关系型数据库 MySQL
  • LFI to RCE
  • DiffuRec: A Diffusion Model for Sequential Recommendation
  • 将二进制的stl文件转换为ascii的形式
  • stm32F103、GD32F103读写Nor Flash实战指南
  • 四川省社科联期刊:不建议在读硕士、博士将导师挂名为第一作者
  • 日月谭天丨赖清德强推“脱中入北”是把台湾带向死路
  • 我国核电总体规模首次跃居世界第一,发电量持续增长
  • 快捷公寓单间不足5平方米?公寓方:预订平台图片只是参考,已退房款
  • 特朗普政府称将恢复被终止的外国学生合法身份
  • 政治局会议:积极维护多边主义,反对单边霸凌行径