Pulse wave FFT/iFFT attenuates original wave

This is more of a general dsp question, but I thought I’d ask it here as I am using dsp::FFT (and this is a pretty responsive community).

I’m playing around with band limiting single cycle waveforms for a wavetable synth. As part of this, I’m running them through a fft/ifft cycle where I do some processing in the frequency domain before the ifft. I have a set of simple waveforms I’m testing on and a unity test where I just do a fft/ifft with no processing for baseline verification. In the unity case, I would expect the wave I put in would not be transformed after the fft/ifft.

I notice that of my simple waveforms (sine, square, triangle, saw, 1/8 pulse width, 1/4 pulse width), the pulse width waves get attenuated in the fft/ifft unity process. It seems functional - the 1/8 width wave comes back with a normalized amplitude of .25. The 1/4 width wave is .5. In both cases, the lower part of the wave is still -1.

I’d like to understand why this is happening. I’ve done all kinds of searches as well as read up on the DFT in detail and just haven’t connected the dots on what the property is on the pulse wave that makes this happen. I’ve also tried other fft implementations but get the same results so I know it’s not related to dsp::FFT. Does anybody have any thoughts on this?

Thanks!

Seems strange, can you give a minimal code example where it happens?

 dsp::FFT fft (4); // for 2^4 = 16 samples
    std::vector<float> data (32); // 2*16 for complex values

    FloatVectorOperations::fill (data.data(), -1.0f, 12);
    FloatVectorOperations::fill (data.data() + 12, 1.0f, 4);

    fft.performRealOnlyForwardTransform (data.data());
    fft.performRealOnlyInverseTransform (data.data());

    auto max = FloatVectorOperations::findMaximum (data.data(), 16);
    auto min = FloatVectorOperations::findMinimum (data.data(), 16);

This one is doing just fine, giving +1 as max and -1 as min value.

Asking for a repro ALWAYS points in the right direction :slight_smile:

It turns out my ‘unity’ operation of fft/ifft wasn’t quite unity. I was also setting the value of the first complex sample in my converted frequency array to 0 (after the fft). When I remove this, then my pulse wave comes out properly without a dc offset as expected.

This leads to another question. I thought the typical way to generate bandlimited wavetables was to do a fft, set the first bin to 0 (to remove any dc offset ironically), and then continue along with reducing the harmonics before doing the ifft and building your table.

Is my understanding incorrect and should I not be setting the first value in the frequency array to 0?

Thanks for any pointers - I’m clearly confused at the moment.

Setting it to 0 isn’t a bad idea, as in general you don’t want to have DC in your audio signals. That of course will change the amplitudes of the positive wave and the negative wave, depending on the pulse width. The sum over all samples has to be 0 in order to not have DC in your signal.