C# WPF — NAudio.dll — Аудио полностью прекращает воспроизведение после вызова Остановки, паузы или удаления

#c# #wpf #audio #naudio

Вопрос:

Поэтому я пытаюсь остановить воспроизведение текущего аудио и пытаюсь воспроизвести новое аудио в другом файле. Я использую NAudio.dll

Попытка снова вызвать новый звук приводит к перекрытию звуков. Это делается с помощью:

 SoundPlayer.Instance.Play(new MainSound()); SoundPlayer.Instance.Play(new MainSecondSound());  

Оба этих класса выглядят так, как будто это только что изменилось, поэтому в имени класса указано: MainSound и MainSecondSound:

 class MainSound : SoundTrack  {  public MainSound() : base("SoundName.wav") { }  }  

Или того же результата можно достичь с помощью

 SoundPlayer.Instance.Play("path/to/file/sound.wav"); SoundPlayer.Instance.Play("path/to/file/sound.wav");  

вызов Device.Dispose(); Device.Pause(); или Device.Stop(); приводит к полному прекращению работы проигрывателя , чтобы звуки не воспроизводились снова. Это не то, чего я пытаюсь достичь. Я хочу MainSound перестать играть и MainSecondSound начать. Вот как выглядят мои классы аудиоплееров:

 using NAudio.Wave;  namespace Ball_Rush.Audio {  class AutoDisposableStream : ISampleProvider  {  private readonly AudioFileReader reader;  private bool IsDisposed;   public AutoDisposableStream(AudioFileReader reader)  {  this.reader = reader;  this.WaveFormat = reader.WaveFormat;  }    public int Read(float[] buffer, int offset, int count)  {  if (IsDisposed)  return 0;  int read = reader.Read(buffer, offset, count);  if (read == 0)  {  reader.Dispose();  IsDisposed = true;  }  return read;  }   public WaveFormat WaveFormat { get; private set; }  } }  

Приведенный выше класс используется, если вы вызываете имя файла, например: SoundPlayer.Instance.Play("path/to/file/sound.wav");

 using NAudio.Wave; using NAudio.Wave.SampleProviders; using System; using Ball_Rush.Game;  namespace Ball_Rush.Audio {  class SoundPlayer : IDisposable  {  private static WaveOutEvent Device { get; set; }    private static MixingSampleProvider Mixer { get; set; }   private static MixingSampleProvider Mixer2 { get; set; }   public static readonly SoundPlayer Instance = new SoundPlayer(44100, 2);   public static PlaybackState State { get { return Device.PlaybackState; } }  public static float Volume { get { return Device.Volume; } set { Device.Volume = value; } }  public static bool DestroyOnPlaybackEnd { get; set; }    public SoundPlayer(int sampleRate = 44100, int channelCount = 2)  {  Device = new WaveOutEvent();  Mixer = new MixingSampleProvider(WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channelCount));  Mixer.ReadFully = true;  Volume = GameMaster.Settings.Volume;  Device.Init(Mixer);  Device.Play();  }    private void AddMixerInput(ISampleProvider input)  {  Mixer.AddMixerInput(ConvertToRightChannelCount(input));  }   private ISampleProvider ConvertToRightChannelCount(ISampleProvider input)  {  if (input.WaveFormat.Channels == Mixer.WaveFormat.Channels)  {  return input;  }  if (input.WaveFormat.Channels == 1 amp;amp; Mixer.WaveFormat.Channels == 2)  {  return new MonoToStereoSampleProvider(input);  }  return null;  }   public void Play(string fileName)  {  if (String.IsNullOrWhiteSpace(fileName))  return;   var input = new AudioFileReader(fileName);  Volume = GameMaster.Settings.Volume;  input.Volume = Volume;  AddMixerInput(new AutoDisposableStream(input));  }   public void Play(SoundTrack track)  {  if (track == null)  {  return;  }   Volume = GameMaster.Settings.Volume;  AddMixerInput(new SoundTrackSampleProvider(track));  }   public void Pause()  {  Device.Pause();  }   public void Stop()  {  Device.Stop();  }   public void Dispose()  {  Device.Dispose();  }  } }  

The above class is the main soundplayer. This is what I use to play sounds.

 using System; using NAudio.Wave; using System.IO; using System.Collections.Generic; using System.Linq; using Ball_Rush.Extensions;  namespace Ball_Rush.Audio {  class SoundTrack  {  public string FileName { get; set; }  public float[] AudioData { get; private set; }  public WaveFormat WaveFormat { get; private set; }   public SoundTrack(string fileName)  {  FileName = fileName;   using (var audioFileReader = new AudioFileReader(IO.GlobalPaths.Audio   FileName))  {  WaveFormat = audioFileReader.WaveFormat;  var wholeFile = new Listlt;floatgt;((int)(audioFileReader.Length / 4));  var readBuffer = new float[audioFileReader.WaveFormat.SampleRate * audioFileReader.WaveFormat.Channels];  int samplesRead;  while ((samplesRead = audioFileReader.Read(readBuffer, 0, readBuffer.Length)) gt; 0)  {  wholeFile.AddRange(readBuffer.Take(samplesRead));  }  AudioData = wholeFile.ToArray();  }  }   public static SoundTrack GetAnyWithKey(string key)  {  if (String.IsNullOrWhiteSpace(key))  return null;   string[] files = Directory.GetFiles(IO.GlobalPaths.Audio);   Listlt;stringgt; found = new Listlt;stringgt;();   foreach (var file in files)  if (file.Contains(key))  found.Add(Path.GetFileName(file));   if (found.Count == 0)  return null;   return new SoundTrack(found.PickAny());  }  } }  

The above class gets the file and processes it

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NAudio.Wave;  namespace Ball_Rush.Audio {  class SoundTrackSampleProvider : ISampleProvider  {  private readonly SoundTrack Track;  private long position;   public SoundTrackSampleProvider(SoundTrack track)  {  this.Track = track;  }   public int Read(float[] buffer, int offset, int count)  {  var availableSamples = Track.AudioData.Length - position;  var samplesToCopy = Math.Min(availableSamples, count);  Array.Copy(Track.AudioData, position, buffer, offset, samplesToCopy);  position  = samplesToCopy;  return (int)samplesToCopy;  }   public WaveFormat WaveFormat { get { return Track.WaveFormat; } }  } }  

Этот используется для вызова такого класса, как: SoundPlayer.Instance.Play(new MainSound());