WAVE WIZARD: A 16-BIT SAMPLE GENERATOR FOR THE ATARI ST David Snow Wave Wizard is a MIDI utility that generates sample files by means of additive synthesis. To use the program, you tell it how many sample files you want to create, give them a name, then let it do the rest. Wave Wizard creates dynamic timbres with a complex, bell-like sonority similar to that produced by ring- modulation. Samples created with Wave Wizard can be loaded into any sample-editor that imports Sound Designer files (such as Steinberg's AVALON), then edited to your liking and dumped to a 12 or 16-bit sampler. USING THE PROGRAM There isn't much you need to do to get the Wizard working. First it asks you how many sample files you want to create (from 1 to 8), and then requests a "generic" file name of 1 to 7 characters to assign each file. The program also asks for an optional path designation if you want to direct sample files to a particular drive or folder (for example, "B:\SAMPLES\"). The program takes over from there. As each file in the set is saved to disk, a number will automatically be appended to its name (for example NEWWAVE1.SD, NEWWAVE2.SD, etc.). The total number of files you can create at a time depends on how much disk space you have available. Each file is 132408 bytes long: a normally- formatted double-sided floppy will hold up to 5 Wave Wizard files. As each partial is calculated, its frequency ratio and amplitude are displayed onscreen. When the last file in a set is finished, all the file names are displayed, and you have the option of creating a new set or quitting the program. THEORY OF OPERATION Additive synthesis is the process of creating timbres by mixing together sine waves of different frequencies and amplitudes. The frequency ratios of these sine waves (partials) and the manner in which they vary in amplitude over time give a sound its character. All digital synthesis techniques encode sound as a series of numbers that represent discrete points along a sound wave. An array of such data is called a "wavetable"; Wave Wizard uses a wavetable representing a single cycle of a sine wave as its basic sound-generation element. This array is composed of 256 8-bit words in 2's-complement form, ranging in value from -128 to +127. By sending this data to a digital-to-analog converter (DAC), we can transform those numbers into voltages and reconstruct the sound wave. The rate at which data is sent to the DAC (sampling rate) divided by the size of a wave-cycle (in data words) determines the frequency of the sound. If we send data from our 256-word sine wavetable at a sampling rate of 33.3kHz, the resulting frequency would be 130.07Hz (33300Hz/256 words). If we want to obtain the pitch one octave above this frequency, we can send every other word to the DAC, in effect halving the size of the wavetable (33300/128=260.15Hz). Likewise, if we sent every third word to the DAC, we'd get the frequency one octave and a perfect fifth above our fundamental frequency, and sending every fourth word would produce the pitch two octaves above. By this process you can see how easy it is to produce pitches which are related by integer ratios to the fundamental frequency (i.e. 1:1, 2:1, 3:1, 4:1, etc.). But how can we obtain intervals with fractional components, such as a perfect fifth (ratio 1.5:1)? It makes no sense to ask a computer for data located at an address 1.5 words from the start of a wavetable. The trick is to fudge the math by using the fractional ratio to calculate a "theoretical" index, then chop off the fraction to get a usable integer address: "theoretical" address index: "practical" integer index: 0 0 (+1.5 words=) 1.5 1 (+1.5 words=) 3 3 (+1.5 words=) 4.5 4 (+1.5 words=) 6 6 (+1.5 words=) 7.5 7 (+1.5 words=) 9 9 etc. (Indecies are relative to the starting address of the wavetable.) With that in mind, let's say we want to create a sample file 64K words long, consisting of sine waves at a pitch a perfect fifth above the fundamental. First we create a 64K-word array and initialize all its elements to zero. Then we take the data word located at position 0 of the sine wavetable and stuff it into position 0 of the array. Then we get the word at positon 1 of the wavetable and save it in position 1 of the array; get the word at position 3 of the wavetable, save it in position 2 of the array; get the word at position 4 of the wavetable, save it in position 3 of the array, and so on. When we get to the end of the sine wavetable we jump back to its beginning and start over (a sine wave is symmetrical, so its end matches its beginning). We repeat this process until our sample array is filled with 65536 (64K) samples. We want the amplitude of our sample to change over time, so we need an amplitude envelope for each partial. For this purpose Wave Wizard uses an array 256 words long containing 8-bit data ranging from 0 to 255; each value in the array represents a a breakpoint in a 256-segment envelope. To create a sample file with an amplitude envelope, we perform the wavetable-scanning process described in the preceeding paragraph, but this time multiply each word taken from the sine wavetable by a value from the envelope array before placing into the sample array. Since our envelope has 256 breakpoints and we want our sample file to be 65536 words long, we need to take 256 samples for each breakpoint value in the envelope (65536 words/256 breakpoints). For example, if the first value in our envelope array is 16, we multiply each of the first 256 words taken from the sine table by 16 before putting them in our sample array. If the second amplitude value in the envelope is 17, we multiply each of the second 256 words from the sine table by 17, and so on. Since we're layering sine waves (partials) to build a timbre, we want to add another 64K sample with its own frequency and envelope on top of the one just created. To do this we simply repeat the table-scan/amplitude-multiply process just described using new frequency and envelope parameters, and add the new data to that already in the sample array. You can repeat this process with as many different frequencies and envelopes as you wish, as long as the frequency ratio of any partial to the fundamental is less than 128 (the ratio has to be less than half the size of the sine wavetable in order to prevent aliasing). At the end of this process we will have a sample array filled with data representing a harmonically dynamic sound. However, all this addition and multiplication has driven the data values in excess of 16 bits (-32768 to +32767), so they must be scaled back. This is done by finding the highest absolute value in the entire array, dividing that number by 32767 and rounding the result up to then next highest integer, then dividing every value in the array by that quantity. In order to automatically create samples without user input, Wave Wizard randomizes the number of partials assigned to each sample, the frequency ratio of each partial to the fundamental frequency, the type of amplitude envelope assigned to each partial, and the relative amplitude of each envelope. Because the frequency ratios of each partial are not likely to be integers, the timbres have a rich, somewhat non-tonal quality. The most interesting part of writing the program was devising a simple method to create unique envelopes for each partial. The solution was to create one 512-word long "super-envelope" in the form of linear-sloped triangle. Each partial derives its envelope by slicing a 256-word block from this super-envelope. If the block begins at word 0, the envelope will consist of an upward slope; if it begins at word 256, it will consist of a downward slope; and if it begins anywhere between those two points, the envelope will slope up, peak, then slope down. In order to vary the relative amplitude of each envelope, every partial is assigned an amplitude-offset value which is subtracted from each point in its envelope before amplitude multiplication is performed. Thus, some envelopes will have higher peak values than others. If the result of the subtraction is less than 0, the amplitude is considered to be 0. Wave Wizard is programmed to produce two kinds of samples; "sustained" timbres in which each partial's envelope might begin at any point in the super-envelope, and "percussive" samples in which all partials are assigned a downward-sloping envelope only.