CoreAudio Team
Apple Computer Inc.
March 17, 2004

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
IMPLEMENTATION DESCRIPTION
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

This document attempts to give a description of the accompanying implementation of the OpenAL API set for MacOSX. This
implementation has been completely stripped of any legacy Sound Manager (Carbon) usage and has replaced the direct usage
of a CoreAudio Device with an Audio Unit Graph. This graph consists solely of the 3DMixer AudioUnit and Default Output
AudioUnit. All sample rate conversion (except where described below), mixing, and volume attenuations are now provided
by the 3DMixer.

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
BUILD TIME DEPENDENCIES
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

To build this version of OpenAL on the MacOSX platform, you must have the latest CoreAudio SDK installed (version 1.3.1).
This SDK contains updated Public Utility classes used throughout the implementation.

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
RUNTIME TIME DEPENDENCIES
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

For maximum benefit in both features and performance it is recommended that the library is run on the following 
platform. These pieces provide an optimized 3DMixer, with both feature enhancements and bug fixes.

    Recommended:
    ------------
    OSX: version 10.2.6 or greater AND
    QuickTime: version 6.5.1
    ---AudioToolbox.framework (version 1.3.2)
    ---AudioUnit.framework (version 1.3.2)
    ---CoreAudio.component (version 1.3.2 - this version contains the 2.0 version of the 3DMixer AudioUnit)
    
The library will still run with previous pieces. However, the new optimizations do not exist and some workarounds
for missing features and existing bugs are required.

    Minimum:
    ------------
    OSX: version 10.2 (Jaguar) AND
    QuickTime: version 6.4
    ---AudioToolbox.framework
    ---AudioUnit.framework
    ---CoreAudio.component (contains the 1.3 version of the 3DMixer AudioUnit)

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
PROJECT FILES
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

Two project files have been provided; al_osx.xcode & al_osx.pbproj. I have been primarily using the xcode project during
development. Both projects contain 3 targets:
    
    1) openal.dylib - builds a Library named openal.dylib
    2) al_osx_basic - builds a Framework named OpenAL.framework
    3) All - an aggragate target that builds the framework and library targets

Both projects have 2 build styles. One for Deployment and one for Development.

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
OPENAL API FUNCTIONS
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

The implementation is in C++. The sources are cleanly divided by their OpenAL functionality. By this I mean there are
classes for OpenAL Devices, Contexts, Sources, and Buffers (more on these later). The remaining code is merely to map
the API set to these classes (found in oalImp.cpp) , and to provide some utility APIs (found in oalOSX.cpp) - 
(i.e. alutLoadWaveFile()). The number of source files has actually decreased in this implementation and I think is pretty
straight forward in it's organization.

    Source File Summary:
    --------------------
    oalBuffer.h
    oalContext.cpp & .h
    oalDevice.cpp & .h
    oalImp.cpp & .h
    oalOSX.cpp & .h
    oalSource.cpp & .h
    
    Public Utility Classes (found in /Developer/Examples/CoreAudio/):
    ----------------------
    CAMutex.cpp & .h
    CAGuard.cpp & .h
    CAHostTimeBase.cpp & .h
    CAStreamBasicDescription.cpp & .h
    CADebugMacros.cpp & .h

As mentioned above, Public Utility classes from the CoreAudio SDK are used throughout the implementation. Some of
these classes are actually used only when some build flags used for development are turned on.

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------
C++ CLASSES
----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

I found while reading the OpenAL documentation for the first time that the OAL objects mapped themselves well to self
contained C++ classes, so that's how I approached the implementation. I'll describe each class below and any details
that seem worth mentioning in this document.

As much as possible, I tried to implement to the specification document, even though most existing implementations 
probably may not support all of it's features of the specification.

Notable areas that still need to be addressed;
    
    - Doppler:  The 3DMixer actually has doppler support built in, but I have left it off for now as I think to make 
                this feature useful, an application has to have it avilable during development so the behavior 
                and speed of the OALSources actually produces the desired effect for the listener. I don't believe
                Ryan has any doppler support in UT2003, do any implmentations make use of this part of the
                specification?

    - Source Cone Support: Again, do any implmentations make use of this part of the
                specification?

A minimal set of globals are kept in the oalImp.cpp source which is the entry way into the library for all the APIs
of the specification. These global state are for:

        - Current OAL Context
        - Current OAL Device
        - Maximum Mixer Bus Count (used by an extension I have added, see the ReadMe also provided)
        - Convert Upon Loading Flag (used by an extension I have added, see the ReadMe also provided)
        
        - A Map of OAL Devices created by the user
        - A Map of OAL Buffers generated by the user
        - A Map of OAL Contexts generated by the user

