AI脑洞板
完整教案
自学课件
第 12 课 · 共 12/51 课

让板子听见 麦克风怎样把声音变成数字

课时
待定
器材
ESP32-S3 触摸屏板 + USB 线
前置知识
无
配套代码
见项目 demo 目录

你好,我是吴老师。

这份是给你自己读的——不用等我讲,你一段一段往下看,看到让你停下来的地方,就照着做一遍。看不懂的整段复制给 AI,加一句"请一次只解释一个概念,讲完问我一个小问题"。

读完之后,你应该能:说清麦克风和扬声器在"声↔电"上是反过来的;解释 ADC 怎么把声音变成数字;说出回声程序在搬什么;用一个数表示"这一段声音有多大"。

用时:60–90 分钟。准备:板子、数据线、已经接入板卡 Skill 的 WorkBuddy。


一、上一课的反向操作

上一课我们让板子开口:你会生成数字、送出去,扬声器就响。

这一课把它整个倒过来:让板子听见。

先做最直观的实验:对板子说一句话,它一字不差地重复给你听。这个实验叫回声(echo),就像对着山谷喊话。

动手之前先想一个反直觉的问题:说话是空气振动撞到耳朵,可板子没有耳朵,它只有数字。你说的话到了板子里,会变成什么?

——变成一堆数字。

那它是怎么把"空气振动"变成数字的?往下看。

二、先做回声实验

请使用课程的 esp32s3-touchboard-hardware-dev Skill,做一个"回声"程序:
板子从麦克风连续采声音,把采到的声音立刻从扬声器放出来,
就像对着山谷喊话一样。初始化音频时复用本课例程里 ES8311 + I2S 的初始化方式。
屏幕显示"回声中,说句话试试"。帮我新建程序并烧录。

💡 想先一步听到效果? 本页「本节演示」里的回声已经是做好的成品——点【在线烧录】一键烧进板子,先玩 30 秒;有底了再回来自己动手让 AI 写一个。

对着它说句话。你听到的自己的声音和平常不一样吧?

✏️ 可以直接在表格里填写
现象勾选
声音发闷、变扁
有呲啦杂音
尖叫(啸叫)

大部分人听到的自己的录音都"不像自己"。因为平时你说话,声音既从空气传到耳朵,也从骨头直接传到脑袋;录音只剩空气这一路。找同桌听,他们反而觉得像你。

三、麦克风:一面反过来工作的"鼓"

上一课扬声器是"电动的鼓":电压变 → 纸盆动 → 空气推。

麦克风刚好反过来:空气推 → 纸盆动 → 产生微弱电压。

扬声器麦克风
谁先动电压先动,纸盆跟着动纸盆先动,电压跟着产生
能量方向电 → 声声 → 电

⚠️ 比喻有边界:现在手机里那种小话筒(MEMS)没有看得见的"纸盆",但"声 → 电"的方向不变。

自己动手看一下"方向反过来"是什么意思(点上面的按钮切换):

重点看时机:扬声器是"电压先动,纸盆才动";麦克风是"纸盆先动,电压才产生"—— 同一面鼓,能量往哪边走,就决定了它是扬声器还是麦克风。

麦克风给出的电压又小又连续,可板子只会处理数字。怎么进去?——靠 ADC。

四、ADC:给电压"拍照"

第 11 课的 DAC 把数字变电压;这一课的 ADC 反过来:电压变数字。

ADC 的干活方式就是拍照:

每隔一小段固定时间,看一眼电压多大,记成一个数字。看一眼记一个,再看一眼再记一个。

  • 每秒"拍"多少次 = 采样率(上次是"送"的节奏,这次是"拍"的节奏)
  • 每个数字分多细 = 位深。我们用 16 位:把电压分成 65536 格,每格一个数字

整条录音链:

空气振动 → 麦克风 → 微弱电压 → ADC 按节奏拍照成数字 → 数字存起来

自己"拍"一遍(拖下面的滑杆改采样率和位深):

一定要拖这两个滑杆试试:

  • 采样率调很低 → 绿点变得很稀,波形细节丢了(录音会又闷又糊);
  • 位深调很低 → 点被"台阶化",波形和实际取值差很远(声音会有沙沙的量化噪声)。

这两个数字,就是录音时最常要权衡的两个东西。

五、声波的样子:上上下下的一串数

你的话变成一长串数字,画出来是波浪状:

  • 起伏多快 = 频率 → 音调
  • 起伏多高 = 振幅 → 响度(音量)
  • 起伏什么形状 = 波形 → 音色

音量在程序里 = 这些数字离开中间 0 有多远。 数字都贴着 0 → 安静;数字冲很高 → 响。

切换三种场景,看"音量"这个数怎么跟着变:

注意两件事:

  1. 安静不是 0 —— 世界上没有绝对的安静,麦克风总能测到一点底噪,所以安静时是几十,不是零;
  2. 柱子是平滑变化的 —— 不是每 0.1 秒猛跳一下。"响"在程序里不是感觉,是数字。

