我非常新的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的背景是相当有限的。
我怎么能获得频率强度值的这种频谱分析的每一帧的阵列? 我可以从那里弄清楚休息了,我只需要知道如何获得相应的数据。
你所要做的是所谓的语音活动检测 。 有许多方法这一点,最简单的可能是一个简单的带通滤波器,即通过频率处的讲话是最强的,这为1kHz和8kHz的之间。 然后,您可以用有限的带通比较总信号能量,如果大部分能量是在话音频带,划分帧讲话。 这是一种选择,但也有其他人了。
为了获得在峰的频率,你可以使用FFT来获得频谱,然后使用peakdetect.m 。 但是,这是一个非常幼稚的做法,因为你会得到很多山峰,属于基本正弦波的谐波频率。
理论上应该使用某种倒频谱(也称为光谱的光谱),这降低了在光谱基频谐波周期性,然后使用与PEAKDETECT。 或者,你可以使用现有的工具,即做到这一点,如普瑞特 。
要知道,语音分析通常是在大约30毫秒帧进行,在10毫秒步进。 通过确保在共振峰N个连续帧被检测到,你可以进一步滤除错误检测。
你为什么不使用fft
用`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');
为什么你想使用复杂的东西?
一个很好的和完整的解决方案可以发现https://dsp.stackexchange.com/questions/1522/simplest-way-of-detecting-where-audio-envelopes-start-and-stop
看一看的STFT(短时傅立叶变换)或(甚至更好)的DWT数据(离散小波变换),这两者都将估计块(窗口)的频率成分,这是你所需要的,如果你想检测在某些(“讲话”)频率的振幅的突然变化。
因为它计算在信号的整个持续时间的相对频率内容,使得不可能确定何时某个频率的信号发生不使用FFT。
如果你还在使用内置的STFT功能,然后绘制你可以使用下面的命令最大
plot(T,(floor(abs(max(S,[],1)))))