применение окна к аудиосэмплам - PullRequest
0 голосов
/ 13 января 2019

Использование arm_mult_f32 для умножения двух массивов дает неожиданные (мусорные) результаты.

Я читал о DSP. Я создаю коэффициенты Ханна для применения к выборочным данным PCM до БПФ.

Функция ханнинга взята из примера hann.m matlab, который я обнаружил, с той лишь разницей, что stm32f4 имеет только FPU с одинарной точностью, поэтому я использую uint32_t для полей данных, а не double.

сначала, определения.

FFT_LEN = 256;                   

float32_t FFTBuf[FFT_LEN * 2];   // data set twice the fft length as output 

                                 //symetrically repeated
float32_t FFTMagBuf[FFT_LEN];    //

float32_t * hann_window;
float32_t * hann_buff;
float32_t * hanning(uint32_t, uint8_t)

вызовите функцию Ханнинга для заполнения окна.

hann_window = hanning(FFT_LEN * 2, 2);    // creates a dynamic array and 
                                          //populates it with coeffs.


hann_buff = (float32_t *)calloc(FFT_LEN * 2, (sizeof(float32_t)));
memset(hann_buff, 0, FFT_LEN * 2 * sizeof(float32_t));   //intermediate 
                                                         //buffer



then when all pcm samples are read

arm_mult_f32(FFTBuf, &hann_window[0], &hann_buff[0], (FFT_LEN * 2)); // 

arm_cfft_f32(&arm_cfft_sR_f32_len256, &hann_buff[0], 0, 1);

arm_cmplx_mag_f32(&hann_buff[0], FFTMagBuf, FFT_LEN);

Функция Ханна выглядит следующим образом

float32_t *hanning(uint32_t N, uint8_t itype)
  {
    uint32_t half, i, idx, n;
    float32_t *w;

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

    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);
  }

С оконной функцией я получаю хорошие значения, я проверил код с синусоидальный сигнал 4 кГц, и он дает правильный результат (без оконного материала Hann)

Образец нового вывода выглядит не очень хорошо.

{1.10114283e-019, 0 <repeats 48 times>, 35050560, inf, 0.0352631919, 
1.08468142e-019, 2.84188939e-009, inf, 143872, 142068.25, 3.31743232e+010, 
8800024, 3.29058877e+010, 0, 1.53397155e-019, 4.58692708e-013, 61631.5938, 
0, inf, 1154.63733, inf, inf, inf, inf, inf, inf, inf, 1.14477244e+011, 

Согласно предложению, удалено динамическое распределение. Новый выход выглядит красиво, и имеет смысл. Далее нормализую ввод и продолжу мое путешествие.

{6120297, 4445404.5, 1772673.5, 1041102.38, 659743.438, 484291.75, 
513112.688, 289598.594, 668016.812, 487091.375, 315217.875, 585517.562, 
513285.281, 268263.375, 69867.4531, 108220.406, 85955.2031, 75381.0234, 
124448.68, 559070.812, 996484.75, 1008192.25, 515462.312, 316204.938, 
124825.734, 
...