我对Matlab很新,我正在尝试编写一个简单的基于频率的语音检测算法。最终目标是在wav文件上运行脚本,并为每个语音段输出开始/结束时间。如果使用代码:
fr = 128;
[ audio, fs, nbits ] = wavread(audioPath);
spectrogram(audio,fr,120,fr,fs,'yaxis')
我得到了一个有用的频率强度与时间的关系曲线:
通过观察它,很容易看出语音何时发生。我可以编写一种算法,通过查看每个x轴框架来自动化检测过程,确定哪些频率占优势(具有最高强度),测试主导频率以查看它们是否足够超过某个强度阈值(图中的黄色和红色之间的差异,然后将该帧标记为语音或非语音。一旦标记了帧,就可以很容易地获得每个语音段的开始/结束时间。
我的问题是我不知道如何访问这些数据。我可以使用代码:
[S,F,T,P] = spectrogram(audio,fr,120,fr,fs);
获取光谱图的所有功能,但该代码的结果对我没有任何意义。 S,F,T,P阵列和矩阵的界限与我在图表上看到的任何内容都不相关。我查看了帮助文件和API,但是当他们开始抛出算法名称和首字母缩略词时我感到困惑 - 我的DSP背景非常有限。
如何获得此频谱图分析每帧的频率强度值数组?我可以从那里找出其余部分,我只需要知道如何获得适当的数据。
答案 0 :(得分:1)
Why don't you use fft
with `fftshift:
%% Time specifications:
Fs = 100; % samples per second
dt = 1/Fs; % seconds per sample
StopTime = 1; % seconds
t = (0:dt:StopTime-dt)';
N = size(t,1);
%% Sine wave:
Fc = 12; % hertz
x = cos(2*pi*Fc*t);
%% Fourier Transform:
X = fftshift(fft(x));
%% Frequency specifications:
dF = Fs/N; % hertz
f = -Fs/2:dF:Fs/2-dF; % hertz
%% Plot the spectrum:
figure;
plot(f,abs(X)/N);
xlabel('Frequency (in hertz)');
title('Magnitude Response');
为什么要使用复杂的东西?
中可以找到一个很好的完整解决方案答案 1 :(得分:1)
看看STFT(短时傅立叶变换)或(甚至更好)DWT(离散小波变换),它们都会估计数据块(窗口)中的频率内容,这就是你需要的想要检测某些(“语音”)频率的幅度的突然变化。
不要使用FFT ,因为它计算信号整个持续时间内的相对频率内容,因此无法确定何时某个频率出现在信号。
答案 2 :(得分:1)
您要做的是语音活动检测。有许多方法,最简单的可能是一个简单的带通滤波器,它通过语音最强的频率,这在1kHz到8kHz之间。然后,您可以将总信号能量与带通限制进行比较,如果大部分能量在语音频段中,则将帧分类为语音。这是一个选择,但也有其他选择。
要获得峰值频率,您可以使用FFT获取频谱,然后使用peakdetect.m。但这是一种非常天真的方法,因为你会得到很多峰值,属于基本正弦的谐波频率。
理论上你应该使用某种倒谱(也称为频谱),它可以减少谐波在频谱中与基频的周期性,然后将其与峰值检测结合使用。或者,您可以使用现有工具,例如praat。
请注意,语音分析通常在大约30ms的帧上完成,步进10ms。您可以通过确保在N个连续帧中检测到共振峰来进一步滤除错误检测。
答案 3 :(得分:0)
如果你仍然使用内置的STFT功能,那么要绘制最大值,你可以使用以下命令
plot(T,(floor(abs(max(S,[],1)))))