如何用XAudio2重复播放相同的声音?

发布于 2024-12-21 09:48:54 字数 1462 浏览 2 评论 0原文

我需要使用 XAudio2 在我的应用程序中重复播放单个声音,例如枪声。

这是我为此目的编写的代码的一部分:

public sealed class X2SoundPlayer : IDisposable
    {
        private readonly WaveStream _stream;
        private readonly AudioBuffer _buffer;
        private readonly SourceVoice _voice;

        public X2SoundPlayer(XAudio2 device, string pcmFile)
        {
            var fileStream = File.OpenRead(pcmFile);
            _stream = new WaveStream(fileStream);
            fileStream.Close();

            _buffer = new AudioBuffer
                          {
                              AudioData = _stream,
                              AudioBytes = (int) _stream.Length,
                              Flags = BufferFlags.EndOfStream

                          };

            _voice = new SourceVoice(device, _stream.Format);
        }

        public void Play()
        {
            _voice.SubmitSourceBuffer(_buffer);
            _voice.Start();
        }

        public void Dispose()
        {
            _stream.Close();
            _stream.Dispose();
            _buffer.Dispose();
            _voice.Dispose();
        }
    }

上面的代码实际上基于 SlimDX 示例。

它现在所做的是,当我重复调用 Play() 时,声音播放如下:

声音->声音->声音

所以它只是填充缓冲区并播放它。

但是,我需要能够在当前声音正在播放时播放相同的声音,因此这两个或更多声音应该同时混合和播放。

这里是否有我错过的东西,或者我当前的解决方案不可能(也许 SubmixVoices 可以提供帮助)?

我试图在文档中找到相关的内容,但没有成功,并且网上没有太多可以参考的示例。

谢谢。

I need to play single sound repeatedly in my app, for example, a gunshot, using XAudio2.

This is the part of the code I wrote for that purpose:

public sealed class X2SoundPlayer : IDisposable
    {
        private readonly WaveStream _stream;
        private readonly AudioBuffer _buffer;
        private readonly SourceVoice _voice;

        public X2SoundPlayer(XAudio2 device, string pcmFile)
        {
            var fileStream = File.OpenRead(pcmFile);
            _stream = new WaveStream(fileStream);
            fileStream.Close();

            _buffer = new AudioBuffer
                          {
                              AudioData = _stream,
                              AudioBytes = (int) _stream.Length,
                              Flags = BufferFlags.EndOfStream

                          };

            _voice = new SourceVoice(device, _stream.Format);
        }

        public void Play()
        {
            _voice.SubmitSourceBuffer(_buffer);
            _voice.Start();
        }

        public void Dispose()
        {
            _stream.Close();
            _stream.Dispose();
            _buffer.Dispose();
            _voice.Dispose();
        }
    }

The code above is actually based on SlimDX sample.

What it does now is, when I call Play() repeatedly, the sound plays like:

sound -> sound -> sound

So it just fills the buffer and plays it.

But, I need to be able to play the same sound while the current one is playing, so effectively these two or more should mix and play at the same time.

Is there something here that I've missed, or it's not possible with my current solution (perhaps SubmixVoices could help)?

I'm trying to find something related in docs, but I've had no success, and there are not many examples online I could reference.

Thanks.

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

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

发布评论

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

评论(1

辞别 2024-12-28 09:48:54

虽然为此目的使用 XACT 是更好的选择,因为它支持声音提示(正是我所需要的),但我确实设法让它以这种方式工作。

我更改了代码,以便它始终从流中创建新的 SourceVoice 对象并播放它。

        // ------ code piece 

        /// <summary>
        /// Gets the available voice.
        /// </summary>
        /// <returns>New SourceVoice object is always returned. </returns>
        private SourceVoice GetAvailableVoice()
        {
            return new SourceVoice(_player.GetDevice(), _stream.Format);
        }

        /// <summary>
        /// Plays this sound asynchronously.
        /// </summary>
        public void Play()
        {
            // get the next available voice
            var voice = GetAvailableVoice();
            if (voice != null)
            {
                // submit new buffer and start playing.
                voice.FlushSourceBuffers();
                voice.SubmitSourceBuffer(_buffer);

                voice.Start();
            }
        }

Although it's better option to use XACT for this purpose because it supports sound cues (exactly what I needed), I did managed to get it working this way.

I've changed the code so it would always create new SourceVoice object from the stream and play it.

        // ------ code piece 

        /// <summary>
        /// Gets the available voice.
        /// </summary>
        /// <returns>New SourceVoice object is always returned. </returns>
        private SourceVoice GetAvailableVoice()
        {
            return new SourceVoice(_player.GetDevice(), _stream.Format);
        }

        /// <summary>
        /// Plays this sound asynchronously.
        /// </summary>
        public void Play()
        {
            // get the next available voice
            var voice = GetAvailableVoice();
            if (voice != null)
            {
                // submit new buffer and start playing.
                voice.FlushSourceBuffers();
                voice.SubmitSourceBuffer(_buffer);

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