Replace MiniTK.Audio with OpenAL-CS.

This commit is contained in:
Paul Chote
2015-12-27 14:35:03 +00:00
parent 453cb17a0f
commit 9f41743465
8 changed files with 112 additions and 84 deletions

View File

@@ -141,11 +141,8 @@ distributed under the CC BY-SA 3.0 license.
Using SharpFont created by Robert Rouhani and Using SharpFont created by Robert Rouhani and
distributed under the MIT license. distributed under the MIT license.
Using the Open Toolkit distributed under the Using SDL2-CS and OpenAL-CS created by Ethan
MIT license. Lee and released under the zlib license.
Using SDL2# created by Ethan Lee and released
under the zlib license.
Using Eluant created by Chris Howie and released Using Eluant created by Chris Howie and released
under the MIT license. under the MIT license.

View File

@@ -117,7 +117,7 @@ pdefault_SRCS := $(shell find OpenRA.Platforms.Default/ -iname '*.cs')
pdefault_TARGET = OpenRA.Platforms.Default.dll pdefault_TARGET = OpenRA.Platforms.Default.dll
pdefault_KIND = library pdefault_KIND = library
pdefault_DEPS = $(game_TARGET) 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_SRCS := $(shell find OpenRA.Platforms.Null/ -iname '*.cs')
pnull_TARGET = OpenRA.Platforms.Null.dll pnull_TARGET = OpenRA.Platforms.Null.dll
@@ -394,6 +394,7 @@ install-core: default
@$(CP_R) glsl "$(DATA_INSTALL_DIR)" @$(CP_R) glsl "$(DATA_INSTALL_DIR)"
@$(CP_R) lua "$(DATA_INSTALL_DIR)" @$(CP_R) lua "$(DATA_INSTALL_DIR)"
@$(CP) SDL2-CS* "$(DATA_INSTALL_DIR)" @$(CP) SDL2-CS* "$(DATA_INSTALL_DIR)"
@$(CP) OpenAL-CS* "$(DATA_INSTALL_DIR)"
@$(CP) Eluant* "$(DATA_INSTALL_DIR)" @$(CP) Eluant* "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) ICSharpCode.SharpZipLib.dll "$(DATA_INSTALL_DIR)" @$(INSTALL_PROGRAM) ICSharpCode.SharpZipLib.dll "$(DATA_INSTALL_DIR)"
@$(INSTALL_PROGRAM) FuzzyLogicLibrary.dll "$(DATA_INSTALL_DIR)" @$(INSTALL_PROGRAM) FuzzyLogicLibrary.dll "$(DATA_INSTALL_DIR)"

View File

