gpt4 book ai didi

matlab - 如何找到周期性声音信号的频率?

转载 作者:行者123 更新时间:2023-12-02 22:47:05 35 4
gpt4 key购买 nike

我正在研究具有明显规则模式的步行模式的声音信号:

Sound of a walking person, X in seconds, Y in sound signal

然后我想我可以使用 FFT 函数获得步行频率(图像中大约 1.7Hz):

    x = walk_5; % Walking sound with a size of 711680x2 double
Fs = 48000; % sound frquency
L=length(x);

t=(1:L)/Fs; %time base
plot(t,x);
figure;

NFFT=2^nextpow2(L);
X=fft(x,NFFT);
Px=X.*conj(X)/(NFFT*L); %Power of each freq components
fVals=Fs*(0:NFFT/2-1)/NFFT;
plot(fVals,Px(1:NFFT/2),'b','LineSmoothing','on','LineWidth',1);
title('One Sided Power Spectral Density');
xlabel('Frequency (Hz)')
ylabel('PSD');

但它并没有给我我的预期:

FFT结果:

FFT result

缩放图像有很多噪音:
zoom image has lots of noises

1.7Hz附近没有信息
enter image description here

这是来自日志域的图表,使用
    semilogy(fVals,Px(1:NFFT));

虽然它非常对称:
enter image description here

我找不到我的代码有什么问题。您是否有任何解决方案可以轻松地从步行模式中提取 1.7Hz?

这是mat中音频文件的链接
https://www.dropbox.com/s/craof8qkz9n5dr1/walk_sound.mat?dl=0

非常感谢你!

最佳答案

我建议您忘记 DFT 方法,因为由于多种原因,您的信号不适合这种类型的分析。即使通过查看您感兴趣的频率范围内的频谱,也没有简单的方法来估计峰值:

enter image description here

当然,您可以尝试使用 PSD/STFT 和其他时髦的方法,但这有点过头了。对于这项任务,我可以想到两种相当简单的方法。

第一个是简单地基于自相关函数。

  • 计算 ACF
  • 定义它们之间的最小距离。由于您知道预期频率约为 1.7Hz,因此它对应于 0.58s。让我们将其设为 0.5 秒作为最小距离。
  • 计算找到的峰之间的平均距离。

  • 这给了我一个大约 1.72 Hz 的频率。

    enter image description here

    第二种方法是基于对信号的观察已经有一些周期性的峰值。因此,我们可以简单地使用 findpeaks 搜索它们。功能。
  • 以与之前相同的方式定义最小峰值距离。
  • 定义最小峰高。例如最大峰值的 10%。
  • 获取平均差异。

  • 这给了我 1.7 Hz 的平均频率。

    enter image description here

    简单快速的方法。显然有一些可以改进的地方,例如:
  • 精炼阈值
  • 找到正峰值和负峰值
  • 处理一些丢失的峰值,即由于低幅度

  • 无论如何,这应该让你开始,而不是被蹩脚的 FFT 和懒惰的 semilogx 所困。

    代码片段:
    load walk_sound

    fs = 48000;
    dt = 1/fs;

    x = walk_5(:,1);
    x = x - mean(x);
    N = length(x);
    t = 0:dt:(N-1)*dt;

    % FFT based
    win = hamming(N);
    X = abs(fft(x.*win));
    X = 2*X(1:N/2+1)/sum(win);
    X = 20*log10(X/max(abs(X)));
    f = 0:fs/N:fs/2;

    subplot(2,1,1)
    plot(t, x)
    grid on
    xlabel('t [s]')
    ylabel('A')
    title('Time domain signal')

    subplot(2,1,2)
    plot(f, X)
    grid on
    xlabel('f [Hz]')
    ylabel('A [dB]')
    title('Signal Spectrum')

    % Autocorrelation
    [ac, lag] = xcorr(x);
    min_dist = ceil(0.5*fs);
    [pks, loc] = findpeaks(ac, 'MinPeakDistance', min_dist);

    % Average distance/frequency
    avg_dt = mean(gradient(loc))*dt;
    avg_f = 1/avg_dt;

    figure
    plot(lag*dt, ac);
    hold on
    grid on
    plot(lag(loc)*dt, pks, 'xr')
    title(sprintf('ACF - Average frequency: %.2f Hz', avg_f))


    % Simple peak finding in time domain
    [pkst, loct] = findpeaks(x, 'MinPeakDistance', min_dist, ...
    'MinPeakHeight', 0.1*max(x));

    avg_dt2 = mean(gradient(loct))*dt;
    avg_f2 = 1/avg_dt2;

    figure
    plot(t, x)
    grid on
    hold on
    plot(loct*dt, pkst, 'xr')
    xlabel('t [s]')
    ylabel('A')
    title(sprintf('Peak search in time domain - Average frequency: %.2f Hz', avg_f2))

    关于matlab - 如何找到周期性声音信号的频率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32370936/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com