如何在 Matlab 中生成频率为 x 轴的 wav 文件的频谱图

How to generate the spectrogram of a wav file in Matlab with frequency on the x-axis

作为研究项目的一部分,我想通过生成频谱图来分析声音文件。

我已经能够在 matlab 中成功生成波形文件的频谱图,y 轴为频率,x 轴为时间。但是,我想生成 x 轴上的频率和 y 轴上的时间的频谱图。如何做到这一点?

我搜索了堆栈,但没有找到任何可接受的答案。

我的代码生成频谱图,y 轴为频率,x 轴为时间(Matlab 代码):

[song, fs] = wavread('filename.wav');
windowSize = 256;
windowOverlap = [];
freqRange = 0:300;
spectrogram(song, windowSize, windowOverlap, freqRange, fs, 'yaxis');

我将函数频谱图中的参数 'yaxis' 更改为 'xaxis',现在频率在 x 轴上,时间在 y 轴上。但是,我得到的频谱图与从可靠来源生成的频谱图不同。

这是我生成的频谱图 -

可靠来源生成的频谱图(我没有代码)。

此外,两个频谱图中的配色方案不同。我的录音是 50 秒,而标签上显示的时间是 9 秒。我该如何解决这些问题?

我的最终任务是能够在 android 设备上生成频谱图(可能使用 android 中的 GraphView 库)。所以我必须编写代码来生成 Java.

中的频谱图

非常感谢任何帮助。

前言

抱歉,我没有 Mathworks 放入 spectrogram 的任何工具箱,但这是我放入 public 域中的一些代码,可以为我完成这项工作。

它比 spectrogram 更实用,但具有后者的许多功能,正如我将使用 Matlab 附带的 handel 音频剪辑('Hallelujah!')进行演示一样。

设置

我不会假定您熟悉 git 或 Matlab 命名空间。

  1. 在您的 Matlab 路径中的某处创建一个名为 +arf 的目录(例如,~/Documents/MATLAB 甚至您当前的代码目录)。
  2. 下载stft.m并放入+arf/
  3. 同时下载 partition.m+arf/

这将创建一个 arf namespace,其中包含 arf.stftarf.partition 函数(后者由 arf.stft 使用)。

代码

clearvars

% Load data: this is an audio clip built into Matlab.
handel = load('handel');
% To hear this audio clip, run the following:
% >> soundsc(handel.y, handel.Fs)

% STFT parameters.
% 1000 samples is roughly 1/8th of a second. A reasonable chunk size.
samplesPerChunk = 1000;
% Overlap a lot between chunks to see a smooth STFT.
overlapSamples = round(samplesPerChunk * 0.9);

% Generate STFT
[stftArr, fVec, tVec] = arf.stft(handel.y, ...
                                 samplesPerChunk, ...
                                 'noverlap', overlapSamples, ...
                                 'fs', handel.Fs);

% Plot results
figure('color', 'white');
imagesc(fVec / 1e3, tVec, 20 * log10(abs(stftArr)).');
axis xy
colorbar
xlabel('frequency (KHz)')
ylabel('time (s)')
caxis(max(caxis) - [40 0])
title('`handel` spectrogram via STFT, top 40 dB')

上面的代码

  1. 加载打包到 Matlab 中的 handel 音频剪辑(这是来自乔治·弗里德里克·汉德尔 弥赛亚 的九秒剪辑),
  2. 为STFT定义一些参数,
  3. arf.stft()
  4. 评估 STFT
  5. 绘制 STFT。

提示:在你 运行 上面的代码之后,或者只是 load 行之后,你可以用 soundsc(handel.y, handel.Fs).

收听原始剪辑

结果

在频谱图中,可以清楚地看到前两首长的哈利路亚,然后是两首较短的,最后是最后一首长的。沿 y 轴的时间 运行s 如您所愿。

代码演示了如何指定块长度(此处为 1000 个样本,或 ≈⅛ 秒)和重叠量(块长度的 90%,因此有 900 个重叠样本)。注:

  • 块长度越大,时间分辨率越低(但频率分辨率越高)。
  • 重叠越少,STFT 随时间出现的锯齿状越多,平滑度越低(您支付的 computational/memory 开销就越少)。重叠量必须在 0(块之间没有重叠)和 chunk size - 1.
  • 之间

如果你只是玩弄块长度,你会感觉到 STFT 给你调整的主旋钮。通常,一个人会选择块大小的 25% 或 50% 之间的重叠,以获得相当平滑的频谱图,而无需大量的计算开销。

N.B。您可以通过将额外的参数传递给 arf.stft,特别是 arf.stft( ..., 'nfft', 2^nextpow2(samplesPerChunk * 8)) 来增加沿 频率 维度的平滑度。这明确设置了要创建的频率仓的数量(最终,评估了这个大小的 FFT)。默认值相当于 2^nextpow2(samplesPerChunk),因此将其乘以 8 会将每个块的频谱上采样八倍。