Getting notified when a sound is done playing in OpenAL
Asked Answered
C

4

7

I'm using OpenAL on iPhone to play multiple audio samples simultaneously.

Can I get OpenAL to notify me when a single sample is done playing?

I'd like to avoid hardcoding the sample length and setting a timer.

Chausses answered 25/6, 2009 at 21:19 Comment(3)
This question is 5 years old at this point, but for newbs to OpenAL like myself, there is now an Objective-C APi for OpenAL, and a class in the demo project (SourceNotificationsDemo) that demonstrates this functionality.Leucoma
@Leucoma could you provide a link?Freaky
Project here: github.com/kstenerud/ObjectAL-for-iPhoneLeucoma
U
3

If you have the OpenAL source abstracted into a class, I guess you can simply call performSelector:afterDelay: when you start the sound:

- (void) play
{
    [delegate performSelector:@selector(soundHasFinishedPlaying)
        afterDelay:self.length];
    …
}

(If you stop the sound manually in the meantime, the callback can be cancelled, see the NSObject Class Reference.) Or you can poll the AL_SOURCE_STATE:

- (void) checkStatus
{
    ALint state;
    alGetSourcei(source, AL_SOURCE_STATE, &state);
    if (state == AL_PLAYING)
        return;
    [timer invalidate];
    [delegate soundHasFinishedPlaying];
}

I don’t know how to have OpenAL call you back. What exactly do you want the callback for? Some things can be solved better without a callback.

Unwonted answered 6/7, 2009 at 19:26 Comment(0)
S
5

I didn't have much luck with callbacks in OpenAL. In my state machines, I simply poll the source and delay the transition until it's done.


    - (BOOL)playing {
        ALint sourceState;
        alGetSourcei(sourceID, AL_SOURCE_STATE, &sourceState);
        return sourceState == AL_PLAYING;
    }

// ... //

    case QSTATE_DYING:
        if (![audioSource playing])
            [self transitionTo:QSTATE_DEAD];

If this isn't what you need, then you're best bet is probably a timer. You shouldn't need to hardcode any values. You can determine the playback time when you're populating your buffers.

A bit of insight into the "why" of the question might offer some additional choices.

Splenectomy answered 9/12, 2009 at 22:47 Comment(0)
U
3

If you have the OpenAL source abstracted into a class, I guess you can simply call performSelector:afterDelay: when you start the sound:

- (void) play
{
    [delegate performSelector:@selector(soundHasFinishedPlaying)
        afterDelay:self.length];
    …
}

(If you stop the sound manually in the meantime, the callback can be cancelled, see the NSObject Class Reference.) Or you can poll the AL_SOURCE_STATE:

- (void) checkStatus
{
    ALint state;
    alGetSourcei(source, AL_SOURCE_STATE, &state);
    if (state == AL_PLAYING)
        return;
    [timer invalidate];
    [delegate soundHasFinishedPlaying];
}

I don’t know how to have OpenAL call you back. What exactly do you want the callback for? Some things can be solved better without a callback.

Unwonted answered 6/7, 2009 at 19:26 Comment(0)
B
2

This OpenAL guide suggests a possible solution:

The 'stream' function also tells us if the stream is finished playing.

...and provides sample source code to illustrate the usage.

Blakley answered 26/6, 2009 at 2:59 Comment(1)
(The linked solution is polling with alGetSourcei(source, AL_SOURCE_STATE, &result) which is what I'd also recommend. +1Blithe
A
2

Wait, are you talking about having finished one sample (e.g., 1/44100 second for 44.1 KHz audio)? Or are you talking about knowing that a source has played through its buffer and has no more audio to play?

For the latter, I've had good results polling a source for the AL_BUFFERS_PROCESSED property when I stream buffers to a source; it might work for the single-buffer case to look for a non-zero value of this property.

Absalom answered 6/7, 2009 at 19:18 Comment(1)
Once you have queued buffers to a source, AL_BUFFERS_RPOCESSED will never return 0. Even if you stop or pause the source, or it completes its buffer. The value only decreases if you rewind the source or unqueue buffers. A non-zero value only shows that at least one buffer has finished playing at some point.Blithe

© 2022 - 2024 — McMap. All rights reserved.