You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matlab Spectrogram函数问题:无法获取图中对应dB值

Matlab频谱图P矩阵与图中dB/Hz刻度不符的问题

问题描述

运行Matlab程序读取音频文件并显示功率谱图,需要获取指定时间和频率对应的dB/Hz值。目前图上能看到合理的x(频率)、y(时间)、z(dB/Hz)刻度值,但调用[S, F, T, P, Fc, Tc] = spectrogram(...)后,得到的P矩阵数值在0.0000至0.0002之间,和图中-80到-100的dB/Hz刻度不符,不清楚P的含义,也不知道如何获取对应图中刻度的矩阵。

原代码如下:

clicky = audioread('ChamberTesting_Feb13.wav'); %normalized

quiet_n = audioread('quiet60_normalized.wav'); %normalized

%spectrogram(clicky(:,1),1000,500,1000,Fs); %channel 1 spectrogram
spectrogram(quiet_n(:,1),1000,500,1000,Fs); %channel 1 spectrogram
view(90,90)

%s = spectrogram(clicky(:,1),1000,500,1000,Fs);
s = spectrogram(quiet_n(:,1),1000,500,1000,Fs);
C = get(gca, 'children');
X = get(C, 'Xdata');
Y = get(C, 'Ydata');
Z = get(C, 'Zdata');



delta = 1; %change in time from peak
diff = 10;
differences_count = 0;

for j = 1:5
    for i = 1:40
        num_init = Z(i,j)
        num_comp = Z(i, j+delta) 
        if abs(num_init-num_comp)>diff & differences_count<10
            differences_count = differences_count+1;
        end
    end
end

if(differences_count>5)
    disp("CLICKY!")
end

解决方案

1. P矩阵的含义

spectrogram函数返回的P是线性刻度的功率谱密度(PSD),单位与输入信号幅值相关(你的音频是归一化到[-1,1]的,所以P的单位为1/Hz)。而绘图时Matlab会自动将线性PSD转换为对数刻度的dB/Hz值,转换公式为:

P_dB = 10 * log10(P);

你看到的0.00000.0002的线性值是显示精度问题,真实数值更小(比如1e-81e-10),转换后正好对应图中-80~-100的dB/Hz刻度。

2. 获取对应图中刻度的矩阵

直接对P进行dB转换即可得到与图中Z轴刻度一致的矩阵,为避免log10(0)的计算错误,可添加机器精度eps:

P_dB = 10 * log10(P + eps);

3. 优化后的代码

无需从图形对象中提取Zdata,直接用转换后的P_dB矩阵计算更可靠高效:

% 读取音频时同时获取采样率Fs
[clicky, Fs] = audioread('ChamberTesting_Feb13.wav'); %normalized
[quiet_n, Fs] = audioread('quiet60_normalized.wav'); %normalized

% 绘制频谱图(可选,用于可视化)
spectrogram(quiet_n(:,1),1000,500,1000,Fs);
view(90,90)

% 获取线性PSD及对应频率、时间轴
[S, F, T, P] = spectrogram(quiet_n(:,1),1000,500,1000,Fs);
% 转换为dB/Hz刻度,添加eps避免计算错误
P_dB = 10 * log10(P + eps);

delta = 1; % 时间步长
diff = 10; % dB差值阈值
differences_count = 0;

% 循环时避免索引越界,P_dB的行对应频率,列对应时间
time_len = size(P_dB, 2);
for j = 1:(time_len - delta)
    for i = 1:size(P_dB, 1)
        num_init = P_dB(i,j);
        num_comp = P_dB(i, j+delta);
        if abs(num_init - num_comp) > diff && differences_count < 10
            differences_count = differences_count + 1;
        end
    end
end

if differences_count > 5
    disp("CLICKY!")
end

补充说明

你之前通过get(gca, 'children')获取的Zdata是已经转换后的dB值,但这种方式依赖图形对象结构,不如直接计算P_dB稳定。另外,P矩阵维度为[频率点数, 时间帧数],对应图中的X(频率)和Y(时间)轴,循环时需注意索引对应关系。

内容的提问来源于stack exchange,提问作者jukebox41188

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 12:33:29