7

我在 iPhone 上使用 OpenAL 同时播放多个音频样本。

当单个样本播放完毕时,我可以让 OpenAL 通知我吗?

我想避免对样本长度进行硬编码并设置计时器。

4

4 回答 4

5

我对 OpenAL 中的回调不太走运。在我的状态机中,我只是轮询源并延迟转换直到它完成。


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

// ... //

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

如果这不是您所需要的,那么您最好的选择可能是一个计时器。您不需要对任何值进行硬编码。您可以在填充缓冲区时确定播放时间。

深入了解问题的“为什么”可能会提供一些额外的选择。

于 2009-12-09T22:47:02.260 回答
3

如果您将 OpenAL 源抽象为一个类,我想您可以performSelector:afterDelay:在启动声音时简单地调用:

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

(如果同时手动停止声音,可以取消回调,请参阅NSObject 类参考。)或者您可以轮询AL_SOURCE_STATE

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

我不知道如何让 OpenAL 给您回电。你到底想要回调什么?有些事情不需要回调就可以更好地解决。

于 2009-07-06T19:26:41.900 回答
1

此 OpenAL 指南提出了一个可能的解决方案:

'stream' 函数还告诉我们流是否完成播放。

...并提供示例源代码来说明用法。

于 2009-06-26T02:59:45.513 回答
1

等等,你是说完成一个样本(例如,44.1 KHz 音频的 1/44100 秒)?或者您是在谈论知道源已通过其缓冲区播放并且没有更多音频可播放?

对于后者,当我将缓冲区流式传输到源时,我在轮询 AL_BUFFERS_PROCESSED 属性的源时取得了很好的结果;它可能适用于单缓冲区情况,以查找此属性的非零值。

于 2009-07-06T19:18:45.673 回答