When we synthesized the clink of the wineglass, we saw that adding together simple sine waves, or partials, allowed us to make a more complex, real-world sound, an approach called additive synthesis. In theory, by using additive synthesis we could synthesize any possible sound this way. Due to work of a mathematician named Jean-Baptiste Fourier,2 we know that periodic signals can be broken down and described by sines and cosines, called Fourier series.3 The practical application is that by adding sine waves together we can generate waves other than the simple sine waves we’ve been generating so far with the osc~ object. If we do this when the patch is loaded, we can fill an array with this data and then play it back using a simple oscillator built for that purpose, and we can generate waves with widely varying timbres. These waves can allow us to build many different types of sounds.
Making a Sine Wave by Other Means
To see how to use this technique, let’s build a sine-wave wavetable and play it back at 440 Hz instead of playing a sine wave using an osc~. Create a patch called sine_wave_wavetable.pd. Then choose Put > Array, name the array “sine,”
and choose not to save the contents of the array. Then create a loadbang con-nected to a message with the two messages sine sinesum 1024 1 and sine normalize 1, starting with a semicolon (;) to signify custom messages, as we’ve done before. You should have a patch that looks like the one in Figure 14, Building a Sine-Wave Wavetable, on page 75.
The messages use two functions of Pd that act on arrays. Let’s look at each of them.
The sinesum Message
The first message uses a function called sinesum, which takes two arguments:
a number of points to generate into the array, and a list of space-separated numbers that represent the amplitudes of partials to generate. In other words, the first in the list represents the fundamental, the second represents the first overtone, and so on. The message starts with the table name, so in total 2. http://en.wikipedia.org/wiki/Jean-Baptiste_Joseph_Fourier
3. http://en.wikipedia.org/wiki/Fourier_series
loadbang
;
sine sinesum 1024 1;
sine normalize 1;
sine
Figure 14—Building a Sine-Wave Wavetable
the message sine sinesum 1024 1 means “Generate into the array named sine 1,024 points worth of data describing 1 sine wave with an amplitude of 1 as the fundamental.”
The Normalize Message
The second message tells the array named sine to normalize itself to 1. Nor-malization is the process of adjusting the array’s contents so that the greatest value becomes 1 and the rest are adjusted proportionally. This makes sure that after we generate the wave the highest value doesn’t exceed 1 but also is no lower than 1, so the sound is as loud as it can be without exceeding the limits of the system when playing it back.
Let’s look at the sinesum function again. Its purpose is to generate a Fourier series of sine waves added together. Since in this case we only passed a list with one number, 1, to the function, it generated only one sine wave. Now we have an array containing one period of a sine wave. All that remains is to have some way to play the data out of that array as a wave, and we can have an alternative to the osc~ object.
Wavetable Playback
To play back the contents of an array, we can use an object called tabplay~, which basically sends the data in an array straight through to its outlet once.
This technique works fine for sample-based synthesis, where we expect to play the data in the array as a sound. In wavetable synthesis we expect the data in the array to be one cycle of a periodic wave, so to play it back as a wave we need something that will continuously play the array’s contents at the speed we choose. The object we want here is called tabosc4~.
Add a tabosc4~ sine connected to an output~ to the previous patch. This new object will act as an oscillator that takes data from an array. The frequency it plays at is sent to its inlet, so, as the following image shows, the patch also needs a number connected to the tabosc4~. Notice in the following figure how the message box also has a new first line with a 440, so it now does double duty by sending the frequency we want to the tabosc4~ through the number box as well as sending the initialization messages to the array. Turn the vol-ume up on the output~, and you should hear the 440 Hz sine wave you’ve come to know and love.
loadbang
tabosc4~ sine 440
440;
sine sinesum 1024 1;
sine normalize 1;
output~
volume dsp
sine
Now before we generate more interesting waves, let’s address a few more things about this new patch. The first is why there is a 4 at the end of tabosc4~, and the second is why we used 1024 as the first argument to sinesum. The tabosc4~ object has a 4 at the end of it to signify that it uses 4-point polynomial interpolation as it converts a constant number of data points from an array into a signal at different frequencies. Basically this means that it will do its best to smooth out the signal as it jumps from point to point of data in the array, no matter at which frequency the oscillator is generating a signal.
This is directly related to why we passed 1024 to the sinesum function. The help for tabosc4~ says that it expects the size of the array that it plays to be a power of two with an additional three points, one at the beginning and two at the end. The additional point at the beginning should be the same value as the final point in the array, excluding the two additional end points, and the final two should be copies of the first point in the array, excluding the additional beginning point. This is so that the tabosc4~ can make a smooth transition between each period of the wave. Luckily using sinesum or cosinesum takes care of this for us, as well as resizing the array.
When we specified 1024 as the size of array to generate, sinesum actually gen-erated the extra transition points and added them to the array, resizing it to 1027. We used 1024 because it gives us plenty of room for enough points to make a nice-sounding sine wave. The help entry for tabosc4~ suggests using an array of size 512 for any generated wave with up to 15 partials. When generating above 15 partials it suggests using 32 times the number of partials and then rounding that up to a power of 2. Since we generated only one partial, 1024 is twice as big as the Pd manual says it needs to be. This could be a tradeoff between superhigh quality and memory.
Now let’s look at generating some different waves with many more than just one partial.