That's it. All other state is kept the various class objects that can come and go as requested by the user.

----------------------------------------------------------------------------------------------------------------------
OALDevice Class
----------------------------------------------------------------------------------------------------------------------

Though I don't believe there has been an implementation yet that actually supported multiple OAL Devices (correct me
if I am mistaken here), this one should. I haven't done any testing in this area yet so I would not be surprised to
find some bugs when switching between devices, but the way the code is organized it should be no problem to do so.

The primary function of this class is to create and maintain the Audio Unit Graph. It modifies the graph when necessary 
in response to: 
        
    1) the caller of the library
        For example, if the caller wants to change the rendering quality used by the mixer, the OALDevice class would
        be responsible for resetting the mixer busses. 
    
    2) needs of the OALSource objects
        For example, when an OAL source is requested to play, it needs to get an available mixer bus to attach to so it can
        provide data to the mixer. The OALDevice class does this bus management
    
    3) changes made to the HAL device being tracked by the default output unit
        For Example, if the user changed (by using the Audio MIDI Setup app for example) the sampling rate of the 
        audio hardware being used by the default output unit, it is likely that some amount of reconfiguration 
        of the AUGraph would be required.

 Though an OALContext can only belong to single device, the OALDevice class does not need to have any knowledge of the 
 context's themselves (however the OALContext does know which OALDevice it is owned by).
 
 At this time, I am only creating OALDevices that use the DefaultOutput AudioUnit. If you are not familiar with the
 Default Output Device, it is the device that is set by the user in the Sound Panel of the System Preferences. It is
 also settable in the Audio MIDI Setup application found in /Applications/Utilities/. The Default Output Device is the device
 that would be used by QuickTime or iTunes for example. The Default 'System' Output Device (these can be the same piece
 of hardware) is the device used by the system for alert sounds and finder ui sounds.
 
----------------------------------------------------------------------------------------------------------------------
OALContext Class
----------------------------------------------------------------------------------------------------------------------

Again, I am not sure if any other implementations allow multiple OAL Contexts, but this one should. As with the multiple
OAL Device support, I haven't done any testing for this so there may be bugs when switching contexts. There should really
be no problem in setting up multiple spatial environments and switching between them since all the state about the context
is kept in the class object.

The primary job of the OALContext class to to delegate set and get info calls that are intended to be OAL Context specific
as indicated by the OAL specification. i.e. setting listener gain, setting doppler, get source count, creating a source

The OAL Context class also owns an stl multimap to keep track of the OALSources created for that context.

----------------------------------------------------------------------------------------------------------------------
OALSource Class
----------------------------------------------------------------------------------------------------------------------

The OALSource class gets a large portion of the actual work being done to play sound through the library. It maintains
and manages it's own buffer queue, it pulls data and does any necessary processing from the OAL Buffers to pass onto the 
AUGraph, it translates the OAL coordinates to listener centric coordinates that the mixer needs. It knows which 
OALContext and OALDevice it belongs to so it can make requests to the AUGraph owned by the OALDevice, but with 
settings that may be OALContext specific.

The OAL source class creates any necessary AudioConverter for the data that is to be played in it's buffer queue, at
the time that the buffers are appended to the cue. (currently, the AudioConverters are only used for int to float, and
deinterleaving since I have continued to only support the 8 and 16bit pcm data formats. - it would be trivial however
to add support for other compressed formats since these converters are already in place and are capable of decompressing
many different formats)

Not sure about other implementations, but this one should be able to have a buffer queue that consists of buffers 
containing differently formatted audio data. Look at the DoRender() method to see how the buffer queue is traversed.

----------------------------------------------------------------------------------------------------------------------
OALBuffer
----------------------------------------------------------------------------------------------------------------------

OpenAL Buffers are maintained merely by a multimap of OALBuffer structs. These structs maintain some state about the 
buffer. An OALBuffer is knowledgable of what AudioConverter is needs to use in order to convert the source data to a
format that the AUGraph likes.

----------------------------------------------------------------------------------------------------------------------
Utility Functions
----------------------------------------------------------------------------------------------------------------------

Same WAVE file utilities as previous implementations. The alutLoadWAVFile() API uses the AudioFile APIs found in the
AudioToolbox.frameework, eliminating the need for the library to have any file parsing code. Originally, I had not
implemented the alutLoadWAVMemory(). Seems this is necessary after all so I just readded the existing implementation
of this API.
