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

esp32开发与应用(边采样边播放音频)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

前面说到了音频的播放,一般采用i2s的格式,也就是bclk、lrclk、sda。今天来学一下麦克风。如果是播放音乐,没有麦克风也是可以的。但很多时候,我们还是有麦克风采样、录制的需求。所以这个时候,就要学一下麦克风采样。

1、麦克风接口

一般mic有两种接口,一种是pdm接口,也就是只有clk和data。还有一种就是i2s接口,这种就和之前的音乐播放一样的接口,即3个pin,lrclk、bclk和sda。

2、管脚分配

如果是mic,一般走4和5;如果是i2s,一般走26、25、22。

3、电压分配

3.3v即可。

4、芯片选型

这次采用的麦克风mic采样芯片,和前面一篇文章其实是一块板子,使用的芯片是lm2718。

5、示例代码

考虑到之前学习过音频播放,这里采用的方式是一边采样、一边播放的方式。这样既可以巩固原来的知识点,又可以学习到新的mic采样知识。整个就是一个扩音器的效果。

#include <stdint.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "driver/i2s_std.h" #include "driver/i2s_pdm.h" static const char *TAG = "MIC_LOOPBACK"; #define SAMPLE_RATE 16000 // ---- Mic (PDM RX) pins ---- #define PDM_CLK_GPIO GPIO_NUM_4 #define PDM_DATA_GPIO GPIO_NUM_5 // ---- Speaker (I2S STD TX, NS4168) pins ---- #define I2S_BCLK GPIO_NUM_26 #define I2S_WS GPIO_NUM_25 #define I2S_DOUT GPIO_NUM_22 #define READ_CHUNK_SAMPLES 512 // ~32ms per chunk @16kHz, controls latency static i2s_chan_handle_t rx_chan = NULL; // mic static i2s_chan_handle_t tx_chan = NULL; // speaker // ---------- Mic: PDM RX on I2S_NUM_0 ---------- static void mic_init(void) { i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &rx_chan)); i2s_pdm_rx_config_t pdm_rx_cfg = { .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(SAMPLE_RATE), .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), .gpio_cfg = { .clk = PDM_CLK_GPIO, .din = PDM_DATA_GPIO, .invert_flags = { .clk_inv = false }, }, }; pdm_rx_cfg.slot_cfg.slot_mask = I2S_PDM_SLOT_LEFT; // try _RIGHT if silent/noisy ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_rx_cfg)); ESP_ERROR_CHECK(i2s_channel_enable(rx_chan)); ESP_LOGI(TAG, "Mic (PDM RX) ready on I2S_NUM_0, CLK=%d DATA=%d", PDM_CLK_GPIO, PDM_DATA_GPIO); } // ---------- Speaker: standard I2S TX on I2S_NUM_1 (same as your NS4168 code) ---------- static void speaker_init(void) { i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_1, I2S_ROLE_MASTER); ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, NULL)); i2s_std_config_t std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE), .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), .gpio_cfg = { .mclk = I2S_GPIO_UNUSED, .bclk = I2S_BCLK, .ws = I2S_WS, .dout = I2S_DOUT, .din = I2S_GPIO_UNUSED, }, }; ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &std_cfg)); ESP_ERROR_CHECK(i2s_channel_enable(tx_chan)); ESP_LOGI(TAG, "Speaker (I2S STD TX) ready on I2S_NUM_1, BCLK=%d WS=%d DOUT=%d", I2S_BCLK, I2S_WS, I2S_DOUT); } // ---------- Loop: read from mic, write straight to speaker ---------- static void loopback_task(void *arg) { int16_t *buf = malloc(READ_CHUNK_SAMPLES * sizeof(int16_t)); if (!buf) { ESP_LOGE(TAG, "malloc failed"); vTaskDelete(NULL); return; } // Optional software gain: raw PDM mic level is often quiet. // Adjust or set to 1.0f if it clips/distorts. const float GAIN = 4.0f; while (1) { size_t bytes_read = 0; esp_err_t ret = i2s_channel_read(rx_chan, buf, READ_CHUNK_SAMPLES * sizeof(int16_t), &bytes_read, portMAX_DELAY); if (ret != ESP_OK || bytes_read == 0) { continue; } int samples = bytes_read / sizeof(int16_t); for (int i = 0; i < samples; i++) { int32_t v = (int32_t)(buf[i] * GAIN); if (v > INT16_MAX) v = INT16_MAX; if (v < INT16_MIN) v = INT16_MIN; buf[i] = (int16_t)v; } size_t bytes_written = 0; ESP_ERROR_CHECK( i2s_channel_write(tx_chan, buf, bytes_read, &bytes_written, portMAX_DELAY) ); } free(buf); vTaskDelete(NULL); } void app_main(void) { ESP_LOGI(TAG, "Mic -> Speaker realtime loopback starting"); mic_init(); speaker_init(); xTaskCreate(loopback_task, "loopback_task", 4096, NULL, 5, NULL); }