六、回声在搬什么

回声程序的中文伪代码:

不断重复:
    从麦克风读一串数字
    把这一串数字原样送出去

读进来什么样,送出去就什么样——板子并不"理解"你的话,它只是忠实地把数字搬了个家。让板子听懂话(语音识别),是以后联网课程的事。

七、让屏幕看见声音:音量柱

怎么用一个数代表"这段声音多大"?

简单办法:把 0.1 秒内所有采样(1600 个)的绝对值加起来除以个数 → 平均音量。

请做一个"音量指示器":
麦克风每 0.1 秒算一次平均音量,
屏幕左边画一根柱子,音量越大柱子越高(超过安全值变红),
上面实时显示音量数值。柱子要平滑变化,不要乱跳。

然后测三个场景:

✏️ 可以直接在表格里填写
场景我预测实际
安静
正常说话
喊

"响"在程序里不是感觉,是数字。 安静时几十,说话时几百上千,喊叫更高。

八、啸叫是什么

板子靠近扬声器,可能听到刺耳尖叫——啸叫。

声音链:扬声器放出 → 麦克风收进 → 放大 → 再放出……绕圈变大,变成尖叫。

✏️ 可以直接在表格里填写
我做的操作看到/听到
板子靠近喇叭
移开

这不是故障,是"回声变成循环"。电话会议、演唱会都怕它。你能想一个简单的压制办法吗?(提示:声音已经很大时,别急着放大。)

九、没声音排查

现象先检查
回声没声音串口报初始化失败了吗?麦克风方向对吗?
声音很轻调大音量
全是嘶嘶底噪去安静环境;看缓冲大小
一冲一冲读和放是不是互相堵死了

十、拓展:把声音画成彩色瀑布 ⭐

前面我们把 0.1 秒的声音压成了一个数(音量)。可这样也太浪费了——那 1600 个数字里,明明还藏着"这句话是低音还是高音、有没有吹口哨"的信息。

想把它们挖出来,就要用到 FFT(快速傅里叶变换)。

先理解它在干什么

想象一锅汤:你尝一口,只知道"咸"。这就像音量——把整段声音压成一个数。

FFT 干的是另一件事:把这段声音拆开,告诉你里面有多少"低音成分"、多少"中音"、多少"高音"。

打拍子类比更准一点:任何一段声音,都可以看成很多个不同音高的纯音叠在一起。FFT 就是把这段声音拆回那些纯音,然后告诉你每个音高各占多大声。

拆完之后我们得到一排数字:第 1 格是 62.5 Hz 有多大,第 2 格是 125 Hz 有多大……一直到第 128 格。

FFT 把混在一起的声音拆成每个音高各多大声:原来一条波形里藏着好几个音

把这一排数字画出来

横轴 = 频率(左边低音、右边高音),颜色 = 强度(越红越响)。画成一排竖直的柱子。

然后让画面往下流:每隔 64 毫秒画一排新的,旧的被挤下去。竖轴就变成了时间。

这叫做瀑布图——像瀑布一样,新的在最上面,一层层往下流。

频谱瀑布流:横轴是频率、往下流的是时间、颜色是强度

动手做

请使用课程的 esp32s3-touchboard-hardware-dev Skill,做一个"频谱瀑布流":
麦克风以 16kHz 采样,攒够 1024 个采样(64 毫秒)做一次 256 点 FFT,
把 120 个频段画成彩色竖条,让画面一行一行往下流动成瀑布。
横轴是频率(左边低音右边高音),颜色表示强度(黑→蓝→青→绿→黄→红)。
屏幕用 sprite 画(大缓冲放 PSRAM),并接入 ScreenMirror 方便抓帧。

五种声音,五种图案

这是本课最好玩的部分。对着板子做下面五件事,把看到的形状记下来:

你做什么瀑布上出现什么为什么
安静不说话整片偏暗,只有最左边一点底噪没有声音,只剩电路自己的噪声
说一句话左边一片上下跳动的亮色人声能量集中在低中频;说话时音高在变,所以亮块在动
吹口哨一根又直又亮的细柱口哨几乎是单一频率——这是最漂亮的一张图
拍手 / 敲桌子一瞬间整排都亮(一条横线)拍手是"宽频"冲击,所有频率同时有能量
唱「啊」再升高音亮柱整体向右移动升高音 = 频率变高 = 往右边走

💡 吹口哨那一根柱,就是 FFT 最直观的证据:它真的把"一个频率"从声音里挑出来了。

按一下 BOOT 试试

短按板子上的 BOOT 键,会响三声轻柔的音(C5→E5→G5)。

这三声从扬声器放出来,立刻被麦克风收回去——瀑布上会出现三条竖直的亮柱。

这是"声音看得见"最直接的证据,也能顺便检查麦克风是不是好的。

