diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj
index ba98ce4776..eb43a104a6 100644
--- a/OpenRa.Game/OpenRa.Game.csproj
+++ b/OpenRa.Game/OpenRa.Game.csproj
@@ -63,10 +63,6 @@
False
..\Ijw.DirectX\Ijw.Framework\IjwFramework\bin\Debug\IjwFramework.dll
-
- False
- ..\thirdparty\irrKlang.NET2.0.dll
-
3.5
@@ -135,6 +131,7 @@
+
diff --git a/OpenRa.Game/Sound.cs b/OpenRa.Game/Sound.cs
index 25d3cf0e0f..1543f16239 100644
--- a/OpenRa.Game/Sound.cs
+++ b/OpenRa.Game/Sound.cs
@@ -1,7 +1,9 @@
-using IjwFramework.Collections;
-using IrrKlang;
+using System;
+using IjwFramework.Collections;
using OpenRa.FileFormats;
using OpenRa.Traits;
+using OpenRa.Support;
+using System.Runtime.InteropServices;
namespace OpenRa
{
@@ -14,49 +16,42 @@ namespace OpenRa
//TODO: read these from somewhere?
static float soundVolume;
static float musicVolume;
- static bool paused;
+ // static bool paused;
static ISoundSource LoadSound(string filename)
{
var data = AudLoader.LoadSound(FileSystem.Open(filename));
- return soundEngine.AddSoundSourceFromPCMData(data, filename,
- new AudioFormat()
- {
- ChannelCount = 1,
- FrameCount = data.Length / 2,
- Format = SampleFormat.Signed16Bit,
- SampleRate = 22050
- });
+ return soundEngine.AddSoundSourceFromMemory(data, 1, 16, 22050);
}
public static void Initialize()
{
- soundEngine = new ISoundEngine();
+ soundEngine = new OpenAlSoundEngine();
sounds = new Cache(LoadSound);
music = null;
- soundVolume = soundEngine.SoundVolume;
- musicVolume = soundEngine.SoundVolume;
+ soundVolume = soundEngine.Volume;
+ musicVolume = soundEngine.Volume;
}
public static void Play(string name)
{
var sound = sounds[name];
// todo: positioning
- soundEngine.Play2D(sound, false /* loop */, false, false);
+ soundEngine.Play2D(sound, false);
}
-
+
public static void PlayMusic(string name)
{
var sound = sounds[name];
- music = soundEngine.Play2D(sound, true /* loop */, false, false);
+ music = soundEngine.Play2D(sound, true);
music.Volume = musicVolume;
}
- public static bool Paused
- {
- get { return paused; }
- set { paused = value; soundEngine.SetAllSoundsPaused(paused); }
- }
+ //public static bool Paused
+ //{
+ // get { return paused; }
+ // set { paused = value; soundEngine.SetAllSoundsPaused(paused); }
+ //}
public static float Volume
{
@@ -64,29 +59,30 @@ namespace OpenRa
set
{
soundVolume = value;
- soundEngine.SoundVolume = value;
+ soundEngine.Volume = value;
}
}
-
+
public static float MusicVolume
{
get { return musicVolume; }
- set {
+ set
+ {
musicVolume = value;
if (music != null)
music.Volume = value;
}
}
- public static void SeekMusic(uint delta)
- {
- if (music != null)
- {
- music.PlayPosition += delta;
- if (music.PlayPosition < 0 || music.PlayPosition > music.PlayLength)
- music.PlayPosition = 0;
- }
- }
+ //public static void SeekMusic(uint delta)
+ //{
+ // if (music != null)
+ // {
+ // music.PlayPosition += delta;
+ // if (music.PlayPosition < 0 || music.PlayPosition > music.PlayLength)
+ // music.PlayPosition = 0;
+ // }
+ //}
public static void PlayVoice(string phrase, Actor voicedUnit)
{
@@ -115,4 +111,91 @@ namespace OpenRa
Play(clip + variant);
}
}
+
+ interface ISoundEngine
+ {
+ ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate);
+ ISound Play2D(ISoundSource sound, bool loop);
+ float Volume { get; set; }
+ }
+
+ interface ISoundSource {}
+ interface ISound
+ {
+ float Volume { get; set; }
+ }
+
+ class OpenAlSoundEngine : ISoundEngine
+ {
+ float volume = 1f;
+
+ public OpenAlSoundEngine()
+ {
+ //var str = Alc.alcGetString(IntPtr.Zero, Alc.ALC_DEFAULT_DEVICE_SPECIFIER);
+ var dev = OpenAlInterop.alcOpenDevice(IntPtr.Zero);
+ if (dev == IntPtr.Zero)
+ throw new InvalidOperationException("Can't create OpenAL device");
+ var ctx = OpenAlInterop.alcCreateContext(dev, IntPtr.Zero);
+ OpenAlInterop.alcMakeContextCurrent(ctx);
+ }
+
+ public ISoundSource AddSoundSourceFromMemory(byte[] data, int channels, int sampleBits, int sampleRate)
+ {
+ return new OpenAlSoundSource(data, channels, sampleBits, sampleRate);
+ }
+
+ public ISound Play2D(ISoundSource sound, bool loop)
+ {
+ return new OpenAlSound((sound as OpenAlSoundSource).buffer, loop);
+ }
+
+ public float Volume
+ {
+ get { return volume; }
+ set { OpenAlInterop.alListenerf(OpenAlInterop.AL_GAIN, volume = value); }
+ }
+ }
+
+ class OpenAlSoundSource : ISoundSource
+ {
+ public readonly int buffer;
+
+ static int MakeALFormat(int channels, int bits)
+ {
+ if (channels == 1)
+ return bits == 16 ? OpenAlInterop.AL_FORMAT_MONO16 : OpenAlInterop.AL_FORMAT_MONO8;
+ else
+ return bits == 16 ? OpenAlInterop.AL_FORMAT_STEREO16 : OpenAlInterop.AL_FORMAT_STEREO8;
+ }
+
+ public OpenAlSoundSource(byte[] data, int channels, int sampleBits, int sampleRate)
+ {
+ OpenAlInterop.alGenBuffers(1, out buffer);
+ OpenAlInterop.alBufferData(buffer, MakeALFormat(channels, sampleBits), data, data.Length, sampleRate);
+ }
+ }
+
+ class OpenAlSound : ISound
+ {
+ public readonly int source;
+ float volume = 1f;
+
+ public OpenAlSound(int buffer, bool looping)
+ {
+ OpenAlInterop.alGenSources(1, out source);
+ OpenAlInterop.alSourcef(source, OpenAlInterop.AL_PITCH, 1f);
+ OpenAlInterop.alSourcef(source, OpenAlInterop.AL_GAIN, 1f);
+ OpenAlInterop.alSource3f(source, OpenAlInterop.AL_POSITION, 0f, 0f, 0f);
+ OpenAlInterop.alSource3f(source, OpenAlInterop.AL_VELOCITY, 0f, 0f, 0f);
+ OpenAlInterop.alSourcei(source, OpenAlInterop.AL_BUFFER, buffer);
+ OpenAlInterop.alSourcei(source, OpenAlInterop.AL_LOOPING, looping ? OpenAlInterop.AL_TRUE : OpenAlInterop.AL_FALSE);
+ OpenAlInterop.alSourcePlay(source);
+ }
+
+ public float Volume
+ {
+ get { return volume; }
+ set { OpenAlInterop.alSourcef(source, OpenAlInterop.AL_GAIN, volume = value); }
+ }
+ }
}
diff --git a/OpenRa.Game/Support/OpenAlInterop.cs b/OpenRa.Game/Support/OpenAlInterop.cs
new file mode 100644
index 0000000000..73e4025425
--- /dev/null
+++ b/OpenRa.Game/Support/OpenAlInterop.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace OpenRa.Support
+{
+ public static class OpenAlInterop
+ {
+ public static readonly int AL_GAIN = 0x100A;
+
+ public static readonly int AL_FORMAT_MONO8 = 0x1100;
+ public static readonly int AL_FORMAT_MONO16 = 0x1101;
+ public static readonly int AL_FORMAT_STEREO8 = 0x1102;
+ public static readonly int AL_FORMAT_STEREO16 = 0x1103;
+
+ public static readonly int AL_PITCH = 0x1003;
+
+ public static readonly int AL_POSITION = 0x1004;
+ public static readonly int AL_DIRECTION = 0x1005;
+ public static readonly int AL_VELOCITY = 0x1006;
+
+ public static readonly int AL_LOOPING = 0x1007;
+ public static readonly int AL_BUFFER = 0x1009;
+
+ public static readonly int AL_TRUE = 1;
+ public static readonly int AL_FALSE = 0;
+
+
+ [DllImport("OpenAL32.dll")]
+ public static extern IntPtr alcOpenDevice(IntPtr deviceName);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern IntPtr alcCreateContext(IntPtr device, IntPtr attrList);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern bool alcMakeContextCurrent(IntPtr context);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alListenerf(int param, float value);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alGenBuffers(int n, out int buffers);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alBufferData(int buffer, int format,
+ [MarshalAs(UnmanagedType.LPArray)] byte[] data, int size, int freq);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alGenSources(int n, out int sources);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alSourcef(int source, int param, float value);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alSource3f(int source, int param, float v1, float v2, float v3);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alSourcei(int source, int param, int value);
+
+ [DllImport("OpenAL32.dll")]
+ public static extern void alSourcePlay(int source);
+ }
+}
diff --git a/thirdparty/irrKlang.NET2.0.dll b/thirdparty/irrKlang.NET2.0.dll
deleted file mode 100644
index a558e4fb00..0000000000
Binary files a/thirdparty/irrKlang.NET2.0.dll and /dev/null differ
diff --git a/thirdparty/irrKlang.txt b/thirdparty/irrKlang.txt
deleted file mode 100644
index 92648dec0d..0000000000
--- a/thirdparty/irrKlang.txt
+++ /dev/null
@@ -1 +0,0 @@
-irrKlang library is from http://www.ambiera.com/irrklang/
\ No newline at end of file