Audio Library Programming Guide - Managed Controls


Device List

When it is initialized, the
AFList creates a list of AFDevice objects. Each AFDevice is associated with the Core Audio AudioDeviceID of a physical device (often called a sound card). A sound device that has both input and output codecs is listed in both the input AFList and the output AFList.

An
AFList is used to initialize the AFSoundcard. As mentioned in the previous section of this document, the easiest way to create an AFSoundcard is to use the AFManager. The AFManager will create all the other objects such as AFList and AFDevice objects that are needed, and will release them when you release the AFManager.

You can create as many
AFSoundcard objects as you wish. Each AFSoundcard maps to a physical sound device. Multiple AFSoundcards can map to the same physical device.

When an
AFSoundcard is first initialized, it is mapped to the default sound device. The default input and output devices are normally selected from the Sound Preference Pane in the Mac OS X System Preferences.

You can change the physical sound device by sending the
AFSoundcard either a -selectDevice: or a -selectDeviceName: message.


[ inputSoundcard selectDevice:device ] ;
[ outputSoundcard selectDeviceName:@"Built-in Line Output" ] ;


The argument of the -selectDevice call is a reference to an AFDevice object. You can get a list of devices that is available to an AFSoundcard by sending it a -devices message.


NSArray* arrayOfDevices = [ inputSoundcard devices ] ;


The name that is sent to
-selectDeviceName: is the name that Core Audio associates with a built-in audio device or an external sound device. The name can be obtained from an AFDevice by sending it the -name message.


AFDevice *device = [ [ outputSoundcard devices ] objectAtIndex:0 ] ;
[ outputSoundcard selectDeviceName:[ device name ] ] ;


You will typically use the device names to populate a popup button that is used for selecting sound cards.

The currently mapped or selected device of an AFSoundcard can be obtained by sending the -selectedDevice to the receiver.


AFDevice *device = [ outputSoundcard selectedDevice ] ;


When an external sound card is inserted or removed, an AFSoundcard calls its delegate's hardwareChanged method with the selector value of kAudioHardwarePropertyDevices. You can update your popup menu upon receiving this callback.


- (void)soundCard:(AFSoundcard*)card hardwareChanged:(AudioObjectPropertySelector)selector



Automatically Managing a Device Popup Menu

Instead of managing your own device popup menu, you can ask the
AFSoundcard to do it for you. The entire process described above will be done for you automatically.


[ inputSoundcard setManagedDeviceMenu:popupButton ] ;


When an AFSoundcard receives the -setManagedDeviceMenu: message, it populates the NSPopUpButton with the names of available input or output sound devices.

AFSoundcard selects a new device when you manually select an item from the managed popup menu. AFSoundcard will also update any sampling rate, source and format popup menus that it is asked to manage, to match the new sound device. When a selected audio device is removed from the computer, AFSoundcard switches to using the default audio device and it also changes the menu selection.

Unless there are some device parameters that you wish to micromanage, it is highly recommended that you just let the AFSoundcard manage the popup menus for you. By choosing to do this, you will not need to even know what an AFDevice or an AFList is. The only two classes of the Audio Library that you need to work with are the AFManager and AFSoundcard classes.


Device Sampling Rate

A list of usable sampling rates (array of NSNumbers) can be obtained with:


NSArray *samplingRates = [ [ inputSoundcard selectedDevice ] samplingRates ] ;


Some sound cards allow contiguous ranges of sampling rates. Audio Library limits the sampling rates to the same discrete rates that are shown in the Audio MIDI Setup utility.

The sampling rate of an AFSoundcard can be read and set with the following methods.


- (float)samplingRate ;
- (void)setSamplingRate:(float)rate ;


When the sampling rate of the selected device changes (even when it is switched by a different process), AFSoundcard sends its delegate a -samplingRateChangedTo message:


- (void)soundCard:(AFSoundcard*)card samplingRateChangedTo:(float)samplingRate ;



Automatically Managing a Sampling Rate Popup Menu

Just as with the device popup menu, you can let
AFSoundcard manage a sampling rate popup menu for you.


[ inputSoundcard setManagedSamplingRateMenu:popupButton ] ;


When
AFSoundcard receives an NSPopUpButton from -setManagedSamplingRateMenu:, it populates the menu with the available sampling rates and selects the sampling rate that is currently being used by the device.

AFSoundcard switches the sampling rate of the device when you manually select an item from the managed popup menu. If a different process changes the sampling rate of the device, AFSoundcard automatically changes the menu selection, and sends the samplingRateChangedTo callback to its delegate.


