为什么我画的频谱图和audacity、audition不一样?
文章目录
- 系列文章目录
目录
文章目录
前言
一、问题引入
二、使用步骤
三、分析和改进
总结
前言
我们知道audacity和audition都有频谱分析这个窗口,一般过程肯定是分帧加窗,fft变换然后呈现,
大体这个过程是没问题的,但为什么我画出来的频谱图和它们的不一样?本篇文章就来分析这个
一、问题引入
一个典型的wav(一个底噪)的波形频谱,在audition里面展示如下:
fft频谱分析如下:
注意三个要素,window窗长,选取整个wav数据范围,采用hanning窗
二、使用步骤
根据上面的分析,我们自己写了一个频谱分析的spectrum【AI写的,我哪有那么厉害】
clear all
close all
clc[x,fs] = audioread('4-OK.wav');% 1. 分帧处理(假设信号长度是帧长的整数倍)
N = length(x);
signal = x;
winLen =2048;
numFrames = floor(N/winLen);
frames = reshape(signal(1:numFrames*winLen), winLen, numFrames);% 2. 加Hanning窗
window = hann(winLen);logMagAll = zeros(winLen/2+1, 1);
for i = 1:numFramesframe = frames(:,i) .* window;mag = abs(fft(frame, winLen));logMagAll = logMagAll + 10*log10(mag(1:winLen/2+1).^2 + 1e-16);
endlogMag = logMagAll/numFrames ;% 5. 绘图
freq = (0:winLen/2)/winLen * fs; % 频率轴
figure;
semilogx(freq(2:end), logMag(2:end)); % 对数频率轴,跳过DC
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
title('Power Spectrum (Hanning window)');
grid on;
核心过程就是 分帧,加窗,先求 log对数,然后算完之后求平均
频谱形状是对的,但发现底噪和整体幅度有差别
底噪是-60,audition显示底噪是-100多呢,这个地方肯定有问题,但俩形状相似,很可能是增益导致,差了倍数。
倍数差在边度呢?
三、分析和改进
audition的源代码肯定是没有,人商业软件,被adobe买了,别想了。我们可以参考audacity 的, 先看看audacity分析的频谱如何
低频底噪太低,没显示全,但是没关系,鼠标可以放到低频,给出信息,大概-100多dB,那和audition的一样,audacity的源代码可是有的哦,马上参考它的代码;
经过一系列的分析,我们知道这个函数是画频谱的地方【具体怎么分析得到的的可以参考韦神解五次方程的过程,就是题感!】
关键是这个地方
方框部分,有个时域加权,对窗口系数的加权!
能量谱没有什么特殊的,就是普通的fft计算
回到 SpectrumAnalyst::Calculate 函数,这个地方 by每帧会 直接求和
也就是 应该先 求能量谱的总和,不着急求 log,

等出每一帧的while循环之后呢
能量谱求 20倍log,幅度谱求10倍log
再乘以scale,scale里面有对每一帧的平均,194行
到这里就明白了,注意要点有两个
1、注意要乘窗口归一化权重 wss
2、注意先求 幅度谱加和,再平均,然后上对数,而不是先对数,再加和平均,经常玩log的都知道,说白了其实一个是算术平均,一个是几何平均
行了,道理都清楚了,代码的事情让deepseek 出!嗷嗷的来吧你就
clear all
close all
clc[x,fs] = audioread('4-OK.wav');% 1. 分帧处理(假设信号长度是帧长的整数倍)
N = length(x);
signal = x;
winLen =2048;
numFrames = floor(N/winLen);
frames = reshape(signal(1:numFrames*winLen), winLen, numFrames);% 2. 加Hanning窗
window = hann(winLen);
wss = sum(window); % 窗谱和
if wss > 0wss = 4.0 / (wss^2); % 窗谱平方和归一化因子
elsewss = 1.0;
end% 3. 计算每帧幅度谱平方和
MagAll = zeros(winLen/2+1, 1);
for i = 1:numFramesframe = frames(:,i) .* window;mag = abs(fft(frame, winLen));MagAll = MagAll + mag(1:winLen/2+1).^2;
end% 4. 计算对数幅度谱
scale = wss / numFrames;
logMag = 10 * log10(MagAll * scale);% 5. 绘图
freq = (0:winLen/2)/winLen * fs; % 频率轴
figure;
semilogx(freq(2:end), logMag(2:end)); % 对数频率轴,跳过DC
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
title('Power Spectrum (Hanning window)');
grid on;
再看频谱图
行了,应该对上了,齐刷的!
总结
1、要会发现问题,别总以为自己的代码最牛逼,实际根本不符合规律,-30dB底噪那么大,可能么?
2、要利用互联网资源,能开源的为毛不用,deepseek自己写也不一定你给正确代码,还得靠自己分析
3、要会用deepseek,巧用ai,不受制于ai,才不会被ai卷死