[Openal] Status of OpenAL 1.1 on OS X

George Warner geowar at apple.com
Fri Aug 18 15:48:55 PDT 2006


Several Mac OS X OpenAL developers have requested a replacement for
alutLoadWAVFile (and I needed it for a few of my projects ;-) so...

[BEGIN]
//*****************************************************
#pragma mark - includes & imports
//-----------------------------------------------------
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>

#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <OpenAL/MacOSX_OALExtensions.h>
//*****************************************************
#pragma mark - local ( static ) function prototypes
//-----------------------------------------------------

static UInt32    GetOALFormatFromASBD( AudioStreamBasicDescription *inASBD
);

//*****************************************************
#pragma mark - exported function implementations
//-----------------------------------------------------


//*************************************************************************
//
//    alutCreateBufferFromFile (  inFilename )
//
//    Purpose:    Create OpenAL buffer from contents of a file
//
//    Inputs:        inFilename - address of complete file name ( path )
//
//  Returns:    On success, a handle to an OpenAL buffer containing the
loaded sound.
//                It returns AL_NONE on failure.
//
ALuint alutCreateBufferFromFile ( const char * inFilename )
{
    ALuint result = AL_NONE;    // assume failure
    ExtAudioFileRef tExtAudioFileRef = NULL;
    AudioBufferList tABL;
    
    tABL.mNumberBuffers = 1;
    tABL.mBuffers[0].mNumberChannels = 0;
    tABL.mBuffers[0].mDataByteSize = 0;
    tABL.mBuffers[0].mData = nil;
    
    do {
        // Open the input file
        FSRef tFSRef;
        OSStatus status = FSPathMakeRef( ( const UInt8 * )inFilename,
&tFSRef, FALSE );
        if ( noErr != status ) break;
        
        FSCatalogInfo tFSCatalogInfo;
        status = FSGetCatalogInfo( &tFSRef, kFSCatInfoDataSizes,
&tFSCatalogInfo, NULL, NULL, NULL );
        if ( noErr != status ) break;
        
        tABL.mBuffers[0].mData = malloc( tFSCatalogInfo.dataLogicalSize );
        if ( !tABL.mBuffers[0].mData ) {
            status = memFullErr;
            break;
        }
        
        status = ExtAudioFileOpen( &tFSRef, &tExtAudioFileRef );
        if ( noErr != status ) break;
        
        AudioStreamBasicDescription tASBD;
        UInt32 asbd_size = sizeof( AudioStreamBasicDescription );
        status = ExtAudioFileGetProperty( tExtAudioFileRef,
kExtAudioFileProperty_FileDataFormat, &asbd_size, &tASBD );
        if ( noErr != status ) break;

        // configure output ASBD
        tASBD.mFormatID = kAudioFormatLinearPCM;
        tASBD.mFormatFlags = kAudioFormatFlagIsBigEndian |
kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;


        status = ExtAudioFileSetProperty( tExtAudioFileRef,
kExtAudioFileProperty_ClientDataFormat, asbd_size, &tASBD );
        if ( noErr != status ) break;

        tABL.mBuffers[0].mNumberChannels = tASBD.mChannelsPerFrame;
        tABL.mBuffers[0].mDataByteSize = tFSCatalogInfo.dataLogicalSize;

        SInt64 totalAudioFrames;
        UInt32 ioPropertyDataSize = sizeof( totalAudioFrames );
        status = ExtAudioFileGetProperty( tExtAudioFileRef,
kExtAudioFileProperty_FileLengthFrames, &ioPropertyDataSize,
&totalAudioFrames );
        if ( noErr != status ) break;

        UInt32 numberOfFrames = totalAudioFrames;
        status = ExtAudioFileRead( tExtAudioFileRef, &numberOfFrames, &tABL
);
        if ( noErr != status ) break;
        

        // load data in buffer

        ALenum  format = GetOALFormatFromASBD( &tASBD );
        if ( !format ) break;
        
        alGenBuffers( 1, &result );
        status = alGetError( );

        if ( AL_NO_ERROR != status ) break;
        
        ALsizei size = tFSCatalogInfo.dataLogicalSize;
        ALsizei freq = tASBD.mSampleRate;

        alBufferData( result, format, tABL.mBuffers[0].mData, size, freq );
        status = alGetError( );
        if ( AL_NO_ERROR != status ) break;
        
    } while ( FALSE );
    
    if ( tExtAudioFileRef ) {
        ExtAudioFileDispose( tExtAudioFileRef );
    }
    
    if ( tABL.mBuffers[0].mData ) {
        free( tABL.mBuffers[0].mData );
    }
    
    return result;
}
//*****************************************************
#pragma mark - local ( static ) function implementations
//-----------------------------------------------------
static UInt32    GetOALFormatFromASBD( AudioStreamBasicDescription *inASBD )
{
    UInt32 result = 0;
    
    switch ( inASBD->mFormatID ) {
        case kAudioFormatLinearPCM: {
            // NOTE: if float: return 0;
            if ( inASBD->mFormatFlags & kAudioFormatFlagIsFloat ) {
                result = 0;        // float currently unsupported
            } else {
                if ( 16 == inASBD->mBitsPerChannel ) {
                    if ( 1 == inASBD->mChannelsPerFrame ) {
                        result = AL_FORMAT_MONO16;
                    } if ( 2 == inASBD->mChannelsPerFrame ) {
                        result = AL_FORMAT_STEREO16;
                    }
                } else if ( 8 == inASBD->mBitsPerChannel ) {
                    if ( 1 == inASBD->mChannelsPerFrame ) {
                        result = AL_FORMAT_MONO8;
                    } if ( 2 == inASBD->mChannelsPerFrame ) {
                        result = AL_FORMAT_STEREO8;
                    }
                }
            }
            break;
        }
        default: {
            break;
        }
    }
    return result;
}
[END]

-- 
Enjoy,
George Warner,
Schizophrenic Optimization Scientist
Apple Developer Technical Support (DTS)





More information about the Openal mailing list