mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-10 00:20:36 -04:00
Removed NioTSO client and server
- NioTSO client isn't needed because we're using RayLib - Added FreeSO's API server to handle most backend operations
This commit is contained in:
parent
f12ba1502b
commit
22191ce648
591 changed files with 53264 additions and 3362 deletions
288
server/tso.common/Audio/MP3Player.cs
Executable file
288
server/tso.common/Audio/MP3Player.cs
Executable file
|
@ -0,0 +1,288 @@
|
|||
using Mp3Sharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FSO.Common.Audio
|
||||
{
|
||||
public class MP3Player : ISFXInstanceLike
|
||||
{
|
||||
public static bool NewMode = true;
|
||||
|
||||
private Mp3Stream Stream;
|
||||
public DynamicSoundEffectInstance Inst;
|
||||
private int LastChunkSize = 1; //don't die immediately..
|
||||
private Thread DecoderThread;
|
||||
|
||||
private List<byte[]> NextBuffers = new List<byte[]>();
|
||||
private List<int> NextSizes = new List<int>();
|
||||
private int Requests;
|
||||
private AutoResetEvent DecodeNext;
|
||||
private AutoResetEvent BufferDone;
|
||||
private bool EndOfStream;
|
||||
private bool Active = true;
|
||||
private Thread MainThread; //keep track of this, terminate when it closes.
|
||||
|
||||
private SoundState _State = SoundState.Stopped;
|
||||
private bool Disposed = false;
|
||||
|
||||
private float _Volume = 1f;
|
||||
private float _Pan;
|
||||
|
||||
private object ControlLock = new object();
|
||||
private string Path;
|
||||
public int SendExtra = 2;
|
||||
|
||||
private static byte[] Blank = new byte[65536];
|
||||
|
||||
public MP3Player(string path)
|
||||
{
|
||||
Path = path;
|
||||
// //let's get started...
|
||||
|
||||
DecodeNext = new AutoResetEvent(true);
|
||||
BufferDone = new AutoResetEvent(false);
|
||||
MainThread = Thread.CurrentThread;
|
||||
|
||||
Task.Run((Action)Start);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
Stream = new Mp3Stream(Path);
|
||||
Stream.DecodeFrames(1);
|
||||
var freq = Stream.Frequency;
|
||||
lock (ControlLock)
|
||||
{
|
||||
if (Disposed) return;
|
||||
Inst = new DynamicSoundEffectInstance(freq, AudioChannels.Stereo);
|
||||
Inst.IsLooped = false;
|
||||
Inst.BufferNeeded += SubmitBufferAsync;
|
||||
if (_State == SoundState.Playing) Inst.Play();
|
||||
else if (_State == SoundState.Paused)
|
||||
{
|
||||
Inst.Play();
|
||||
Inst.Pause();
|
||||
}
|
||||
Inst.Volume = _Volume;
|
||||
Inst.Pan = _Pan;
|
||||
Requests = 2;
|
||||
}
|
||||
|
||||
//SubmitBuffer(null, null);
|
||||
//SubmitBuffer(null, null);
|
||||
|
||||
DecoderThread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
while (Active && MainThread.IsAlive)
|
||||
{
|
||||
DecodeNext.WaitOne(128);
|
||||
bool go;
|
||||
lock (this) go = Requests > 0;
|
||||
while (go)
|
||||
{
|
||||
var buf = new byte[262144];// 524288];
|
||||
var read = Stream.Read(buf, 0, buf.Length);
|
||||
lock (this)
|
||||
{
|
||||
Requests--;
|
||||
NextBuffers.Add(buf);
|
||||
NextSizes.Add(read);
|
||||
if (read == 0)
|
||||
{
|
||||
EndOfStream = true;
|
||||
BufferDone.Set();
|
||||
return;
|
||||
}
|
||||
BufferDone.Set();
|
||||
}
|
||||
lock (this) go = Requests > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) { }
|
||||
});
|
||||
DecoderThread.Start();
|
||||
DecodeNext.Set();
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
_State = SoundState.Playing;
|
||||
Inst?.Play();
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
_State = SoundState.Stopped;
|
||||
Inst?.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
_State = SoundState.Paused;
|
||||
Inst?.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
_State = SoundState.Playing;
|
||||
Inst?.Resume();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
Disposed = true;
|
||||
Inst?.Dispose();
|
||||
Stream?.Dispose();
|
||||
|
||||
Active = false;
|
||||
DecodeNext.Set(); //end the mp3 thread immediately
|
||||
|
||||
EndOfStream = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnded()
|
||||
{
|
||||
return EndOfStream && Inst.PendingBufferCount == 0;
|
||||
}
|
||||
|
||||
public float Volume
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
if (Inst != null) return Inst.Volume;
|
||||
else return _Volume;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
_Volume = value;
|
||||
if (Inst != null) Inst.Volume = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float Pan
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
if (Inst != null) return Inst.Pan;
|
||||
else return _Pan;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
_Pan = value;
|
||||
if (Inst != null) Inst.Pan = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SoundState State
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (ControlLock)
|
||||
{
|
||||
if (Inst != null) return Inst.State;
|
||||
else return _State;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsLooped { get; set; }
|
||||
|
||||
private void SubmitBuffer(object sender, EventArgs e)
|
||||
{
|
||||
byte[] buffer = new byte[524288];
|
||||
lock (this)
|
||||
{
|
||||
var read = Stream.Read(buffer, 0, buffer.Length);
|
||||
LastChunkSize = read;
|
||||
if (read == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Inst.SubmitBuffer(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
|
||||
private void SubmitBufferAsync(object sender, EventArgs e)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (EndOfStream) return;
|
||||
var gotData = false;
|
||||
lock (this)
|
||||
{
|
||||
if (NextBuffers.Count > 0)
|
||||
{
|
||||
if (NextSizes[0] > 0) Inst.SubmitBuffer(NextBuffers[0], 0, NextSizes[0]);
|
||||
gotData = true;
|
||||
NextBuffers.RemoveAt(0);
|
||||
NextSizes.RemoveAt(0);
|
||||
Requests++;
|
||||
DecodeNext.Set();
|
||||
if (SendExtra > 0)
|
||||
{
|
||||
SendExtra--;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (EndOfStream) return;
|
||||
}
|
||||
if (!gotData)
|
||||
{
|
||||
Inst.SubmitBuffer(Blank, 0, Blank.Length);
|
||||
Requests++;
|
||||
DecodeNext.Set();
|
||||
return;
|
||||
//if (NewMode) BufferDone.WaitOne(128);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ISFXInstanceLike
|
||||
{
|
||||
float Volume { get; set; }
|
||||
float Pan { get; set; }
|
||||
SoundState State { get; }
|
||||
bool IsLooped { get; set; }
|
||||
void Play();
|
||||
void Stop();
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Dispose();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue