И так, приемлемое решение нашлось.
Алгоритм:
1. Входной сигнал разбиваем на блоки длинной в несколько раз большей чем длинна самого длинного периода (я взял 5).
2. Считается автокорреляция блока.
3. Ищется первый максимум (кроме центрального). Расстояние этого максимума от центрального - искомый период.
4. Можно еще дополнительные меры предпринять, напрмер иногда второй максимум получается немного больше первого, такие вещи можно отфильтровать пытась сначала искать максимум там, где он ожидается (ранее вычисленный период), а только потом глобально. Можно делать перекрывающиеся блоки, и т.д.
Вот код на матлабе и результат его работы.
CODE
clear all
Fd = 44100;
data = wavread('~/guitar2.wav');
s = data';
l = 535 * 5; % Fd / 82 Hz = 535 (e string frequency).
zz(length(s)) = 0;
for i = 1:l:length(s)-l,
tt = xcorr(s(i:i+l));
[~, i1] = max(tt); % always at l/2
for j = i1:length(tt),
if tt(j+1) > tt(j), i2 = j; break; end; % Find first local minimum
end
[~, i3] = max(tt(i2:length(tt)));
zzv = (i2+i3)-i1;
for j = i:i+l, zz(j) = zzv; end;
end
figure; hold on; plot(s); plot(zz / 2000, 'r');
Сообщение отредактировал Taradov Alexander - Aug 24 2010, 18:42
Эскизы прикрепленных изображений