谐波幅度大于基波幅度

Posted

技术标签:

【中文标题】谐波幅度大于基波幅度【英文标题】:A harmonic's amplitude is greater than the fundamental one 【发布时间】:2013-10-03 10:43:26 【问题描述】:

我正在编写一个 MATLAB 代码来检测钢琴录音中的频率。

我使用了我使用键盘录制的 C 音阶音频文件 (C4 D4 E4 F4 G4 A4 B4 C5)

当我简单地执行 FFT(不闯入窗口)时,基频具有更高的幅度,这非常好。

但是为了更准确,我做了以下步骤 1. 使用高斯边缘检测滤波器对我的音频信号进行快速卷积以获得包络。 2. 实现了一个峰值检测算法来找到音符的起始点。 3. 取每个 Onset,我对每个 Onset 进行 FFT,从而得到每个音符的 FFT。 但是,当我对上述音频文件执行此操作时,我得到了错误的结果,有时谐波的幅度比第一个更高。

clear all;
clear max;
clc;

%% create 5s sample at 10kHz with tone from 1s to 2s
FS = 10000; % 10kHz
N=5*FS;
song =  randn(N,2)/10;
song(FS:2*FS,:)=10*repmat(sin(261*pi*2*(0:FS)/FS)',1,2)+song(FS:2*FS,:);

P = 2000;   
t=0:1/FS:(N-1)/FS;                  % define time period


song = sum(song,2);                        
song=abs(song);


%----------------------Finding the envelope of the signal-----------------%
% Gaussian Filter
x = linspace( -1, 1, P);                      % create a vector of P values between -1 and 1 inclusive
sigma = 0.335;                                % standard deviation used in Gaussian formula
myFilter = -x .* exp( -(x.^2)/(2*sigma.^2));  % compute first derivative, but leave constants out
myFilter = myFilter / sum( abs( myFilter ) ); % normalize


% fft convolution
myFilter = myFilter(:);                         % create a column vector
song(length(song)+length(myFilter)-1) = 0;      %zero pad song
myFilter(length(song)) = 0;                     %zero pad myFilter
edges =ifft(fft(song).*fft(myFilter));

tedges=edges(P:N+P-1);                      % shift by P/2 so peaks line up w/ edges
tedges=tedges/max(abs(tedges));                 % normalize

%---------------------------Onset Detection-------------------------------%
% This section does the peak picking algorithm
max_col = maxtab(:,1);
peaks_det = max_col/FS;
No_of_peaks = length(peaks_det);

%---------------------------Performing FFT--------------------------------

    song_seg = song(max_col(1):max_col(2)-1);
    L = length(song_seg);    
    NFFT = 2^nextpow2(L); % Next power of 2 from length of y

    seg_fft = fft(song_seg,NFFT);%/L;

    f = FS/2*linspace(0,1,NFFT/2+1);
    seg_fft2 = 2*abs(seg_fft(1:NFFT/2+1));
    L5 = length(song_seg);

    fmin = 60;
    fmax = 1000;
    region_of_interest = fmax>f & f>fmin;
    froi = f(region_of_interest);

    [p_max,loc] = max(seg_fft2(region_of_interest));

    % index into froi to find the frequency of the peaks
    p_max;


     f_p_max = froi(loc);

     [points, locatn] = findpeaks(seg_fft2(region_of_interest));        
     aboveMax = points > 0.4*p_max;

        if any(aboveMax)
            peak_points = points(aboveMax)
        f_peak = froi(locatn(aboveMax))

    end

 end

我在这里做错了什么???这里真的很需要帮助......

可以看出,D4的f0根本没有被检测到,而C4和E4的f0相比于它们的谐波,幅度较小

【问题讨论】:

我有两点意见。 1)你确定你正确使用了fft(看看fftshift的帮助),因为我相信你的频率计算是错误的。 2)您能否将代码精简到最基本的部分并提供示例数据,以便我们重现您的麻烦。还要提供你得到的输出和你应该得到的输出。 你指的是用来找信封的 fft ive 吗?? 不,我说的是你是如何绘制它的。但我看到你使用了帮助中的代码。您能否进一步压缩代码 - 比如说删除所有峰值检测,只需硬编码一个音符并删除所有绘图,这样就只剩下代码来生成表格的第一行了。 一行看起来很可疑:f = FS/2*linspace(0,1,NFFT/2+1); - 你确定这些是音符的正确频率空间吗? 我希望代码足够简洁。嗯,是。这是MATLAB帮助中提到的代码.....:/ 【参考方案1】:

使用 FFT,我发现了频域中的峰值。如果我们非常幸运,这可能对应于基本注释。否则,这可能是一般的 1 次谐波。

我不知道峰值是在基波还是在 1 次谐波。 我的工作就是找出这个。

我做的是……

    我有一个“max_user_freq”变量,它对应于 FFT 中出现峰值的频率。 注意:“Spectrum[]”是幅度规格变量。

    我计算频谱的最大值[m],其中 m 范围从频率 注意:频率必须缩放到 m。就我而言:m=freq*length(fraw)/22050;

    完整代码:

    f1=(max_freq/2)-0.05*max_freq;

    f1=圆形(f1); f2=(max_freq/2)+0.05*max_freq; f2=圆形(f2); 米=[]; spec_index_fund_note=m; spec_fund_max=spectrum(f1*length(fraw)/22050;

    对于 m=f1:f2 spec_index_fund_note(m)=m*length(fraw)/22050; 如果(频谱(spec_index_fund_note(m))>spec_fund_max) spec_fund_max=spectrum(spec_index_fund_note(m)); 结束

    结束

    if((谱(max_freq_index)-specval_fund_note)/谱(max_freq_index)>) display('1次谐波超过基波,重试'); 结束

【讨论】:

【参考方案2】:

过滤 abs(song) 可以很好地找到包络,但是在找到峰值时,您需要计算 fft 原始信号(没有“abs”)。

要查看差异,请尝试:

clear;
FS = 10000;
s=sin(261*pi*2*(0:FS)/FS);
NFFT = 2^nextpow2(length(s));
S1=fft(s,NFFT);
S2=fft(abs(s),NFFT);
f = FS/2*linspace(0,1,NFFT/2+1);
plot(f,abs(S1(1:NFFT/2+1))); % peak near 261
plot(f,abs(S2(1:NFFT/2+1))); % peak near 522

【讨论】:

谢谢.. 我看到了不同之处。但真正奇怪的事情发生了。所有谐波更大的音符现在都具有更大的基频(完美),但所有早期 DID 具有更高基频的音符现在都具有稍大的二次谐波!!!!你知道为什么会这样吗???【参考方案3】:

我在 matlab 中编写代码并开发对音乐家有用的应用程序。我自己是一名音乐家。所以,我知道运行我的算法的音乐理论。 我在matlab中开发了算法,告诉你你弹钢琴的确切音阶。看看

MATLAB MUSICIAN's BLOG

【讨论】:

以上是关于谐波幅度大于基波幅度的主要内容,如果未能解决你的问题,请参考以下文章

音频信号的基波谐波

声音加法合成 - 任何谐波幅度

信号初级谐波

周期信号频谱的三个特点

利用python和jupyter notebook交互式小部件生成方波,可以实时调节谐波个数和基波频率

求matlab周期三角波信号频谱分析的代码,能画出三角波信号、幅度谱和相位谱。