我正在尝试制作乐器类型的应用程序。我遇到的问题是只有旧的声音完成后才能播放新的声音。我希望能够同时播放它们。
这就是我的代码的样子:
首先,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();
}
}
谷歌不是很有帮助,我找不到任何有用的东西。那么如何同时播放多个声音呢?
答案 0 :(得分:2)
您必须创建(最好是池)多个SourceVoice实例并同时播放它们。
事实上,您当前的代码应该有效,不是吗?您可能希望在回放完成后将SourceEnd事件侦听器添加到SourceVoice以自行处理,并记住在调用SourceVoice的构造函数时启用回调。
答案 1 :(得分:0)
只需将 mciSendString 与 open 和 play 命令一起使用。此示例在启动时一起播放 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);
}