Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AudioToolbox/OpenAL ExtAudioFile to play compressed audio

I'm currently using OpenAL to play game music. It works fine, except that it doesn't work with anything except for raw WAV files. This means that I end up with a ~9mb soundtrack.

I'm new to OpenAL, and I'm using code directly from Apple's example (https://developer.apple.com/library/ios/#samplecode/MusicCube/Listings/Classes_MyOpenALSupport_h.html%23//apple_ref/doc/uid/DTS40008978-Classes_MyOpenALSupport_h-DontLinkElementID_9) to get the buffer data.

Question: Is there any way to modify this function so it reads compressed audio and decodes it on the fly?
I'm not so worried about the audio file format, just as long as it can be played and is compressed (like mp3, aac, caf). The only reason I want to do this (obviously) is to reduce file size.

Edit: It seems that the problem is not so much in OpenAL as the method I'm using to get the buffer. The function at https://developer.apple.com/library/ios/#samplecode/MusicCube/Listings/Classes_MyOpenALSupport_h.html%23//apple_ref/doc/uid/DTS40008978-Classes_MyOpenALSupport_h-DontLinkElementID_9 uses AudioFileOpenURL and AudioFileReadBytes. Is there any way to get the framework to decode the audio for me using ExtAudioFileOpenURL and ExtAudioFileRead?

I have tried the code here: https://devforums.apple.com/message/10678#10678, but I don't know what to make of it. The function I use to get the buffer is at https://developer.apple.com/library/ios/#samplecode/MusicCube/Listings/Classes_MyOpenALSupport_h.html%23//apple_ref/doc/uid/DTS40008978-Classes_MyOpenALSupport_h-DontLinkElementID_9, and I haven't really modified it, so that's what I need to build on.

I've started a bounty because I really need this, hopefully someone can point me in the right direction.

like image 702
Greg Avatar asked Feb 23 '23 14:02

Greg


2 Answers

You'll need to use audio services to load other formats. Bear in mind that OpenAL ONLY supports uncompressed PCM data, so any data you load needs to be uncompressed during load.

Here's some code that will load any format supported by iOS: https://github.com/kstenerud/ObjectAL-for-iPhone/blob/master/ObjectAL/ObjectAL/Support/OALAudioFile.m

If you want to stream compressed soundtrack-type audio, use AVAudioPlayer since it plays compressed audio straight from disk.

like image 57
Karl Avatar answered Feb 26 '23 22:02

Karl


You don't need any third party library to open archived files. With a little help from AudioToolbox/AudioToolbox.h framework you can open and read the data of a .caf file which is a very good choice by the way (better than mp3 or ogg) in terms of performance (minimal CPU impact during decompression). So ,when the data gets to OpenAL it is already PCM, ready to fill the buffers. Here is some sample code on how you can achieve this:

-(void) prepareFiles:(NSString *) filePath{

    // get the full path of the file
    NSString* fileName = [[NSBundle mainBundle] pathForResource:filePath ofType:@"caf"];    

    // open the file using the custom created methods (see below)
    AudioFileID fileID = [self openAudioFile:fileName];     
    preparedAudioFileSize = [self audioFileSize:fileID];

    if (preparedAudioFile){
        free(preparedAudioFile);
        preparedAudioFile = nil;
    }
    else{
        ;
    }
    preparedAudioFile = malloc(preparedAudioFileSize);

    //read the data from the file into soundOutData var
    AudioFileReadBytes(fileID, false, 0, &preparedAudioFileSize, preparedAudioFile);
    //close the file    
    AudioFileClose(fileID);
}



-(AudioFileID)openAudioFile:(NSString*)filePath
{
    AudioFileID fileID;
    NSURL * url = [NSURL fileURLWithPath:filePath];
    OSStatus result = AudioFileOpenURL((CFURLRef)url, kAudioFileReadPermission, 0, &fileID);

    if (result != noErr) {
        NSLog(@"fail to open: %@",filePath);
    }
    else {
        ;
    }
    return fileID;
}


-(UInt32)audioFileSize:(AudioFileID)fileDescriptor
{
    UInt64 outDataSize = 0;
    UInt32 thePropSize = sizeof(UInt64);
    OSStatus result = AudioFileGetProperty(fileDescriptor, kAudioFilePropertyAudioDataByteCount, &thePropSize, &outDataSize);
    if(result != 0) NSLog(@"cannot find file size");
    return (UInt32)outDataSize;
}
like image 35
Rad'Val Avatar answered Feb 26 '23 21:02

Rad'Val