diff --git a/ANX.Framework/ANX.Framework.csproj b/ANX.Framework/ANX.Framework.csproj index 29384d5b..c33deda5 100644 --- a/ANX.Framework/ANX.Framework.csproj +++ b/ANX.Framework/ANX.Framework.csproj @@ -445,6 +445,7 @@ + diff --git a/ANX.Framework/Audio/AudioEngine.cs b/ANX.Framework/Audio/AudioEngine.cs index dbdd688c..f7d63611 100644 --- a/ANX.Framework/Audio/AudioEngine.cs +++ b/ANX.Framework/Audio/AudioEngine.cs @@ -4,7 +4,6 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; using ANX.Framework.Audio.XactParser; -using ANX.Framework.NonXNA; using ANX.Framework.NonXNA.Development; using ANX.Framework.NonXNA.PlatformSystem; @@ -44,17 +43,12 @@ namespace ANX.Framework.Audio #endregion #region Constructor (TODO) - public AudioEngine(string settingsFile) - { - // TODO: get renderer details - RendererDetails = new ReadOnlyCollection(new List()); + public AudioEngine(string settingsFile) + : this(settingsFile, TimeSpan.FromMilliseconds(250.0), String.Empty) + { + } - Stream loadingStream = PlatformSystem.Instance.OpenReadFilestream(settingsFile); - generalSettings = new XactGeneralSettings(loadingStream); - loadingStream.Dispose(); - } - - public AudioEngine(string settingsFile, TimeSpan lookAheadTime, string rendererId) + public AudioEngine(string settingsFile, TimeSpan lookAheadTime, string rendererId) { // TODO: get renderer details RendererDetails = new ReadOnlyCollection(new List()); diff --git a/ANX.Framework/Audio/DynamicSoundEffectInstance.cs b/ANX.Framework/Audio/DynamicSoundEffectInstance.cs index be9dde52..d4b85906 100644 --- a/ANX.Framework/Audio/DynamicSoundEffectInstance.cs +++ b/ANX.Framework/Audio/DynamicSoundEffectInstance.cs @@ -1,5 +1,7 @@ using System; +using ANX.Framework.NonXNA; using ANX.Framework.NonXNA.Development; +using ANX.Framework.NonXNA.SoundSystem; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. @@ -7,82 +9,75 @@ using ANX.Framework.NonXNA.Development; namespace ANX.Framework.Audio { - [PercentageComplete(0)] - public sealed class DynamicSoundEffectInstance : SoundEffectInstance - { - #region Events - public event EventHandler BufferNeeded; - #endregion + [PercentageComplete(100)] + [TestState(TestStateAttribute.TestState.Untested)] + [Developer("AstrorEnales")] + public sealed class DynamicSoundEffectInstance : SoundEffectInstance + { + private IDynamicSoundEffectInstance nativeDynamicInstance; + private readonly AudioChannels channels; + private readonly int sampleRate; - #region Public - public override bool IsLooped - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } + public event EventHandler BufferNeeded; - public int PendingBufferCount - { - get - { - throw new NotImplementedException(); - } - } - #endregion + #region Public + public int PendingBufferCount + { + get { return nativeDynamicInstance.PendingBufferCount; } + } + #endregion - #region Constructor - public DynamicSoundEffectInstance(int sampleRate, AudioChannels channels) - { - throw new NotImplementedException(); - } - #endregion + #region Constructor + public DynamicSoundEffectInstance(int sampleRate, AudioChannels channels) + { + this.sampleRate = sampleRate; + this.channels = channels; + var creator = AddInSystemFactory.Instance.GetDefaultCreator(); + nativeDynamicInstance = creator.CreateDynamicSoundEffectInstance(); + nativeDynamicInstance.BufferNeeded += OnBufferNeeded; + SetNativeInstance(nativeDynamicInstance); + } + #endregion - #region GetSampleDuration - public TimeSpan GetSampleDuration(int sizeInBytes) - { - throw new NotImplementedException(); - } - #endregion + private void OnBufferNeeded(object sender, EventArgs args) + { + BufferNeeded.Invoke(this, EventArgs.Empty); + } - #region GetSampleSizeInBytes - public int GetSampleSizeInBytes(TimeSpan duration) - { - throw new NotImplementedException(); - } - #endregion + #region GetSampleDuration + public TimeSpan GetSampleDuration(int sizeInBytes) + { + float sizeMulBlockAlign = (float)sizeInBytes / ((int)channels * 2); + return TimeSpan.FromMilliseconds(sizeMulBlockAlign * 1000f / sampleRate); + } + #endregion - #region Play - public override void Play() - { - throw new NotImplementedException(); - } - #endregion + #region GetSampleSizeInBytes + public int GetSampleSizeInBytes(TimeSpan duration) + { + int timeMulSamples = (int)(duration.TotalMilliseconds * (sampleRate / 1000f)); + return (timeMulSamples + timeMulSamples % (int)channels) * ((int)channels * 2); + } + #endregion + + public void SubmitBuffer(byte[] buffer) + { + nativeDynamicInstance.SubmitBuffer(buffer); + } - #region SubmitBuffer - public void SubmitBuffer(byte[] buffer) - { - throw new NotImplementedException(); - } - #endregion + public void SubmitBuffer(byte[] buffer, int offset, int count) + { + nativeDynamicInstance.SubmitBuffer(buffer, offset, count); + } - #region SubmitBuffer - public void SubmitBuffer(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - #endregion - - #region Dispose - protected override void Dispose(bool disposing) - { - throw new NotImplementedException(); - } - #endregion - } + protected override void Dispose(bool disposing) + { + if (nativeDynamicInstance != null) + { + nativeDynamicInstance.BufferNeeded -= OnBufferNeeded; + } + nativeDynamicInstance = null; + base.Dispose(true); + } + } } diff --git a/ANX.Framework/Audio/RendererDetail.cs b/ANX.Framework/Audio/RendererDetail.cs index bdd6b7b3..2d3aff69 100644 --- a/ANX.Framework/Audio/RendererDetail.cs +++ b/ANX.Framework/Audio/RendererDetail.cs @@ -16,22 +16,16 @@ namespace ANX.Framework.Audio #endregion #region Public - public string FriendlyName - { - get - { - return friendlyName; - } - } + public string FriendlyName + { + get { return friendlyName; } + } - public string RendererId - { - get - { - return rendererId; - } - } - #endregion + public string RendererId + { + get { return rendererId; } + } + #endregion #region Constructor internal RendererDetail(string setFriendlyName, string setRendererId) @@ -66,10 +60,8 @@ namespace ANX.Framework.Audio #region Equality public override bool Equals(object obj) { - if (obj != null && obj is RendererDetail) - { + if (obj is RendererDetail) return this == (RendererDetail)obj; - } return false; } diff --git a/ANX.Framework/Audio/SoundEffectInstance.cs b/ANX.Framework/Audio/SoundEffectInstance.cs index 656de509..68443a8b 100644 --- a/ANX.Framework/Audio/SoundEffectInstance.cs +++ b/ANX.Framework/Audio/SoundEffectInstance.cs @@ -15,7 +15,7 @@ namespace ANX.Framework.Audio public class SoundEffectInstance : IDisposable { #region Private - private ISoundEffectInstance nativeInstance; + internal ISoundEffectInstance NativeInstance { get; private set; } internal bool IsFireAndForget { get; private set; } #endregion @@ -24,31 +24,31 @@ namespace ANX.Framework.Audio public virtual bool IsLooped { - get { return nativeInstance.IsLooped; } - set { nativeInstance.IsLooped = value; } + get { return NativeInstance.IsLooped; } + set { NativeInstance.IsLooped = value; } } public float Pan { - get { return nativeInstance.Pan; } - set { nativeInstance.Pan = value; } + get { return NativeInstance.Pan; } + set { NativeInstance.Pan = value; } } public float Pitch { - get { return nativeInstance.Pitch; } - set { nativeInstance.Pitch = value; } + get { return NativeInstance.Pitch; } + set { NativeInstance.Pitch = value; } } public SoundState State { - get { return nativeInstance.State; } + get { return NativeInstance.State; } } public float Volume { - get { return nativeInstance.Volume; } - set { nativeInstance.Volume = value; } + get { return NativeInstance.Volume; } + set { NativeInstance.Volume = value; } } #endregion @@ -60,7 +60,7 @@ namespace ANX.Framework.Audio internal SoundEffectInstance(SoundEffect setParent, bool setIsFireAndForget) { IsFireAndForget = setIsFireAndForget; - nativeInstance = GetCreator().CreateSoundEffectInstance(setParent.NativeSoundEffect); + NativeInstance = GetCreator().CreateSoundEffectInstance(setParent.NativeSoundEffect); } ~SoundEffectInstance() @@ -69,6 +69,11 @@ namespace ANX.Framework.Audio } #endregion + internal void SetNativeInstance(IDynamicSoundEffectInstance dynamicInstance) + { + NativeInstance = dynamicInstance; + } + #region GetCreator private static ISoundSystemCreator GetCreator() { @@ -84,28 +89,28 @@ namespace ANX.Framework.Audio public void Apply3D(AudioListener[] listeners, AudioEmitter emitter) { - nativeInstance.Apply3D(listeners, emitter); + NativeInstance.Apply3D(listeners, emitter); } #endregion #region Pause public void Pause() { - nativeInstance.Pause(); + NativeInstance.Pause(); } #endregion #region Play public virtual void Play() { - nativeInstance.Play(); + NativeInstance.Play(); } #endregion #region Resume public void Resume() { - nativeInstance.Resume(); + NativeInstance.Resume(); } #endregion @@ -117,7 +122,7 @@ namespace ANX.Framework.Audio public void Stop(bool immediate) { - nativeInstance.Stop(immediate); + NativeInstance.Stop(immediate); } #endregion @@ -129,10 +134,10 @@ namespace ANX.Framework.Audio protected virtual void Dispose(bool disposing) { - if (nativeInstance != null) + if (NativeInstance != null) { - nativeInstance.Dispose(); - nativeInstance = null; + NativeInstance.Dispose(); + NativeInstance = null; } IsDisposed = true; diff --git a/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs b/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs index 8ecf7029..928f456d 100644 --- a/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs +++ b/ANX.Framework/Content/MediaTypeReaders/SoundEffectReader.cs @@ -1,13 +1,13 @@ using System; -using ANX.Framework.Audio; using System.IO; using System.Runtime.InteropServices; +using ANX.Framework.Audio; namespace ANX.Framework.Content { internal class SoundEffectReader : ContentTypeReader { - private struct WAVEFORMATEX + private struct WaveFormatEx { public ushort wFormatTag; public ushort nChannels; @@ -23,11 +23,11 @@ namespace ANX.Framework.Content int formatCount = input.ReadInt32(); byte[] header = input.ReadBytes(formatCount); - WAVEFORMATEX headerStruct; + WaveFormatEx headerStruct; unsafe { fixed(byte* ptr = &header[0]) - headerStruct = (WAVEFORMATEX)Marshal.PtrToStructure((IntPtr)ptr, typeof(WAVEFORMATEX)); + headerStruct = (WaveFormatEx)Marshal.PtrToStructure((IntPtr)ptr, typeof(WaveFormatEx)); } int dataCount = input.ReadInt32(); @@ -38,10 +38,10 @@ namespace ANX.Framework.Content int duration = input.ReadInt32(); - byte[] soundData = null; - using (MemoryStream mStream = new MemoryStream(20 + header.Length + 8 + data.Length)) + byte[] soundData; + using (var mStream = new MemoryStream(20 + header.Length + 8 + data.Length)) { - BinaryWriter writer = new BinaryWriter(mStream); + var writer = new BinaryWriter(mStream); writer.Write("RIFF".ToCharArray()); writer.Write(20 + header.Length + data.Length); writer.Write("WAVE".ToCharArray()); diff --git a/ANX.Framework/NonXNA/SoundSystem/IDynamicSoundEffectInstance.cs b/ANX.Framework/NonXNA/SoundSystem/IDynamicSoundEffectInstance.cs new file mode 100644 index 00000000..3e522a6a --- /dev/null +++ b/ANX.Framework/NonXNA/SoundSystem/IDynamicSoundEffectInstance.cs @@ -0,0 +1,17 @@ +using System; + +// 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.Framework.NonXNA.SoundSystem +{ + public interface IDynamicSoundEffectInstance : ISoundEffectInstance + { + event EventHandler BufferNeeded; + int PendingBufferCount { get; } + + void SubmitBuffer(byte[] buffer); + void SubmitBuffer(byte[] buffer, int offset, int count); + } +} \ No newline at end of file diff --git a/ANX.Framework/NonXNA/SoundSystem/ISoundEffectInstance.cs b/ANX.Framework/NonXNA/SoundSystem/ISoundEffectInstance.cs index 3b5c7eba..3166c6fe 100644 --- a/ANX.Framework/NonXNA/SoundSystem/ISoundEffectInstance.cs +++ b/ANX.Framework/NonXNA/SoundSystem/ISoundEffectInstance.cs @@ -7,45 +7,18 @@ using ANX.Framework.Audio; namespace ANX.Framework.NonXNA.SoundSystem { - public interface ISoundEffectInstance : IDisposable - { - bool IsLooped - { - get; - set; - } + public interface ISoundEffectInstance : IDisposable + { + bool IsLooped { get; set; } + float Pan { get; set; } + float Pitch { get; set; } + SoundState State { get; } + float Volume { get; set; } - float Pan - { - get; - set; - } - - float Pitch - { - get; - set; - } - - SoundState State - { - get; - } - - float Volume - { - get; - set; - } - - void Play(); - - void Pause(); - - void Stop(bool immediate); - - void Resume(); - - void Apply3D(AudioListener[] listeners, AudioEmitter emitter); - } + void Play(); + void Pause(); + void Stop(bool immediate); + void Resume(); + void Apply3D(AudioListener[] listeners, AudioEmitter emitter); + } } diff --git a/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs b/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs index 6d09b291..df710dad 100644 --- a/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs +++ b/ANX.Framework/NonXNA/SoundSystem/ISoundSystemCreator.cs @@ -36,5 +36,7 @@ namespace ANX.Framework.NonXNA.SoundSystem int GetDefaultMicrophone(ReadOnlyCollection allMicrophones); ISong CreateSong(Song parentSong, Uri uri); + + IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance(); } } diff --git a/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs b/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs index 23acfef4..7fc76947 100644 --- a/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs +++ b/SoundSystems/ANX.SoundSystem.OpenAL/Creator.cs @@ -160,6 +160,12 @@ namespace ANX.SoundSystem.OpenAL #endregion public ISong CreateSong(Song parentSong, Uri uri) + { + PreventSystemChange(); + throw new NotImplementedException(); + } + + public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance() { PreventSystemChange(); throw new NotImplementedException(); diff --git a/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs b/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs index a50ee60a..cedac182 100644 --- a/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs +++ b/SoundSystems/ANX.SoundSystem.PsVita/Creator.cs @@ -171,5 +171,11 @@ namespace ANX.SoundSystem.PsVita AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem); throw new NotImplementedException(); } + + public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance() + { + AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem); + throw new NotImplementedException(); + } } } diff --git a/SoundSystems/ANX.SoundSystem.Windows.XAudio/Creator.cs b/SoundSystems/ANX.SoundSystem.Windows.XAudio/Creator.cs index dd4a9da6..79ba96af 100644 --- a/SoundSystems/ANX.SoundSystem.Windows.XAudio/Creator.cs +++ b/SoundSystems/ANX.SoundSystem.Windows.XAudio/Creator.cs @@ -154,6 +154,12 @@ namespace ANX.SoundSystem.Windows.XAudio } public ISong CreateSong(Song parentSong, Uri uri) + { + PreventSystemChange(); + throw new NotImplementedException(); + } + + public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance() { PreventSystemChange(); throw new NotImplementedException();