Search code examples
iphonestreamingopenalinterrupt-handling

openAL streaming & interruptions


I made an iphone application which uses OpenAL to play many sounds. These sounds are in mp3, quite heavy (more than 1mn)and I stream them (2 buffers per sound) in order to use less memory. To manage interruptions, I use this code :

In OpenALSupport.c file :

  //used to disable openAL during a call
    void openALInterruptionListener ( void   *inClientData, UInt32 inInterruptionState) 
    {
        if (inInterruptionState == kAudioSessionBeginInterruption) 
        {
            alcMakeContextCurrent (NULL);
        }
    }

    //used to restore openAL after a call
    void restoreOpenAL(void* a_context)
    {
        alcMakeContextCurrent(a_context);
    }

In my SoundManager.m file :

 - (void) restoreOpenAL
    {
        restoreOpenAL(mContext);
    }

    //OPENAL initialization
    - (bool) initOpenAL
    {   
        // Initialization
        mDevice = alcOpenDevice(NULL);
        if (mDevice) {
    ...

            // use the device to make a context
            mContext=alcCreateContext(mDevice,NULL);
            // set my context to the currently active one
            alcMakeContextCurrent(mContext);

            AudioSessionInitialize (NULL, NULL, openALInterruptionListener, mContext);

            NSError *activationError = nil;
            [[AVAudioSession sharedInstance] setActive: YES error: &activationError];

            NSError *setCategoryError = nil;

            [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: &setCategoryError];

            ...
    }

And finally in my AppDelegate :

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [[CSoundManager getInstance] restoreOpenAL];
    ...
}

With this method the sounds are back after a call , but flows seem to be played randomly. Is there a specific way to manage interruption with streaming sounds ? I don't find any article about that.

Thanks for your help.


Solution

  • Ok, I answer to my own question.

    I solved the problem by managing error on my streaming method :

    - (void) updateStream
    {
    ALint processed;    
    alGetSourcei(sourceID, AL_BUFFERS_PROCESSED, &processed);
    
    while(processed--)
    {
        oldPosition = position;
    
        NSUInteger buffer;
    
        alSourceUnqueueBuffers(sourceID, 1, &buffer);
    
        ////////////////////
        //code freshly added
        ALint err = alGetError();
        if (err != 0) 
        {
            NSLog(@"Error Calling alSourceUnQueueBuffers: %d",err);
            processed++;
            //restore old position for the next buffer
            position = oldPosition;
            usleep(10000);
            continue;
        }
        ////////////////////    
    
        [self stream:buffer];
    
        alSourceQueueBuffers(sourceID, 1, &buffer);
    
        ////////////////////
        //code freshly added
        err = alGetError();
        if (err != 0) 
        {
            NSLog(@"Error Calling alSourceQueueBuffers: %d",err);
            processed++;
            usleep(10000);
            //restore old position for the next buffer 
            position = oldPosition;
        }
        ///////////////////
    }
    

    }