Most audio units are user adjustable in real time. For example, a reverb unit might have user settings for initial delay, reverberation density, decay time, and dry/wet mix. Such adjustable settings are called parameters. Parameters have floating point or integer values. Floating point parameters typically use a slider interface in the audio unit’s view. You can associate names with integer values to provide a menu interface for a parameter, such as to let the user pick tremolo type in a tremolo effect unit. Built-in (developer defined) combinations of parameter settings in an audio unit are called factory presets.
All audio units also have characteristics, typically non-time varying and not directly settable by a user, called properties. A property is a key/value pair that refines the plug-in API of your audio unit by declaring attributes or behavior. For example, you use the property mechanism to declare such audio unit characteristics as sample latency and audio data stream format. Each property has an associated data type to hold its value. For more on properties, as well as definitions of latency and stream format, see “Commonly Used Properties.”
Host applications can query an audio unit about its parameters and about its standard properties, but not about its custom properties. Custom properties are for communication between an audio unit and a custom view designed in concert with the audio unit.
To get parameter information from an audio unit, a host application first gets the value of the audio unit’s kAudioUnitProperty_ParameterList property, a property provided for you by superclasses in the SDK. This property’s value is a list of the defined parameter IDs for the audio unit. The host can then query the kAudioUnitProperty_ParameterInfo property for each parameter ID.
Hosts and views can also receive parameter and property change information using notifications, as described in “Parameter and Property Events.”
Defining and Using Parameters
Factory Presets and Parameter Persistence
Defining and Using Properties
Specifying parameters means specifying which settings you’d like to offer for control by the user, along with appropriate units and ranges. For example, an audio unit that provides a tremolo effect might offer a parameter for tremolo rate. You’d probably specify a unit of hertz and might specify a range from 1 to 10.
To define the parameters for an audio unit, you override the GetParameterInfo method from the AUBase class. You write this method to tell the view how to represent a control for each parameter, and to specify each parameter’s default value.
The GetParameterInfo method may be called:
By the audio unit’s view (custom if you provide one, generic otherwise) when the view is drawn on screen
By a host application that is providing a generic view for the audio unit
By a host application that is representing the audio unit’s parameters on a hardware control surface
To make use of a parameter’s current setting (as adjusted by a user) when rendering audio, you call the GetParameter method. This method is inherited from the AUEffectBase class.
The GetParameter method takes a parameter ID as its one argument and returns the parameter’s current value. You typically make this call within the audio unit’s Process method to update the parameter value once for each render cycle. Your rendering code can then use the parameter’s current value.
In addition to the GetParameterInfo method (for telling a view or host about a parameter’s current value) and the GetParameter method (for making use of a parameter value during rendering), an audio unit needs a way to set its parameter values. For this it typically uses the SetParameter method, from the AUEffectBase class.
There are two main times an audio unit calls the SetParameter method:
During instantiation—in its constructor method—to set its default parameter values
When running—when a host or a view invokes a parameter value change—to update its parameter values
The SetParameter method takes two method parameters—the ID of the parameter to be changed and its new value, as shown in Listing 2-10:
Listing 2-10 The SetParameter method
void SetParameter( |
UInt32 paramID, |
Float32 value |
); |
The audio unit you build in “Tutorial: Building a Simple Effect Unit with a Generic View” makes use of all three of these methods: GetParameterInfo, GetParameter, and SetParameter.
An audio unit sometimes needs to invoke a value change for one of its parameters. It might do this in response to a change (invoked by a view or host) in another parameter. When an audio unit on its own initiative changes a parameter value, it should post an event notification.
For example, in a bandpass filter audio unit, a user might lower the upper corner frequency to a value below the current setting of the frequency band’s lower limit. The audio unit could respond by lowering the lower corner frequency appropriately. In such a case, the audio unit is responsible for posting an event notification about the self-invoked change. The notification informs the view and the host of the lower corner frequency parameter’s new value. To post the notification, the audio unit follows a call to the SetParameter method with a call to the AUParameterListenerNotify method.
You specify factory presets to provide convenience and added value for users. The more complex the audio unit, and the greater its number of parameters, the more a user will appreciate factory presets.
For example, the Mac OS X Matrix Reverb unit contains more than a dozen parameters. A user could find setting them in useful combinations daunting. The developers of the Matrix Reverb took this into account and provided a wide range of factory presets with highly descriptive names such as Small Room, Large Hall, and Cathedral.
The GetPresets method does for factory presets what the GetParameterInfo method does for parameters. You define factory presets by overriding GetPresets, and an audio unit’s view calls this method to populate the view’s factory presets menu.
When a user chooses a factory preset, the view calls the audio unit’s NewFactoryPresetSet method. You define this method in parallel with the GetPresets method. For each preset you offer in the factory presets menu, you include code in the NewFactoryPresetSet method to set that preset when the user requests it. For each factory preset, this code consists of a series of SetParameter method calls. See “Tutorial: Building a Simple Effect Unit with a Generic View” for step-by-step guidance on implementing factory presets.
Parameter persistence is a feature, provided by a host application, that lets a user save parameter settings from one session to the next. When you develop audio units using the Core Audio SDK, your audio units will automatically support parameter persistence.
Host application developers provide parameter persistence by taking advantage of the SDK’s kAudioUnitProperty_ClassInfo property. This property uses a CFPropertyListRef dictionary to represent the current settings of an audio unit.
There are more than 100 Apple-defined properties available for audio units. You find their declarations in the AudioUnitProperties.h header file in the Audio Unit framework. Each type of audio unit has a set of required properties as described in the Audio Unit Specification.
You can get started as an audio unit developer without touching or even being aware of most of these properties. In most cases, superclasses from the Core Audio SDK take care of implementing the required properties for you. And, in many cases, the SDK sets useful values for them.
Yet the more you learn about the rich palette of available audio unit properties, the better you can make your audio units.
Each Apple-defined property has a corresponding data type to represent the property’s value. Depending on the property, the data type is a structure, a dictionary, an array, or a floating point number.
For example, the kAudioUnitProperty_StreamFormat property, which describes an audio unit’s audio data stream format, stores its value in the AudioStreamBasicDescription structure. This structure is declared in the CoreAudioTypes.h header file in the CoreAudio framework.
The AUBase superclass provides general getting and setting methods that you can override to implement properties, as described in “Defining Custom Properties.” These methods, GetPropertyInfo, GetProperty, and SetProperty, work with associated “dispatch” methods in the SDK that you don’t call directly. The dispatch methods, such as DispatchGetPropertyInfo, provide most of the audio unit property magic for the SDK. You can examine them in the AUBase.cpp file in the SDK to see what they do.
The AUEffectBase class, MusicDeviceBase class, and other subclasses override the property accessor methods with code for properties specific to one type of audio unit. For example, the AUEffectBase class handles property calls that are specific to effect units, such as the kAudioUnitProperty_BypassEffect property.
For some commonly used properties, the Core Audio SDK provides specific accessor methods. For example, The CAStreamBasicDescription class in the SDK provides methods for managing the AudioStreamBasicDescription structure for the kAudioUnitProperty_StreamFormat property.
Here are a few of the properties you may need to implement for your audio unit. You implement them when you want to customize your audio unit to vary from the default behavior for the audio unit’s type:
kAudioUnitProperty_StreamFormat
Declares the audio data stream format for an audio unit’s input or output channels. A host application can set the format for the input and output channels separately. If you don’t implement this property to describe additional stream formats, a superclass from the SDK declares that your audio unit supports the default stream format: non-interleaved, 32-bit floating point, native-endian, linear PCM.
kAudioUnitProperty_BusCount
Declares the number of buses (also called elements) in the input or output scope of an audio unit. If you don’t implement this property, a superclass from the SDK declares that your audio unit uses a single input and output bus, each with an ID of 0.
kAudioUnitProperty_Latency
Declares the minimum possible time for a sample to proceed from input to output of an audio unit, in seconds. For example, an FFT-based filter must acquire a certain number of samples to fill an FFT window before it can calculate an output sample. An audio unit with a latency as short as two or three samples should implement this property to report its latency.
If the sample latency for your audio unit varies, use this property to report the maximum latency. Alternatively, you can update the kAudioUnitProperty_Latency property value when latency changes, and issue a property change notification using the Audio Unit Event API.
If your audio unit’s latency is 0 seconds, you don’t need to implement this property. Otherwise you should, to let host applications compensate appropriately.
kAudioUnitProperty_TailTime
Declares the time, beyond an audio unit’s latency, for a nominal-level signal to decay to silence at an audio unit’s output after it has gone instantaneously to silence at the input. Tail time is significant for audio units performing an effect such as delay or reverberation. Apple recommends that all audio units implement the kAudioUnitProperty_TailTime property, even if its value is 0.
If the tail time for your audio unit varies—such as for a variable delay—use this property to report the maximum tail time. Alternatively, you can update the kAudioUnitProperty_TailTime property value when tail time changes, and issue a property change notification using the Audio Unit Event API.
kAudioUnitProperty_SupportedNumChannels
Declares the supported numbers of input and output channels for an audio unit. The value for this property is stored in a channel information structure (AUChannelInfo), which is declared in the AudioUnitProperties.h header file:
typedef struct AUChannelInfo { |
SInt16 inChannels; |
SInt16 outChannels; |
} AUChannelInfo; |
Field values | Example | Meaning, using example |
|---|---|---|
both fields are |
| This is the default case. Any number of input and output channels, as long as the numbers match |
one field is |
| Any number of input channels, exactly two output channels |
one field is |
| Any number of input channels, any number of output channels |
both fields have non-negative values |
| Exactly two input channels, exactly six output channels |
| No input channels, exactly two output channels (such as for an instrument unit with stereo output) | |
both fields have negative values, neither of which is |
| Up to four input channels and up to eight output channels |
If you don’t implement this property, a superclass from the SDK declares that your audio unit can use any number of channels provided the number on input matches the number on output.
kAudioUnitProperty_CocoaUI
Declares where a host application can find the bundle and the main class for a Cocoa-based view for an audio unit. Implement this property if you supply a Cocoa custom view.
The kAudioUnitProperty_TailTime property is the most common one you’ll need to implement for an effect unit. To do this:
Override the SupportsTail method from the AUBase superclass by adding the following method statement to your audio unit custom class definition:
virtual bool SupportsTail () {return true;} |
If your audio unit has a tail time other than 0 seconds, override the GetTailTime method from the AUBase superclass. For example, if your audio unit produces reverberation with a maximum decay time of 3000 mS, add the following override to your audio unit custom class definition:
virtual Float64 GetTailTime() {return 3;} |
You can define custom audio unit properties for passing information to and from a custom view. For example, the FilterDemo project in the Core Audio SDK uses a custom property to communicate the audio unit’s frequency response to its view. This allows the view to draw the frequency response as a curve.
To define a custom property when building your audio unit from the SDK, you override the GetPropertyInfo and GetProperty methods from the AUBase class. Your custom view calls these methods when it needs the current value of a property of your audio unit.
You add code to the GetPropertyInfo method to return the size of each custom property and a flag indicating whether it is writable. You can also use this method to check that each custom property is being called with an appropriate scope and element. Listing 2-11 shows this method’s signature:
Listing 2-11 The GetPropertyInfo method from the SDK’s AUBase class
virtual ComponentResult GetPropertyInfo ( |
AudioUnitPropertyID inID, |
AudioUnitScope inScope, |
AudioUnitElement inElement, |
UInt32 &outDataSize, |
Boolean &outWritable); |
You add code to the GetProperty method to tell the view the current value of each custom property:
Listing 2-12 The GetProperty method from the SDK’s AUBase class
virtual ComponentResult GetProperty ( |
AudioUnitPropertyID inID, |
AudioUnitScope inScope, |
AudioUnitElement inElement, |
void *outData); |
You would typically structure the GetPropertyInfo and GetProperty methods as switch statements, with one case per custom property. Look at the Filter::GetPropertyInfo and Filter::GetProperty methods in the FilterDemo project to see an example of how to use these methods.
You override the SetProperty method to perform whatever work is required to establish new settings for each custom property.
Each audio unit property must have a unique integer ID. Apple reserves property ID numbers between 0 and 63999. If you use custom properties, specify ID numbers of 64000 or greater.
Last updated: 2007-10-31