Axel Azzopardi Axel Azzopardi - 7 days ago 5
C# Question

Traversing List C#

I am playing around with some C# and I was coding a piano application.

Whenever the user clicks a piano note, I am storing the location of the sound (.wav) into a list... the following is some code in the button1_MouseDown method.

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);
}


Now, I want to traverse the loop to play all the clicked keys at one go. I am doing this as follows (when user clicks on the play button)

int k = 0;
for (k = 1; k < music.Count; k++)
{
SoundPlayer sp = new SoundPlayer();
sp.SoundLocation = music[k];
sp.Play();
}


The thing is, that whenever the play button is clicked only the last note pressed is played.However, when I debug, somehow, all the notes are played. Any ideas?

Answer

According to MSDN, this is the description of the Play method:

Plays the .wav file using a new thread, and loads the .wav file first if it has not been loaded.

So whenever you invoke Play, it's runs asynchronously and your loop continues to execute playing the next wav file before the current one is completed. When you debug, you are probably waiting anyways before proceeding in the loop.

Instead, try using PlaySync to play the sound synchronously

PS. Also, you might want to consider using the instances of SoundPlayer in your list instead of the filename to avoid creating new instances each time you play the wav file:

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();
}

Note that the index in the for loop should start at 0 as well