两个你可能想问的

为什么右边经常是黑的?

因为自然界的声音能量大多集中在低频。你说话时高频部分本来就弱得多,直接画出来右半屏几乎全黑、什么都看不见。

所以程序里加了个高频补偿:按每倍频程 +4.5 dB 放大高频。就像调音响的"高音旋钮"——不改变横轴"左低右高"的真实对应,只是让细节看得见。所有的频谱仪都这么干。

为什么一帧要算 4 次 FFT 再平均?

单次 FFT 得到的数字很"毛躁",画面会一直闪。算 4 次取平均就稳多了——这和上一节音量柱加平滑是同一个思路。

还能怎么玩

想法怎么做
声音指纹对比钢琴不同音、不同人说话,瀑布图案差在哪
谁在说话用图案区分男声女声、大人小孩
噪音地图记录一天里教室什么时候最吵(配合 TF 卡)
音乐可视化放歌,让瀑布的颜色跟着节奏变

🔗 这里连上了第 24 课:语音识别(ASR)的第一步,就是把声音变成这样一张频谱图,再交给 AI 去认。今天你是用眼睛看,AI 是用"眼睛"看同一张图。

十一、自检小测

先自己想,再点开对答案。

1. 麦克风和扬声器,在"声↔电"方向上的关系是什么?

正好反过来。

  • 扬声器:电 → 声(电压推纸盆,把空气推出一层层波)
  • 麦克风:声 → 电(空气推它的膜片,产生微弱的电压变化)

一个"把电变成声音",一个"把声音变成电"——第 11 课和这一课,是同一个过程倒过来走。

2. ADC 是干什么的?和 DAC 什么关系?

ADC = 模数转换器:把电压变成数字。 它和 DAC 正好相反:

方向在哪
DAC(第 11 课)数字 → 电压ES8311
ADC(这一课)电压 → 数字ES8311

一颗 ES8311 就同时干这两件事,所以它叫"编解码芯片"(codec)。

3. 采样率和位深各决定什么?用"拍照"怎么解释?

ADC 干活就像给电压拍照:

  • 采样率 = 每秒拍几张(16000 = 每秒拍 16000 张) → 拍得少,波形细节丢了,录回来又闷又糊。
  • 位深 = 每张照片的颜色分多少级(16 位 = 把电压分成 65536 格) → 分得少,点被"台阶化",声音有沙沙的量化噪声。

采样率管"多勤",位深管"多细"。

4. 回声程序在搬什么?板子理解你说的话吗?

搬的是数字。

麦克风收到声音 → ADC 拍成数字 → 原样送出去给扬声器。

板子完全不理解你说的话——它只是把一串数字从进口搬到出口,一个都不改。 理解内容需要语音识别(那是第 24 课的事)。

5. "音量"在程序里到底是什么?怎么算出来?

音量 = 这些数字离开中间的 0 有多远。

  • 数字都贴着 0 → 安静
  • 数字冲得很高(或很低)→ 响

所以算音量,就是看取到的这一段数字偏离 0 的程度(取绝对值、求平均)。

6. 为什么把麦克风和喇叭凑太近会"啸叫"?

因为形成了一个循环:

喇叭发出声音 → 麦克风又收到 → 送进喇叭放大 → 再发出来 → 麦克风又收到 …

每一圈都放大一点,很快就变成刺耳的尖叫。

所以录音/放音时别把板子凑太近,也别把音量开太大。

十二、还能玩什么

方向想法
噪音报警器音量超阈值屏幕变红 + 灯亮
拍手开关灯拍一下亮、再拍灭(要区分一次和两次)
吹气游戏吹气让屏幕上的球飞起来
神秘低语回声 + 上一课变调,变机器人音

想做"板子听得懂人话"?那叫语音识别,等学了网络再回来。今天先把"收数字"练熟——下一课我们要打开盖子,看这些数字是怎么在两根线之间跑起来的。

第 12 课 · 回声

第 12 课 · 回声

你对着板子说话,它把你的话立刻原样重复出来。

12麦克风回声录音
第 12 课 · 音量指示器

第 12 课 · 音量指示器

让屏幕「看见」声音大小——麦克风的音量变成一根会升降的柱子。

12麦克风音量平滑
第 12 课 · 噪音报警器

第 12 课 · 噪音报警器

谁一吵(音量超过阈值),屏幕变红、RGB 灯亮红灯,安静下来才恢复。

12麦克风报警阈值
第 12 课 · 拍手开关灯

第 12 课 · 拍手开关灯

拍一下手灯亮,再拍一下灯灭——把声音当成「事件」来处理。

12麦克风事件拍手RGB灯
第 12 课 · 频谱瀑布流(拓展)

第 12 课 · 频谱瀑布流(拓展)

让声音变成彩色瀑布:横轴是频率、往下流的是时间、颜色是强度。

12麦克风FFT频谱采样