Device Format

"Device format" refers to the number of channels and the number of bits per sample.

An array of allowable formats (AFFormat objects) can be obtained with:


NSArray *formats = [ [ inputSoundcard selectedDevice ] formats ] ;


The format of an AFSoundcard can be read and set with the following methods.


- (AFFormat*)format ;
- (void)setFormat:(AFFormat*)format ;


When the format of the selected device changes (even when the number of channels or number of bits per channel is switched by a different process), AFSoundcard sends its delegate a -formatChangedToChannels:bits message:


- (void)soundCard:(AFSoundcard*)card formatChangedToChannels:(int)channels bits:(int)bits ;



Automatically Managing a Device Format Popup Menu

You can let
AFSoundcard manage a format popup menu for you.


[ inputSoundcard setManagedFormatMenu:popupButton ] ;


When
AFSoundcard receives an NSPopUpButton from -setManagedFormatMenu:, it populates the menu with the available format pairs and selects the format that is currently being used by the device.

AFSoundcard changes the format of the device when you manually select an item from the managed popup menu. If a different process changes the number of channels or number of bits of device that is connected to the AFSoundcard, AFSoundcard automatically changes the menu selection, and sends the formatChangedToChannels callback to its delegate.


Sources

The converters of some sound devices can be switched between multiple "sources." For example, an input codec can be connected to either a microphone level input or to a line level input. Similarly, an output can be connected to either the speaker or to a headphones jack of a computer.

Since they share the same codec, you cannot use the sources concurrently, you can only switch between the different input or output connections.

An array of names of sources (NSStrings) can be obtained with:


NSArray *sources = [ [ inputSoundcard selectedDevice ] sources ] ;


The source of an AFSoundcard can be read and set with the following methods.


- (NSString*)source ;
- (void)setSource:(NSString*)sourceName ;


When the source of the selected device changes (even when the source is switched by a different process), AFSoundcard sends its delegate a -soundSourceChangedTo message:


- (void)soundCard:(AFSoundcard*)card soundSourceChangedTo:(NSString*)source ;



Automatically Managing a Source Popup Menu

You can let
AFSoundcard manage a source popup menu for you.


[ inputSoundcard setManagedSourceMenu:popupButton ] ;


When
AFSoundcard receives an NSPopUpButton from -setManagedSourceMenu:, it populates the menu with the available sources and selects the source that is currently being used by the device. Devices with no sources will return an empty menu.

AFSoundcard changes the source of the device when you manually select an item from the managed popup menu. If a different process changes the source of device that is connected to the AFSoundcard, AFSoundcard automatically changes the menu selection, and sends the soundSourceChangedTo callback to its delegate.


Volume Control

Although some sound cards do not have digitally controllable attenuators, many of them have. Some stereo devices come with a master volume control to provide a common attenuation for both channels. Other multichannel devices have separate volume controls for each channel.

You can find out the sound card has a volume control by sending the receiver a
deviceHasVolumeControl message.


Boolean hasVolumeControl = [ inputSoundcard deviceHasVolumeControl:channel ] ;


Channel 0 corresponds to the master volume control. For a stereo device, channel 1 usually corresponds to the left channel and channel 2 corresponds to the right channel. For multi-channel decides, the channel numbers are 1-based.

For channels that have volume controls, you can read and set the volume setting with:


- (float)volumeForChannel:(int)channel ;
- (Boolean)setVolume:(float)value channel:(int)channel ;


volumeForChannel returns -1 if the volume cannot be obtain for the channel that is passed in. Otherwise it returns a floating point value between 0.0 and 1.0.

When the volume of a device changes (even when the volume is changed by a different process), AFSoundcard sends its delegate a -volumeChangedTome message:


- (void)soundCard:(AFSoundcard*)card volumeChangedTo:(float)value channel:(int)ch ;



Automatically Managing a Volume Control Slider

You can let
AFSoundcard manage a volume slider for you.


[ inputSoundcard setManagedVolumeSlider:slider channel:n ] ;


When
AFSoundcard receives an NSSlider from -setManagedVolumerSlider:, it sets the slider value. If there is no attenuator for the channel that is sent in, the slider will be disabled by AFSoundcard.

AFSoundcard changes the volume of the particular channel of the device when you manually changes the slider knob setting. If a different process changes the attenuation, AFSoundcard automatically changes the setting of the slider knob, and sends the volumeChangedTo callback to its delegate.