简介这份资源面向音频处理初学者与信号分析入门者用Matlab演示如何读取WAV音频并绘制时域波形、FFT频谱、时域分贝图与频谱分贝图四类图表帮助理解分贝计算与频谱特性。包内共1个doc文件约154KB以文档形式给出完整代码与运行结果涵盖wavread读取、采样率与位深度获取、时间向量构造、fft变换及20*log10对数尺度绘制等关键环节。示例选取音乐与安静环境下敲击桌面两段10秒音频对比复杂波形与简单脉冲在时频域上的差异便于直观感受响度与频率结构。已有2194人学习下载适合需要快速上手音频可视化、为降噪或音频编码打基础的读者参考。1. 从一段敲桌声说起Matlab 音频分贝图到底能看出什么很多人第一次用 Matlab 处理音频都是被作业或者项目逼的手里有一段 wav想看看它的时域波形和频谱最好再画成分贝图。但真跑起来才发现wavread报错、分贝图全是负无穷、频谱横轴对不上——这些坑一个比一个玄学。这份资源给的就是一套能直接跑的 Matlab 脚本读 wav、算 FFT、画时域波形、画频谱、再画两张分贝图四宫格一次出图。它解决的不是“音频处理有多深”的问题而是“我手头这段录音到底长什么样、能量集中在哪、响度怎么分布”这种最实际的诉求。适合信号处理课设、音频分析入门、以及需要快速给一段录音做可视化体检的从业者。下面我按“能跑起来 → 看懂每行 → 避开坑 → 进阶验证”的顺序拆一遍。2. 把 wav 读进来并画出四宫格脚本结构与参数含义2.1 读取音频与时间轴、频率轴的构造原始代码用的是wavread这是老版本 Matlab 的函数新版本已经换成audioread。如果你直接抄原代码在 R2015b 之后的版本会直接报错。我一般会先确认手头 Matlab 的版本再决定用哪个函数。下面这段是兼容写法优先走audioread读不到再回退% 读取 wav 文件返回音频数据 x、采样率 fs % audioread 是新版推荐函数wavread 在旧版可用 try [x, fs] audioread(08.wav); % 新版 Matlab catch [x, fs, bits] wavread(08.wav); % 旧版回退 end % 如果是双声道取左声道避免后续 fft 维度混乱 if size(x, 2) 1 x x(:, 1); end N length(x); % 总采样点数 t (1:N) / fs; % 时间轴单位秒 f0 fs / N; % 频率分辨率 n 1:N/2; % 只取前半段利用 FFT 对称性 f (n - 1) * f0; % 频率轴单位 Hz这里有几个参数必须说清楚。fs是采样率常见 44100 Hz 或 48000 Hz它决定了你能分析的最高频率是fs/2也就是奈奎斯特频率。N是总点数10 秒 44100 Hz 的音频就是 441000 个点。f0 fs/N是频率分辨率意思是频谱上相邻两个点之间隔了多少 HzN 越大分辨率越细。n 1:N/2是因为实信号的 FFT 结果关于中点对称后半段是冗余的取一半就够了。f (n-1)*f0里减 1 是为了让第一个点对应 0 Hz也就是直流分量。提示如果你的音频是立体声直接对二维矩阵做fft会得到二维结果画图时维度对不上。先取单声道是省事的做法。2.2 FFT 变换与四个子图的布局逻辑拿到x和fs之后核心就是fft和subplot。原始代码把四张图塞进一个figure的 2×2 布局里顺序是左上时域波形、右上频谱幅值、左下时域分贝、右下频谱分贝。这个顺序不是随便排的它对应的是“先看整体形状再看能量分布最后看动态范围”的分析习惯。y fft(x); % 对整段音频做快速傅里叶变换 mag abs(y(n)); % 取前半段幅值 figure(1); % 左上时域波形 subplot(2,2,1); plot(t, x); title(时域波形); xlabel(时间/t); ylabel(振幅/A); grid on; % 右上FFT 幅值谱 subplot(2,2,2); plot(f, mag); title(FFT 变换后信号的频谱特性); xlabel(频率/Hz); ylabel(幅值/A); grid on; % 左下时域分贝图 subplot(2,2,3); x_db 20 * log10(abs(x) / max(abs(x)) eps); plot(t, x_db); title(时域分贝图); xlabel(时间/t); ylabel(振幅/dB); grid on; % 右下频谱分贝图 subplot(2,2,4); y_db 20 * log10(mag / max(mag) eps); plot(f, y_db); title(FFT 变换后信号的频谱特性); xlabel(频率/Hz); ylabel(振幅/dB); grid on;fft(x)返回的是复数数组abs取模得到幅值。分贝计算用20*log10(A/Amax)这是电压/振幅类的标准公式如果是功率类才用10*log10。原始代码里max(abs(x))做归一化保证最大值对应 0 dB其余为负值。这里我加了eps原因是当某个采样点恰好为 0 时log10(0)会返回-Inf画图时整条线会断掉或者出现异常尖峰。加一个极小值eps能避免这个问题这是实际跑图时很容易忽略的一步。注意max(abs(x))如果音频整段都是静音最大值接近 0归一化会放大噪声。实际用的时候先检查一下max(abs(x))是不是小得离谱。3. 分贝图为什么全是负值对数压缩与动态范围的实际意义3.1 20*log10 的物理含义与归一化选择很多人第一次看到分贝图第一反应是“怎么全是负数”。这其实是对数的正常表现。分贝本质是两个量的比值取对数当你用最大值做参考时最大值就是 0 dB比它小的全是负的。比如某个点幅值是最大值的十分之一20*log10(0.1) -20 dB是百分之一就是-40 dB。所以分贝图上的负值不代表“没有信号”而是代表“比最强点弱多少”。归一化的选择也有讲究。原始代码用max(abs(x))做参考得到的是相对分贝。如果你想要绝对声压级那需要知道录音设备的灵敏度和增益普通 wav 文件里没有这个信息所以相对分贝是更实际的做法。我一般会在图里保留这个归一化同时在标题或注释里写清楚“相对最大值”。% 相对分贝以当前信号最大幅值为 0 dB 参考 x_db 20 * log10(abs(x) / max(abs(x)) eps); % 如果想看绝对幅值对应的分贝不推荐除非知道校准信息 % x_db_abs 20 * log10(abs(x) eps);对比一下音乐和敲桌声这两类信号。音乐的能量分布比较连续时域分贝图上的起伏相对平滑频谱分贝图在很宽的频率范围内都有可观的值。敲桌声是瞬态信号时域分贝图上会看到几个明显的尖峰其余时间迅速掉到 -60 dB 甚至更低频谱上能量集中在低频段高频衰减很快。这两种图放在一起看就能直观判断信号类型。3.2 频谱分贝图里高频为什么掉得那么快如果你仔细看频谱分贝图的右半段会发现高频部分的 dB 值一路往下掉有时候掉到 -80 dB 以下。这不是代码写错了而是大多数真实音频的共性能量主要集中在低频和中频高频天然弱。再加上 FFT 的幅值没有做归一化补偿点数越多单个频点的幅值越小分贝值也会整体下移。这里有个容易翻车的地方有人为了让图“好看”把max(mag)换成max(mag(1:100))或者手动加一个偏移量结果分贝图的参考点变了不同图之间没法对比。我的习惯是保持参考点一致如果确实需要看高频细节单独放大某段频率范围而不是改归一化基准。% 只看 0 到 5000 Hz 的频谱分贝 idx f 5000; figure(2); plot(f(idx), y_db(idx)); title(0-5000 Hz 频谱分贝图); xlabel(频率/Hz); ylabel(振幅/dB); grid on;这样既保留了原始分贝关系又能把关心的频段看清楚。对于敲桌声这种低频为主的信号0 到 2000 Hz 往往就包含了绝大部分能量。4. 避坑与排查wavread 报错、维度不匹配、分贝图断裂4.1 wavread 在新版 Matlab 中直接报错现象运行原始代码第一行就提示Undefined function wavread。原因是wavread在 R2015b 之后被移除替换为audioread。解决方法是改用audioread注意返回值只有两个音频数据和采样率没有位深度。如果你确实需要位深度可以用audioinfo单独查。info audioinfo(08.wav); disp(info.BitsPerSample); % 查看位深度4.2 立体声文件导致 fft 结果维度错误现象plot(f, abs(y(n)))报错提示向量长度不一致。原因是立体声 wav 读进来是 N×2 矩阵fft之后还是 N×2而f是长度为 N/2 的向量维度对不上。解决方法是在读入后立刻取单声道或者对每一列分别做 FFT。我一般直接取左声道省事且够用。4.3 分贝图出现 -Inf 或断线现象时域分贝图上有几段直接消失或者出现垂直的异常线。原因是某些采样点幅值为 0log10(0)返回-Inf。解决方法是在对数运算里加eps或者把 0 值替换成一个极小值。原始代码没有处理这个遇到静音段就会翻车。x_db 20 * log10(abs(x) / max(abs(x)) eps);4.4 频率轴与频谱图对不上现象频谱图的横轴范围是 0 到 22050 Hz但明显感觉峰值位置不对。原因是f (n-1)*f0里n从 1 开始减 1 之后第一个点是 0 Hz这是对的。但如果你的n定义成了1:N/21长度会多一个点和y(n)的长度不匹配。检查length(f)和length(y(n))是否相等不相等就调整n的范围。4.5 音频路径含中文或空格导致读取失败现象audioread提示文件不存在但路径明明是对的。原因是旧版 Matlab 对中文路径支持不好或者路径里的空格没有转义。解决方法是用绝对路径并且把音频文件放在纯英文、无空格的目录下。如果必须用中文路径先cd到文件所在目录再用相对文件名读取。5. 进阶验证用分贝图对比两段录音的响度与频率结构5.1 把音乐和敲桌声放在同一套坐标下对比原始资源给了两段音频一段 10 秒音乐一段 10 秒敲桌声。单独看每段的分贝图只能知道“长什么样”把两段放在一起才能看出差异。我一般会写一个循环把两段音频的分贝图叠在同一张图上或者并排显示。下面这个写法可以把时域分贝和频谱分贝分别对比files {08.wav, 07.wav}; labels {音乐, 敲桌声}; colors {b, r}; figure(3); for k 1:2 [x, fs] audioread(files{k}); if size(x, 2) 1, x x(:, 1); end N length(x); t (1:N) / fs; f0 fs / N; n 1:N/2; f (n - 1) * f0; y fft(x); mag abs(y(n)); x_db 20 * log10(abs(x) / max(abs(x)) eps); y_db 20 * log10(mag / max(mag) eps); subplot(2,1,1); plot(t, x_db, colors{k}); hold on; subplot(2,1,2); plot(f, y_db, colors{k}); hold on; end subplot(2,1,1); title(时域分贝对比); xlabel(时间/t); ylabel(振幅/dB); legend(labels); grid on; subplot(2,1,2); title(频谱分贝对比); xlabel(频率/Hz); ylabel(振幅/dB); legend(labels); grid on; xlim([0 5000]); % 主要能量在低频限制横轴看得更清楚这段代码的关键点在于两段音频各自用自己的最大值做归一化所以对比的是“相对动态范围”而不是绝对响度。如果你想知道哪段录音实际更响需要看原始幅值的最大值而不是分贝图。分贝图在这里的作用是看能量分布的形状差异。5.2 用分贝图判断录音质量的一个实用技巧我平时拿到一段陌生录音会先跑一遍这套四宫格然后重点看两个地方。第一时域分贝图的底部噪声线在什么水平。如果安静段的 dB 值在 -40 dB 以上说明底噪偏大可能是录音环境或设备增益没调好。第二频谱分贝图在 10000 Hz 以上的衰减速度。如果高频掉得特别陡可能是音频被压缩过或者采样率本身就不高。还有一个验证方法是把同一段音频分别用audioread和audioinfo读一遍确认采样率、位深度、声道数是否和预期一致。有时候文件扩展名是 wav但内部编码不是 PCMaudioread能读但数据可能已经被解码过一次分贝图会失真。这种情况用audioinfo看CompressionMethod字段就能确认。从那以后我每次拿到新录音都强制先跑一遍audioinfo加四宫格确认采样率和底噪没问题再往下做分析。希望帮到你。本文还有配套的精品资源点击获取