MusicKit
0.0.0
|
MKUnitGenerators are the building blocks of DSP music synthesis. More...
#include <MKUnitGenerator.h>
MKUnitGenerators are the building blocks of DSP music synthesis.
Each MKUnitGenerator subclass represents a modular DSP program (a unit generator) that provides a particular synthesis operation, such as waveform generation, filtering, and mixing. Sound is synthesized by downloading unit generators to the DSP, interconnecting them, and making them run.
To download a copy of a particular unit generator to the DSP, you send the allocUnitGenerator: message to an open MKOrchestra object, passing the class of the MKUnitGenerator that represents the unit generator. For example, to download a copy of the unoise unit generator (which generates white noise), you allocate an instance of the UnoiseUG class:
// Create an MKOrchestra and a variable for the MKUnitGenerator.
MKOrchestra *anOrch = [MKOrchestra new]; id aNoise; // Open the MKOrchestra; check for failure. if (![anOrch open]) . . .
// The MKUnitGenerator object is created at the same time that the // unit generator program is download to the DSP.
aNoise = [anOrch allocateUnitGenerator: [UnoiseUGx class]];
Notice that the receiver of the class message in the final line of the example is UnoiseUGx. The “x” is explained later in this class description.
To connect two MKUnitGenerators together, you allocate a patchpoint through which they can communicate. A patchpoint is a type of MKSynthData object that's designed to be used for just this purpose, to communicate data from the output of one MKUnitGenerator to the input of another. For example, to connect our UnoiseUGx object to a sound-output MKUnitGenerator, such as Out1aUGx, a patchpoint must be allocated and then passed as the argument in an invocation of UnoiseUGx's setOutput: method and Out1aUGx's setInput: method. But in order to do this, you have to understand a little bit about DSP memory spaces:
The DSP's memory is divided into three sections, P, X, and Y: P memory holds program data; X and Y contain data. Unit generator programs are always downloaded to P memory; the memory represented by a MKSynthData object is allocated in either X or Y, as the argument to MKOrchestra's allocSynthData: method is MK_xData or MK_yData. In general, there's no difference between the two data memory spaces (the one difference is mentioned below); dividing data memory into two partitions allows the DSP to be used more efficiently (although it presents some complications to the programmer, which you're living through right now). Most of the methods defined in the MKUnitGenerator class are subclass responsiblities or are provided to help define the functionality of a subclass. The most important of these are runSelf, idleSelf, and finishSelf. These methods implement the behavior of the object in response to the run, finish, and idle messages, respectively.
In addition to implementing the subclass responsibility methods, you should also provide methods for poking values into the memory arguments of the DSP unit generator that the MKUnitGenerator represents. For example, an oscillator MKUnitGenerator would provide a setFreq: method to set the frequency of the unit generator that's running on the DSP.
MKUnitGenerator subclasses are created from DSP macro code. The utility dspwrap turns a DSP macro into a MKUnitGenerator master class, implementing some of the subclass responsibility methods.
It also creates a number of classes that inherit from your MKUnitGenerator subclass; these are called leaf classes. A leaf class represents a specific memory space configuration on the DSP. For example, OnePoleUG is a one-pole filter MKUnitGenerator master class provided by the Music Kit. It has an input and an output argument that refer to either the x or the y memory spaces on the DSP. To provide for all memory space configurations, dspwrap creates the leaf classes OnePoleUGxx, OnePoleUGxy, OnePoleUGyx, and OnePoleUGyy.
You can modify a master class - for example, the setFreq: method mentioned above would be implemented in a master class - but you never create an instance of one. MKUnitGenerator objects are always instances of leaf classes.