1

When I am using Intel IPP's ippsFFTFwd_RToCCS_64f and then ippsMagnitude_64fc I get a massive peak at zero index in magnitudes array.

My sine wave is long and main component I am interested is somewhere between 0.15 Hz and 0.25 Hz. I take the sample with 500Hz sampling frequency. If I reduce mean from the signal before FFT I get really small zero component not that peak anymore. Below is a pic of magnitudes array head:

enter image description here

Also the magnitude scaling seems to be 10 times the magnitude I see in the time series of the signal e.g. if amplitude is 29 in magnitudes it is 290.

I Am not sure why this is so and my question is 1. Do I really need to address the zero index peak with mean reduction and 2. Where does this scale of 10 come?

void CalculateForwardTransform(array<double> ^signal, array<double> ^transformedSignal, array<double> ^magnitudes)
{ 
    // source signal
    pin_ptr<double> pinnedSignal = &signal[0];
    double *pSignal = pinnedSignal;
    int order = (int)Math::Round(Math::Log(signal->Length, 2));

    // get sizes
    int sizeSpec = 0, sizeInit = 0, sizeBuf = 0;
    int status = ippsFFTGetSize_R_64f(order, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuf);

    // memory allocation
    IppsFFTSpec_R_64f* pSpec;
    Ipp8u *pSpecMem = (Ipp8u*)ippMalloc(sizeSpec);
    Ipp8u *pMemInit = (Ipp8u*)ippMalloc(sizeInit);
    
    //  FFT specification structure initialized
    status = ippsFFTInit_R_64f(&pSpec, order, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, pSpecMem, pMemInit);

    // transform
    pin_ptr<double> pinnedTransformedSignal = &transformedSignal[0];
    double *pDst = pinnedTransformedSignal;
    Ipp8u *pBuffer = (Ipp8u*)ippMalloc(sizeBuf);
    status = ippsFFTFwd_RToCCS_64f(pSignal, pDst, pSpec, pBuffer);

    // get magnitudes
    pin_ptr<double> pinnedMagnitudes = &magnitudes[0];
    double *pMagn = pinnedMagnitudes;
    status = ippsMagnitude_64fc((Ipp64fc*)pDst, pMagn, magnitudes->Length); // magnitudes is half of signal len

    // free memory
    ippFree(pSpecMem);
    ippFree(pMemInit);
    ippFree(pBuffer);
}
eemilk
  • 1,375
  • 13
  • 17
  • 1
    For 1: for low frequency signal analysis a small constant bias can really interfere (especially due to spectral leakage) so yes it's better if you can remove that bias. For 2: I'd expect a scaling of the magnitude by the FFT (see eg. [this answer](https://stackoverflow.com/questions/25797670/plotting-fft-on-octave/25799234#25799234)). However only a factor of 10 seems strangely very little scaling if you are using significantly more than 20 samples for your FFT (but I can't confirm without knowing the actual number of samples you pass to the FFT routine). – SleuthEye Jul 15 '20 at 02:30
  • Okay, the data was sort of half wave, now that I have full length of sine wave (0.17Hz) I can get the magnitude right with: magnitude[i] * 2/N, where N is signal length and in this case 2879 data points. Thanks for answering, I will proceed with bias removing. – eemilk Jul 16 '20 at 09:35

1 Answers1

1

Do I really need to address the zero index peak with mean reduction?

For low frequency signal analysis a small bias can really interfere (especially due to spectral leakage). For sake of illustration, consider the following low-frequency signal tone and another one with a constant bias tone_with_bias:

fs = 1;
f0 = 0.15;
for (int i = 0; i < N; i++)
{
  tone[i] = 0.001*cos(2*M_PI*i*f0/fs);
  tone_with_bias[i] = 1 + tone[i];
}

If we plot the frequency spectrum of a 100 sample window of these signals, you should notice that the spectrum of tone_with_bias completely drowns out the spectrum of tone: Spectrum of tone & tone with bias

So yes it's better if you can remove that bias. However, it should be emphasized that this is possible provided that you know the nature of the bias. If you know that the bias is indeed a constant, removing it will reveal the low-frequency component. Otherwise, removing the mean from the signal may not achieve the desired effect if the bias is just a very low-frequency component.

Where does this scale of 10 come?

Scaling of the magnitude by the FFT should be expected, as described in this answer of approximately 0.5*N (where N is the FFT size). If you were processing a small chunk of 20 samples, then you should get such a factor of 10 scaling. If you scale the output of the FFT by 2/N (or equivalently scale by 2 while also using the IPP_FFT_DIV_FWD_BY_N flag) you should get results that have similar magnitudes as the time-domain signal.

SleuthEye
  • 14,379
  • 2
  • 32
  • 61
  • This makes no sense. Subtracting the mean of the signal is numerically identical to setting the zero frequency bin to 0. Adding a constant to the signal only affects the zero frequency bin. Maybe you are using a window in your transform, which adds higher frequency if the signal has a non-zero mean. This “spectral leakage” you refer to cannot be anything else than an artifact caused by the windowing. Note that OP is not windowing their signal prior to transform. – Cris Luengo Jul 23 '20 at 01:39
  • @CrisLuengo while estimating the spectrum you inevitably have to window the signal (and not adding an explicit window is equivalent to using a rectangular window), so will have to consider some form of leakage. If you interpolate the spectrum of that bias by padding in the time domain (admittedly akin to windowing), you'd notice a sinc like function that crosses zero at all but the 0 bin. This become relevant when the bias is not quite constant such that the zero-crossings don't quite line up with the bins. – SleuthEye Jul 23 '20 at 02:17
  • Note also that I didn't say the OP should subtract the mean (which as you said, would only affect bin 0), but rather to remove biases if possible. A high-pass or band-pass filter would be better suited for that. – SleuthEye Jul 23 '20 at 02:55