0

几天来,我一直在玩 SharpDX.XAudio2,虽然事情在很大程度上是积极的(这里和那里奇怪的软件怪癖),但以下问题让我完全陷入困境:

我正在使用 VS2015 在 C# .NET 中工作。
我正在尝试同时播放多个声音。

为此,我做了:
- Test.cs:包含主要方法
- cSoundEngine.cs:包含 XAudio2、MasteringVoice 和声音管理方法。
- VoiceChannel.cs:保存 SourceVoice,以及将来的任何 sfx/相关数据。

cSoundEngine:

    List<VoiceChannel> sourceVoices;
    XAudio2 engine;
    MasteringVoice master;

public cSoundEngine()
    {
        engine = new XAudio2();
        master = new MasteringVoice(engine);
        sourceVoices = new List<VoiceChannel>();
    }

public VoiceChannel AddAndPlaySFX(string filepath, double vol, float pan)
    {
        /**
         * Set up and start SourceVoice
         */
        NativeFileStream fileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
        SoundStream soundStream = new SoundStream(fileStream);
        SourceVoice source = new SourceVoice(engine, soundStream.Format);
        AudioBuffer audioBuffer = new AudioBuffer()
        {
            Stream = soundStream.ToDataStream(),
            AudioBytes = (int)soundStream.Length,
            Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
        };

        //Make voice wrapper
        VoiceChannel voice = new VoiceChannel(source);
        sourceVoices.Add(voice);

        //Volume
        source.SetVolume((float)vol);

        //Play sound
        source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
        source.Start();

        return voice;
    }

测试.cs:

            cSoundEngine engine = new cSoundEngine();
            total = 6;

            for (int i = 0; i < total; i++)
            {
                string filepath = System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.FullName + @"\Assets\Planet.wav";
                VoiceChannel sfx = engine.AddAndPlaySFX(filepath, 0.1, 0);
            }
            Console.Read(); //Input anything to end play.

目前在 VoiceChannel.cs 中没有任何值得展示的内容 - 它包含“SourceVoice source”,这是构造函数中发送的一个参数!

一切都很好,运行良好,最多有 5 种声音(总计 = 5)。您所听到的只是 Planet.wav 的幸福无人机。但是,任何高于 5 的值都会导致控制台冻结约 5 秒,然后关闭(可能是调试器无法处理的 c++ 错误)。可悲的是,没有错误信息可供我们查看或其他任何内容。
来自测试:
- 只要您没有超过 5 个正在运行的源语音,就不会崩溃。
- 改变采样率似乎没有帮助。
- 将主对象的 inputChannels 设置为不同的数字没有区别。
- MasteringVoice 似乎说输入声音的最大数量是 64。
- 从不同的 wav 文件中播放每个 sfx 没有区别。
- 为 sourcevoices 和/或 master 设置音量没有区别。

XAudio2 API 文档中,我发现了这句话:'XAudio2 消除了多声道声音的 6 声道限制,并在任何支持多声道的声卡上支持多声道音频。该卡不需要硬件加速。. 这是我找到提到这个问题的最接近的东西。

我对 sfx 的编程经验并不丰富,其中很多对我来说都很陌生,所以请在适当的时候称我为白痴,但请尝试用外行的方式解释事情。

请,如果您有任何想法或答案,他们将不胜感激!
-乔什

4

1 回答 1

0

正如 Chuck 所建议的那样,我创建了一个保存 .wav 数据的数据库,并且我只是在每个缓冲区中引用单个数据存储。这已将声音限制提高到 20 - 但是这并没有从整体上解决问题,可能是因为我没有正确实现这一点。执行:

class SoundDataBank
{
    /**
     * Holds a single byte array for each sound
     */

    Dictionary<eSFX, Byte[]> bank;
    string curdir => Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;

    public SoundDataBank()
    {
        bank = new Dictionary<eSFX, byte[]>();
        bank.Add(eSFX.planet, NativeFile.ReadAllBytes(curdir + @"\Assets\Planet.wav"));
        bank.Add(eSFX.base1, NativeFile.ReadAllBytes(curdir + @"\Assets\Base.wav"));
    }

    public Byte[] GetSoundData(eSFX sfx)
    {
        byte[] output = bank[sfx];
        return output;
    }

}

在 SoundEngine 中,我们创建一个 SoundBank 对象(在 SoundEngine 构造函数中初始化):

    SoundDataBank soundBank;

    public VoiceChannel AddAndPlaySFXFromStore(eSFX sfx, double vol)
    {
        /**
         * sourcevoice will be automatically added to MasteringVoice and engine in the constructor.
         */
        byte[] buffer = soundBank.GetSoundData(sfx);
        MemoryStream memoryStream = new MemoryStream(buffer);
        SoundStream soundStream = new SoundStream(memoryStream);
        SourceVoice source = new SourceVoice(engine, soundStream.Format);
        AudioBuffer audioBuffer = new AudioBuffer()
        {
            Stream = soundStream.ToDataStream(),
            AudioBytes = (int)soundStream.Length,
            Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
        };


        //Make voice wrapper
        VoiceChannel voice = new VoiceChannel(source, engine, MakeOutputMatrix());

        //Volume
        source.SetVolume((float)vol);

        //Play sound
        source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
        source.Start();

        sourceVoices.Add(voice);

        return voice;
    }

现在按照这个实现,我可以播放多达 20 种音效 - 但不是因为我们是从音库播放的。事实上,即使运行旧的音效方法,现在也能获得多达 20 个 sfx 实例。

由于我们在 SoundBank 的构造函数中完成了 NativeFile.ReadAllBytes(curdir + @"\Assets\Base.wav"),因此这已提高到 20 个。

我怀疑 NativeFile 保存了已加载文件数据的存储,因此无论您运行原始的 SoundEngine.AddAndPlaySFX() 还是 SoundEngine.AddAndPlaySFXFromStore(),它们都是从内存中运行的?

无论哪种方式,这比以前的限制增加了四倍,所以这非常有用 - 但需要进一步的工作。

于 2018-12-03T21:14:04.600 回答