找到信号中的主音

信息处理 fft matlab 离散信号
2022-02-10 21:51:37

我以 48k 的采样率获得 256个样本,并被要求找出主音的频率和最大音的幅度。绘制时数据如下所示:

n

我假设我必须使用 FFT 变换来做到这一点。我在matlab中试过这个:

Fs = 48000;
x = dataSet; % 256 samples data set
xdft = fft(x);
maxAmp = max(abs(xdft));
%Not sure how I can grab the tones here
freq = 0:Fs / length(x):Fs/2;

不太确定如何进行,有什么想法吗?

3个回答

我认为您无法正确构建频率轴。一旦你这样做了,你就可以做一个简单的峰值选择。我已经为您重新编写了代码:

Fs = 48000;
x = dataSet;            % 256 samples data set
fftLength = length(x);  % Always make sure to be at least as long as your data. 
xdft = fft(x,fftLength);
maxAmp = max(abs(xdft));

freq = [0:fftLength-1].*(Fs/fftLength); % This is your total freq-axis
freqsYouCareAbout = freq(freq < Fs/2);  % You only care about either the pos or neg 
                                        % frequencies, since they are redundant for
                                        % a real signal.

xdftYouCareAbout = abs(xdft(1:round(fftLength/2))); % Take the absolute magnitude.

[maxVal, index] = max(xdftYouCareAbout); % maxVal is your (un-normalized) maximum amplitude

maxFreq = freqsYouCareAbout(index); % This is the frequency of your dominant signal. 

您是否尝试过绘制 的大小xdft您应该能够看到峰在哪里。要找到与任何峰值相关的频率,请找到峰值幅度所在的索引,并使用它从像你的数组中提取频率freq,除非你应该从 0 到Fswith创建它

freq = 0:Fs/(length(xdft)-1):Fs;

因为 DFT 从 0 运行到采样频率。如果您希望它在 range-Fs/2:Fs/2中,您可以使用 对其重新排序fftshift,但我会让您阅读该功能。您还应该发现频谱是对称的,因此您将获得最强频率的两个峰值(相同高度)。当然,您可以轻松地删除一半的频谱进行处理。

好的,这里有几个问题:

  1. 您需要去趋势:-) 数据以删除非零均值。

    x = dataSet - mean(dataSet);

    这是因为最大的分量(当我进行 FFT 时)是 DC 偏移。

  2. 然后,您可以使用任意数量的技术来找到下一个最高值。前面的答案很好。这个链接有一个我在很多个月前做过的实现,叫做discperiod.

    omega1 = discperiod(dataSet);

  3. 然而,这只会在频谱中找到下一个最高峰。因此,您需要删除在步骤 2 中找到的频率分量。要以统计上合理的方式执行此操作,您需要找到该分量的幅度和相位。一种方法是解决最小二乘问题:

    minA,ϕt=0T1|x[t]Acos(omega1t+ϕ)|2
    也就是说,最小化Aϕ. 这可以很简单地通过找到 FFT 系数来完成omega1朱利叶斯·O·史密斯三世在这里得出了这一结论。 那么平均校正是

    x_res = x - A*cos(omega*[0:T-1]'+phi);

  4. 试图从中找到下一个最高峰x_res可能会出现问题:下一个最高峰可能位于第一个峰的“边缘”(刚刚被移除)。这是因为该discperiod函数将可能的频率量化为 FFT bin 频率。解决此问题的一种简单方法是选择 Mohammad 所称fftLength的与所需精度一样大的值。这可能比信号的长度大几倍。


没有更多的时间!以后会尝试写更多。