使用 LMS 算法估计瞬时频率

信息处理 离散信号 估计 自适应滤波器 线性预测 lms
2022-01-23 12:29:00

我希望有人可以帮助我解决以下问题:

我想估计一个声音文件的频率,该声音文件由具有不同频率的正弦曲线和加性白噪声组成:

x[n]=sin(Θ[n]n)+w[n]

现在我使用 LMS 算法实现了一个线性预测器来估计 AR 过程的参数(如 Haykin:自适应滤波器理论中所述)。

x(n)=k=1Mak(n)x(nk)+v(n)

w^(n+1)=w^(n)+μx(nk)fM(n)

fM(n)=u(n)k=1Mw^(n)x(nk)是预测误差。

由此我计算时变频率函数: F(ω,n)=1|1k=1Mw^k(n)ejωk|2

如下所示:

在此处输入图像描述

现在我通过搜索每个时间样本 n 的 F 的最大值来计算瞬时频率。但问题是,它非常嘈杂,并且在转换时频率过冲很多:

在此处输入图像描述

现在我想问是否有任何方法可以优化计算,我会很高兴有一些想法。

1个回答

我没有声称这是最佳的,我也不认为你提到的过冲一定是不正确的。没有任何东西可以瞬间改变,因此当您从一个正弦曲线过渡到下一个正弦曲线时,您一定会看到一定范围的频率。

我对最小二乘估计的第一个想法是在展开阶段使用迭代器。由于频率是相位的导数,如果我们将频率积分,我们将得到相位。就线性系统而言,这看起来像

Ax=ϕ,

在哪里

A=[100110111]

是展开阶段要获得展开的相位,您需要通过 I/Q 解调过程对实值信号进行分析。的最小二乘解将是频率的估计。ϕx

我拼凑的八度音阶代码如下。由于问题很小,我明确地形成了,但对于更大的问题,您可能希望使用类似的函数句柄来解决系统问题。我还在频率上运行了一个移动平均线,这样从一个到另一个的跳跃会更平滑一些,这应该会减少过冲。Alsqr()

在此处输入图像描述

randn( 'seed', 71924 );
rand( 'seed', 7192 );

fmin = 100;
fmax = 1e3;
fs = 1.2 * 2 * fmax;
T = 5;
t = ( 0 : 1/fs : T ).';
Ns = length(t);

% Define some noise.
snr = 10.^( 50 / 10 );
n = sqrt( 1/snr ) * randn( Ns, 1 );

% Choose some random frequecies.
Nf = 50;
f = fmin + ( fmax - fmin ) * rand(Nf,1);

% Choose the intervals.
tmp = randperm( Ns );
inds = sort( tmp( 1 : Nf - 1 ) );

% Define the frequency for each sample.
fvec = zeros( Ns, 1 );
last = 1;
for ii = 1 : length(inds)
  fvec( last : inds(ii) ) = f(ii);
  last = inds(ii) + 1;
end
fvec(last+1:end) = f(end);

% Moving average over the frequencies to prevent
% bandwidth when the frequency changes.
fvec = conv( fvec, 1/3 * ones(3,1), 'same' );

% Define the sinusoid with time-varying frequency.
% We do so in a way that makes it phase continuous.
% We also add the noise here.
x = cos( 2*pi * cumsum( fvec ) ./ fs ) + n;

% The frequency sample locations.
df = fs / Ns;
floc = ( 0 : df : ( fs - df ) ) - ( fs - mod( Ns, 2 ) * df ) / 2;

% Shift the center of the positive half of the
% spectrum to zero.
y = x .* exp( -1j * 2*pi * t * fs/4 );

% Design a half-band filter.
Ntap = 51;
N = Ntap - 1;
p = ( -N/2 : N/2 ).';
s = sin( p * pi/2 ) ./ ( p * pi + eps );
s( N/2 + 1 )= 1/2;          
win = kaiser( Ntap, 6 );
h = s .* win;

% Form an analytic signal.
z = conv( y, h, 'same' ) .* exp( 1j * 2*pi * t * fs/4 );

% The unwrapped angle.
phi = unwrap( angle( z ) );

% Use an intergrator to get a least-squares
% estimate of the phase.
A = tril( ones( Ns, Ns ) );
fest = ( A \ phi ) * fs / (2*pi);

figure();
hold on;
plot( t, fest );
plot( t, fvec );
legend( 'Estimated', 'Truth' );
xlabel( 'Time (s)' );
ylabel( 'Frequency (Hz)' );