using NAudio.Wave; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; namespace CDSAE3_Lian_Lian_Kan.Sound { internal class AudioPlayer : IDisposable { readonly byte[] source_obj; readonly MemoryStream sound; readonly MemoryStream ms; readonly Mp3FileReader ws; readonly BlockAlignReductionStream blockAlignReductionStream; readonly Wave16ToFloatProvider wave16ToFloatProvider; readonly WaveOutEvent waveOutEvent; readonly Action? finished; readonly string file_name; bool shuting_down = false; internal int volume { get; set; } internal AudioPlayer(string file_name, int volume) { this.file_name = file_name; this.volume = volume; file_name = file_name.Split('.').First().Replace(" ", "_").Replace("-", "_"); source_obj = Etcs.audio_Res_Manager.Get_Audio_Resources(file_name); sound = new MemoryStream(source_obj); ms = new MemoryStream(StreamToBytes(sound)); ws = new Mp3FileReader(ms); blockAlignReductionStream = new BlockAlignReductionStream(ws); wave16ToFloatProvider = new Wave16ToFloatProvider(blockAlignReductionStream); wave16ToFloatProvider.Volume = volume / 100f; waveOutEvent = new WaveOutEvent(); waveOutEvent.Init(wave16ToFloatProvider); waveOutEvent.PlaybackStopped += WaveOutEvent_PlaybackStopped; } internal AudioPlayer(string file_name, int volume, Action finished) { this.file_name = file_name; this.volume = volume; this.finished = finished; file_name = file_name.Split('.').First().Replace(" ", "_").Replace("-", "_").Replace(",","_"); source_obj = Etcs.audio_Res_Manager.Get_Audio_Resources(file_name); sound = new MemoryStream(source_obj); ms = new MemoryStream(StreamToBytes(sound)); ws = new Mp3FileReader(ms); blockAlignReductionStream = new BlockAlignReductionStream(ws); wave16ToFloatProvider = new Wave16ToFloatProvider(blockAlignReductionStream); wave16ToFloatProvider.Volume = volume / 100f; waveOutEvent = new WaveOutEvent(); waveOutEvent.Init(wave16ToFloatProvider); waveOutEvent.PlaybackStopped += WaveOutEvent_PlaybackStopped; } public void volume_change(int val) { volume = val; wave16ToFloatProvider.Volume = volume / 100f; } public void pause_song() => waveOutEvent.Pause(); public void resume_song() => waveOutEvent.Play(); private void WaveOutEvent_PlaybackStopped(object? sender, StoppedEventArgs e) { if(shuting_down) return; finished?.Invoke(file_name,this); Dispose(); } public void Dispose() { shuting_down = true; waveOutEvent.Stop(); sound.Dispose(); ms.Dispose(); try { ws.Dispose(); }catch(Exception) { } blockAlignReductionStream.Dispose(); waveOutEvent.Dispose(); GC.SuppressFinalize(this); } internal static byte[] StreamToBytes(Stream stream) { long originalPosition = 0; if (stream.CanSeek) { originalPosition = stream.Position; stream.Position = 0; } try { byte[] readBuffer = new byte[4096]; int totalBytesRead = 0; int bytesRead; while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0) { totalBytesRead += bytesRead; if (totalBytesRead == readBuffer.Length) { int nextByte = stream.ReadByte(); if (nextByte != -1) { byte[] temp = new byte[readBuffer.Length * 2]; Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length); Buffer.SetByte(temp, totalBytesRead, (byte)nextByte); readBuffer = temp; totalBytesRead++; } } } byte[] buffer = readBuffer; if (readBuffer.Length != totalBytesRead) { buffer = new byte[totalBytesRead]; Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead); } return buffer; } finally { if (stream.CanSeek) { stream.Position = originalPosition; } } } } }