我正在使用Octave开发语音识别系统。我试图通过检测频率的差异来检测音素。目前我已经阅读了wav文件,将值组织成块并将fft
应用于整体数据。之后,我用plot(abs(real(fft(q))))
绘制新数据,创建此图表:
我如何获得频率值(图表的峰值)?
答案 0 :(得分:16)
如果您无权访问findpeaks
,其工作原理背后的基本前提是,对于信号中的每个点,它会搜索以此为中心的三元素窗口,并检查是否此窗口的中心大于此窗口的左右元素。您希望能够找到正峰值和负峰值,因此您需要检查绝对值。
因此,您可以做的是制作两个额外的信号,将信号向左移1,向右移1。当我们这样做时,我们实际上将检查从秒开始的峰值信号中的元素,以便为向左看的空间腾出空间。我们会一直检查第二个最后一个元素,以便为向右看提供空间。因此,我们实际上会检查N - 2
版本信号的峰值,其中N
是信号的长度。因此,当我们创建左移位信号时,我们提取信号的第一个元素,直到第三个最后一个元素。当我们创建右移位信号时,我们从第三个元素中提取直到最后一个元素。原始信号将删除其第一个和最后一个元素。
因此,通过这种方式检查峰值,我们将丢失数据的第一个和最后一个点,但这应该是合适的,因为在开始和结束时很可能不会出现任何峰值。之后,创建所有这些信号,只需使用逻辑索引来查看原始信号中的相应值(没有第一个和最后一个元素)是否大于其相应位置中的其他两个信号。
因此,假设您的信号存储在f
中,您将执行以下操作:
f1 = abs(f(2:end-1)); %// Original signal
f2 = abs(f(1:end-2)); %// Left shift
f3 = abs(f(3:end)); %// Right shift
idx = find(f1 > f2 & f1 > f3) + 1; %// Get the locations of where we find our peaks
idx
将包含峰值出现位置的索引位置。请记住,我们已开始在第二位置搜索峰值,因此您需要添加1 以适应此次转变。如果您想查找实际时间(或您的情况下的频率)值,您只需使用idx
索引用于生成信号并找到它们的时间(或频率)数组。因此,让我们使用一个人工案例,我生成一个0到3秒的正弦曲线,频率为1 Hz。因此:
t = 0 : 0.01 : 3;
f = sin(2*pi*t);
现在,如果我们用这个信号运行上面的代码,我们就会找到峰值的位置。然后,我们可以使用这些位置索引到t
和f
,并绘制信号以及我们检测到峰值的位置。因此:
plot(t, f, t(idx), f(idx), 'r.')
这就是我得到的:
请记住,这是检测峰值的一种非常简单的方法,但这基本上是在findpeaks
中完成的。如果您使用上面的代码,它基本上会找到所有峰值。因此,代码会在上图中找到数十个峰值,因为您的频谱中存在局部最大值。您可能想要确定强峰的位置。人们通常做的是使用阈值来表示峰值在决定是否为有效峰值之前应该有多大。因此,您可以强制执行阈值,并执行以下操作:
thresh = ... ; %// Define threshold here
idx = find(f1 > f2 & f1 > f3 & f1 > thresh) + 1; %// Get the locations of where we find our peaks
在您的图表中,您可能需要设置此值,以便找到幅度大于10的任何峰值。
findpeaks
还有很多其他的事情,例如滤除嘈杂的峰值和其他一些强有力的措施。如果要使用findpeaks
,则需要确保安装信号包。您只需使用Octave命令提示符中的pkg install
并安装signal
包即可。具体来说,试试这个:
pkg install -forge signal
安装signal
软件包后,您可以执行以下操作将其加载到Octave环境中:
pkg load signal
如果必须安装依赖项,它会在您尝试安装signal
软件包时告诉您。有关详细信息,请查看此链接:https://www.gnu.org/software/octave/doc/interpreter/Installing-and-Removing-Packages.html
mkoctfile
代表制作/编译Octave文件。如果您没有mkoctfile
,请确保安装了最新版本的Octave。我建议你做的事情是简单安装Homebrew或MacPorts并以这种方式获得Octave。安装后,您应该能够mkoctfile
正常工作。但是,如果仍然不能,则可能需要安装兼容的编译器。简单的方法是从Xcode安装Command Line Developer工具。转到to this link,然后转到其他工具。
答案 1 :(得分:2)
您可以使用八度信号包中的findpeaks函数:
http://octave.sourceforge.net/signal/function/findpeaks.html