Previous Section: A More Complex Cmix Instrument
Extensions and Variations
Many of the programming constructs encountered in various CMIX instruments are intended to improve the speed of execution. For example, the *table* function in the *snazzypan* instrument does not need to be invoked to update the channel 0 and channel 1 amplitude for every sample. One method for decreasing the number of calls to the *table* function might be:
countdown = 0;
for (i = 0; i < nsamps; i++) {
while (!countdown--) {
amp = table(i,pfunc_loc,tabs);
countdown = 100;
}
...
This would cause the *table* function to be called only once every 100 samples, when "countdown" becomes 0. The variable "countdown" is initially set to 0 before entering the sample loop to ensure that "amp" will be assigned a value for the first sample processed.
Another CMIX speed-up involves reading and/or writing a large block of samples into a buffer for processing. Although the low-level CMIX i/o routines do indeed perform block reads and writes, the overhead associated with the *GETIN* and *ADDOUT* macros (along with the other CMIX i/o macros) can be greatly reduced through a block read or write. CMIX has several functions for doing block i/o: *bgetin* reads a chunk of samples into an array, *baddout* writes an array of samples to the disk. A modification of *snazzypan* using these block i/o routines could look like this:
for (i = nsamps; i > 0; i -= array_size) {
bgetin(in_array, 0, array_size);
k = 0;
for (j = 0; j < array_size, j++) {
amp = table(i,pfunc_loc,tabs; out_array[k] = in_array[0] * (1.0 - amp) * p[3];
out_array[k+1] = in_array[0] * amp * p[3];
k += 2;
}
baddout(out_array, 1, array_size * 2);
}
*bgetin* and *baddout* both take three arguments: the name of the array to be read or written, the CMIX file descriptor number for the soundfile being accessed, and the number of samples in the array. This segment assumes that "in_array" has been declared as a floating point array having "array_size" elements in it, and "out_array" is declared to have twice as many elements in it. This is because the output array must contain stereo information, or channel 0 and channel 1 samples. Note that the channel sample data must alternate every other sample in the output array. There is also one small bug in this code -- when "nsamps" is not evenly divisible by "array_size" (as is usually the case), the final "in_array" will not be completely filled with new samples. Fixing this is not too difficult and would be a wonderfully instructive and informative exercise in CMIX programming!
Although *snazzypan* isn't all that complex, the basic principles for constructing a CMIX instrument hold true for a wide range of synthesis and signal-processing algorithms. CMIX has a fairly robust set of unit generator functions; several types of oscillators, a number of filter units, delay units, etc. The source code for these can all be found in the *cmix/lib* directory. There are also a fair number of example instruments in the *cmixinsts.tar.Z* in the *pub/music* directory at the princeton.edu ftp archive.
Next Section: Compiling CMIX Instruments
What is CMIX? - Index -
Cmix Home Page