0
$\begingroup$

Hey I have this CSV file which contains 8 chunks of 256 samples of a sine wave with different frequencies (each chunk has different frequency starting from 8 to 64Hz).

The total samples of this file is 8x256=2048.

I am attempting to plot a frequency-magnitude spectrum but I'm having issues doing so, when I plot 1024 samples (4 spikes of 256 chunks each) I get this result:

enter image description here

As you can see, there is some noise effect in that spectrum.

I am using this formula to calculate Hanning Window:

value = time_samples[i];
double multiplier = 0.5 * (1 - cos(2*M_PI*i/N));
chunk[i] = {value * multiplier , 0 };// generate (complex) sine waveform

But that is working half of the times, when I plot the first 2 chunks (512 samples) it looks like I want it to look all the time:

enter image description here

As you can see it's smooth, so I don't understand why it's working with the first 2 chunks but not with 4.

Here is my code:

const int N = 2048; // Samples
typedef std::complex<float> Complex;
int main(int argc, char** argv)
{
    QApplication a(argc, argv);
    vector<float> time_samples = read_csv("sine_samples.csv");
    vector<float> magnitude(N);
    Complex chunk[N];

    float Fs = 200; // How many time points are needed i,e., Sampling Frequency
    float value;
    for (int i = 0; i < N; i++)
    {;
        value = time_samples[i];
        double multiplier = 0.5 * (1 - cos(2*M_PI*i/N));
        chunk[i] = {value * multiplier , 0 };// generate (complex) sine waveform
    }
    CArray data(chunk, N); 
    fft(data);
    int temp = N/2;
    int temp2 = Fs / 2;
    for (int i = 0; i < temp; i++)
    {
        magnitude[i] = abs(data[i]);
    }
    float resolution_freq = ((float)temp2 / temp);
    vector<float> freq_vector = arange(0, temp2, resolution_freq);

    QChartView *chartView = plot_freq_magnitude_spectrum(freq_vector,magnitude);
    QMainWindow window;
    window.setCentralWidget(chartView);
    window.resize(1800, 1000);
    window.show();

    return a.exec();

}

Using Dan' solution I changed this line:

double multiplier = 0.5 * (1 - cos(2*M_PI*i/N));

to

double multiplier = 0.5 * (1 - cos(2*M_PI*i/256));

in order to window each chunk instead of the whole samples, and I got back this result when running it on 1024 samples (4 spikes):

enter image description here

$\endgroup$
4
  • $\begingroup$ Is the data in the file noisy? $\endgroup$ Aug 26, 2021 at 3:04
  • $\begingroup$ No, it's a pure sine wave @CrisLuengo $\endgroup$ Aug 26, 2021 at 10:51
  • $\begingroup$ Is the window done to each chunk separately or on the whole data set with one window once the chunks are put together? And do you mean with 8 chunks you have eight separate frequencies? $\endgroup$ Aug 26, 2021 at 11:42
  • $\begingroup$ The window done to the whole data set 2048 times, each time to different sample as you can see in that for loop, yes 8 chunks of 8 different frequencies each chunk contains 256 samples @DanBoschen $\endgroup$ Aug 26, 2021 at 11:48

2 Answers 2

1
$\begingroup$

Another solution is to window each chunk prior to combining- this will minimize the discontinuity that occurs between the chunks, which is the source of the noise.

$\endgroup$
2
  • $\begingroup$ This solution worked for me and did minimize the discontinuity, I added it to my question so you can see it yourself $\endgroup$ Aug 26, 2021 at 13:02
  • $\begingroup$ Perfect glad it worked for you. Thanks for adding the result. $\endgroup$ Aug 26, 2021 at 13:09
1
$\begingroup$

You apply a Hanning window to the entire 2048 sample vector and apply an FFT (instead of doing one chunk at a time).

If you FFT the whole thing, you are simply concatenating the chunks. The problem is that you have a large discontinuities at most chunk transitions. These discontinuities create spectral spreading and the ripples that you see.

If you want to get rid of this, you need to start each chunk at the same phase where the previous chunk ended and not at $\phi = 0$

Something like this

float phi = 0;
float dphi;
for (iFreq = 0; i < numFreqs; i++)
{
    dphi = 2*M_PI*freqs[iFreq]/fs;
    for (i = 0; i < chunkSzie; i++)
    {
        chunk[i][iFreq] = sin(phi);
        phi += dphi;
    }
}
$\endgroup$
1
  • $\begingroup$ Can you share more info regarding the code, such as what is numFreqs or freqs variable , and chunk is a 1d complex<double> so how can you do chunk[i][iFreq] $\endgroup$ Aug 26, 2021 at 12:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.