Реализация окна Ханна - PullRequest
       70

Реализация окна Ханна

7 голосов
/ 24 августа 2010

Я беру блоки входящих данных и пропускаю их через fftw, чтобы получить спектральную информацию. Кажется, все работает, но я думаю, что у меня возникают проблемы с алиасами.

Я пытался понять, как реализовать окно Hann в моих блоках данных. Google подвел меня для примеров. Любые идеи или ссылки, на которые я должен смотреть?

double dataIn[2048] > /* windowing here? */ > FFT > double freqBins[2048]

Обновление

Спасибо Оли за указание на проблему, которую я на самом деле пытаюсь решить, это спектральную утечку, а НЕ наложение имен ...

Ответы [ 6 ]

16 голосов
/ 24 августа 2010

http://en.wikipedia.org/wiki/Hann_function. Реализация следует из определения довольно просто. Просто используйте функцию w(n) в качестве множителя, переберите все ваши сэмплы (меняя n по ходу), и все.

for (int i = 0; i < 2048; i++) {
    double multiplier = 0.5 * (1 - cos(2*PI*i/2047));
    dataOut[i] = multiplier * dataIn[i];
}
4 голосов
/ 22 марта 2017

Почему бы не использовать реализацию окна Hann в Math.NET?

double[] hannDoubles = MathNet.Numerics.Window.HannPeriodic(dataIn.Length);
for (int i = 0; i < dataIn.Length; i++)
{
    dataOut[i] = hannDoubles[i] * dataIn[i];
}

Находится здесь: https://numerics.mathdotnet.com/api/MathNet.Numerics/Window.htm

2 голосов
/ 25 июля 2014

Полная функция, эквивалентная MATLAB hanning.m, находится здесь здесь :

/*  function w = hanning(varargin)
%   HANNING   Hanning window.
%   HANNING(N) returns the N-point symmetric Hanning window in a column
%   vector.  Note that the first and last zero-weighted window samples
%   are not included.
%
%   HANNING(N,'symmetric') returns the same result as HANNING(N).
%
%   HANNING(N,'periodic') returns the N-point periodic Hanning window,
%   and includes the first zero-weighted window sample.
%
%   NOTE: Use the HANN function to get a Hanning window which has the
%          first and last zero-weighted samples.ep
    itype = 1 --> periodic
    itype = 0 --> symmetric
    default itype=0 (symmetric)

    Copyright 1988-2004 The MathWorks, Inc.
%   $Revision: 1.11.4.3 $  $Date: 2007/12/14 15:05:04 $
*/

float *hanning(int N, short itype)
{
    int half, i, idx, n;
    float *w;

    w = (float*) calloc(N, sizeof(float));
    memset(w, 0, N*sizeof(float));

    if(itype==1)    //periodic function
        n = N-1;
    else
        n = N;

    if(n%2==0)
    {
        half = n/2;
        for(i=0; i<half; i++) //CALC_HANNING   Calculates Hanning window samples.
            w[i] = 0.5 * (1 - cos(2*PI*(i+1) / (n+1)));

        idx = half-1;
        for(i=half; i<n; i++) {
            w[i] = w[idx];
            idx--;
        }
    }
    else
    {
        half = (n+1)/2;
        for(i=0; i<half; i++) //CALC_HANNING   Calculates Hanning window samples.
            w[i] = 0.5 * (1 - cos(2*PI*(i+1) / (n+1)));

        idx = half-2;
        for(i=half; i<n; i++) {
            w[i] = w[idx];
            idx--;
        }
    }

    if(itype==1)    //periodic function
    {
        for(i=N-1; i>=1; i--)
            w[i] = w[i-1];
        w[0] = 0.0;
    }
    return(w);
}
2 голосов
/ 24 августа 2010

Не ответ на ваш вопрос, но в стороне от вашей проблемы.Работа с окнами помогает решить проблемы спектральной утечки , а не проблемы сглаживания .

Эффекты спектральной утечки возникают, когда частотные компоненты вашего сигнала не являются точными целыми подмножками вашегочастота дискретизации.

Если у вас есть псевдонимы, то вы в корне ошибаетесь.Вам нужно будет либо увеличить частоту дискретизации, либо вставить (лучший) фильтр сглаживания перед тем, как производить выборку.

2 голосов
/ 24 августа 2010

Википедия - твой друг: Окно Ханнинга

Наверняка, твой гугл придумал википедию ?! В любом случае просто создайте функцию, которая возвращает массив длины N с коэффициентами Хеннинга и умножьте этот массив на dataIn[2048].

1 голос
/ 04 августа 2017

Это нормально, но большинство людей, вероятно, хотят сделать это на тысячах массивов, заполненных данными. Вы можете заполнить массив только постоянными множителями один раз при инициализации вашей программы (используйте тот же массив размеров, который вы передаете в FFT), а затем просто умножить каждую точку в вашем реальном массиве на каждую точку в массиве множителей. Быстрее / дешевле, чем каждый раз повторять все эти косинусы.

...