QUOTE (tmtlib @ Nov 14 2011, 06:19)

Фазу приводят к диапазону -3.14...+3.14, пример в градусах: это что-то наподобие того, что 350 градусов привратится в -10 и т.д. Т.е. вектор (Im,Re) всегда в правом полукруге от -90 до 90 градусов.
Именно на этом этапе алгоритм перестанет работать, если нет перекрытия. Как показывает автор "матерьяльчика" в последней табличке (Pass 4) для отсутствия перекрытия.
http://www.dspdimension.com/admin/pitch-sh...g-using-the-ft/Для частот на границе бинов получаем 2 значения частоты для примерно одинаковых величин спектральной мощности, и только одно из них правильное. Поскольку максимум двух равных величин при реальных вычислениях определяется шумом, то в этом случае алгоритм будет выбирать правильное значение с вероятностью 0.5. Впрочем можно попытаться определить частоту другим методом по каждому из блоков отдельно и потом взять то значение которое ближе к этой оценке, но это уже как бы гибрид
QUOTE (tmtlib @ Nov 13 2011, 15:50)

2) Для каждого из 512 элемента считаем фазу. Если по простому, то фаза[i]:=ArcTan(Im[i] / Re[i]); Можно сделать получше, расписав разные случаи (если Re[i]=0 и т.д.)
3) храним фазы за предыдущий проход FFT и за текущий. m_fftLastPhase[i] - это старая фаза, а phase - это на самом деле phase[i], т.е. фаза[i] от текущего FFT. Заметил, что метод лучше работает если применить сглаживающее окно.
Для определения частоты вам не нужны все FFT_N значений фазы, поскольку только FFT_N/FFT_STEP значений фазы около максимума спектральной мощности правильные, а остальные искажены врэпингом на 2*pi (Pass 5). Более того в реальной ситуации присутствуют шумы и большинство из этих FFT_N/FFT_STEP правильных оценок (если их много) будут реально сильно зашумлены из-за очень быстрого падения уровня сигнала в бине при отклонении от центрального. Мы помним, что отклик бинов на синусоиду падает в соответствии с функцией спектрального окна, и в лучшем случае он будет спадать как синк или быстрее. В реальной ситуации только 2-4 центральных бина будут давать значимую оценку частоты, причем наименее искажены шумом будут только одна (если частота близко к центру бина) или две (если частота на границе бинов) оценки для центральных бинов (где максимум спектральной мощности). Остальные "утонут" под шумом
Все 512 значений могут представлять интерес только для визуализации "сонограм", поскольку они, в большинстве, шумоподобны.
Поэтому приведеный алгоритм "недоделаный" - мало того что он неэффективен, но он не содержит последнего шага, поскольку он генерирует FFT_N значений частоты из которых в лучшем случае (отсутствие шума) только FFT_N/FFT_STEP правильны и не сказано, как правильные выбрать из массива оценок, большинство из которых неправильны, см. таблички у автора
http://www.dspdimension.com/admin/pitch-sh...g-using-the-ft/По смыслу понятно, что выбирать нужно где-то возле максимума спектральной мощности
С учетом сказанного простейший алгоритм будет выглядеть так:
1) Берём FFT и получаем массивы амплитуд мнимой и действительной части по 512 элементов в каждом Im[0..511], Re[0..511].
2) Вычисляем энергию для каждого k E[k]=Re*Re+Im*Im
3) Находим максимум E[k] - пусть будет E() для kmax. Здесь вообще-то нужно проверять что kmax не прыгает. Если изменение kmax от фрейма к фрейму больше 1 по модулю - то это не синусоида, выход по ошибке
4) Для элементов kmax, kmax-1, kmax+1 считаем фазу. фаза[]:=ATAN2(Im[], Re[]); другие элементы на самом деле не нужны, в них отсутствует полезная информация
3) храним посчитаные фазы за предыдущий проход FFT и за текущий. m_fftLastPhase[i] - это старая фаза, а phase - это на самом деле phase[kmax], т.е. фаза[kmax] от текущего FFT. Поскольку kmax гарантировано не меняется больше чем на 1, то в любом случае значение фазы для kmax посчитаны и для предыдущего фрейма и есть в массиве
Если перекрытие FFT_N/FFT_STEP >2 то оценку можно немного улучшить если использовать не одно значение максимума, а два первых максимума и построить взвешенную оценку для частоты по этим двум оценкам.
Если главный максимальный бин k0=kmax, а следующий по энергии k1=arg max(E(kmax-1), E(kmax+1)), то можно построить оценку типа
(f(k1)*E(k1)+f(k0)*E(k0))/(E(k0)+E(k1)) с большим иммунитетом к шуму, главным образом для частот на границе бинов (поскольку в этом случае будет две равноценных оценки)
А так да, идея алгоритма на вскидку смотрится очень хорошо