mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-06 04:25:05 -04:00
111 lines
2.9 KiB
C#
111 lines
2.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using OpenTK;
|
|
using SharpWave;
|
|
using SharpWave.Codecs;
|
|
using SharpWave.Codecs.Vorbis;
|
|
|
|
namespace ClassicalSharp.Audio {
|
|
|
|
public sealed partial class AudioPlayer {
|
|
|
|
Soundboard digBoard, stepBoard;
|
|
const int maxSounds = 10;
|
|
Sound[] pending;
|
|
int pendingCount;
|
|
|
|
public void SetSound( bool enabled ) {
|
|
if( enabled )
|
|
InitSound();
|
|
else
|
|
DisposeSound();
|
|
}
|
|
|
|
void InitSound() {
|
|
disposingSound = false;
|
|
if( digBoard == null )
|
|
InitSoundboards();
|
|
|
|
soundContainer = new BinContainer( 44100, maxSounds );
|
|
pending = new Sound[maxSounds];
|
|
soundCodec = (BinCodec)soundContainer.GetAudioCodec();
|
|
soundThread = MakeThread( DoSoundThread, ref soundOut,
|
|
"ClassicalSharp.DoSound" );
|
|
}
|
|
|
|
EventWaitHandle soundHandle = new EventWaitHandle( false, EventResetMode.AutoReset );
|
|
BinContainer soundContainer;
|
|
BinCodec soundCodec;
|
|
|
|
void DoSoundThread() {
|
|
while( !disposingSound ) {
|
|
soundHandle.WaitOne();
|
|
if( disposingSound ) break;
|
|
|
|
soundOut.PlayStreaming( soundContainer );
|
|
}
|
|
}
|
|
|
|
public void Tick( double delta ) {
|
|
if( pendingCount > 0 ) {
|
|
Sound snd = pending[0];
|
|
byte[] data = snd.Metadata == 1 ? digBoard.Data : stepBoard.Data;
|
|
|
|
soundCodec.AddSound( data, snd.Offset, snd.Length, snd.Channels );
|
|
RemoveFirstPendingSound();
|
|
soundHandle.Set();
|
|
}
|
|
}
|
|
|
|
public void PlayDigSound( SoundType type ) { PlaySound( type, digBoard ); }
|
|
|
|
public void PlayStepSound( SoundType type ) { PlaySound( type, stepBoard ); }
|
|
|
|
void PlaySound( SoundType type, Soundboard board ) {
|
|
if( type == SoundType.None || soundOut == null )
|
|
return;
|
|
Sound target = board.PlayRandomSound( type );
|
|
target.Metadata = board == digBoard ? (byte)1 : (byte)2;
|
|
Console.WriteLine( "ADD " + target.Offset + " : " + target.Length + " : " + target.Channels );
|
|
|
|
if( pendingCount == maxSounds )
|
|
RemoveFirstPendingSound();
|
|
pending[pendingCount++] = target;
|
|
}
|
|
|
|
void MakeSound( ref Sound src, ref bool play, AudioChunk target ) {
|
|
if( src == null ) return;
|
|
play = true;
|
|
|
|
target.Frequency = src.SampleRate;
|
|
target.BitsPerSample = src.BitsPerSample;
|
|
target.Channels = src.Channels;
|
|
|
|
target.BytesOffset = src.Offset;
|
|
target.BytesUsed = src.Length;
|
|
src = null;
|
|
}
|
|
|
|
void RemoveFirstPendingSound() {
|
|
for( int i = 1; i < maxSounds - 1; i++ )
|
|
pending[i] = pending[i + 1];
|
|
pending[maxSounds - 1] = null;
|
|
pendingCount--;
|
|
}
|
|
|
|
void DisposeSound() {
|
|
disposingSound = true;
|
|
soundHandle.Set();
|
|
DisposeOf( ref soundOut, ref soundThread );
|
|
}
|
|
|
|
void InitSoundboards() {
|
|
digBoard = new Soundboard();
|
|
digBoard.Init( "dig" );
|
|
stepBoard = new Soundboard();
|
|
stepBoard.Init( "step" );
|
|
}
|
|
}
|
|
}
|