Add partially working dig sounds.

This commit is contained in:
UnknownShadow200 2015-11-27 22:38:43 +11:00
parent f864d0e527
commit 4d7ca25459
6 changed files with 153 additions and 47 deletions

View File

@ -17,7 +17,8 @@ namespace ClassicalSharp {
// Column 1 // Column 1
Make( -140, -150, "Use sound (WIP)", Anchor.Centre, OnWidgetClick, Make( -140, -150, "Use sound (WIP)", Anchor.Centre, OnWidgetClick,
g => g.UseSound ? "yes" : "no", g => g.UseSound ? "yes" : "no",
(g, v) => g.UseSound = v == "yes" ), (g, v) => { g.UseSound = v == "yes";
g.AudioManager.SetSound( g.UseSound ); } ),
Make( -140, -100, "Show hover names", Anchor.Centre, OnWidgetClick, Make( -140, -100, "Show hover names", Anchor.Centre, OnWidgetClick,
g => g.Players.ShowHoveredNames ? "yes" : "no", g => g.Players.ShowHoveredNames ? "yes" : "no",
@ -51,7 +52,7 @@ namespace ClassicalSharp {
Make( 140, -150, "Use music (WIP)", Anchor.Centre, OnWidgetClick, Make( 140, -150, "Use music (WIP)", Anchor.Centre, OnWidgetClick,
g => g.UseMusic ? "yes" : "no", g => g.UseMusic ? "yes" : "no",
(g, v) => { g.UseMusic = v == "yes"; (g, v) => { g.UseMusic = v == "yes";
g.AudioManager.SetState( g.UseMusic ); } ), g.AudioManager.SetMusic( g.UseMusic ); } ),
Make( 140, -100, "View bobbing", Anchor.Centre, OnWidgetClick, Make( 140, -100, "View bobbing", Anchor.Centre, OnWidgetClick,
g => g.ViewBobbing ? "yes" : "no", g => g.ViewBobbing ? "yes" : "no",

View File

@ -0,0 +1,104 @@
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 AudioManager {
Soundboard digBoard, stepBoard;
public void SetSound( bool enabled ) {
if( enabled )
InitSound();
else
DisposeSound();
}
void InitSound() {
disposingSound = false;
if( digBoard == null ) InitSoundboards();
soundThread = MakeThread( DoSoundThread, ref soundOut,
"ClassicalSharp.DoSound" );
}
AudioChunk soundChunk = new AudioChunk();
object soundLock = new object();
volatile int soundsCount = 0;
const int maxSounds = 5;
Sound[] sounds = new Sound[maxSounds];
byte[][] soundDatas = new byte[maxSounds][];
void DoSoundThread() {
while( !disposingSound ) {
bool playSound = false;
lock( soundLock ) {
if( soundsCount > 0 ) {
soundChunk.Data = soundDatas[0];
Sound meta = sounds[0];
playSound = true;
RemoveOldestSound();
soundChunk.Frequency = meta.SampleRate;
soundChunk.BitsPerSample = meta.BitsPerSample;
soundChunk.Channels = meta.Channels;
soundChunk.BytesOffset = meta.Offset;
soundChunk.BytesUsed = meta.Length;
}
}
if( playSound )
soundOut.PlayRaw( soundChunk );
Thread.Sleep( 1 );
}
}
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 sound = board.PlayRandomSound( type );
lock( soundLock ) {
if( soundsCount == maxSounds )
RemoveOldestSound();
sounds[soundsCount] = sound;
soundDatas[soundsCount] = board.Data;
soundsCount++;
}
}
void RemoveOldestSound() {
for( int i = 0; i < maxSounds - 1; i++ ) {
sounds[i] = sounds[i + 1];
soundDatas[i] = soundDatas[i + 1];
}
sounds[maxSounds - 1] = null;
soundDatas[maxSounds - 1] = null;
soundsCount--;
}
void DisposeSound() {
disposingSound = true;
DisposeOf( ref soundOut, ref soundThread );
}
void InitSoundboards() {
digBoard = new Soundboard();
digBoard.Init( "dig" );
stepBoard = new Soundboard();
stepBoard.Init( "step" );
}
}
}

View File

@ -1,55 +1,32 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using OpenTK;
using SharpWave; using SharpWave;
using SharpWave.Codecs.Vorbis; using SharpWave.Codecs.Vorbis;
namespace ClassicalSharp.Audio { namespace ClassicalSharp.Audio {
public sealed class AudioManager { public sealed partial class AudioManager {
IAudioOutput musicOut, soundOut; IAudioOutput musicOut, soundOut;
Soundboard digBoard, stepBoard;
string[] musicFiles; string[] musicFiles;
Thread musicThread, soundThread;
public AudioManager() { public AudioManager() {
digBoard = new Soundboard();
digBoard.Init( "dig" );
stepBoard = new Soundboard();
stepBoard.Init( "step" );
musicFiles = Directory.GetFiles( "audio", "*.ogg" ); musicFiles = Directory.GetFiles( "audio", "*.ogg" );
} }
public void SetState( bool state ) { public void SetMusic( bool enabled ) {
if( state ) if( enabled )
Init(); InitMusic();
else else
Dispose(); DisposeMusic();
} }
public void Init() { void InitMusic() {
// TODO: why is waveOut crashing?
if( false/*Configuration.RunningOnWindows*/ ) {
musicOut = new WinMmOut();
soundOut = new WinMmOut();
} else {
musicOut = new OpenALOut();
soundOut = new OpenALOut();
}
musicOut.Create( 5 );
soundOut.Create( 5, musicOut );
InitThreads();
}
Thread musicThread, soundThread;
void InitThreads() {
disposingMusic = false; disposingMusic = false;
musicThread = new Thread( DoMusicThread ); musicThread = MakeThread( DoMusicThread, ref musicOut,
musicThread.Name = "ClassicalSharp.DoMusicThread"; "ClassicalSharp.DoMusic" );
musicThread.IsBackground = true;
musicThread.Start();
} }
void DoMusicThread() { void DoMusicThread() {
@ -68,22 +45,37 @@ namespace ClassicalSharp.Audio {
} }
} }
bool disposingMusic; bool disposingMusic, disposingSound;
public void Dispose() { public void Dispose() {
DisposeMusic(); DisposeMusic();
DisposeSound(); DisposeSound();
} }
public void DisposeMusic() { void DisposeMusic() {
disposingMusic = true; disposingMusic = true;
musicOut.Stop(); DisposeOf( ref musicOut, ref musicThread );
musicThread.Join();
musicOut.Dispose();
} }
public void DisposeSound() { Thread MakeThread( ThreadStart func, ref IAudioOutput output, string name ) {
// TODO: stop playing current sound and/or music // TODO: why is waveOut crashing?
soundOut.Dispose(); output = new OpenALOut();
output.Create( 5 );
Thread thread = new Thread( func );
thread.Name = name;
thread.IsBackground = true;
thread.Start();
return thread;
}
void DisposeOf( ref IAudioOutput output, ref Thread thread ) {
if( output == null ) return;
output.Stop();
thread.Join();
output.Dispose();
output = null;
thread = null;
} }
} }
} }

View File

@ -14,6 +14,8 @@ namespace ClassicalSharp.Audio {
static string[] soundNames; static string[] soundNames;
static Soundboard() { static Soundboard() {
soundNames = Enum.GetNames( typeof( SoundType ) ); soundNames = Enum.GetNames( typeof( SoundType ) );
for( int i = 0; i < soundNames.Length; i++ )
soundNames[i] = soundNames[i].ToLower();
} }
public void Init( string group ) { public void Init( string group ) {
@ -43,7 +45,7 @@ namespace ClassicalSharp.Audio {
if( line.Length == 0 || line[0] == '#' ) continue; if( line.Length == 0 || line[0] == '#' ) continue;
string[] parts = line.Split( ',' ); string[] parts = line.Split( ',' );
if( parts.Length < 6 ) continue; if( parts.Length < 6 ) continue;
string name = parts[0]; string name = parts[0].ToLower();
int sampleRate, bitsPerSample, channels; int sampleRate, bitsPerSample, channels;
int offset, length; int offset, length;
@ -63,19 +65,24 @@ namespace ClassicalSharp.Audio {
} }
void GetGroups() { void GetGroups() {
string last = rawSounds[0].Name; string last = Group( rawSounds[0].Name );
int offset = 0, count = 0; int offset = 0, count = 0;
for( int i = 0; i < rawSounds.Count; i++ ) { for( int i = 0; i < rawSounds.Count; i++ ) {
if( rawSounds[i].Name != last ) { string group = Group( rawSounds[i].Name );
if( group != last ) {
groupFlags[last] = (count << 12) | offset; groupFlags[last] = (count << 12) | offset;
offset = i; offset = i;
last = rawSounds[i].Name; last = group;
count = 0; count = 0;
} }
count++; count++;
} }
groupFlags[last] = (count << 12) | offset; groupFlags[last] = (count << 12) | offset;
} }
string Group( string name ) {
return name.Substring( 0, name.Length - 1 );
}
} }
public class Sound { public class Sound {

View File

@ -4,7 +4,7 @@
<ProjectGuid>{BEB1C785-5CAD-48FF-A886-876BF0A318D4}</ProjectGuid> <ProjectGuid>{BEB1C785-5CAD-48FF-A886-876BF0A318D4}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>WinExe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>ClassicalSharp</RootNamespace> <RootNamespace>ClassicalSharp</RootNamespace>
<AssemblyName>ClassicalSharp</AssemblyName> <AssemblyName>ClassicalSharp</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion> <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
@ -125,6 +125,7 @@
<Compile Include="2D\Widgets\TextWidget.cs" /> <Compile Include="2D\Widgets\TextWidget.cs" />
<Compile Include="2D\Widgets\Widget.cs" /> <Compile Include="2D\Widgets\Widget.cs" />
<Compile Include="Audio\AudioManager.cs" /> <Compile Include="Audio\AudioManager.cs" />
<Compile Include="Audio\AudioManager.Sounds.cs" />
<Compile Include="Audio\Soundboard.cs" /> <Compile Include="Audio\Soundboard.cs" />
<Compile Include="Blocks\Block.cs" /> <Compile Include="Blocks\Block.cs" />
<Compile Include="Blocks\BlockInfo.BoundingBox.cs" /> <Compile Include="Blocks\BlockInfo.BoundingBox.cs" />

View File

@ -94,6 +94,7 @@ namespace ClassicalSharp {
if( game.Map.IsValidPos( pos ) && (block = game.Map.GetBlock( pos )) != 0 if( game.Map.IsValidPos( pos ) && (block = game.Map.GetBlock( pos )) != 0
&& inv.CanDelete[block] ) { && inv.CanDelete[block] ) {
game.ParticleManager.BreakBlockEffect( pos, block ); game.ParticleManager.BreakBlockEffect( pos, block );
game.AudioManager.PlayDigSound( game.BlockInfo.DigSounds[block] );
game.UpdateBlock( pos.X, pos.Y, pos.Z, 0 ); game.UpdateBlock( pos.X, pos.Y, pos.Z, 0 );
game.Network.SendSetBlock( pos.X, pos.Y, pos.Z, false, (byte)inv.HeldBlock ); game.Network.SendSetBlock( pos.X, pos.Y, pos.Z, false, (byte)inv.HeldBlock );
} }