6、测试和验证

测试的话,就是等程序烧入之后,看看对着mic说话的时候,听听喇叭里面有没有声音就好。

http://www.jsqmd.com/news/1257961/

相关文章:

  • TAS3251音频DSP寄存器配置实战:CRC/XOR校验与时钟树详解
  • STM32定时器输入捕获实现精确频率测量的原理与实战
  • java: Backtracking Algorithm
  • 2026 年新消息:湛江值得关注的清理化粪池服务商深度剖析,别再等!化粪池堵塞的致命信号你必须知道 - 企业官方推荐【认证】
  • 张高兴的 Hailo-10 开发指南:(二)使用 LangChain 搭建本地大模型 RAG 问答应用
  • CloudWatch 日志保留策略自动化:全账号 200+ 日志组统一 7 天,月省 $3000
  • 技术简历制作全攻略:Word/LaTeX/Markdown模板与ATS优化技巧
  • 北京办理中国到肯尼亚签证正规代办旅行社服务指南 - 品牌优推
  • 2026 年 7 月新发布:绥德专业的岩棉板供货厂家怎么联系,冬天保暖的秘密:别再用传统材料了-龙飒岩棉保温棉 - 品质体验官
  • 本地数字人工具部署指南:从环境配置到批量处理实战
  • 充血模型 :DDD中的领域对象里可以放什么方法?
  • 私有化部署智能问答:OpenClaw与Ollama金融级实践
  • MySQL 8.0 安装配置全攻略:从下载到连接验证,避开新手常见坑
  • 基于LangChain与ReAct机制构建AI智能体:从原理到实战
  • 2026龙虾国产化定制替代方案有哪些?企业级OpenClaw私有化定制部署方案
  • HTTPS协议深度解析:从TLS握手到安全迁移实战指南
  • C语言逆向解析Wallpaper Engine资源包:从PKG文件格式到RePKG工具实现
  • 2026年中国到尼日利亚的签证代办旅行社口碑挑选指南 - 品牌优推
  • 2026 年现阶段乌鲁木齐诚信的防护网生产商有哪些,穿透性极强!这道屏障如何帮你省下万元?-玖龙盛邦护栏网 - 行业推荐官【官方】
  • AI工具如何提升学术写作效率:从选题到答辩的全流程优化
  • 2026 年更新:大连靠谱的下水道疏通服务团队电话,堵塞的瞬间,如何秒杀水管黑洞? - 企业推荐官【认证】
  • 工业电流采样实战:AMC1304隔离式Δ-Σ调制器原理、选型与PCB布局指南
  • 2026年汽车托运物流实力公司推荐几家 合规服务商选型参考 - 品牌优推
  • 阿里开源前端AI代理Page Agent:零后端依赖,用自然语言控制网页
  • Rust开发轻量级Markdown阅读器:多标签管理与源码编辑实践
  • Flutter动画插值全解析:从Tween到Curve的十五个常用缓动参数详解
  • 企业AI转型实战:从技术落地到业务融合
  • 提示词改写失效?92%的从业者踩中的4个隐形陷阱,及权威验证的3层语义重构模型
  • PLC与气动元件控制:从电磁阀驱动到多气缸协调编程实战
  • 动图魔方 HarmonyOS 设计(22):PixelMap 生命周期与内存释放