我正在玩一些C#,我正在编写钢琴应用程序。
每当用户点击钢琴音符时,我将声音的位置(.wav)存储到列表中...以下是button1_MouseDown方法中的一些代码。
if (e.Button == MouseButtons.Left)
{
SoundPlayer sp = new SoundPlayer();
string musName = Convert.ToString(mk.pitch);
string loc = @"D:\OneDrive\Year 2 Semester 1\OOP\Notes-Sound files\Notes-Sound files\mapped\" + musName + ".wav";
sp.SoundLocation = loc;
sp.Play();
music.Add(loc);
}
现在,我想遍历循环以一次播放所有单击的键。我这样做如下(当用户点击播放按钮时)
int k = 0;
for (k = 1; k < music.Count; k++)
{
SoundPlayer sp = new SoundPlayer();
sp.SoundLocation = music[k];
sp.Play();
}
问题是,只要点击播放按钮,就会播放按下的最后一个音符。但是,当我调试时,不知何故,所有音符都会播放。有什么想法吗?
答案 0 :(得分:5)
根据MSDN,这是Play
方法的说明:
使用新线程播放.wav文件,如果尚未加载,则首先加载.wav文件。
因此,每当您调用Play
时,它都会异步运行,并且您的循环将继续执行播放下一个wav文件,然后再完成当前的文件。在调试时,您可能还在等待,然后继续循环。
相反,请尝试使用PlaySync
同步播放声音
PS。此外,您可能需要考虑在列表中使用SoundPlayer
的实例而不是文件名,以避免每次播放wav文件时都创建新实例:
List<SoundPlayer> music = new List<SoundPlayer>();
//...
//In your first loop, you would add the SoundPlayer object
music.Add(sp);
//..
//Then when you're playing back:
for (int k = 0; k < music.Count; k++)
{
music[k].PlaySync();
}
请注意,for
循环中的索引也应该从0开始
答案 1 :(得分:0)
您可能需要使用Asynchronously
播放声音LoadAsync
,例如:How to: Load a Sound Asynchronously within a Windows Form
答案 2 :(得分:0)
你的主要问题是所有音符都会播放,但后续音符实际上会在第一个音符完成之前开始播放。因此,您只听到最后一个。
使用同时播放声音的PlaySync,如果由于某种原因必须遍历List<>
并说,请在播放前检查每个项目(好吧,至少如果你派生的话) SoundPlayer到另一个类,以便它实际上有东西要检查),你可以使用检查PlaySync调用。
SoundPlayer sp = new SoundPlayer();
foreach(var note in music)
{
sp.SoundLocation = note;
bool everythingIsFine = false;
// Logic for everythingIsFine;
if(everythingIsFine){
sp.PlaySync();
}
}