1

I'm trying to get the amplitudes and phases of a (falling) saw-tooth signal. My saw-tooth is 1024 samples long and generated as

int numSamples = 1024;
for (int i = 0; i < numSamples; i++)
{
    samples[i] = -((float)i / (float)(numSamples - 1) * 2.0f - 1.0f);
}

I setup the real and imaginary arrays as

for (int i = 0; i < numSamples; i++)
{
    double sample = samples[i];
    re[i] = sample;
    im[i] = 0.0;
}

then passing it into the FFT function. I readout the result as

int numPartials = numSamples / 2;
for (int i = 1; i < numPartials; i++)
{
    outMagnitudes[i] = (float)sqrt(re[i] * re[i] + im[i] * im[i]);
    outPhases[i] = (float)atan2(im[i], re[i]);
}

2 problems occur:

  • the magnitudes are only half as large as they should be
  • the phases range linearly from -PI/2 for the first partial to zero for the last one where I'd expect them all to be zero for the given signal

I really don't get what I do wrong here.

Does anyone have an idea ?

Lenny
  • 71
  • 6

1 Answers1

1

You only print half of the FFT result, which only contains half the energy, thus you get half sized magnitudes. The rest is in the negative frequency mirrored complex conjugate half.

Your sawtooth isn't circularly centered around sample[0], so there is a phase shift.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • What do you mean exactly by "Your sawtooth isn't circularly centered around sample[0], so there is a phase shift." ? Currently the -1/1 jump is at sample[0]. What's wrong with that ? Shouldn't all harmonic sines have their phase at 0 at sample[0] in order to produce the saw ? Like here: https://www.youtube.com/watch?v=wNwJOBmqBsc I don't really get it... – Lenny Apr 28 '17 at 03:37
  • @Lenny consider what the requirement for 0-phase implies: that the input is solely made up of cosines, i.e., is symmetric. By the conventions that FFT libraries usually adopt, this means that (using Python notation) `input[1:]` must be symmetric, i.e., `input[1:] == reverse(input[1:])`. In your case, the sawtooth needs to have a rise and a fall, e.g., any scaled-shifted version of `[0, 1, 2, 3, 2, 1]` for a 6-element input would work. (And you can build a 2048-long version of this for your case.) – Ahmed Fasih Apr 28 '17 at 05:11
  • It is definitely confusing, connecting the conventions used by FFT libraries with the insights of general Fourier theory… hopefully we can clarify it for you. – Ahmed Fasih Apr 28 '17 at 05:11
  • I must admit, I'm still confused. The reason I need this is that I have a wave-table oscillator (the samples) and want to write an editor in which you can switch forth and back between time-domain (the 1024 samples) and frequency-domain (the 512 magnitudes and phases). So I need conversion functions. Could somebody maybe give me some pseudo-code on how to prepare re/im to convert from samples to mag/phase and another one which uses mag/phase to restore the original samples ? I guess pseudocode would be easiest for me to grasp... – Lenny Apr 28 '17 at 11:55
  • I now get some proper mag/phase from samples (not sure if I do it exactly right) by considering the mirrored part of the re/im as well, but I'm still unable to restore the original samples from these... – Lenny Apr 28 '17 at 12:00