From 9f4174346595b7e2aa31117a26b66837e1e8100e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 27 Dec 2015 14:35:03 +0000 Subject: [PATCH] Replace MiniTK.Audio with OpenAL-CS. --- AUTHORS | 7 +- Makefile | 3 +- OpenRA.Platforms.Default/OpenAlSoundEngine.cs | 165 +++++++++--------- .../OpenRA.Platforms.Default.csproj | 3 + packaging/package-all.sh | 3 + packaging/windows/OpenRA.nsi | 2 + thirdparty/fetch-thirdparty-deps.ps1 | 7 + thirdparty/fetch-thirdparty-deps.sh | 6 + 8 files changed, 112 insertions(+), 84 deletions(-) diff --git a/AUTHORS b/AUTHORS index 7a97d8bc0b..9e13f4d0fc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -141,11 +141,8 @@ distributed under the CC BY-SA 3.0 license. Using SharpFont created by Robert Rouhani and distributed under the MIT license. -Using the Open Toolkit distributed under the -MIT license. - -Using SDL2# created by Ethan Lee and released -under the zlib license. +Using SDL2-CS and OpenAL-CS created by Ethan +Lee and released under the zlib license. Using Eluant created by Chris Howie and released under the MIT license. diff --git a/Makefile b/Makefile index c8b3adeacf..7867c52e9c 100644 --- a/Makefile +++ b/Makefile @@ -117,7 +117,7 @@ pdefault_SRCS := $(shell find OpenRA.Platforms.Default/ -iname '*.cs') pdefault_TARGET = OpenRA.Platforms.Default.dll pdefault_KIND = library pdefault_DEPS = $(game_TARGET) -pdefault_LIBS = $(COMMON_LIBS) thirdparty/download/SDL2-CS.dll $(pdefault_DEPS) +pdefault_LIBS = $(COMMON_LIBS) thirdparty/download/SDL2-CS.dll thirdparty/download/OpenAL-CS.dll $(pdefault_DEPS) pnull_SRCS := $(shell find OpenRA.Platforms.Null/ -iname '*.cs') pnull_TARGET = OpenRA.Platforms.Null.dll @@ -394,6 +394,7 @@ install-core: default @$(CP_R) glsl "$(DATA_INSTALL_DIR)" @$(CP_R) lua "$(DATA_INSTALL_DIR)" @$(CP) SDL2-CS* "$(DATA_INSTALL_DIR)" + @$(CP) OpenAL-CS* "$(DATA_INSTALL_DIR)" @$(CP) Eluant* "$(DATA_INSTALL_DIR)" @$(INSTALL_PROGRAM) ICSharpCode.SharpZipLib.dll "$(DATA_INSTALL_DIR)" @$(INSTALL_PROGRAM) FuzzyLogicLibrary.dll "$(DATA_INSTALL_DIR)" diff --git a/OpenRA.Platforms.Default/OpenAlSoundEngine.cs b/OpenRA.Platforms.Default/OpenAlSoundEngine.cs index 5880f74426..91cc787e43 100644 --- a/OpenRA.Platforms.Default/OpenAlSoundEngine.cs +++ b/OpenRA.Platforms.Default/OpenAlSoundEngine.cs @@ -11,13 +11,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; +using OpenAL; using OpenRA.FileFormats; using OpenRA.FileSystem; using OpenRA.GameRules; using OpenRA.Primitives; using OpenRA.Traits; -using OpenTK; -using OpenTK.Audio.OpenAL; namespace OpenRA.Platforms.Default { @@ -51,31 +51,39 @@ namespace OpenRA.Platforms.Default IntPtr device; float volume = 1f; - Dictionary sourcePool = new Dictionary(); + Dictionary sourcePool = new Dictionary(); - static string[] QueryDevices(string label, AlcGetStringList type) + static string[] QueryDevices(string label, int type) { // Clear error bit - AL.GetError(); + AL10.alGetError(); - var devices = Alc.GetString(IntPtr.Zero, type).ToArray(); - if (AL.GetError() != ALError.NoError) + var devices = new List(); + var next = ALC10.alcGetString(IntPtr.Zero, type); + do + { + var str = Marshal.PtrToStringAnsi(next); + next += str.Length + 1; + devices.Add(str); + } while (Marshal.ReadByte(next) != 0); + + if (AL10.alGetError() != AL10.AL_NO_ERROR) { Log.Write("sound", "Failed to query OpenAL device list using {0}", label); return new string[] { }; } - return devices; + return devices.ToArray(); } static string[] PhysicalDevices() { // Returns all devices under Windows Vista and newer - if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT")) - return QueryDevices("ALC_ENUMERATE_ALL_EXT", AlcGetStringList.AllDevicesSpecifier); + if (ALC11.alcIsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT")) + return QueryDevices("ALC_ENUMERATE_ALL_EXT", ALC11.ALC_ALL_DEVICES_SPECIFIER); - if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT")) - return QueryDevices("ALC_ENUMERATION_EXT", AlcGetStringList.DeviceSpecifier); + if (ALC11.alcIsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT")) + return QueryDevices("ALC_ENUMERATION_EXT", ALC10.ALC_DEVICE_SPECIFIER); return new string[] { }; } @@ -89,25 +97,25 @@ namespace OpenRA.Platforms.Default else Console.WriteLine("Using default device"); - device = Alc.OpenDevice(Game.Settings.Sound.Device); + device = ALC10.alcOpenDevice(Game.Settings.Sound.Device); if (device == IntPtr.Zero) { Console.WriteLine("Failed to open device. Falling back to default"); - device = Alc.OpenDevice(null); + device = ALC10.alcOpenDevice(null); if (device == IntPtr.Zero) throw new InvalidOperationException("Can't create OpenAL device"); } - var ctx = Alc.CreateContext(device, (int[])null); - if (ctx == ContextHandle.Zero) + var ctx = ALC10.alcCreateContext(device, (int[])null); + if (ctx == IntPtr.Zero) throw new InvalidOperationException("Can't create OpenAL context"); - Alc.MakeContextCurrent(ctx); + ALC10.alcMakeContextCurrent(ctx); for (var i = 0; i < PoolSize; i++) { - var source = 0; - AL.GenSources(1, out source); - if (0 != AL.GetError()) + var source = 0U; + AL10.alGenSources(new IntPtr(1), out source); + if (AL10.alGetError() != AL10.AL_NO_ERROR) { Log.Write("sound", "Failed generating OpenAL source {0}", i); return; @@ -117,35 +125,40 @@ namespace OpenRA.Platforms.Default } } - int GetSourceFromPool() + bool TryGetSourceFromPool(out uint source) { foreach (var kvp in sourcePool) { if (!kvp.Value.IsActive) { sourcePool[kvp.Key].IsActive = true; - return kvp.Key; + source = kvp.Key; + return true; } } - var freeSources = new List(); + var freeSources = new List(); foreach (var key in sourcePool.Keys) { int state; - AL.GetSource(key, ALGetSourcei.SourceState, out state); - if (state != (int)ALSourceState.Playing && state != (int)ALSourceState.Paused) + AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state); + if (state != AL10.AL_PLAYING && state != AL10.AL_PAUSED) freeSources.Add(key); } if (freeSources.Count == 0) - return -1; + { + source = 0; + return false; + } foreach (var i in freeSources) sourcePool[i].IsActive = false; sourcePool[freeSources[0]].IsActive = true; - return freeSources[0]; + source = freeSources[0]; + return true; } public ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate) @@ -195,8 +208,8 @@ namespace OpenRA.Platforms.Default atten = 0.66f * ((PoolSize - activeCount * 0.5f) / PoolSize); } - var source = GetSourceFromPool(); - if (source == -1) + uint source; + if (!TryGetSourceFromPool(out source)) return null; var slot = sourcePool[source]; @@ -210,7 +223,7 @@ namespace OpenRA.Platforms.Default public float Volume { get { return volume; } - set { AL.Listener(ALListenerf.Gain, volume = value); } + set { AL10.alListenerf(AL10.AL_GAIN, volume = value); } } public void PauseSound(ISound sound, bool paused) @@ -220,11 +233,11 @@ namespace OpenRA.Platforms.Default var key = ((OpenAlSound)sound).Source; int state; - AL.GetSource(key, ALGetSourcei.SourceState, out state); - if (state == (int)ALSourceState.Playing && paused) - AL.SourcePause(key); - else if (state == (int)ALSourceState.Paused && !paused) - AL.SourcePlay(key); + AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state); + if (state == AL10.AL_PLAYING && paused) + AL10.alSourcePause(key); + else if (state == AL10.AL_PAUSED && !paused) + AL10.alSourcePlay(key); } public void SetAllSoundsPaused(bool paused) @@ -232,11 +245,11 @@ namespace OpenRA.Platforms.Default foreach (var key in sourcePool.Keys) { int state; - AL.GetSource(key, ALGetSourcei.SourceState, out state); - if (state == (int)ALSourceState.Playing && paused) - AL.SourcePause(key); - else if (state == (int)ALSourceState.Paused && !paused) - AL.SourcePlay(key); + AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state); + if (state == AL10.AL_PLAYING && paused) + AL10.alSourcePause(key); + else if (state == AL10.AL_PAUSED && !paused) + AL10.alSourcePlay(key); } } @@ -245,14 +258,14 @@ namespace OpenRA.Platforms.Default var sounds = sourcePool.Select(s => s.Key).Where(b => { int state; - AL.GetSource(b, ALGetSourcei.SourceState, out state); - return (state == (int)ALSourceState.Playing || state == (int)ALSourceState.Paused) && + AL10.alGetSourcei(b, AL10.AL_SOURCE_STATE, out state); + return (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED) && (music == null || b != ((OpenAlSound)music).Source) && (video == null || b != ((OpenAlSound)video).Source); }); foreach (var s in sounds) - AL.Source(s, ALSourcef.Gain, volume); + AL10.alSourcef(s, AL10.AL_GAIN, volume); } public void StopSound(ISound sound) @@ -262,9 +275,9 @@ namespace OpenRA.Platforms.Default var key = ((OpenAlSound)sound).Source; int state; - AL.GetSource(key, ALGetSourcei.SourceState, out state); - if (state == (int)ALSourceState.Playing || state == (int)ALSourceState.Paused) - AL.SourceStop(key); + AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state); + if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED) + AL10.alSourceStop(key); } public void StopAllSounds() @@ -272,20 +285,20 @@ namespace OpenRA.Platforms.Default foreach (var key in sourcePool.Keys) { int state; - AL.GetSource(key, ALGetSourcei.SourceState, out state); - if (state == (int)ALSourceState.Playing || state == (int)ALSourceState.Paused) - AL.SourceStop(key); + AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state); + if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED) + AL10.alSourceStop(key); } } public void SetListenerPosition(WPos position) { // Move the listener out of the plane so that sounds near the middle of the screen aren't too positional - AL.Listener(ALListener3f.Position, position.X, position.Y, position.Z + 2133); + AL10.alListener3f(AL10.AL_POSITION, position.X, position.Y, position.Z + 2133); var orientation = new[] { 0f, 0f, 1f, 0f, -1f, 0f }; - AL.Listener(ALListenerfv.Orientation, ref orientation); - AL.Listener(ALListenerf.EfxMetersPerUnit, .01f); + AL10.alListenerfv(AL10.AL_ORIENTATION, orientation); + AL10.alListenerf(EFX.AL_METERS_PER_UNIT, .01f); } public void Dispose() @@ -293,53 +306,50 @@ namespace OpenRA.Platforms.Default if (device == IntPtr.Zero) return; - Alc.CloseDevice(device); + ALC10.alcCloseDevice(device); device = IntPtr.Zero; } } class OpenAlSoundSource : ISoundSource { - public readonly int Buffer; + public readonly uint Buffer; - static ALFormat MakeALFormat(int channels, int bits) + static int MakeALFormat(int channels, int bits) { if (channels == 1) - return bits == 16 ? ALFormat.Mono16 : ALFormat.Mono8; + return bits == 16 ? AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_MONO8; else - return bits == 16 ? ALFormat.Stereo16 : ALFormat.Stereo8; + return bits == 16 ? AL10.AL_FORMAT_STEREO16 : AL10.AL_FORMAT_STEREO8; } public OpenAlSoundSource(byte[] data, int channels, int sampleBits, int sampleRate) { - AL.GenBuffers(1, out Buffer); - AL.BufferData(Buffer, MakeALFormat(channels, sampleBits), data, data.Length, sampleRate); + AL10.alGenBuffers(new IntPtr(1), out Buffer); + AL10.alBufferData(Buffer, MakeALFormat(channels, sampleBits), data, new IntPtr(data.Length), new IntPtr(sampleRate)); } } class OpenAlSound : ISound { - public readonly int Source = -1; + public readonly uint Source = uint.MaxValue; float volume = 1f; - public OpenAlSound(int source, int buffer, bool looping, bool relative, WPos pos, float volume) + public OpenAlSound(uint source, uint buffer, bool looping, bool relative, WPos pos, float volume) { - if (source == -1) - return; - Source = source; Volume = volume; - AL.Source(source, ALSourcef.Pitch, 1f); - AL.Source(source, ALSource3f.Position, pos.X, pos.Y, pos.Z); - AL.Source(source, ALSource3f.Velocity, 0f, 0f, 0f); - AL.Source(source, ALSourcei.Buffer, buffer); - AL.Source(source, ALSourceb.Looping, looping); - AL.Source(source, ALSourceb.SourceRelative, relative); + AL10.alSourcef(source, AL10.AL_PITCH, 1f); + AL10.alSource3f(source, AL10.AL_POSITION, pos.X, pos.Y, pos.Z); + AL10.alSource3f(source, AL10.AL_VELOCITY, 0f, 0f, 0f); + AL10.alSourcei(source, AL10.AL_BUFFER, (int)buffer); + AL10.alSourcei(source, AL10.AL_LOOPING, looping ? 1 : 0); + AL10.alSourcei(source, AL10.AL_SOURCE_RELATIVE, relative ? 1 : 0); - AL.Source(source, ALSourcef.ReferenceDistance, 6826); - AL.Source(source, ALSourcef.MaxDistance, 136533); - AL.SourcePlay(source); + AL10.alSourcef(source, AL10.AL_REFERENCE_DISTANCE, 6826); + AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 136533); + AL10.alSourcePlay(source); } public float Volume @@ -351,8 +361,7 @@ namespace OpenRA.Platforms.Default set { - if (Source != -1) - AL.Source(Source, ALSourcef.Gain, volume = value); + AL10.alSourcef(Source, AL10.AL_GAIN, volume = value); } } @@ -361,7 +370,7 @@ namespace OpenRA.Platforms.Default get { int pos; - AL.GetSource(Source, ALGetSourcei.SampleOffset, out pos); + AL10.alGetSourcei(Source, AL11.AL_SAMPLE_OFFSET, out pos); return pos / 22050f; } } @@ -371,8 +380,8 @@ namespace OpenRA.Platforms.Default get { int state; - AL.GetSource(Source, ALGetSourcei.SourceState, out state); - return state == (int)ALSourceState.Playing; + AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out state); + return state == AL10.AL_PLAYING; } } } diff --git a/OpenRA.Platforms.Default/OpenRA.Platforms.Default.csproj b/OpenRA.Platforms.Default/OpenRA.Platforms.Default.csproj index 9f59300bee..d00b2d3c9a 100644 --- a/OpenRA.Platforms.Default/OpenRA.Platforms.Default.csproj +++ b/OpenRA.Platforms.Default/OpenRA.Platforms.Default.csproj @@ -40,6 +40,9 @@ ..\thirdparty\download\SDL2-CS.dll + + ..\thirdparty\download\OpenAL-CS.dll + diff --git a/packaging/package-all.sh b/packaging/package-all.sh index 50201944f3..bbee48755b 100755 --- a/packaging/package-all.sh +++ b/packaging/package-all.sh @@ -55,6 +55,9 @@ cp thirdparty/download/SharpFont* packaging/built cp thirdparty/download/SDL2-CS* packaging/built cp thirdparty/SDL2-CS* packaging/built +# OpenAL-CS +cp thirdparty/download/OpenAL-CS* packaging/built + # Mono.NAT for UPnP support cp thirdparty/download/Mono.Nat.dll packaging/built diff --git a/packaging/windows/OpenRA.nsi b/packaging/windows/OpenRA.nsi index ba374dabde..5af1886c19 100644 --- a/packaging/windows/OpenRA.nsi +++ b/packaging/windows/OpenRA.nsi @@ -99,6 +99,7 @@ Section "Game" GAME File "${SRCDIR}\OpenRA.ico" File "${SRCDIR}\SharpFont.dll" File "${SRCDIR}\SDL2-CS.dll" + File "${SRCDIR}\OpenAL-CS.dll" File "${SRCDIR}\global mix database.dat" File "${SRCDIR}\MaxMind.Db.dll" File "${SRCDIR}\MaxMind.GeoIP2.dll" @@ -215,6 +216,7 @@ Function ${UN}Clean Delete $INSTDIR\eluant.dll Delete $INSTDIR\freetype6.dll Delete $INSTDIR\SDL2-CS.dll + Delete $INSTDIR\OpenAL-CS.dll Delete $INSTDIR\SmarIrc4net.dll RMDir /r $INSTDIR\Support diff --git a/thirdparty/fetch-thirdparty-deps.ps1 b/thirdparty/fetch-thirdparty-deps.ps1 index d9c49236df..a5958f8d49 100644 --- a/thirdparty/fetch-thirdparty-deps.ps1 +++ b/thirdparty/fetch-thirdparty-deps.ps1 @@ -123,6 +123,13 @@ if (!(Test-Path "SDL2-CS.dll")) (New-Object System.Net.WebClient).DownloadFile("https://github.com/OpenRA/SDL2-CS/releases/download/20150709/SDL2-CS.dll", $target) } +if (!(Test-Path "OpenAL-CS.dll")) +{ + echo "Fetching OpenAL-CS from GitHub." + $target = Join-Path $pwd.ToString() "OpenAL-CS.dll" + (New-Object System.Net.WebClient).DownloadFile("https://github.com/OpenRA/OpenAL-CS/releases/download/20151227/OpenAL-CS.dll", $target) +} + if (!(Test-Path "Eluant.dll")) { echo "Fetching Eluant from GitHub." diff --git a/thirdparty/fetch-thirdparty-deps.sh b/thirdparty/fetch-thirdparty-deps.sh index 3785a98bf5..a26f8402b2 100755 --- a/thirdparty/fetch-thirdparty-deps.sh +++ b/thirdparty/fetch-thirdparty-deps.sh @@ -107,6 +107,12 @@ if [ ! -f SDL2-CS.dll ]; then curl -s -L -O https://github.com/OpenRA/SDL2-CS/releases/download/20150709/SDL2-CS.dll fi +if [ ! -f OpenAL-CS.dll -o ! -f OpenAL-CS.dll.config ]; then + echo "Fetching OpenAL-CS from GitHub." + curl -s -L -O https://github.com/OpenRA/OpenAL-CS/releases/download/20151227/OpenAL-CS.dll + curl -s -L -O https://github.com/OpenRA/OpenAL-CS/releases/download/20151227/OpenAL-CS.dll.config +fi + if [ ! -f Eluant.dll ]; then echo "Fetching Eluant from GitHub." curl -s -L -O https://github.com/OpenRA/Eluant/releases/download/20151127/Eluant.dll