#ifndef MICROPHONE_H #define MICROPHONE_H #include #include #include // INMP441 麦克风模块类 - 所有功能集成在头文件中 class INMP441Microphone { private: // I2S 端口配置 static const i2s_port_t I2S_PORT = I2S_NUM_0; // GPIO 引脚定义 int sck_pin; // 串行时钟引脚 int ws_pin; // 字选择引脚 int sd_pin; // 串行数据引脚 // 采样配置 uint32_t sample_rate; uint16_t buffer_size; bool initialized; public: // 构造函数 INMP441Microphone(int sck = 14, int ws = 15, int sd = 32, uint32_t rate = 16000, uint16_t buf_size = 1024) { sck_pin = sck; ws_pin = ws; sd_pin = sd; sample_rate = rate; buffer_size = buf_size; initialized = false; } // 析构函数 ~INMP441Microphone() { if (initialized) { end(); } } // 初始化麦克风 bool begin() { if (initialized) { return true; } // I2S 配置 i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = sample_rate, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 4, .dma_buf_len = buffer_size, .use_apll = false, .tx_desc_auto_clear = false, .fixed_mclk = 0 }; // I2S 引脚配置 i2s_pin_config_t pin_config = { .bck_io_num = sck_pin, // 串行时钟 (SCK) .ws_io_num = ws_pin, // 字选择 (WS) .data_out_num = I2S_PIN_NO_CHANGE, // 不使用输出 .data_in_num = sd_pin // 串行数据输入 (SD) }; // 安装和启动 I2S 驱动 esp_err_t err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL); if (err != ESP_OK) { Serial.printf("Failed to install I2S driver: %s\n", esp_err_to_name(err)); return false; } err = i2s_set_pin(I2S_PORT, &pin_config); if (err != ESP_OK) { Serial.printf("Failed to set I2S pins: %s\n", esp_err_to_name(err)); i2s_driver_uninstall(I2S_PORT); return false; } // 清空 DMA 缓冲区 i2s_zero_dma_buffer(I2S_PORT); initialized = true; Serial.println("INMP441 microphone initialized successfully"); return true; } // 停止麦克风 void end() { if (initialized) { i2s_driver_uninstall(I2S_PORT); initialized = false; Serial.println("INMP441 microphone stopped"); } } // 读取音频数据 (返回16位PCM数据) size_t readAudioData(int16_t* buffer, size_t buffer_len) { if (!initialized || buffer == nullptr || buffer_len == 0) { return 0; } // 创建临时缓冲区用于存储32位原始数据 int32_t* raw_buffer = (int32_t*)malloc(buffer_len * sizeof(int32_t)); if (raw_buffer == nullptr) { return 0; } size_t bytes_read = 0; esp_err_t err = i2s_read(I2S_PORT, raw_buffer, buffer_len * sizeof(int32_t), &bytes_read, portMAX_DELAY); if (err != ESP_OK) { free(raw_buffer); return 0; } // 转换32位数据到16位PCM size_t samples_read = bytes_read / sizeof(int32_t); for (size_t i = 0; i < samples_read && i < buffer_len; i++) { // INMP441 输出24位数据在32位容器的高24位 // 右移8位得到24位数据,再右移8位得到16位数据 buffer[i] = (int16_t)(raw_buffer[i] >> 16); } free(raw_buffer); return samples_read; } // 读取音频数据 (返回32位原始I2S数据) size_t readRawData(int32_t* buffer, size_t buffer_len) { if (!initialized || buffer == nullptr || buffer_len == 0) { return 0; } size_t bytes_read = 0; esp_err_t err = i2s_read(I2S_PORT, buffer, buffer_len * sizeof(int32_t), &bytes_read, portMAX_DELAY); if (err != ESP_OK) { return 0; } return bytes_read / sizeof(int32_t); } // 获取采样率 uint32_t getSampleRate() const { return sample_rate; } // 获取缓冲区大小 uint16_t getBufferSize() const { return buffer_size; } // 检查是否已初始化 bool isInitialized() const { return initialized; } // 设置采样率 (需要重新初始化) void setSampleRate(uint32_t rate) { bool was_initialized = initialized; if (was_initialized) { end(); } sample_rate = rate; if (was_initialized) { begin(); } } // 获取音频电平 (RMS值) float getAudioLevel(int16_t* buffer, size_t buffer_len) { if (buffer == nullptr || buffer_len == 0) { return 0.0f; } float sum = 0.0f; for (size_t i = 0; i < buffer_len; i++) { float sample = (float)buffer[i]; sum += sample * sample; } return sqrt(sum / buffer_len); } // 检测音频活动 (简单的音量阈值检测) bool detectAudioActivity(int16_t* buffer, size_t buffer_len, int16_t threshold = 1000) { if (buffer == nullptr || buffer_len == 0) { return false; } // 计算RMS值 float rms = getAudioLevel(buffer, buffer_len); // 检查是否超过阈值 return rms > threshold; } // 打印音频统计信息 void printAudioStats(int16_t* buffer, size_t buffer_len, unsigned long timestamp) { if (buffer == nullptr || buffer_len == 0) { return; } // 计算音频统计信息 float audioLevel = getAudioLevel(buffer, buffer_len); bool hasActivity = detectAudioActivity(buffer, buffer_len, 1000); // 找到最大值和最小值 int16_t maxVal = buffer[0]; int16_t minVal = buffer[0]; for (size_t i = 1; i < buffer_len; i++) { if (buffer[i] > maxVal) maxVal = buffer[i]; if (buffer[i] < minVal) minVal = buffer[i]; } // 打印统计信息 Serial.printf("[%6lu] RMS: %8.1f | 活动: %s | 最大: %6d | 最小: %6d | 样本: %d\n", timestamp / 1000, audioLevel, hasActivity ? "是" : "否", maxVal, minVal, buffer_len); } // 打印引脚连接信息 void printPinInfo() { Serial.println("INMP441 引脚连接:"); Serial.printf(" SCK -> GPIO%d\n", sck_pin); Serial.printf(" WS -> GPIO%d\n", ws_pin); Serial.printf(" SD -> GPIO%d\n", sd_pin); Serial.println(" VDD -> 3.3V"); Serial.println(" GND -> GND"); } }; #endif // MICROPHONE_H