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