@@ -11,13 +11,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using OpenAL;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.FileSystem; using OpenRA.FileSystem;
using OpenRA.GameRules; using OpenRA.GameRules;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
using OpenTK;
using OpenTK.Audio.OpenAL;
namespace OpenRA.Platforms.Default namespace OpenRA.Platforms.Default
{ {
@@ -51,31 +51,39 @@ namespace OpenRA.Platforms.Default
IntPtr device; IntPtr device;
float volume = 1f; float volume = 1f;
Dictionary<int, PoolSlot> sourcePool = new Dictionary<int, PoolSlot>(); Dictionary<uint, PoolSlot> sourcePool = new Dictionary<uint, PoolSlot>();
static string[] QueryDevices(string label, AlcGetStringList type) static string[] QueryDevices(string label, int type)
{ {
// Clear error bit // Clear error bit
AL.GetError(); AL10.alGetError();
var devices = Alc.GetString(IntPtr.Zero, type).ToArray(); var devices = new List<string>();
if (AL.GetError() != ALError.NoError) 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); Log.Write("sound", "Failed to query OpenAL device list using {0}", label);
return new string[] { }; return new string[] { };
} }
return devices; return devices.ToArray();
} }
static string[] PhysicalDevices() static string[] PhysicalDevices()
{ {
// Returns all devices under Windows Vista and newer // Returns all devices under Windows Vista and newer
if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT")) if (ALC11.alcIsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT"))
return QueryDevices("ALC_ENUMERATE_ALL_EXT", AlcGetStringList.AllDevicesSpecifier); return QueryDevices("ALC_ENUMERATE_ALL_EXT", ALC11.ALC_ALL_DEVICES_SPECIFIER);
if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT")) if (ALC11.alcIsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT"))
return QueryDevices("ALC_ENUMERATION_EXT", AlcGetStringList.DeviceSpecifier); return QueryDevices("ALC_ENUMERATION_EXT", ALC10.ALC_DEVICE_SPECIFIER);
return new string[] { }; return new string[] { };
} }
@@ -89,25 +97,25 @@ namespace OpenRA.Platforms.Default
else else
Console.WriteLine("Using default device"); Console.WriteLine("Using default device");
device = Alc.OpenDevice(Game.Settings.Sound.Device); device = ALC10.alcOpenDevice(Game.Settings.Sound.Device);
if (device == IntPtr.Zero) if (device == IntPtr.Zero)
{ {
Console.WriteLine("Failed to open device. Falling back to default"); Console.WriteLine("Failed to open device. Falling back to default");
device = Alc.OpenDevice(null); device = ALC10.alcOpenDevice(null);
if (device == IntPtr.Zero) if (device == IntPtr.Zero)
throw new InvalidOperationException("Can't create OpenAL device"); throw new InvalidOperationException("Can't create OpenAL device");
} }
var ctx = Alc.CreateContext(device, (int[])null); var ctx = ALC10.alcCreateContext(device, (int[])null);
if (ctx == ContextHandle.Zero) if (ctx == IntPtr.Zero)
throw new InvalidOperationException("Can't create OpenAL context"); throw new InvalidOperationException("Can't create OpenAL context");
Alc.MakeContextCurrent(ctx); ALC10.alcMakeContextCurrent(ctx);
for (var i = 0; i < PoolSize; i++) for (var i = 0; i < PoolSize; i++)
{ {
var source = 0; var source = 0U;
AL.GenSources(1, out source); AL10.alGenSources(new IntPtr(1), out source);
if (0 != AL.GetError()) if (AL10.alGetError() != AL10.AL_NO_ERROR)
{ {
Log.Write("sound", "Failed generating OpenAL source {0}", i); Log.Write("sound", "Failed generating OpenAL source {0}", i);
return; return;
@@ -117,35 +125,40 @@ namespace OpenRA.Platforms.Default
} }
} }
int GetSourceFromPool() bool TryGetSourceFromPool(out uint source)
{ {
foreach (var kvp in sourcePool) foreach (var kvp in sourcePool)
{ {
if (!kvp.Value.IsActive) if (!kvp.Value.IsActive)
{ {
sourcePool[kvp.Key].IsActive = true; sourcePool[kvp.Key].IsActive = true;
return kvp.Key; source = kvp.Key;
return true;
} }
} }
var freeSources = new List<int>(); var freeSources = new List<uint>();
foreach (var key in sourcePool.Keys) foreach (var key in sourcePool.Keys)
{ {
int state; int state;
AL.GetSource(key, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
if (state != (int)ALSourceState.Playing && state != (int)ALSourceState.Paused) if (state != AL10.AL_PLAYING && state != AL10.AL_PAUSED)
freeSources.Add(key); freeSources.Add(key);
} }
if (freeSources.Count == 0) if (freeSources.Count == 0)
return -1; {
source = 0;
return false;
}
foreach (var i in freeSources) foreach (var i in freeSources)
sourcePool[i].IsActive = false; sourcePool[i].IsActive = false;
sourcePool[freeSources[0]].IsActive = true; sourcePool[freeSources[0]].IsActive = true;
return freeSources[0]; source = freeSources[0];
return true;
} }
public ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate) 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); atten = 0.66f * ((PoolSize - activeCount * 0.5f) / PoolSize);
} }
var source = GetSourceFromPool(); uint source;
if (source == -1) if (!TryGetSourceFromPool(out source))
return null; return null;
var slot = sourcePool[source]; var slot = sourcePool[source];
@@ -210,7 +223,7 @@ namespace OpenRA.Platforms.Default
public float Volume public float Volume
{ {
get { return 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) public void PauseSound(ISound sound, bool paused)
@@ -220,11 +233,11 @@ namespace OpenRA.Platforms.Default
var key = ((OpenAlSound)sound).Source; var key = ((OpenAlSound)sound).Source;
int state; int state;
AL.GetSource(key, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
if (state == (int)ALSourceState.Playing && paused) if (state == AL10.AL_PLAYING && paused)
AL.SourcePause(key); AL10.alSourcePause(key);
else if (state == (int)ALSourceState.Paused && !paused) else if (state == AL10.AL_PAUSED && !paused)
AL.SourcePlay(key); AL10.alSourcePlay(key);
} }
public void SetAllSoundsPaused(bool paused) public void SetAllSoundsPaused(bool paused)
@@ -232,11 +245,11 @@ namespace OpenRA.Platforms.Default
foreach (var key in sourcePool.Keys) foreach (var key in sourcePool.Keys)
{ {
int state; int state;
AL.GetSource(key, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
if (state == (int)ALSourceState.Playing && paused) if (state == AL10.AL_PLAYING && paused)
AL.SourcePause(key); AL10.alSourcePause(key);
else if (state == (int)ALSourceState.Paused && !paused) else if (state == AL10.AL_PAUSED && !paused)
AL.SourcePlay(key); AL10.alSourcePlay(key);
} }
} }
@@ -245,14 +258,14 @@ namespace OpenRA.Platforms.Default
var sounds = sourcePool.Select(s => s.Key).Where(b => var sounds = sourcePool.Select(s => s.Key).Where(b =>
{ {
int state; int state;
AL.GetSource(b, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(b, AL10.AL_SOURCE_STATE, out state);
return (state == (int)ALSourceState.Playing || state == (int)ALSourceState.Paused) && return (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED) &&
(music == null || b != ((OpenAlSound)music).Source) && (music == null || b != ((OpenAlSound)music).Source) &&
(video == null || b != ((OpenAlSound)video).Source); (video == null || b != ((OpenAlSound)video).Source);
}); });
foreach (var s in sounds) foreach (var s in sounds)
AL.Source(s, ALSourcef.Gain, volume); AL10.alSourcef(s, AL10.AL_GAIN, volume);
} }
public void StopSound(ISound sound) public void StopSound(ISound sound)
@@ -262,9 +275,9 @@ namespace OpenRA.Platforms.Default
var key = ((OpenAlSound)sound).Source; var key = ((OpenAlSound)sound).Source;
int state; int state;
AL.GetSource(key, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
if (state == (int)ALSourceState.Playing || state == (int)ALSourceState.Paused) if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED)
AL.SourceStop(key); AL10.alSourceStop(key);
} }
public void StopAllSounds() public void StopAllSounds()
@@ -272,20 +285,20 @@ namespace OpenRA.Platforms.Default
foreach (var key in sourcePool.Keys) foreach (var key in sourcePool.Keys)
{ {
int state; int state;
AL.GetSource(key, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
if (state == (int)ALSourceState.Playing || state == (int)ALSourceState.Paused) if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED)
AL.SourceStop(key); AL10.alSourceStop(key);
} }
} }
public void SetListenerPosition(WPos position) 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 // 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 }; var orientation = new[] { 0f, 0f, 1f, 0f, -1f, 0f };
AL.Listener(ALListenerfv.Orientation, ref orientation); AL10.alListenerfv(AL10.AL_ORIENTATION, orientation);
AL.Listener(ALListenerf.EfxMetersPerUnit, .01f); AL10.alListenerf(EFX.AL_METERS_PER_UNIT, .01f);
} }
public void Dispose() public void Dispose()
@@ -293,53 +306,50 @@ namespace OpenRA.Platforms.Default
if (device == IntPtr.Zero) if (device == IntPtr.Zero)
return; return;
Alc.CloseDevice(device); ALC10.alcCloseDevice(device);
device = IntPtr.Zero; device = IntPtr.Zero;
} }
} }
class OpenAlSoundSource : ISoundSource 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) if (channels == 1)
return bits == 16 ? ALFormat.Mono16 : ALFormat.Mono8; return bits == 16 ? AL10.AL_FORMAT_MONO16 : AL10.AL_FORMAT_MONO8;
else 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) public OpenAlSoundSource(byte[] data, int channels, int sampleBits, int sampleRate)
{ {
AL.GenBuffers(1, out Buffer); AL10.alGenBuffers(new IntPtr(1), out Buffer);
AL.BufferData(Buffer, MakeALFormat(channels, sampleBits), data, data.Length, sampleRate); AL10.alBufferData(Buffer, MakeALFormat(channels, sampleBits), data, new IntPtr(data.Length), new IntPtr(sampleRate));
} }
} }
class OpenAlSound : ISound class OpenAlSound : ISound
{ {
public readonly int Source = -1; public readonly uint Source = uint.MaxValue;
float volume = 1f; 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; Source = source;
Volume = volume; Volume = volume;
AL.Source(source, ALSourcef.Pitch, 1f); AL10.alSourcef(source, AL10.AL_PITCH, 1f);
AL.Source(source, ALSource3f.Position, pos.X, pos.Y, pos.Z); AL10.alSource3f(source, AL10.AL_POSITION, pos.X, pos.Y, pos.Z);
AL.Source(source, ALSource3f.Velocity, 0f, 0f, 0f); AL10.alSource3f(source, AL10.AL_VELOCITY, 0f, 0f, 0f);
AL.Source(source, ALSourcei.Buffer, buffer); AL10.alSourcei(source, AL10.AL_BUFFER, (int)buffer);
AL.Source(source, ALSourceb.Looping, looping); AL10.alSourcei(source, AL10.AL_LOOPING, looping ? 1 : 0);
AL.Source(source, ALSourceb.SourceRelative, relative); AL10.alSourcei(source, AL10.AL_SOURCE_RELATIVE, relative ? 1 : 0);
AL.Source(source, ALSourcef.ReferenceDistance, 6826); AL10.alSourcef(source, AL10.AL_REFERENCE_DISTANCE, 6826);
AL.Source(source, ALSourcef.MaxDistance, 136533); AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 136533);
AL.SourcePlay(source); AL10.alSourcePlay(source);
} }
public float Volume public float Volume
@@ -351,8 +361,7 @@ namespace OpenRA.Platforms.Default
set set
{ {
if (Source != -1) AL10.alSourcef(Source, AL10.AL_GAIN, volume = value);
AL.Source(Source, ALSourcef.Gain, volume = value);
} }
} }
@@ -361,7 +370,7 @@ namespace OpenRA.Platforms.Default
get get
{ {
int pos; int pos;
AL.GetSource(Source, ALGetSourcei.SampleOffset, out pos); AL10.alGetSourcei(Source, AL11.AL_SAMPLE_OFFSET, out pos);
return pos / 22050f; return pos / 22050f;
} }
} }
@@ -371,8 +380,8 @@ namespace OpenRA.Platforms.Default
get get
{ {
int state; int state;
AL.GetSource(Source, ALGetSourcei.SourceState, out state); AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out state);
return state == (int)ALSourceState.Playing; return state == AL10.AL_PLAYING;
} }
} }
} }

