Список обхода 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();
 }

Дело в том, что всякий раз, когда нажимается кнопка воспроизведения, воспроизводится только последняя нажатая нота. Однако, когда я каким-то образом отлаживаю, воспроизводятся все ноты. Любые идеи?


person Axel    schedule 30.11.2016    source источник
comment
Привет, я думаю, что вам нужно дождаться воспроизведения каждой ноты, прежде чем играть следующую   -  person j_freyre    schedule 30.11.2016
comment
Я также предполагаю, что вам не нужно будет инициализировать нового игрока в каждой отдельной итерации, но вне цикла.   -  person HimBromBeere    schedule 30.11.2016


Ответы (3)


Согласно 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.

person KMoussa    schedule 30.11.2016
comment
@KMoussa Где мне разместить 'var music = new List‹SoundPlayer›();' - person Axel; 30.11.2016
comment
@AxelAzzopardi вместо music списка/массива strings, которые вы сейчас объявляете - person KMoussa; 30.11.2016
comment
Разве вызов PlaySync на других SoundPlayers, как в этом примере, не приведет к фактическому запуску асинхронно? Как music[1] узнает, что музыка[0] закончила играть? Не лучше ли просто запустить один MusicPlayer, а затем изменить SoundLocation в цикле и играть синхронно? - person Jerri Kangasniemi; 30.11.2016
comment
@KMoussa Произошла ошибка, поскольку var может появляться только в объявлении локальной переменной. У меня есть 2 метода. Если я помещу его в один метод, другой метод его не найдет. - person Axel; 30.11.2016
comment
@AxelAzzopardi извините за ошибку, вы не можете использовать var для членов класса, попробуйте List<SoundPlayer> music = new List<SoundPlayer>(); в качестве поля в своем классе - person KMoussa; 30.11.2016
comment
@JerriKangasniemi Я не думаю, что вызов PlaySync в том же экземпляре или нет, повлияет на то, является ли он синхронным или асинхронным, метод синхронизации не вернет управление циклу до тех пор, пока не будет воспроизведен звук, поэтому цикл не будет продолжаться до этого. Вы можете быть правы с точки зрения производительности, но я не уверен - person KMoussa; 30.11.2016
comment
@KMoussa ты легенда - person Axel; 30.11.2016
comment
@AxelAzzopardi :) - person KMoussa; 30.11.2016

вам может понадобиться воспроизвести звук Asynchronously с помощью LoadAsync, как здесь: Как: асинхронно загрузить звук в форме Windows

person Rahul Hendawe    schedule 30.11.2016

Ваша основная проблема заключается в том, что все ноты воспроизводятся, но последующие ноты фактически начинают воспроизводиться до того, как первая будет сделана. Таким образом, вы слышите только последнее.

Используйте PlaySync, который воспроизводит звуки синхронно, и если вам по какой-то причине нужно пройти через List<> и сказать, сделайте проверку каждого элемента перед воспроизведением (ну, по крайней мере, если вы унаследуете SoundPlayer от другого класса, чтобы у него действительно было что-то для check), вы можете использовать проверку для вызова PlaySync.

SoundPlayer sp = new SoundPlayer();

foreach(var note in music)
{
    sp.SoundLocation = note;
    bool everythingIsFine = false;

    // Logic for everythingIsFine;

    if(everythingIsFine){
        sp.PlaySync(); 
    }
}
person Jerri Kangasniemi    schedule 30.11.2016