
- Recursive Time-Frequency Reassignment published in IEEE Transactions on Signal Processing
Today I proudly present the original manuscript from my 2009 IEEE Transactions on Signal Processing publication. It can be downloaded by clicking the article thumbnail. I also share a corresponding MATLAB implementation in the code snippets below.
The functions rspec() and rrspec() in rspec.m and rrspec.m computes the recursive Short-Time Fourier Transform (STFT) and the reassigned version, respectively. A usage example is included in the file usage_ex.m: it shows how to apply the functions on a linear chirp in the 40 to 80 Hz bandwidth.
Usage Example (usage_ex.m):
% % Usage example for the functions rspec() and rrspec() % This script can be found online at http://8-void.com % % Author: Geir Kjetil Nilsen (geir.kjetil.nilsen@gmail.com) 2008 % fs = 1000; t=0:0.001:1; s=chirp(t,40,.5,60); s = [zeros(1,100) s zeros(1,100)]; rtfr = rspec(s, fs, 4, 1:.5:100); rrtfr = rrspec(s, fs, 4, 1:.5:100); subplot(2,1,1), imagesc(rtfr), subplot(2,1,2), imagesc(rrtfr);
Recursive STFT spectrogram (rspec.m):
function rtfr = rspec(x,fs,k,f);
% rtfr = rtfr(x,fs,k,f) computes the recursive STFT spectrogram with
% the constants defined
% x - input signal
% fs - sampling frequency
% k - order
% f - frequency vector
%
% Equations referred to are found in the journal paper "Recursive
% Time-Frequency Reassignment" available in IEEE's Transactions on Signal
% Processing. This script can be found online at http://8-void.com
%
% Author: Geir Kjetil Nilsen (geir.kjetil.nilsen@gmail.com) 2009
% Updated December, 2012.
%
if k < 2 || k > 5
sprintf('k must be in the range 2 <= k <= 5')
rtfr = 0;
return;
end;
T = 1/fs;
nf = length(f);
N = length(x);
rtfr = zeros(nf, N);
Omega = f(2)-f(1); % frequency spacing
% Balance time-frequency resolution in number of samples, eq. 16
sigma_p = (sqrt(Omega)*factorial(k-1))/(sqrt(2*pi*T)*(k-1)^(k-1)*exp(-(k-1)));
coef = cell(10,1);
for j = 1:nf;
omega_p = 2*pi*f(j);
p = -sigma_p + i*omega_p; % eq. 6
a = exp(p*T);
% Coefficients from eq. 14, k = 2...5
% Numerator coefficients in coef{i}, i = 2n+1, n = 1,2,3,4
% Demoninator coefficients in coef{i}, i = 2n, n = 1,2,3,4,5
coef{3} = sigma_p^2*T^2*[0 a];
coef{4} = [1 -2*a a.^2];
coef{5} = sigma_p^3*T^3*[0 1/2*a 1/2*a.^2];
coef{6} = [1 -3*a 3*a.^2 -a.^3];
coef{7} = sigma_p^4*T^4*[0 1/6*a 2/3*a.^2 1/6*a.^3];
coef{8} = [1 -4*a 6*a.^2 -4*a.^3 a.^4];
coef{9} = sigma_p^5*T^5*[0 1/24*a 11/24*a.^2 11/24*a.^3 1/24*a.^4];
coef{10}= [1 -5*a 10*a.^2 -10*a.^3 5*a.^4 -a.^5];
rtfr(nf-j+1,:) = filter(coef{2*k-1},coef{2*k},x); % Eq. 16
end;
rtfr = abs(rtfr);
Recursive Reassigned STFT spectrogram (rrspec.m):
function [rrtfr coef dcoef tcoef] = rrspec(x,fs,k,f);
% rrtfr = rrspec(x,fs,k,f) computes the recursive reassigned STFT spectrogram with
% the constants defined
% x - input signal
% fs - sampling frequency
% k - order
% f - frequency vector
%
% Equations referred to are found in the journal paper "Recursive
% Time-Frequency Reassignment" available in IEEE's Transactions on Signal
% Processing. This script can be found online at http://8-void.com
%
% Author: Geir Kjetil Nilsen (geir.kjetil.nilsen@gmail.com) 2009
% Updated December, 2012.
%
if k < 2 || k > 4
sprintf('k must be in the range 2 <= k <= 4')
rrtfr = 0;
return;
end;
T = 1/fs;
nf = length(f);
N = length(x);
w = zeros(nf, N);
w_d = zeros(nf, N);
w_t = zeros(nf, N);
rrtfr = zeros(nf,N);
Omega = f(2)-f(1);
% Balance time-frequency resolution in number of samples, eq. 16
sigma_p = (sqrt(Omega)*factorial(k-1))/(sqrt(2*pi*T)*(k-1)^(k-1)*exp(-(k-1)));
coef = cell(2,1);
dcoef = cell(2,1);
tcoef = cell(2,1);
for j = 1:nf;
omega_p = 2*pi*f(j);
p = -sigma_p + i*omega_p; % eq. 6
a = exp(p*T);
% Coefficients from eq. 14, k = 2...5
% Numerator coefficients in coef{i}, i = 2n+1, n = 1,2,3,4
% Demoninator coefficients in coef{i}, i = 2n, n = 2,3,4,5
coef{3} = sigma_p^2*T^2*[0 a];
coef{4} = [1 -2*a a.^2];
coef{5} = sigma_p^3*T^3*[0 1/2*a 1/2*a.^2];
coef{6} = [1 -3*a 3*a.^2 -a.^3];
coef{7} = sigma_p^4*T^4*[0 1/6*a 2/3*a.^2 1/6*a.^3];
coef{8} = [1 -4*a 6*a.^2 -4*a.^3 a.^4];
coef{9} = sigma_p^5*T^5*[0 1/24*a 11/24*a.^2 11/24*a.^3 1/24*a.^4];
coef{10}= [1 -5*a 10*a.^2 -10*a.^3 5*a.^4 -a.^5];
% Coefficients from eq. 23, k = 2...4
dcoef{3} = sigma_p.^2*T*[1 -a*(1 - p*T)];
dcoef{4} = coef{4};
dcoef{5} = sigma_p.^3*T.^2*[0 a/2*(2 + p*T) -a.^2/2*(2 - p*T)];
dcoef{6} = coef{6};
dcoef{7} = sigma_p.^4*T.^3*[0 a/6*(3 + p*T) a.^2*2/3*p*T -a.^3/6*(3 - p*T)];
dcoef{8} = coef{8};
% Coefficients from eq. 24, k = 2...4
tcoef{3} = 2/sigma_p*coef{5};
tcoef{4} = coef{6};
tcoef{5} = 3/sigma_p*coef{7};
tcoef{6} = coef{8};
tcoef{7} = 4/sigma_p*coef{9};
tcoef{8} = coef{10};
w(j,:) = filter( coef{2*k-1}, coef{2*k},x); % Eq. 16
w_d(j,:) = filter(dcoef{2*k-1}, dcoef{2*k},x); % Freq. reass. coeffs with eq. 16
w_t(j,:) = filter(tcoef{2*k-1}, tcoef{2*k},x); % Time reass. coeffs with eq. 16
end;
rtfr = abs(w);
step = f(2)-f(1);
f0 = f(1);
% eq. 27
for n = 1:N;
for f = 1:nf;
that = n - round(1/T*real(w_t(f,n)./w(f,n))); % eq. 26
that = min(max(that, 1),N); % edge
fhat = round(1/step*imag(w_d(f,n)./w(f,n))/2.0/pi - 1/step*(f0)); % eq. 25
fhat = mod(fhat, nf) + 1; % edge
rrtfr(nf - fhat + 1,that) = rrtfr(nf - fhat + 1,that) + rtfr(f,n);
end;
end;