View File

@@ -40,6 +40,9 @@
<Reference Include="SDL2-CS"> <Reference Include="SDL2-CS">
<HintPath>..\thirdparty\download\SDL2-CS.dll</HintPath> <HintPath>..\thirdparty\download\SDL2-CS.dll</HintPath>
</Reference> </Reference>
<Reference Include="OpenAL-CS">
<HintPath>..\thirdparty\download\OpenAL-CS.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="DefaultPlatform.cs" /> <Compile Include="DefaultPlatform.cs" />

View File

@@ -55,6 +55,9 @@ cp thirdparty/download/SharpFont* packaging/built
cp thirdparty/download/SDL2-CS* packaging/built cp thirdparty/download/SDL2-CS* packaging/built
cp thirdparty/SDL2-CS* packaging/built cp thirdparty/SDL2-CS* packaging/built
# OpenAL-CS
cp thirdparty/download/OpenAL-CS* packaging/built
# Mono.NAT for UPnP support # Mono.NAT for UPnP support
cp thirdparty/download/Mono.Nat.dll packaging/built cp thirdparty/download/Mono.Nat.dll packaging/built

View File

@@ -99,6 +99,7 @@ Section "Game" GAME
File "${SRCDIR}\OpenRA.ico" File "${SRCDIR}\OpenRA.ico"
File "${SRCDIR}\SharpFont.dll" File "${SRCDIR}\SharpFont.dll"
File "${SRCDIR}\SDL2-CS.dll" File "${SRCDIR}\SDL2-CS.dll"
File "${SRCDIR}\OpenAL-CS.dll"
File "${SRCDIR}\global mix database.dat" File "${SRCDIR}\global mix database.dat"
File "${SRCDIR}\MaxMind.Db.dll" File "${SRCDIR}\MaxMind.Db.dll"
File "${SRCDIR}\MaxMind.GeoIP2.dll" File "${SRCDIR}\MaxMind.GeoIP2.dll"
@@ -215,6 +216,7 @@ Function ${UN}Clean
Delete $INSTDIR\eluant.dll Delete $INSTDIR\eluant.dll
Delete $INSTDIR\freetype6.dll Delete $INSTDIR\freetype6.dll
Delete $INSTDIR\SDL2-CS.dll Delete $INSTDIR\SDL2-CS.dll
Delete $INSTDIR\OpenAL-CS.dll
Delete $INSTDIR\SmarIrc4net.dll Delete $INSTDIR\SmarIrc4net.dll
RMDir /r $INSTDIR\Support RMDir /r $INSTDIR\Support

View File

@@ -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) (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")) if (!(Test-Path "Eluant.dll"))
{ {
echo "Fetching Eluant from GitHub." echo "Fetching Eluant from GitHub."

View File

@@ -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 curl -s -L -O https://github.com/OpenRA/SDL2-CS/releases/download/20150709/SDL2-CS.dll
fi 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 if [ ! -f Eluant.dll ]; then
echo "Fetching Eluant from GitHub." echo "Fetching Eluant from GitHub."
curl -s -L -O https://github.com/OpenRA/Eluant/releases/download/20151127/Eluant.dll curl -s -L -O https://github.com/OpenRA/Eluant/releases/download/20151127/Eluant.dll