ClassiCube/ClassicalSharp/Audio/AudioPlayer.Sounds.cs

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" );
}
}
}