1
$\begingroup$

In the lovely image below we see the addition of sine waves making a square wave. I am coding a wave table synthesiser and thought it would be great to get the user to be able to fiddle with the values of the sine partials and then run an inverse FFT on them to produce the wave form.

enter image description here

I have some code for an FFT and you specify the number of buckets, real and imaginary arrays and the array length. The way it is used in the example is:

  • Imaginary array has all it's values set to 0
  • The real array has its 0th element set to 0
  • The real array has its arrayLength/2 element set to 0
  • Other values are set in the real array. Every time a value is set in the first half of the array one is set at the opposite end of the array, mirroring whatever is happening in the first half of the real array.
  • This spits out a single cycle of the waveform constructed using these sine partials

What are some common patterns for filling these partials to generate waveforms. How do you generate a square wave, a triangle wave, a sawtooth? Can you create noise or is that impossible if it is non periodic?

Extra: What are some tricks for producing 'good' waveforms? This is an opinion question, just a bonus if you have something to share about producing waveforms that sound good. (Good in your opinion :)

For those who would find it interesting there is a flash app here that lets you set the levels of the partials in order to construct waveforms, it's fun.

$\endgroup$
  • $\begingroup$ Short answer: you can't generate a square wave or triangular wave etc, not via an iFFT, no matter what the array length is in that iFFT. $\endgroup$ – Dilip Sarwate Oct 10 '15 at 13:38
  • 1
    $\begingroup$ @DilipSarwate: Well, you can, the FFT coefficients are just non-obvious (you have to set more than just the harmonically related ones). Otherwise you wouldn't be able to take the FFT of a square or triangular wave and get its frequency response. Or are you meaning something else? $\endgroup$ – Peter K. Oct 10 '15 at 19:05
  • 1
    $\begingroup$ @PeterK. The Fourier series of a square wave has an infinite number of terms. An FFT can capture only a finite number of them. So one can never reconstruct a square wave exactly. Samples, yes but complete analog signal No. The OP's simulation shows this quite clearly. $\endgroup$ – Dilip Sarwate Oct 10 '15 at 20:58
  • 1
    $\begingroup$ @DilipSarwate : Fair enough. Many people believe the samples are sufficient for all practical purposes.... until you start interpolating. :-) $\endgroup$ – Peter K. Oct 10 '15 at 21:05
  • $\begingroup$ You can come as close as you desire to any waveform. From the desired wave by means of FFT get the desired sinusoids. $\endgroup$ – Moti Oct 11 '15 at 3:24
1
$\begingroup$

You can find the formulas for a rectangular, square, triangle, sawtooth and rectified sinusoidal waveform in Chapter 13 section The Fourier Series, of the Scientist and Engineer's Guide to Digital Signal Processing by Steven W. Smith.

If you IFFT a vector of random numbers, you get out another vector of random numbers that approximately follow a Gaussian distribution, due to the central limit theorem and that each time domain number was formed as a linear combination of multiple frequency domain numbers. But it will be periodic so it won't sound like pure noise unless the vector length is huge.

If you want to construct your own arbitrary waveform from line segments you can use: $$f(x) = \left\{\begin{array}{ll}a + b\ x & \text{if}\ x_0 <= x < x_1\\ 0 & \text{otherwise}\end{array}\right.\\ \hat f(\omega) = \int^{+\infty}_{-\infty} e^{-i\omega\ x} f(x) = \int^{x_1}_{x_0} e^{-i\omega\ x}(a + b\ x) = -\frac{b\ \cos(\omega\ x_0)}{\omega^2} - \frac{(a + b\ x_0)\ \sin(\omega\ x_0)}{\omega} + \frac{b\ \cos(\omega\ x_1)}{\omega^2} + \frac{(a + b\ x_1)\ \sin(\omega\ x_1)}{\omega} + i\ \left(-\frac{(a + b\ x_0)\ \cos(\omega\ x_0)}{\omega} + \frac{b\ \sin(\omega\ x_0)}{\omega^2} + \frac{(a + b\ x_1)\ \cos(\omega\ x_1)}{\omega} - \frac{b\ \sin(\omega\ x_1)}{\omega^2}\right),$$

where $a = \frac{x_0\ y_1 - x_1\ y_0}{x_0 - x_1}$ and $b =\frac{y_0 - y_1}{x_0 - x_1}$ for a line segment starting at $(x_0, y_0)$ and ending at $(x_1, y_1)$ and $\hat f(\omega)$ is the Fourier transform of $f(x)$. Discretely sampling $\hat f(\omega)$ at multiples of $2\pi$ will make $f(x)$ periodic by 1. If you have more than one segment you can sum their Fourier transforms.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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