1

我正在尝试制作乐器类型的应用程序。我遇到的问题是只有在旧声音完成后才会播放新声音。我希望能够同时播放它们。

这就是我的代码的样子:

首先,MyWave 类只保存一个音频缓冲区和一些其他信息:

class MyWave
{
    public AudioBuffer Buffer { get; set; }
    public uint[] DecodedPacketsInfo { get; set; }
    public WaveFormat WaveFormat { get; set; }
}

在 SoundPlayer 类中:

    private XAudio2 xaudio;
    private MasteringVoice mvoice;
    Dictionary<string, MyWave> sounds;

    // Constructor
    public SoundPlayer()
    {
        xaudio = new XAudio2();
        xaudio.StartEngine();
        mvoice = new MasteringVoice(xaudio);
        sounds = new Dictionary<string, MyWave>();
    }

    // Reads a sound and puts it in the dictionary
    public void AddWave(string key, string filepath)
    {
        MyWave wave = new MyWave();

        var nativeFileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read, NativeFileShare.Read);
        var soundStream = new SoundStream(nativeFileStream);
        var buffer = new AudioBuffer() { Stream = soundStream, AudioBytes = (int)soundStream.Length, Flags = BufferFlags.EndOfStream };

        wave.Buffer = buffer;
        wave.DecodedPacketsInfo = soundStream.DecodedPacketsInfo;
        wave.WaveFormat = soundStream.Format;

        this.sounds.Add(key, wave);
    }

    // Plays the sound
    public void Play(string key)
    {
        if (!this.sounds.ContainsKey(key)) return;
        MyWave w = this.sounds[key];

        var sourceVoice = new SourceVoice(this.xaudio, w.WaveFormat);
        sourceVoice.SubmitSourceBuffer(w.Buffer, w.DecodedPacketsInfo);
        sourceVoice.Start();
    }
}

谷歌不是很有帮助,我找不到任何有用的东西。那么如何同时播放多个声音呢?

4

2 回答 2

3

您必须创建(最好是池)多个 SourceVoice 实例并同时播放它们。

实际上,您当前的代码应该可以工作,不是吗?您可能希望将 StreamEnd 事件侦听器添加到 SourceVoice 以在播放完成后自行处理,并记住在调用 SourceVoice 的构造函数时启用回调。

于 2013-02-07T14:55:17.557 回答
0

只需将 mciSendString 与打开和播放命令一起使用。此示例在启动时一起播放 note1.wav 和 note2.wav。

[System.Runtime.InteropServices.DllImport("winmm.dll")]
static extern Int32 mciSendString(string command,                                             
                                  StringBuilder buffer, 
                                  int bufferSize, 
                                  IntPtr hwndCallback);

        public frmGame()
        {
            InitializeComponent();
            DoubleBuffered = true;            
            mciSendString("open note1.wav type waveaudio  alias s1", null, 0, IntPtr.Zero);
            mciSendString("play s1", null, 0, IntPtr.Zero);
            mciSendString("open note2.wav type waveaudio  alias s2", null, 0, IntPtr.Zero);
            mciSendString("play s2", null, 0, IntPtr.Zero);
        }        
于 2021-01-29T14:13:24.537 回答