A Wikibookian believes this page should be split into smaller pages with a narrower subtopic.

You can help by splitting this big page into smaller ones. Please make sure to follow the naming policy. Dividing books into smaller sections can provide more focus and allow each one to do one thing well, which benefits everyone.

This algorithm generates very beautiful sounds, even if its idea is much simpler than that of other algorithms. It generates a perfectly looped wavetable sample which can be used in instruments. It easily generates sounds of ensembles, choirs, metallic sounds (bells) and many others.

This algorithm is public domain. This page includes some public domain C/C++ implementation sources that can be used in your projects or products.

This algorithm is implemented in ZynAddSubFX in the PADsynth module, which you can download to hear for yourself what beautiful sounds it is capable of generating. Before proceeding with reading this document, I recommend that you listen to all sound examples in the next category.

In order to understand how this algorithm works, you need to be familiar with how the author of this text thinks about the musical instruments. Please read an introduction for the description of the meaning and the importance of Bandwidth of each harmonic and Randomness.

This algorithm generates some large wavetables that can played at different speeds to get the desired sound. This algorithm describes only how these wavetables are generated. The result is a perfectly looped wavetable. Unlike other synthesis methods which use Inverse Fast Fourier Transform, this one does not use overlap/add methods and there is only one IFFT for the whole sample.

The basic steps are:

Make a very large array that represents the amplitude spectrum of the sound (default all values are zero)

Generates the distribution of each harmonic in frequency and add it to the array

Put random phases to each frequency of the spectrum

Do a single Inverse Fourier Transform of the whole spectrum. There is no need of any overlapping windows, because there is only one single IFFT for the whole sample.

The ouput is the sample which can be used as a wavetable. In the next image, the steps are represented graphically:

The author of this considers one harmonic(overtone) as being composed of many frequencies. These sine components of one harmonic are spread over a certain band of frequencies. Higher harmonics has bigger bandwidth. In natural choirs/ensembles the bandwidth is proportional to the harmonic's frequency. Here is an example of a spectrum of an instrument generated by this algorithm:

Spectrum

Close-up of the spectrum

The harmonics becomes wider and wider, until at a certain frequency, where they may merge to a noise band (as in the full spectrum image from above). This is a normal thing and I recomand to not avoid this by limiting the bandwidth of the harmonics.

§The frequency distribution of one harmonic/overtone (or the harmonic profile)[edit]

This describes the function of the spread of the harmonic. Here are some examples of how they can be spread:

A special case is where there is only a single sine component inside the hamonic. In this case, the harmonic and the "sine component" are the same thing.
Audio example: Single harmonicComplex sound

Normal (Gaussian) distribution. The sine components amplitude are bell shaped. The largest amplitude is in the center of the band. This distribution gives the most natural sounds (it simulates a very, very large enssemble)
Audio example: Single harmonicComplex sound

Of course, you can use many others harmonic's profile functions. ZynAddSubFX's implementetation of the PADsynth algorithm offers many ways to generate the harmonic profile. Also, it's very important that the harmonic must have the same amplitude, regardless of the profile functions/parameters and the bandwidth.

N - wavetable size. It's recomanded to be a power of 2.
This is, usually, a big number (like 262144)
samplerate - the samplerate (eg. 44100)
f - frequency of the the fundamental note (eg. 440)
bw - bandwidth of first harmonic in cents (eg. 50 cents)
must be greater than zero
number_harmonics - the number of harmonics.
Of course, number_harmonics<(samplerate/f)
A[1..number_harmonics] - amplitude of the harmonics

I wrote some C/C++ implementations of the basic algorithm and the extended algorithm. The "c_basic" directory contains the basic algorithm, "c_extended" contains the extended algorithm and the "c_simple_choir" is the implementation of the basic algorithm to make a simple choir. These implementations are wrote to be easy to understood and they are not optimised for speed. You can test on Linux by running the ./compile.sh scripts. It's recomanded to have snd installed, to make possible to hear the results as wav file. Of course, you can import the results into your instruments, because the waves are perfectly looped (set the first loop point to 0 and the second to the end of the wav). I put the source code under public domain, but it depends on [FFTW3_library], so, if you want to use into your products, you must use your IFFT routines to avoid licensing issues of the FFTW library.

To be easy to use this algorithm into your projects or products, I made a ready-to-use C++ class. Only thing that you have to do, is to provide it an IFFT routine. Please read the header file for details.

When using the wavetables into instruments, on each NoteOn, start from a random position and not from the start. This avoids hearing the same sound on each keystroke

You can use the same wavetable for generating stereo sounds, by playing the same wavetable at different positions for left and right. The best is to make the difference between left right as N/2

Generate different wavetables for different pitches and use the one who is closest to the desired pitch

Upsample or downsample the harmonics's amplitude array before running the algorithm, according to the fundamental frequency. In this case we need to set a parameter "base_frequency" which represents the frequency where the array is left unchanged.Example: we have A_orig[]={1,2,1,3,0,0,1,0} and base_frequency is equal to 440 Hz
Here are some cases:
- A[] for 440 Hz: is the same as A_orig[]
- A[] for 220 Hz: is the A_orig[] upsampled by factor of 2
so: A[]={1, 1, 1.5, 2, 1.5, 1, 2, 3, 1.5, 0, 0, 0, 0.5, 1, 0.5, 0}
(the original A_orig amplitudes are shown as bold)
- A[] for 880 Hz: the A_orig[] is downsampled by a factor of 2
so: A[]={1.5, 2, 0, 0.5}
- A[] for F Hz: the A_orig[] is scaled by a factor of 440/F.

Even if this idea is very simple, the resulting sounds are very natural, because it keeps the spectrum constant according to the harmonic's frequency and not to harmonic's number. This folows the point 4 from the document where I described some principles regarding synthesis.

I hope that this algorithm will be implemented in many software/hardware synthesizers. Use it, spread it, write about it, make beautiful instruments with it. If your synthesizer uses plenty of samples, you can use this algorithm to generate many ready-to-use samples.

Source text The original source text and this page (including images,sounds,etc) are released under Public Domain.