文章目錄
- 系列文章目錄
目錄
文章目錄
前言
一、問題引入
二、使用步驟
三、分析和改進
總結
前言
我們知道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卷死