- Refactorings and basic implementations in the Audio namespace
- Added WaveLoader from my AC.AL project - Implemented OpenALSoundEffect and OpenALSoundEffectInstance (not tested yet!)
This commit is contained in:
parent
e23261bfc3
commit
2bcebca384
@ -56,7 +56,7 @@ namespace ANX.Framework.Audio
|
|||||||
#region ToString
|
#region ToString
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Name;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -20,10 +20,8 @@ namespace ANX.Framework.Audio
|
|||||||
#region Public
|
#region Public
|
||||||
public bool IsDisposed
|
public bool IsDisposed
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyCollection<RendererDetail> RendererDetails
|
public ReadOnlyCollection<RendererDetail> RendererDetails
|
||||||
@ -41,8 +39,7 @@ namespace ANX.Framework.Audio
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioEngine(string settingsFile, TimeSpan lookAheadTime,
|
public AudioEngine(string settingsFile, TimeSpan lookAheadTime, string rendererId)
|
||||||
string rendererId)
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@ -84,12 +81,17 @@ namespace ANX.Framework.Audio
|
|||||||
#region Dispose
|
#region Dispose
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (IsDisposed == false)
|
||||||
|
{
|
||||||
|
IsDisposed = true;
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,8 @@ namespace ANX.Framework.Audio
|
|||||||
|
|
||||||
public bool IsDisposed
|
public bool IsDisposed
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsPaused
|
public bool IsPaused
|
||||||
@ -87,6 +85,10 @@ namespace ANX.Framework.Audio
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructor
|
#region Constructor
|
||||||
|
internal Cue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
~Cue()
|
~Cue()
|
||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
@ -145,7 +147,11 @@ namespace ANX.Framework.Audio
|
|||||||
#region Dispose
|
#region Dispose
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (IsDisposed == false)
|
||||||
|
{
|
||||||
|
IsDisposed = true;
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
|
|||||||
namespace ANX.Framework.Audio
|
namespace ANX.Framework.Audio
|
||||||
{
|
{
|
||||||
#if !WINDOWSMETRO //TODO: search replacement for Win8
|
#if !WINDOWSMETRO //TODO: search replacement for Win8
|
||||||
[SerializableAttribute]
|
[Serializable]
|
||||||
#endif
|
#endif
|
||||||
public sealed class InstancePlayLimitException : ExternalException
|
public sealed class InstancePlayLimitException : ExternalException
|
||||||
{
|
{
|
||||||
|
@ -70,9 +70,7 @@ namespace ANX.Framework.Audio
|
|||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (IsDisposed)
|
if (IsDisposed)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
@ -71,11 +71,9 @@ namespace ANX.Framework.Audio
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private
|
#region Private
|
||||||
internal ISoundEffect nativeSoundEffect;
|
|
||||||
|
|
||||||
private static List<SoundEffectInstance> fireAndForgetInstances;
|
private static List<SoundEffectInstance> fireAndForgetInstances;
|
||||||
|
private List<WeakReference> children;
|
||||||
private List<WeakReference> children = new List<WeakReference>();
|
internal ISoundEffect nativeSoundEffect;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public
|
#region Public
|
||||||
@ -103,13 +101,22 @@ namespace ANX.Framework.Audio
|
|||||||
#region Constructor
|
#region Constructor
|
||||||
static SoundEffect()
|
static SoundEffect()
|
||||||
{
|
{
|
||||||
|
fireAndForgetInstances = new List<SoundEffectInstance>();
|
||||||
|
|
||||||
MasterVolume = 1f;
|
MasterVolume = 1f;
|
||||||
SpeedOfSound = 343.5f;
|
SpeedOfSound = 343.5f;
|
||||||
DopplerScale = 1f;
|
DopplerScale = 1f;
|
||||||
DistanceScale = 1f;
|
DistanceScale = 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SoundEffect()
|
||||||
|
{
|
||||||
|
children = new List<WeakReference>();
|
||||||
|
IsDisposed = false;
|
||||||
|
}
|
||||||
|
|
||||||
private SoundEffect(Stream stream)
|
private SoundEffect(Stream stream)
|
||||||
|
: this()
|
||||||
{
|
{
|
||||||
nativeSoundEffect = GetCreator().CreateSoundEffect(this, stream);
|
nativeSoundEffect = GetCreator().CreateSoundEffect(this, stream);
|
||||||
}
|
}
|
||||||
@ -121,6 +128,7 @@ namespace ANX.Framework.Audio
|
|||||||
|
|
||||||
public SoundEffect(byte[] buffer, int offset, int count, int sampleRate,
|
public SoundEffect(byte[] buffer, int offset, int count, int sampleRate,
|
||||||
AudioChannels channels, int loopStart, int loopLength)
|
AudioChannels channels, int loopStart, int loopLength)
|
||||||
|
: this()
|
||||||
{
|
{
|
||||||
nativeSoundEffect = GetCreator().CreateSoundEffect(this, buffer, offset,
|
nativeSoundEffect = GetCreator().CreateSoundEffect(this, buffer, offset,
|
||||||
count, sampleRate, channels, loopStart, loopLength);
|
count, sampleRate, channels, loopStart, loopLength);
|
||||||
@ -154,12 +162,10 @@ namespace ANX.Framework.Audio
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GetSampleDuration
|
#region GetSampleDuration
|
||||||
public static TimeSpan GetSampleDuration(int sizeInBytes, int sampleRate,
|
public static TimeSpan GetSampleDuration(int sizeInBytes, int sampleRate, AudioChannels channels)
|
||||||
AudioChannels channels)
|
|
||||||
{
|
{
|
||||||
float sizeMulBlockAlign = sizeInBytes / ((int)channels * 2);
|
float sizeMulBlockAlign = sizeInBytes / ((int)channels * 2);
|
||||||
return TimeSpan.FromMilliseconds((double)(sizeMulBlockAlign * 1000f /
|
return TimeSpan.FromMilliseconds((double)(sizeMulBlockAlign * 1000f / (float)sampleRate));
|
||||||
(float)sampleRate));
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -167,10 +173,8 @@ namespace ANX.Framework.Audio
|
|||||||
public static int GetSampleSizeInBytes(TimeSpan duration, int sampleRate,
|
public static int GetSampleSizeInBytes(TimeSpan duration, int sampleRate,
|
||||||
AudioChannels channels)
|
AudioChannels channels)
|
||||||
{
|
{
|
||||||
int timeMulSamples = (int)(duration.TotalMilliseconds *
|
int timeMulSamples = (int)(duration.TotalMilliseconds * (double)((float)sampleRate / 1000f));
|
||||||
(double)((float)sampleRate / 1000f));
|
return (timeMulSamples + timeMulSamples % (int)channels) * ((int)channels * 2);
|
||||||
return (timeMulSamples + timeMulSamples % (int)channels) *
|
|
||||||
((int)channels * 2);
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -41,8 +41,7 @@ namespace ANX.Framework.Audio
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
public WaveBank(AudioEngine audioEngine, string streamingWaveBankFilename,
|
public WaveBank(AudioEngine audioEngine, string streamingWaveBankFilename, int offset, short packetsize)
|
||||||
int offset, short packetsize)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -62,9 +61,7 @@ namespace ANX.Framework.Audio
|
|||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (IsDisposed)
|
if (IsDisposed)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
|
|
||||||
|
@ -12,14 +12,6 @@ namespace ANX.Framework
|
|||||||
{
|
{
|
||||||
public abstract class GameHost
|
public abstract class GameHost
|
||||||
{
|
{
|
||||||
//private EventHandler<EventArgs> Activated;
|
|
||||||
//private EventHandler<EventArgs> Deactivated;
|
|
||||||
//private EventHandler<EventArgs> Exiting;
|
|
||||||
//private EventHandler<EventArgs> Idle;
|
|
||||||
//private EventHandler<EventArgs> Resume;
|
|
||||||
//private EventHandler<EventArgs> Suspend;
|
|
||||||
|
|
||||||
// Events
|
|
||||||
internal event EventHandler<EventArgs> Activated;
|
internal event EventHandler<EventArgs> Activated;
|
||||||
internal event EventHandler<EventArgs> Deactivated;
|
internal event EventHandler<EventArgs> Deactivated;
|
||||||
internal event EventHandler<EventArgs> Exiting;
|
internal event EventHandler<EventArgs> Exiting;
|
||||||
|
@ -16,17 +16,15 @@ namespace ANX.Framework.Media
|
|||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsRated
|
public bool IsRated
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return Rating > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +93,9 @@ namespace ANX.Framework.Media
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region Constructor
|
#region Constructor
|
||||||
private Song()
|
internal Song(string setName)
|
||||||
{
|
{
|
||||||
|
Name = setName;
|
||||||
IsDisposed = false;
|
IsDisposed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,44 +8,47 @@ namespace ANX.Framework.Media
|
|||||||
{
|
{
|
||||||
public sealed class Video
|
public sealed class Video
|
||||||
{
|
{
|
||||||
|
#region Public
|
||||||
public TimeSpan Duration
|
public TimeSpan Duration
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Width
|
public int Width
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Height
|
public int Height
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float FramesPerSecond
|
public float FramesPerSecond
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public VideoSoundtrackType VideoSoundtrackType
|
public VideoSoundtrackType VideoSoundtrackType
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
internal Video(int duration, int width, int height, float framesPerSecond, VideoSoundtrackType soundtrackType)
|
||||||
|
{
|
||||||
|
Duration = new TimeSpan(0, 0, 0, 0, duration);
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
FramesPerSecond = framesPerSecond;
|
||||||
|
VideoSoundtrackType = soundtrackType;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,12 @@
|
|||||||
<Compile Include="OpenALSoundEffectInstance.cs" />
|
<Compile Include="OpenALSoundEffectInstance.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="SupportedPlatformsImpl.cs" />
|
<Compile Include="SupportedPlatformsImpl.cs" />
|
||||||
|
<Compile Include="Wave\ALaw.cs" />
|
||||||
|
<Compile Include="Wave\MsAdpcm.cs" />
|
||||||
|
<Compile Include="Wave\MuLaw.cs" />
|
||||||
|
<Compile Include="Wave\WaveFile.cs" />
|
||||||
|
<Compile Include="Wave\WaveFormat.cs" />
|
||||||
|
<Compile Include="Wave\WaveInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\ANX.Framework\ANX.Framework.csproj">
|
<ProjectReference Include="..\..\ANX.Framework\ANX.Framework.csproj">
|
||||||
|
@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using ANX.Framework.Audio;
|
using ANX.Framework.Audio;
|
||||||
using ANX.Framework.NonXNA;
|
using ANX.Framework.NonXNA;
|
||||||
using ANX.Framework.NonXNA.SoundSystem;
|
using ANX.Framework.NonXNA.SoundSystem;
|
||||||
|
using OpenTK.Audio.OpenAL;
|
||||||
|
|
||||||
// This file is part of the ANX.Framework created by the
|
// This file is part of the ANX.Framework created by the
|
||||||
// "ANX.Framework developer group" and released under the Ms-PL license.
|
// "ANX.Framework developer group" and released under the Ms-PL license.
|
||||||
@ -14,7 +15,6 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
public class Creator : ISoundSystemCreator
|
public class Creator : ISoundSystemCreator
|
||||||
{
|
{
|
||||||
#region Public
|
#region Public
|
||||||
#region Name
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -22,9 +22,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
return "Sound.OpenAL";
|
return "Sound.OpenAL";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Priority
|
|
||||||
public int Priority
|
public int Priority
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -32,9 +30,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IsSupported
|
|
||||||
public bool IsSupported
|
public bool IsSupported
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -45,9 +41,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
os == PlatformName.MacOSX;
|
os == PlatformName.MacOSX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region DistanceScale
|
|
||||||
public float DistanceScale
|
public float DistanceScale
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -59,23 +53,19 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region DopplerScale
|
|
||||||
public float DopplerScale
|
public float DopplerScale
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return AL.Get(ALGetFloat.DopplerFactor);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
AL.DopplerFactor(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region MasterVolume
|
|
||||||
public float MasterVolume
|
public float MasterVolume
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -87,46 +77,41 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region SpeedOfSound
|
|
||||||
public float SpeedOfSound
|
public float SpeedOfSound
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return AL.Get(ALGetFloat.SpeedOfSound);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
AL.SpeedOfSound(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region CreateSoundEffectInstance
|
#region CreateSoundEffectInstance
|
||||||
public ISoundEffectInstance CreateSoundEffectInstance(
|
public ISoundEffectInstance CreateSoundEffectInstance(ISoundEffect nativeSoundEffect)
|
||||||
ISoundEffect nativeSoundEffect)
|
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
PreventSystemChange();
|
||||||
return new OpenALSoundEffectInstance((OpenALSoundEffect)nativeSoundEffect);
|
return new OpenALSoundEffectInstance(nativeSoundEffect as OpenALSoundEffect);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CreateSoundEffect
|
#region CreateSoundEffect
|
||||||
public ISoundEffect CreateSoundEffect(SoundEffect parent, Stream stream)
|
public ISoundEffect CreateSoundEffect(SoundEffect parent, Stream stream)
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
PreventSystemChange();
|
||||||
return new OpenALSoundEffect(parent, stream);
|
return new OpenALSoundEffect(parent, stream);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CreateSoundEffect (TODO)
|
#region CreateSoundEffect (TODO)
|
||||||
public ISoundEffect CreateSoundEffect(SoundEffect parent, byte[] buffer,
|
public ISoundEffect CreateSoundEffect(SoundEffect parent, byte[] buffer, int offset, int count, int sampleRate,
|
||||||
int offset, int count, int sampleRate, AudioChannels channels,
|
AudioChannels channels, int loopStart, int loopLength)
|
||||||
int loopStart, int loopLength)
|
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -134,7 +119,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
#region CreateAudioListener
|
#region CreateAudioListener
|
||||||
public IAudioListener CreateAudioListener()
|
public IAudioListener CreateAudioListener()
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
PreventSystemChange();
|
||||||
return new OpenALAudioListener();
|
return new OpenALAudioListener();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -142,7 +127,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
#region CreateAudioEmitter (TODO)
|
#region CreateAudioEmitter (TODO)
|
||||||
public IAudioEmitter CreateAudioEmitter()
|
public IAudioEmitter CreateAudioEmitter()
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -150,6 +135,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
#region CreateMicrophone
|
#region CreateMicrophone
|
||||||
public IMicrophone CreateMicrophone(Microphone managedMicrophone)
|
public IMicrophone CreateMicrophone(Microphone managedMicrophone)
|
||||||
{
|
{
|
||||||
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -157,6 +143,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
#region GetAllMicrophones
|
#region GetAllMicrophones
|
||||||
public ReadOnlyCollection<Microphone> GetAllMicrophones()
|
public ReadOnlyCollection<Microphone> GetAllMicrophones()
|
||||||
{
|
{
|
||||||
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -164,8 +151,14 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
#region GetDefaultMicrophone
|
#region GetDefaultMicrophone
|
||||||
public int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones)
|
public int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones)
|
||||||
{
|
{
|
||||||
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private void PreventSystemChange()
|
||||||
|
{
|
||||||
|
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using ANX.Framework.Audio;
|
using ANX.Framework.Audio;
|
||||||
using ANX.Framework.NonXNA.SoundSystem;
|
using ANX.Framework.NonXNA.SoundSystem;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework created by the
|
||||||
|
// "ANX.Framework developer group" and released under the Ms-PL license.
|
||||||
|
// For details see: http://anxframework.codeplex.com/license
|
||||||
|
|
||||||
namespace ANX.SoundSystem.OpenAL
|
namespace ANX.SoundSystem.OpenAL
|
||||||
{
|
{
|
||||||
@ -9,14 +14,20 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
{
|
{
|
||||||
#region Private
|
#region Private
|
||||||
internal SoundEffect parent;
|
internal SoundEffect parent;
|
||||||
|
|
||||||
|
private WaveInfo waveInfo;
|
||||||
|
|
||||||
|
private TimeSpan duration;
|
||||||
|
|
||||||
|
internal int bufferHandle;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public (TODO)
|
#region Public
|
||||||
public TimeSpan Duration
|
public TimeSpan Duration
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return duration;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -25,13 +36,23 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
internal OpenALSoundEffect(SoundEffect setParent, Stream stream)
|
internal OpenALSoundEffect(SoundEffect setParent, Stream stream)
|
||||||
{
|
{
|
||||||
parent = setParent;
|
parent = setParent;
|
||||||
|
|
||||||
|
waveInfo = WaveFile.LoadData(stream);
|
||||||
|
|
||||||
|
float sizeMulBlockAlign = waveInfo.Data.Length / ((int)waveInfo.Channels * 2);
|
||||||
|
duration = TimeSpan.FromMilliseconds((double)(sizeMulBlockAlign * 1000f / (float)waveInfo.SampleRate));
|
||||||
|
|
||||||
|
bufferHandle = AL.GenBuffer();
|
||||||
|
AL.BufferData(bufferHandle, waveInfo.OpenALFormat, waveInfo.Data, waveInfo.Data.Length, waveInfo.SampleRate);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Dispose (TODO)
|
#region Dispose
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
waveInfo = null;
|
||||||
|
|
||||||
|
AL.DeleteBuffer(bufferHandle);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using ANX.Framework.Audio;
|
using ANX.Framework.Audio;
|
||||||
using ANX.Framework.NonXNA.SoundSystem;
|
using ANX.Framework.NonXNA.SoundSystem;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework created by the
|
||||||
|
// "ANX.Framework developer group" and released under the Ms-PL license.
|
||||||
|
// For details see: http://anxframework.codeplex.com/license
|
||||||
|
|
||||||
namespace ANX.SoundSystem.OpenAL
|
namespace ANX.SoundSystem.OpenAL
|
||||||
{
|
{
|
||||||
@ -8,18 +13,22 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
{
|
{
|
||||||
#region Private
|
#region Private
|
||||||
private OpenALSoundEffect parent;
|
private OpenALSoundEffect parent;
|
||||||
|
|
||||||
|
private int handle;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public (TODO)
|
#region Public
|
||||||
public bool IsLooped
|
public bool IsLooped
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
bool result;
|
||||||
|
AL.GetSource(handle, ALSourceb.Looping, out result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
AL.Source(handle, ALSourceb.Looping, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,31 +48,33 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
float result;
|
||||||
|
AL.GetSource(handle, ALSourcef.Pitch, out result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
AL.Source(handle, ALSourcef.Pitch, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SoundState State
|
public SoundState State
|
||||||
{
|
{
|
||||||
get
|
get;
|
||||||
{
|
private set;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Volume
|
public float Volume
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
float result;
|
||||||
|
AL.GetSource(handle, ALSourcef.Gain, out result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
AL.Source(handle, ALSourcef.Gain, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@ -72,38 +83,77 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
internal OpenALSoundEffectInstance(OpenALSoundEffect setParent)
|
internal OpenALSoundEffectInstance(OpenALSoundEffect setParent)
|
||||||
{
|
{
|
||||||
parent = setParent;
|
parent = setParent;
|
||||||
|
|
||||||
|
State = SoundState.Stopped;
|
||||||
|
|
||||||
|
handle = AL.GenSource();
|
||||||
|
AL.Source(handle, ALSourcei.Buffer, parent.bufferHandle);
|
||||||
|
IsLooped = false;
|
||||||
|
Pitch = 1f;
|
||||||
|
Volume = 1f;
|
||||||
|
// TODO: Pan = 0f;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Play
|
||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (State != SoundState.Playing)
|
||||||
|
{
|
||||||
|
State = SoundState.Playing;
|
||||||
|
AL.SourcePlay(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Pause
|
||||||
public void Pause()
|
public void Pause()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (State != SoundState.Paused)
|
||||||
|
{
|
||||||
|
State = SoundState.Paused;
|
||||||
|
AL.SourcePause(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Stop
|
||||||
public void Stop(bool immediate)
|
public void Stop(bool immediate)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (State == SoundState.Stopped)
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
if (immediate)
|
||||||
|
{
|
||||||
|
State = SoundState.Stopped;
|
||||||
|
AL.SourceStop(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Resume
|
||||||
public void Resume()
|
public void Resume()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (State != SoundState.Playing)
|
||||||
|
{
|
||||||
|
State = SoundState.Playing;
|
||||||
|
AL.SourcePlay(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public void Apply3D(Framework.Audio.AudioListener[] listeners, Framework.Audio.AudioEmitter emitter)
|
#region Apply3D (TODO)
|
||||||
|
public void Apply3D(AudioListener[] listeners, AudioEmitter emitter)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Dispose (TODO)
|
#region Dispose
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
AL.DeleteSource(handle);
|
||||||
|
handle = -1;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
122
SoundSystems/ANX.SoundSystem.OpenAL/Wave/ALaw.cs
Normal file
122
SoundSystems/ANX.SoundSystem.OpenAL/Wave/ALaw.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework and originally taken from
|
||||||
|
// the AC.AL OpenAL library, released under the MIT License.
|
||||||
|
// For details see: http://acal.codeplex.com/license
|
||||||
|
|
||||||
|
namespace ANX.SoundSystem.OpenAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// http://www.threejacks.com/?q=node/176
|
||||||
|
/// </summary>
|
||||||
|
internal static class ALaw
|
||||||
|
{
|
||||||
|
#region Decode Table
|
||||||
|
private static readonly short[] DecodeTable =
|
||||||
|
{
|
||||||
|
-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
|
||||||
|
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
|
||||||
|
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
|
||||||
|
-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
|
||||||
|
-22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
|
||||||
|
-30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
|
||||||
|
-11008,-10496,-12032,-11520,-8960, -8448, -9984, -9472,
|
||||||
|
-15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
|
||||||
|
-344, -328, -376, -360, -280, -264, -312, -296,
|
||||||
|
-472, -456, -504, -488, -408, -392, -440, -424,
|
||||||
|
-88, -72, -120, -104, -24, -8, -56, -40,
|
||||||
|
-216, -200, -248, -232, -152, -136, -184, -168,
|
||||||
|
-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
|
||||||
|
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
|
||||||
|
-688, -656, -752, -720, -560, -528, -624, -592,
|
||||||
|
-944, -912, -1008, -976, -816, -784, -880, -848,
|
||||||
|
5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
|
||||||
|
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
|
||||||
|
2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
|
||||||
|
3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
|
||||||
|
22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
|
||||||
|
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
|
||||||
|
11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
|
||||||
|
15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
|
||||||
|
344, 328, 376, 360, 280, 264, 312, 296,
|
||||||
|
472, 456, 504, 488, 408, 392, 440, 424,
|
||||||
|
88, 72, 120, 104, 24, 8, 56, 40,
|
||||||
|
216, 200, 248, 232, 152, 136, 184, 168,
|
||||||
|
1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
|
||||||
|
1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
|
||||||
|
688, 656, 752, 720, 560, 528, 624, 592,
|
||||||
|
944, 912, 1008, 976, 816, 784, 880, 848
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Encode Table
|
||||||
|
private static readonly byte[] EncodeTable =
|
||||||
|
{
|
||||||
|
1, 1, 2, 2, 3, 3, 3, 3,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConvertToALaw (TODO)
|
||||||
|
private static void ConvertToALaw(WaveInfo info)
|
||||||
|
{
|
||||||
|
//int sign;
|
||||||
|
//int exponent;
|
||||||
|
//int mantissa;
|
||||||
|
//unsigned char compressedByte;
|
||||||
|
|
||||||
|
//sign = ((~sample) >> 8) & 0x80;
|
||||||
|
//if (!sign)
|
||||||
|
// sample = (short)-sample;
|
||||||
|
//if (sample > cClip)
|
||||||
|
// sample = cClip;
|
||||||
|
//if (sample >= 256)
|
||||||
|
//{
|
||||||
|
// exponent = (int)ALawCompressTable[(sample >> 8) & 0x7F];
|
||||||
|
// mantissa = (sample >> (exponent + 3) ) & 0x0F;
|
||||||
|
// compressedByte = ((exponent << 4) | mantissa);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// compressedByte = (unsigned char)(sample >> 4);
|
||||||
|
//}
|
||||||
|
//compressedByte ^= (sign ^ 0x55);
|
||||||
|
//return compressedByte;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConvertToPcm
|
||||||
|
public static void ConvertToPcm(WaveInfo info)
|
||||||
|
{
|
||||||
|
info.OpenALFormat = info.Channels == 1 ?
|
||||||
|
ALFormat.Mono16 :
|
||||||
|
ALFormat.Stereo16;
|
||||||
|
MemoryStream destStream = new MemoryStream();
|
||||||
|
BinaryWriter destWriter = new BinaryWriter(destStream);
|
||||||
|
for (int index = 0; index < info.Data.Length; index++)
|
||||||
|
{
|
||||||
|
destWriter.Write(DecodeTable[info.Data[index]]);
|
||||||
|
}
|
||||||
|
destWriter.Close();
|
||||||
|
info.Data = destStream.ToArray();
|
||||||
|
destStream.Dispose();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
141
SoundSystems/ANX.SoundSystem.OpenAL/Wave/MsAdpcm.cs
Normal file
141
SoundSystems/ANX.SoundSystem.OpenAL/Wave/MsAdpcm.cs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework and originally taken from
|
||||||
|
// the AC.AL OpenAL library, released under the MIT License.
|
||||||
|
// For details see: http://acal.codeplex.com/license
|
||||||
|
|
||||||
|
namespace ANX.SoundSystem.OpenAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM
|
||||||
|
/// <para />
|
||||||
|
/// http://dslinux.gits.kiev.ua/trunk/lib/audiofile/src/libaudiofile/modules/msadpcm.c
|
||||||
|
/// <para />
|
||||||
|
/// http://netghost.narod.ru/gff/vendspec/micriff/ms_riff.txt
|
||||||
|
/// </summary>
|
||||||
|
internal static class MsAdpcm
|
||||||
|
{
|
||||||
|
#region Decoding Tables
|
||||||
|
private static readonly int[] AdaptationTable =
|
||||||
|
{
|
||||||
|
230, 230, 230, 230, 307, 409, 512, 614,
|
||||||
|
768, 614, 512, 409, 307, 230, 230, 230
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly int[] AdaptCoeff1 =
|
||||||
|
{
|
||||||
|
256, 512, 0, 192, 240, 460, 392
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly int[] AdaptCoeff2 =
|
||||||
|
{
|
||||||
|
0, -256, 0, 64, 0, -208, -232
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region StateObject (helper class)
|
||||||
|
private class StateObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indices in the aCoef array to define the predictor
|
||||||
|
/// used to encode this block.
|
||||||
|
/// </summary>
|
||||||
|
public byte predicator;
|
||||||
|
/// <summary>
|
||||||
|
/// Initial Delta value to use.
|
||||||
|
/// </summary>
|
||||||
|
public short delta;
|
||||||
|
/// <summary>
|
||||||
|
/// The second sample value of the block. When decoding this will be
|
||||||
|
/// used as the previous sample to start decoding with.
|
||||||
|
/// </summary>
|
||||||
|
public short sample1;
|
||||||
|
/// <summary>
|
||||||
|
/// The first sample value of the block. When decoding this will be
|
||||||
|
/// used as the previous' previous sample to start decoding with.
|
||||||
|
/// </summary>
|
||||||
|
public short sample2;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConvertToPcm
|
||||||
|
public static void ConvertToPcm(WaveInfo info)
|
||||||
|
{
|
||||||
|
BinaryReader reader = new BinaryReader(new MemoryStream(info.Data));
|
||||||
|
MemoryStream result = new MemoryStream();
|
||||||
|
BinaryWriter writer = new BinaryWriter(result);
|
||||||
|
|
||||||
|
StateObject first = new StateObject();
|
||||||
|
StateObject second = info.Channels > 1 ? new StateObject() : first;
|
||||||
|
StateObject[] states = { first, second };
|
||||||
|
|
||||||
|
int numSamples = (info.ExtSamplesPerBlock - 2) * info.Channels;
|
||||||
|
int numberOfBlocks = info.Data.Length / info.BlockAlign;
|
||||||
|
for (int blockIndex = 0; blockIndex < numberOfBlocks; blockIndex++)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < info.Channels; index++)
|
||||||
|
{
|
||||||
|
states[index].predicator = reader.ReadByte();
|
||||||
|
}
|
||||||
|
for (int index = 0; index < info.Channels; index++)
|
||||||
|
{
|
||||||
|
states[index].delta = reader.ReadInt16();
|
||||||
|
}
|
||||||
|
for (int index = 0; index < info.Channels; index++)
|
||||||
|
{
|
||||||
|
states[index].sample1 = reader.ReadInt16();
|
||||||
|
}
|
||||||
|
for (int index = 0; index < info.Channels; index++)
|
||||||
|
{
|
||||||
|
states[index].sample2 = reader.ReadInt16();
|
||||||
|
// Write first samples directly from preamble
|
||||||
|
writer.Write(states[index].sample2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write first samples directly from preamble
|
||||||
|
for (int index = 0; index < info.Channels; index++)
|
||||||
|
{
|
||||||
|
writer.Write(states[index].sample1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We decode the samples two at a time
|
||||||
|
for (int index = 0; index < numSamples; index += 2)
|
||||||
|
{
|
||||||
|
byte code = reader.ReadByte();
|
||||||
|
DecodeSample(first, code >> 4, writer);
|
||||||
|
DecodeSample(second, code & 0x0f, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.Close();
|
||||||
|
writer.Close();
|
||||||
|
info.Data = result.ToArray();
|
||||||
|
result.Dispose();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region DecodeSample
|
||||||
|
private static void DecodeSample(StateObject state, int code,
|
||||||
|
BinaryWriter writer)
|
||||||
|
{
|
||||||
|
int linearSample =
|
||||||
|
((state.sample1 * AdaptCoeff1[state.predicator]) +
|
||||||
|
(state.sample2 * AdaptCoeff2[state.predicator])) / 256;
|
||||||
|
|
||||||
|
linearSample = linearSample + (state.delta *
|
||||||
|
((code & 0x08) == 0x08 ? (code - 0x10) : code));
|
||||||
|
|
||||||
|
state.sample2 = state.sample1;
|
||||||
|
// clamp predictor within signed 16-bit range
|
||||||
|
state.sample1 = (short)Math.Min(short.MaxValue,
|
||||||
|
Math.Max(short.MinValue, linearSample));
|
||||||
|
|
||||||
|
state.delta = (short)Math.Max(
|
||||||
|
(state.delta * AdaptationTable[code]) / 256, 16);
|
||||||
|
|
||||||
|
writer.Write(state.sample1);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
111
SoundSystems/ANX.SoundSystem.OpenAL/Wave/MuLaw.cs
Normal file
111
SoundSystems/ANX.SoundSystem.OpenAL/Wave/MuLaw.cs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework and originally taken from
|
||||||
|
// the AC.AL OpenAL library, released under the MIT License.
|
||||||
|
// For details see: http://acal.codeplex.com/license
|
||||||
|
|
||||||
|
namespace ANX.SoundSystem.OpenAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// http://www.threejacks.com/?q=node/176
|
||||||
|
/// </summary>
|
||||||
|
internal static class MuLaw
|
||||||
|
{
|
||||||
|
#region Decode Table
|
||||||
|
private static readonly short[] DecodeTable =
|
||||||
|
{
|
||||||
|
-32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
|
||||||
|
-23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
|
||||||
|
-15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
|
||||||
|
-11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
|
||||||
|
-7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
|
||||||
|
-5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
|
||||||
|
-3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
|
||||||
|
-2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
|
||||||
|
-1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
|
||||||
|
-1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
|
||||||
|
-876, -844, -812, -780, -748, -716, -684, -652,
|
||||||
|
-620, -588, -556, -524, -492, -460, -428, -396,
|
||||||
|
-372, -356, -340, -324, -308, -292, -276, -260,
|
||||||
|
-244, -228, -212, -196, -180, -164, -148, -132,
|
||||||
|
-120, -112, -104, -96, -88, -80, -72, -64,
|
||||||
|
-56, -48, -40, -32, -24, -16, -8, -1,
|
||||||
|
32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
|
||||||
|
23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
|
||||||
|
15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
|
||||||
|
11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
|
||||||
|
7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
|
||||||
|
5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
|
||||||
|
3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
|
||||||
|
2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
|
||||||
|
1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
|
||||||
|
1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
|
||||||
|
876, 844, 812, 780, 748, 716, 684, 652,
|
||||||
|
620, 588, 556, 524, 492, 460, 428, 396,
|
||||||
|
372, 356, 340, 324, 308, 292, 276, 260,
|
||||||
|
244, 228, 212, 196, 180, 164, 148, 132,
|
||||||
|
120, 112, 104, 96, 88, 80, 72, 64,
|
||||||
|
56, 48, 40, 32, 24, 16, 8, 0
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Encode Table
|
||||||
|
private static readonly byte[] EncodeTable =
|
||||||
|
{
|
||||||
|
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConvertToMuLaw (TODO)
|
||||||
|
private static void ConvertToMuLaw(WaveInfo info)
|
||||||
|
{
|
||||||
|
//int sign = (sample >> 8) & 0x80;
|
||||||
|
//if (sign)
|
||||||
|
// sample = (short)-sample;
|
||||||
|
//if (sample > cClip)
|
||||||
|
// sample = cClip;
|
||||||
|
//sample = (short)(sample + cBias);
|
||||||
|
//int exponent = (int)MuLawCompressTable[(sample>>7) & 0xFF];
|
||||||
|
//int mantissa = (sample >> (exponent+3)) & 0x0F;
|
||||||
|
//int compressedByte = ~ (sign | (exponent << 4) | mantissa);
|
||||||
|
|
||||||
|
//return (unsigned char)compressedByte;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConvertToPcm
|
||||||
|
public static void ConvertToPcm(WaveInfo info)
|
||||||
|
{
|
||||||
|
info.OpenALFormat = info.Channels == 1 ?
|
||||||
|
ALFormat.Mono16 :
|
||||||
|
ALFormat.Stereo16;
|
||||||
|
MemoryStream destStream = new MemoryStream();
|
||||||
|
BinaryWriter destWriter = new BinaryWriter(destStream);
|
||||||
|
for (int index = 0; index < info.Data.Length; index++)
|
||||||
|
{
|
||||||
|
destWriter.Write(DecodeTable[info.Data[index]]);
|
||||||
|
}
|
||||||
|
destWriter.Close();
|
||||||
|
info.Data = destStream.ToArray();
|
||||||
|
destStream.Dispose();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
235
SoundSystems/ANX.SoundSystem.OpenAL/Wave/WaveFile.cs
Normal file
235
SoundSystems/ANX.SoundSystem.OpenAL/Wave/WaveFile.cs
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using ANX.Framework.NonXNA;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework and originally taken from
|
||||||
|
// the AC.AL OpenAL library, released under the MIT License.
|
||||||
|
// For details see: http://acal.codeplex.com/license
|
||||||
|
|
||||||
|
namespace ANX.SoundSystem.OpenAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class contains all the loading process of a wave file.
|
||||||
|
/// <para />
|
||||||
|
/// http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html
|
||||||
|
/// <para />
|
||||||
|
/// Chunk information: http://www.sonicspot.com/guide/wavefiles.html
|
||||||
|
/// <para />
|
||||||
|
/// Audio Codecs: http://wiki.multimedia.cx/index.php?title=Category:Audio_Codecs
|
||||||
|
/// <para />
|
||||||
|
/// http://netghost.narod.ru/gff/vendspec/micriff/ms_riff.txt
|
||||||
|
/// <para />
|
||||||
|
/// Most interesting file about many formats:
|
||||||
|
/// http://icculus.org/SDL_sound/downloads/external_documentation/wavecomp.htm
|
||||||
|
/// <para />
|
||||||
|
/// http://sharkysoft.com/archive/lava/docs/javadocs/lava/riff/wave/doc-files/riffwave-content.htm
|
||||||
|
/// </summary>
|
||||||
|
public static class WaveFile
|
||||||
|
{
|
||||||
|
#region LoadData
|
||||||
|
/// <summary>
|
||||||
|
/// Load all information from a wave file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The stream containing the wave file data.</param>
|
||||||
|
public static WaveInfo LoadData(Stream stream)
|
||||||
|
{
|
||||||
|
WaveInfo result = new WaveInfo();
|
||||||
|
|
||||||
|
using (BinaryReader reader = new BinaryReader(stream))
|
||||||
|
{
|
||||||
|
if (CheckHeader(reader) == false)
|
||||||
|
{
|
||||||
|
throw new FormatException("The provided stream is not a valid WAVE file. Unable to load!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Read Chunks
|
||||||
|
while (stream.Position < stream.Length - 8)
|
||||||
|
{
|
||||||
|
string identifier = new string(reader.ReadChars(4));
|
||||||
|
int chunkLength = reader.ReadInt32();
|
||||||
|
|
||||||
|
if (stream.Position + chunkLength > stream.Length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startPosition = (int)reader.BaseStream.Position;
|
||||||
|
|
||||||
|
switch (identifier.ToLower())
|
||||||
|
{
|
||||||
|
case "fmt ":
|
||||||
|
{
|
||||||
|
#region Load fmt chunk
|
||||||
|
result.WaveFormat = (WaveFormat)reader.ReadInt16();
|
||||||
|
result.Channels = reader.ReadInt16();
|
||||||
|
result.SampleRate = reader.ReadInt32();
|
||||||
|
int avgBytesPerSec = reader.ReadInt32();
|
||||||
|
result.BlockAlign = reader.ReadInt16();
|
||||||
|
result.BitsPerSample = reader.ReadInt16();
|
||||||
|
|
||||||
|
if (chunkLength > 16)
|
||||||
|
{
|
||||||
|
short extensionSize = reader.ReadInt16();
|
||||||
|
|
||||||
|
if (chunkLength > 18)
|
||||||
|
{
|
||||||
|
result.ExtSamplesPerBlock = reader.ReadInt16();
|
||||||
|
int speakerPositionMask = reader.ReadInt32();
|
||||||
|
WaveFormat extFormat = (WaveFormat)reader.ReadInt16();
|
||||||
|
if (result.WaveFormat < 0)
|
||||||
|
{
|
||||||
|
result.WaveFormat = extFormat;
|
||||||
|
}
|
||||||
|
byte[] subFormat = reader.ReadBytes(14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.OpenALFormat = (result.Channels == 1 ?
|
||||||
|
(result.BitsPerSample == 8 ?
|
||||||
|
ALFormat.Mono8 :
|
||||||
|
ALFormat.Mono16) :
|
||||||
|
(result.BitsPerSample == 8 ?
|
||||||
|
ALFormat.Stereo8 :
|
||||||
|
ALFormat.Stereo16));
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "fact":
|
||||||
|
{
|
||||||
|
#region Load fact chunk
|
||||||
|
// per channel
|
||||||
|
int numberOfSamples = reader.ReadInt32();
|
||||||
|
// TODO: more
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "data":
|
||||||
|
result.Data = reader.ReadBytes(chunkLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If some chunks are incorrect in data length, we ensure that we
|
||||||
|
// end up in the right position.
|
||||||
|
int lengthRead = (int)reader.BaseStream.Position - startPosition;
|
||||||
|
if (lengthRead != chunkLength)
|
||||||
|
{
|
||||||
|
reader.BaseStream.Seek(chunkLength - lengthRead,
|
||||||
|
SeekOrigin.Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.Data == null)
|
||||||
|
{
|
||||||
|
Logger.Error("There was no data chunk available. Unable to load!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvertFormat(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region CheckHeader
|
||||||
|
private static bool CheckHeader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
string RIFFmagic = new string(reader.ReadChars(4));
|
||||||
|
if(RIFFmagic != "RIFF")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// filesize
|
||||||
|
reader.ReadInt32();
|
||||||
|
|
||||||
|
string identifierWAVE = new string(reader.ReadChars(4));
|
||||||
|
if(identifierWAVE != "WAVE")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ConvertFormat
|
||||||
|
private static void ConvertFormat(WaveInfo info)
|
||||||
|
{
|
||||||
|
switch (info.WaveFormat)
|
||||||
|
{
|
||||||
|
case WaveFormat.PCM:
|
||||||
|
#region Convert 32 to 16 bps (TODO)
|
||||||
|
//if (info.BitsPerSample == 32)
|
||||||
|
//{
|
||||||
|
// BinaryReader sourceReader =
|
||||||
|
// new BinaryReader(new MemoryStream(info.Data));
|
||||||
|
// MemoryStream destStream = new MemoryStream();
|
||||||
|
// BinaryWriter destWriter = new BinaryWriter(destStream);
|
||||||
|
|
||||||
|
// int length = info.Data.Length / 4;
|
||||||
|
// for (int index = 0; index < length; index++)
|
||||||
|
// {
|
||||||
|
// int value = sourceReader.ReadInt32();
|
||||||
|
// destWriter.Write((short)(value / 2));
|
||||||
|
// }
|
||||||
|
// sourceReader.Close();
|
||||||
|
// destWriter.Close();
|
||||||
|
// info.Data = destStream.ToArray();
|
||||||
|
// destStream.Dispose();
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WaveFormat.ALAW:
|
||||||
|
ALaw.ConvertToPcm(info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WaveFormat.MULAW:
|
||||||
|
MuLaw.ConvertToPcm(info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WaveFormat.IEEE_FLOAT:
|
||||||
|
{
|
||||||
|
#region Convert float to pcm
|
||||||
|
bool is64BitFloat = info.BitsPerSample == 64;
|
||||||
|
|
||||||
|
BinaryReader sourceReader =
|
||||||
|
new BinaryReader(new MemoryStream(info.Data));
|
||||||
|
MemoryStream destStream = new MemoryStream();
|
||||||
|
BinaryWriter destWriter = new BinaryWriter(destStream);
|
||||||
|
|
||||||
|
int length = info.Data.Length / (is64BitFloat ? 8 : 4);
|
||||||
|
for (int index = 0; index < length; index++)
|
||||||
|
{
|
||||||
|
double value = is64BitFloat ?
|
||||||
|
sourceReader.ReadDouble() :
|
||||||
|
sourceReader.ReadSingle();
|
||||||
|
|
||||||
|
destWriter.Write((short)(value * 32767));
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceReader.Close();
|
||||||
|
destWriter.Close();
|
||||||
|
info.Data = destStream.ToArray();
|
||||||
|
destStream.Dispose();
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WaveFormat.MS_ADPCM:
|
||||||
|
MsAdpcm.ConvertToPcm(info);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException("The WAVE format " +
|
||||||
|
info.WaveFormat + " is not supported yet. Unable to load!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
33
SoundSystems/ANX.SoundSystem.OpenAL/Wave/WaveFormat.cs
Normal file
33
SoundSystems/ANX.SoundSystem.OpenAL/Wave/WaveFormat.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework and originally taken from
|
||||||
|
// the AC.AL OpenAL library, released under the MIT License.
|
||||||
|
// For details see: http://acal.codeplex.com/license
|
||||||
|
|
||||||
|
namespace ANX.SoundSystem.OpenAL
|
||||||
|
{
|
||||||
|
public enum WaveFormat
|
||||||
|
{
|
||||||
|
PCM = 1,
|
||||||
|
/// <summary>
|
||||||
|
/// http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM
|
||||||
|
/// </summary>
|
||||||
|
MS_ADPCM = 2,
|
||||||
|
IEEE_FLOAT = 3,
|
||||||
|
/// <summary>
|
||||||
|
/// 8-bit ITU-T G.711 A-law
|
||||||
|
/// http://hazelware.luggle.com/tutorials/mulawcompression.html
|
||||||
|
/// </summary>
|
||||||
|
ALAW = 6,
|
||||||
|
/// <summary>
|
||||||
|
/// 8-bit ITU-T G.711 µ-law
|
||||||
|
/// http://hazelware.luggle.com/tutorials/mulawcompression.html
|
||||||
|
/// </summary>
|
||||||
|
MULAW = 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determined by SubFormat
|
||||||
|
/// </summary>
|
||||||
|
WAVE_FORMAT_EXTENSIBLE = 0xFFFE,
|
||||||
|
}
|
||||||
|
}
|
60
SoundSystems/ANX.SoundSystem.OpenAL/Wave/WaveInfo.cs
Normal file
60
SoundSystems/ANX.SoundSystem.OpenAL/Wave/WaveInfo.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
|
||||||
|
// This file is part of the ANX.Framework and originally taken from
|
||||||
|
// the AC.AL OpenAL library, released under the MIT License.
|
||||||
|
// For details see: http://acal.codeplex.com/license
|
||||||
|
|
||||||
|
namespace ANX.SoundSystem.OpenAL
|
||||||
|
{
|
||||||
|
public class WaveInfo
|
||||||
|
{
|
||||||
|
public WaveFormat WaveFormat
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Data
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ALFormat OpenALFormat
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SampleRate
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short BitsPerSample
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short BlockAlign
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Channels
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short ExtSamplesPerBlock
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user