OpenAL 问题 - 改变源增益

发布于 2024-11-28 13:00:12 字数 1989 浏览 0 评论 0原文

我最近一直致力于将我的游戏移植到跨平台,并决定使用 OpenAL 作为我的跨平台音频引擎。

我有 16 个“通道”(OpenAL 源),可以同时播放最多 16 个声音。为了播放声音,我切换哪个缓冲区链接到给定的源,并设置增益、源位置等,以便在给定的“通道”(源)中播放声音。

问题是,我注意到我的“增益”设置似乎没有立即生效。例如,如果在给定源中以 0.5 增益播放响亮的“闪电”声音,那么当我稍后以 0.15 增益播放按钮单击声音时,此单击开始时声音太大。然后,每次播放时,音量都会减小,直到第 3 次或第 4 次点击时,听起来像是在正确的 0.15 增益左右。

第一次按钮点击声几乎听不见,而且音量似乎在逐渐增大,直到达到 0.15 增益。

简而言之,“源”似乎会记住以前的增益设置,即使我在同一源中播放新声音之前重置这些设置!这是一个错误吗?或者我对 OpenAL 有什么不明白的地方?如何让它“立即”更改为新的增益/位置设置?

播放声音的相关代码:

[Channel 是 0 到 15 之间的值,soundID 是 gBuffer 数组中的有效索引,stereoPosition 是 -255 到 255 之间的整数,volume 是 0 到 255 之间的整数。这是来自函数这是我的游戏的包装器,过去使用 0-255 之间的值,因此它将这些值转换为正确的 OpenAL 值。]

    // Stop any sound currently playing in this channel ("source")
alSourceStop( gSource[channel] );

    // What sound effect ("buffer") is currently linked with this channel? (Even if not currently playing)
alGetSourcei( gSource[channel], AL_BUFFER, &curBuffer );

    // attach a different buffer (sound effect) to the source (channel) only if it's different than the previously-attached one.
    // (Avoid error code by changing it only if it's different)
if (curBuffer != gBuffer[soundID])  
    alSourcei( gSource[channel], AL_BUFFER, gBuffer[soundID] );

    // Loop the sound?
alSourcei( gSource[channel], AL_LOOPING, (loopType == kLoopForever)  );

    // For OpenAL, we do this BEFORE starting the sound effect, to avoid sudden changes a split second after it starts!
volume = (volume / 2) + 1;  // Convert from 0-255 to 0-128

{
    float sourcePos[3] = {(float)stereoPosition / 50, 0.0, 2.0};

        // Set Source Position
    alSourcefv( gSource[channelNum], AL_POSITION, sourcePos );  // fv = float vector

        // Set source volume
    alSourcef( gSource[channelNum], AL_GAIN, (float)newVolume / 255 );
}

    // Start playing the sound!
alSourcePlay( gSource[channel] );

如果需要,我也可以发布设置代码,但什么也没有喜欢那里。只需调用

alSourcef( gSource[n], AL_REFERENCE_DISTANCE, 5.0f );

对于每个来源。

I've recently been working on porting my game to be cross-platform, and decided to go with OpenAL for my cross-platform audio engine.

I have 16 "channels" (OpenAL sources) for playing up to 16 sounds concurrently. To play a sound, I switch which buffer is linked to a given source, and also set the gain, source position, and so on in order to play a sound in a given "channel" (source).

The problem is, I've noticed that my "gain" settings do not seem to have immediate effect. For instance, if a loud "lightning" sound plays in a given source at 0.5 gain, then when I have a button click sound play at 0.15 gain later, this click starts off FAR too loud. Then, each subsequent time it is played, the volume decreases until around the 3rd or 4th click it sounds like it's around the proper 0.15 gain.

The first button click is barely audible, and it seems to ramp up in volume until it reaches the 0.15 gain.

So in short, a "source" seems to be remembering the former gain settings, even though I am resetting those before playing a new sound in the same source! Is this a bug? Or something I don't understand about OpenAL? How can I get it to "instantly" change to the new gain/position settings?

Relevant code to play a sound:

[Channel is a value between 0 and 15, soundID is a valid index into the gBuffer array, stereoPosition is an integer between -255 and 255, and volume is between 0 and 255. This is from a function that's a wrapper for my game that used to use values between 0-255, so it converts the values to proper OpenAL values.]

    // Stop any sound currently playing in this channel ("source")
alSourceStop( gSource[channel] );

    // What sound effect ("buffer") is currently linked with this channel? (Even if not currently playing)
alGetSourcei( gSource[channel], AL_BUFFER, &curBuffer );

    // attach a different buffer (sound effect) to the source (channel) only if it's different than the previously-attached one.
    // (Avoid error code by changing it only if it's different)
if (curBuffer != gBuffer[soundID])  
    alSourcei( gSource[channel], AL_BUFFER, gBuffer[soundID] );

    // Loop the sound?
alSourcei( gSource[channel], AL_LOOPING, (loopType == kLoopForever)  );

    // For OpenAL, we do this BEFORE starting the sound effect, to avoid sudden changes a split second after it starts!
volume = (volume / 2) + 1;  // Convert from 0-255 to 0-128

{
    float sourcePos[3] = {(float)stereoPosition / 50, 0.0, 2.0};

        // Set Source Position
    alSourcefv( gSource[channelNum], AL_POSITION, sourcePos );  // fv = float vector

        // Set source volume
    alSourcef( gSource[channelNum], AL_GAIN, (float)newVolume / 255 );
}

    // Start playing the sound!
alSourcePlay( gSource[channel] );

I can post setup code too if desired, but nothing fancy there. Just calling

alSourcef( gSource[n], AL_REFERENCE_DISTANCE, 5.0f );

for each source.

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

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

发布评论

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

评论(1

感情废物 2024-12-05 13:00:12

我们在设置 ByteOffset 以在样本中查找位置时遇到了同样的问题,现在找到了让它工作的解决方案:

在设置任何参数之前始终删除并重新创建源

因此,如果您想更改增益和/或其他参数:

  • OpenAL.AL.DeleteSource(oldSourceID);
  • newSourceId = OpenAL.AL.GenSource();
  • OpenAL.AL.Source(newSourceId, OpenTK.Audio.OpenAL.ALSourcef.Gain, yourVolume);
  • OpenAL.AL.Source(newSourceId, OpenTK.Audio.OpenAL.ALSourcef.xxx, yourOtherParameter);

希望它对您有用,并在 10 年后终于找到了解决方法:-)

We just faced the same problem when setting the ByteOffset for seeking to a position in a sample and found now the solution to get it working:

Just always delete and recreate the source before setting any parameter on it.

So if you want to change the gain and/or other parameters:

  • OpenAL.AL.DeleteSource(oldSourceID);
  • newSourceId = OpenAL.AL.GenSource();
  • OpenAL.AL.Source(newSourceId , OpenTK.Audio.OpenAL.ALSourcef.Gain, yourVolume);
  • OpenAL.AL.Source(newSourceId , OpenTK.Audio.OpenAL.ALSourcef.xxx, yourOtherParameter);

Hope it works for you and finally have a workaround after 10 years :-)

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