当声音在 OpenAL 中播放完毕时收到通知

发布于 2024-07-25 22:34:18 字数 110 浏览 2 评论 0原文

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

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

剩一世无双 2024-08-01 22:34:18

我在 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];

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

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

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.

诗笺 2024-08-01 22:34:18

如果您将 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 给您回电。 您到底想要回调做什么? 有些事情不需要回调就能更好地解决。

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.

放肆 2024-08-01 22:34:18

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

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

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

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.

俏︾媚 2024-08-01 22:34:18

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文