Engineering School, 2nd year
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

210 lines
5.2 KiB

function outSamples = beatTrackingSEF(fileName)
// Spectrogramm filename
sgFile = fileName + '.sg';
if fileinfo(sgFile) == [] then
// Read samples
[x Fs nBits] = wavread(fileName);
// We keep only the first channel
x = x(1, :);
outSamples = x;
// Computes size
[nChannels nSamples] = size(x);
wlen = Fs / 100;
FFTSIZE = 512;
overlap = 2/3;
filter_order = 10; // must always be even
Nfen = wlen; // temporal analysis window length
Nover = round(Nfen*overlap); // overlap in samples
slen = 25e-3; // length in seconds for the widening
miniv = 1e-100;
minimo = 0.1;
medianSize = 150;
c = 0;
beatLimit = 0.5;
// calculate differentiator filter
m = calculate_differentiator(filter_order + 1);
// hop size in time
Nhop = Nfen - Nover;
Fns = Fs / Nhop;
// design of the low-pass smoothing IIR filter
alpha = 0.015;
betav = 0.075;
d = 5;
c = 1;
betav = betav * Fns;
alpha = alpha * Fns;
// SmootingFilter => low-pass smoothing IIR filter definition
s=%s;
num = [ d + c, -(c * exp(-1 / betav) + d * exp(-1 / alpha)) ];
den = [ 1, -(exp(-1 / alpha) + exp(-1 / betav)), exp(-(1 / alpha + 1 / betav)) ];
H_Smoothing = sum(num .* s^[size(num, 'c') - 1: -1 : 0]) / sum(den .* s^[size(den, 'c') - 1: -1 : 0]);
SmootingFilter = syslin('d', H_Smoothing);
// X_fm => spectral analysis
X_fm = specgram(Nover, FFTSIZE * 2, 'hn', x);
X_fm = X_fm( : , 1 : FFTSIZE); // we keep only one half of the spectrum
// G_fm1 => Smooting along the time axis
for i = [1 : FFTSIZE],
G_fm1(:, i) = abs(flts(abs(X_fm(:, i)'), SmootingFilter))';
end
// G_fm2 => log compression
G_fm2 = G_fm1;
G_fm2(G_fm2 == 0) = miniv;
G_fm2 = 20 * log10(G_fm2);
// First derivative
//H_m = [1, -1];
//for i = [1 : FFTSIZE],
// der1(:, i) = abs(convol(H_m, G_fm2( : , i)'))';
//end
H_der = sum(m .* s^[size(m, 'c') - 1: -1 : 0]);
derFilter = syslin('d', s * H_der / s);
for i = [1 : FFTSIZE],
der1( : , i) = abs(flts(G_fm2( : , i)', derFilter))';
end
ds = size(G_fm2, 'r') - size(der1, 'r');
der1 = [zeros(ds, FFTSIZE) ; der1];
der1(der1 < minimo) = 0; // remove small differentiation debris
// eliminate (?) differentiator filter transient
//der1 = der1($ - size(G_fm2, 'r') + 1 : $, : );
// Frequency integration
for i = [1 : size(der1, 'r')],
v_k(1, i) = sum(der1(i, : ));
end
//H_w = window('hn', 2 * slen * Fs + 1);
H_w = window('hn', 51);
H_w = H_w(26 : $);
wv_k = convol(H_w, v_k);
wv_k = wv_k(1 : size(v_k, 'c'));
bn = (~isinf(wv_k)) | (~isnan(wv_k)); // eliminate NaN and Inf if they exist
index = find(bn == %t);
wv_k2 = zeros(size(wv_k));
wv_k2(index) = wv_k(index);
g_k = zeros(1, size(wv_k2, 'c') + medianSize)
g_k(1, medianSize / 2 + 1 : $ - medianSize / 2) = wv_k2;
t_k = zeros(wv_k2);
for i = [medianSize / 2 + 1 : size(g_k, 'c') - medianSize / 2],
t_k(1, i - medianSize / 2) = c * median(g_k(1, i - medianSize / 2 : i + medianSize / 2));
end
p_k = wv_k2 - t_k;
p_k(p_k < 0) = 0;
// normalization
//E_fk = p_k / max(p_k);
//win_size = 150;
//E_fk = [p_k zeros(1, win_size)];
//for i = [1 : size(p_k, 'c')],
// E_fk(1, i) = E_fk(1, i) / max(E_fk(1, i : i + win_size - 1));
//end
//E_fk = E_fk(1 : size(p_k, 'c'));
E_fk = p_k;
win_size = 150;
m = [zeros(1, win_size / 2) p_k zeros(1, win_size / 2)];
for i = [1 : size(p_k, 'c')],
m(1, i) = mean(m(1, i : i + win_size - 1));
end
m = m(win_size / 2 + 1 : win_size / 2 + size(p_k, 'c'));
// Scales
ts = [0 : size(x, 'c') - 1] / Fs;
f = [0 : FFTSIZE - 1] / (2 * FFTSIZE);
t = [1 : size(X_fm, 'r')];
te = [0 : size(E_fk, 'c') - 1] * (size(x, 'c') / Fs) / size(E_fk, 'c');
tb = round(te * Fs) + 1;
// Beat detection
beatIdx = 1;
beat = [];
for i = [1 : size(E_fk, 'c') - 1],
if (E_fk(i) < m(i)) & (E_fk(i + 1) > m(i)) then
// draws a line
beat(beatIdx) = te(i);
beatIdx = beatIdx + 1;
// put a beep (4000 Hz) in the signal
for j = [0 : Fs / 100],
outSamples(tb(i) + j) = .9 * sin(2 * %pi * (j * Fs / 4000));
end
end
end
save(sgFile, X_fm, beat, beatIdx, E_fk, m, G_fm2, der1, te, ts, f, outSamples, x);
else
load(sgFile, 'X_fm', 'beat', 'beatIdx', 'E_fk', 'm', 'G_fm2', 'der1', 'te', 'ts', 'f', 'outSamples', 'x');
end
if input('graph [y/n]', 'string') <> 'y' then
return;
end
// Inversed gray colormap
cm = hotcolormap(128);
//cm = cm($:-1:1,:);
// Graph plotting
scf(0);
subplot(2, 1, 1);
xtitle('Samples of ' + fileName, 'time (s)', 'amplitude');
subplot(2, 1, 2);
xtitle('SEF of ' + fileName, 'time (s)', 'magnitude');
subplot(2, 1, 1);
plot2d(ts, x, style=color('grey'));
for i = [1 : beatIdx - 1],
xsegs([beat(i) beat(i)], [.2 -.2], color('red'));
end
subplot(2, 1, 2);
//plot2d([te(1) te($)], [beatLimit beatLimit], style=color('blue'));
plot2d(te, E_fk, style=color('red'));
plot2d(te, m, style=color('blue'));
if input('spectrogram [y/n]', 'string') <> 'y' then
return;
end
scf(1);
subplot(2, 1, 1);
xtitle('Smoothed & log compressed spectrogram of ' + fileName, 'time (s)', 'frequency');
xset("colormap", cm);
subplot(2, 1, 2);
xtitle('Derivated spectrogram of ' + fileName, 'time (s)', 'frequency');
xset("colormap", cm);
subplot(2, 1, 1);
grayplot(te(10 : $ - 10), f, G_fm2(10 : $ - 10, : ));
subplot(2, 1, 2);
grayplot(te(10 : $ - 10), f, der1(10 : $ - 10, : ));