2024-04-02 21:57:04 +08:00
|
|
|
|
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
|
|
|
|
|
{
|
2024-04-08 21:04:47 +08:00
|
|
|
|
readonly byte[] source_obj;
|
|
|
|
|
readonly MemoryStream sound;
|
|
|
|
|
readonly MemoryStream ms;
|
|
|
|
|
readonly Mp3FileReader ws;
|
|
|
|
|
readonly BlockAlignReductionStream blockAlignReductionStream;
|
|
|
|
|
readonly Wave16ToFloatProvider wave16ToFloatProvider;
|
|
|
|
|
readonly WaveOutEvent waveOutEvent;
|
|
|
|
|
readonly Action<string,AudioPlayer>? finished;
|
|
|
|
|
readonly string file_name;
|
|
|
|
|
bool shuting_down = false;
|
2024-04-02 21:57:04 +08:00
|
|
|
|
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("-", "_");
|
2024-04-08 21:04:47 +08:00
|
|
|
|
source_obj = Etcs.audio_Res_Manager.Get_Audio_Resources(file_name);
|
|
|
|
|
sound = new MemoryStream(source_obj);
|
2024-04-02 21:57:04 +08:00
|
|
|
|
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<string,AudioPlayer> finished)
|
|
|
|
|
{
|
|
|
|
|
this.file_name = file_name;
|
|
|
|
|
this.volume = volume;
|
|
|
|
|
this.finished = finished;
|
2024-04-18 08:38:59 +08:00
|
|
|
|
file_name = file_name.Split('.').First().Replace(" ", "_").Replace("-", "_").Replace(",","_");
|
2024-04-08 21:04:47 +08:00
|
|
|
|
source_obj = Etcs.audio_Res_Manager.Get_Audio_Resources(file_name);
|
|
|
|
|
sound = new MemoryStream(source_obj);
|
2024-04-02 21:57:04 +08:00
|
|
|
|
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)
|
|
|
|
|
{
|
2024-04-08 21:04:47 +08:00
|
|
|
|
if(shuting_down) return;
|
2024-04-02 21:57:04 +08:00
|
|
|
|
finished?.Invoke(file_name,this);
|
|
|
|
|
Dispose();
|
|
|
|
|
}
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
2024-04-08 21:04:47 +08:00
|
|
|
|
shuting_down = true;
|
2024-04-02 21:57:04 +08:00
|
|
|
|
waveOutEvent.Stop();
|
|
|
|
|
sound.Dispose();
|
|
|
|
|
ms.Dispose();
|
2024-04-08 21:04:47 +08:00
|
|
|
|
ws.Dispose();
|
|
|
|
|
blockAlignReductionStream.Dispose();
|
2024-04-02 21:57:04 +08:00
|
|
|
|
waveOutEvent.Dispose();
|
2024-04-08 21:04:47 +08:00
|
|
|
|
GC.SuppressFinalize(this);
|
2024-04-02 21:57:04 +08:00
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|