Working on native DynamicSoundEffectInstance implementation in XAudio and OpenAL
This commit is contained in:
parent
0417857fd9
commit
3e65589f23
@ -33,7 +33,7 @@ namespace ANX.Framework.Audio
|
|||||||
this.sampleRate = sampleRate;
|
this.sampleRate = sampleRate;
|
||||||
this.channels = channels;
|
this.channels = channels;
|
||||||
var creator = AddInSystemFactory.Instance.GetDefaultCreator<ISoundSystemCreator>();
|
var creator = AddInSystemFactory.Instance.GetDefaultCreator<ISoundSystemCreator>();
|
||||||
nativeDynamicInstance = creator.CreateDynamicSoundEffectInstance();
|
nativeDynamicInstance = creator.CreateDynamicSoundEffectInstance(sampleRate, channels);
|
||||||
nativeDynamicInstance.BufferNeeded += OnBufferNeeded;
|
nativeDynamicInstance.BufferNeeded += OnBufferNeeded;
|
||||||
SetNativeInstance(nativeDynamicInstance);
|
SetNativeInstance(nativeDynamicInstance);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,6 @@ namespace ANX.Framework.NonXNA.SoundSystem
|
|||||||
ISong CreateSong(Song parentSong, Uri uri);
|
ISong CreateSong(Song parentSong, Uri uri);
|
||||||
ISong CreateSong(Song parentSong, string filepath, int duration);
|
ISong CreateSong(Song parentSong, string filepath, int duration);
|
||||||
|
|
||||||
IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance();
|
IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance(int sampleRate, AudioChannels channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,6 @@ using System.Runtime.InteropServices;
|
|||||||
[assembly: InternalsVisibleTo("ANX.PlatformSystem.Metro")]
|
[assembly: InternalsVisibleTo("ANX.PlatformSystem.Metro")]
|
||||||
[assembly: InternalsVisibleTo("ANX.PlatformSystem.PsVita")]
|
[assembly: InternalsVisibleTo("ANX.PlatformSystem.PsVita")]
|
||||||
[assembly: InternalsVisibleTo("ANX.SoundSystem.Windows.XAudio")]
|
[assembly: InternalsVisibleTo("ANX.SoundSystem.Windows.XAudio")]
|
||||||
[assembly: InternalsVisibleTo("ANX.SoundSystem.Windows.OpenAL")]
|
[assembly: InternalsVisibleTo("ANX.SoundSystem.OpenAL")]
|
||||||
[assembly: InternalsVisibleTo("ANX.Tools.XNBInspector")]
|
[assembly: InternalsVisibleTo("ANX.Tools.XNBInspector")]
|
||||||
[assembly: InternalsVisibleTo("ANX.Framework.Content.Pipeline")]
|
[assembly: InternalsVisibleTo("ANX.Framework.Content.Pipeline")]
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using ANX.Framework.NonXNA;
|
using ANX.Framework.NonXNA.Development;
|
||||||
using ANX.Framework.NonXNA.PlatformSystem;
|
using ANX.Framework.NonXNA.PlatformSystem;
|
||||||
|
|
||||||
// This file is part of the ANX.Framework created by the
|
// This file is part of the ANX.Framework created by the
|
||||||
@ -9,38 +9,27 @@ using ANX.Framework.NonXNA.PlatformSystem;
|
|||||||
|
|
||||||
namespace ANX.Framework.Storage
|
namespace ANX.Framework.Storage
|
||||||
{
|
{
|
||||||
|
[Developer("AstrorEnales")]
|
||||||
|
[TestState(TestStateAttribute.TestState.Untested)]
|
||||||
public class StorageContainer : IDisposable
|
public class StorageContainer : IDisposable
|
||||||
{
|
{
|
||||||
private INativeStorageContainer nativeImplementation;
|
private readonly INativeStorageContainer nativeImplementation;
|
||||||
|
|
||||||
#region Public
|
#region Public
|
||||||
public event EventHandler<EventArgs> Disposing;
|
public event EventHandler<EventArgs> Disposing;
|
||||||
|
|
||||||
public string DisplayName
|
public string DisplayName { get; protected set; }
|
||||||
{
|
public StorageDevice StorageDevice { get; protected set; }
|
||||||
get;
|
public bool IsDisposed { get; protected set; }
|
||||||
protected set;
|
#endregion
|
||||||
}
|
|
||||||
|
|
||||||
public StorageDevice StorageDevice
|
internal StorageContainer(StorageDevice device, PlayerIndex player, string displayName)
|
||||||
{
|
|
||||||
get;
|
|
||||||
protected set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDisposed
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
protected set;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
internal StorageContainer(StorageDevice device, PlayerIndex player,
|
|
||||||
string displayName)
|
|
||||||
{
|
{
|
||||||
StorageDevice = device;
|
StorageDevice = device;
|
||||||
DisplayName = displayName;
|
DisplayName = displayName;
|
||||||
|
|
||||||
|
// TODO: player!
|
||||||
|
|
||||||
nativeImplementation = PlatformSystem.Instance.CreateStorageContainer(this);
|
nativeImplementation = PlatformSystem.Instance.CreateStorageContainer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +106,8 @@ namespace ANX.Framework.Storage
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Disposing(this, EventArgs.Empty);
|
if (Disposing != null)
|
||||||
|
Disposing(this, EventArgs.Empty);
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using ANX.Framework.NonXNA;
|
using ANX.Framework.NonXNA.Development;
|
||||||
using ANX.Framework.NonXNA.PlatformSystem;
|
using ANX.Framework.NonXNA.PlatformSystem;
|
||||||
|
|
||||||
// This file is part of the ANX.Framework created by the
|
// This file is part of the ANX.Framework created by the
|
||||||
@ -9,6 +9,8 @@ using ANX.Framework.NonXNA.PlatformSystem;
|
|||||||
|
|
||||||
namespace ANX.Framework.Storage
|
namespace ANX.Framework.Storage
|
||||||
{
|
{
|
||||||
|
[Developer("AstrorEnales")]
|
||||||
|
[TestState(TestStateAttribute.TestState.Untested)]
|
||||||
public sealed class StorageDevice
|
public sealed class StorageDevice
|
||||||
{
|
{
|
||||||
#region Private
|
#region Private
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using ANX.Framework.NonXNA.Development;
|
||||||
|
|
||||||
#endregion // Using Statements
|
#endregion // Using Statements
|
||||||
|
|
||||||
@ -11,6 +12,8 @@ using System.Runtime.Serialization;
|
|||||||
|
|
||||||
namespace ANX.Framework.Storage
|
namespace ANX.Framework.Storage
|
||||||
{
|
{
|
||||||
|
[Developer("AstrorEnales")]
|
||||||
|
[TestState(TestStateAttribute.TestState.Untested)]
|
||||||
public class StorageDeviceNotConnectedException : ExternalException
|
public class StorageDeviceNotConnectedException : ExternalException
|
||||||
{
|
{
|
||||||
public StorageDeviceNotConnectedException()
|
public StorageDeviceNotConnectedException()
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
<Compile Include="OpenALAudioListener.cs" />
|
<Compile Include="OpenALAudioListener.cs" />
|
||||||
|
<Compile Include="OpenALDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="OpenALSong.cs" />
|
<Compile Include="OpenALSong.cs" />
|
||||||
<Compile Include="OpenALSoundEffect.cs" />
|
<Compile Include="OpenALSoundEffect.cs" />
|
||||||
<Compile Include="OpenALSoundEffectInstance.cs" />
|
<Compile Include="OpenALSoundEffectInstance.cs" />
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
<Compile Include="OpenALAudioListener.cs" />
|
<Compile Include="OpenALAudioListener.cs" />
|
||||||
|
<Compile Include="OpenALDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="OpenALSong.cs" />
|
<Compile Include="OpenALSong.cs" />
|
||||||
<Compile Include="OpenALSoundEffect.cs" />
|
<Compile Include="OpenALSoundEffect.cs" />
|
||||||
<Compile Include="OpenALSoundEffectInstance.cs" />
|
<Compile Include="OpenALSoundEffectInstance.cs" />
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
<Compile Include="OpenALAudioListener.cs" />
|
<Compile Include="OpenALAudioListener.cs" />
|
||||||
|
<Compile Include="OpenALDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="OpenALSong.cs" />
|
<Compile Include="OpenALSong.cs" />
|
||||||
<Compile Include="OpenALSoundEffect.cs" />
|
<Compile Include="OpenALSoundEffect.cs" />
|
||||||
<Compile Include="OpenALSoundEffectInstance.cs" />
|
<Compile Include="OpenALSoundEffectInstance.cs" />
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
<Compile Include="OpenALAudioListener.cs" />
|
<Compile Include="OpenALAudioListener.cs" />
|
||||||
|
<Compile Include="OpenALDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="OpenALSong.cs" />
|
<Compile Include="OpenALSong.cs" />
|
||||||
<Compile Include="OpenALSoundEffect.cs" />
|
<Compile Include="OpenALSoundEffect.cs" />
|
||||||
<Compile Include="OpenALSoundEffectInstance.cs" />
|
<Compile Include="OpenALSoundEffectInstance.cs" />
|
||||||
|
@ -115,7 +115,15 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
return new OpenALSoundEffect(buffer, offset, count, sampleRate, channels, loopStart, loopLength);
|
return new OpenALSoundEffect(buffer, offset, count, sampleRate, channels, loopStart, loopLength);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region CreateDynamicSoundEffectInstance
|
||||||
|
public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance(int sampleRate, AudioChannels channels)
|
||||||
|
{
|
||||||
|
PreventSystemChange();
|
||||||
|
return new OpenALDynamicSoundEffectInstance(sampleRate, channels);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region CreateAudioListener
|
#region CreateAudioListener
|
||||||
public IAudioListener CreateAudioListener()
|
public IAudioListener CreateAudioListener()
|
||||||
@ -133,7 +141,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CreateMicrophone
|
#region CreateMicrophone (TODO)
|
||||||
public IMicrophone CreateMicrophone(Microphone managedMicrophone)
|
public IMicrophone CreateMicrophone(Microphone managedMicrophone)
|
||||||
{
|
{
|
||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
@ -141,22 +149,23 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GetAllMicrophones
|
#region GetAllMicrophones (TODO)
|
||||||
public ReadOnlyCollection<Microphone> GetAllMicrophones()
|
public ReadOnlyCollection<Microphone> GetAllMicrophones()
|
||||||
{
|
{
|
||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GetDefaultMicrophone
|
#region GetDefaultMicrophone (TODO)
|
||||||
public int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones)
|
public int GetDefaultMicrophone(ReadOnlyCollection<Microphone> allMicrophones)
|
||||||
{
|
{
|
||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region CreateSong
|
||||||
public ISong CreateSong(Song parentSong, Uri uri)
|
public ISong CreateSong(Song parentSong, Uri uri)
|
||||||
{
|
{
|
||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
@ -168,12 +177,7 @@ namespace ANX.SoundSystem.OpenAL
|
|||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
return new OpenALSong(parentSong, filepath, duration);
|
return new OpenALSong(parentSong, filepath, duration);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance()
|
|
||||||
{
|
|
||||||
PreventSystemChange();
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PreventSystemChange()
|
private static void PreventSystemChange()
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,154 @@
|
|||||||
|
using System;
|
||||||
|
using ANX.Framework;
|
||||||
|
using ANX.Framework.Audio;
|
||||||
|
using ANX.Framework.NonXNA.Development;
|
||||||
|
using ANX.Framework.NonXNA.SoundSystem;
|
||||||
|
using OpenTK.Audio.OpenAL;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
[Developer("AstrorEnales")]
|
||||||
|
public class OpenALDynamicSoundEffectInstance : IDynamicSoundEffectInstance
|
||||||
|
{
|
||||||
|
private int source;
|
||||||
|
private readonly int sampleRate;
|
||||||
|
private readonly int channels;
|
||||||
|
private readonly ALFormat format;
|
||||||
|
|
||||||
|
public event EventHandler<EventArgs> BufferNeeded;
|
||||||
|
|
||||||
|
public int PendingBufferCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int queueSize;
|
||||||
|
AL.GetSource(source, ALGetSourcei.BuffersQueued, out queueSize);
|
||||||
|
return queueSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLooped
|
||||||
|
{
|
||||||
|
get { throw new NotImplementedException(); }
|
||||||
|
set { throw new NotImplementedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Pan
|
||||||
|
{
|
||||||
|
get { throw new NotImplementedException(); }
|
||||||
|
set { throw new NotImplementedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Pitch
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
float value;
|
||||||
|
AL.GetSource(source, ALSourcef.Pitch, out value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
set { AL.Source(source, ALSourcef.Pitch, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundState State { get; private set; }
|
||||||
|
|
||||||
|
public float Volume
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
float value;
|
||||||
|
AL.GetSource(source, ALSourcef.Gain, out value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
set { AL.Source(source, ALSourcef.Gain, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpenALDynamicSoundEffectInstance(int setSampleRate, AudioChannels setChannels)
|
||||||
|
{
|
||||||
|
State = SoundState.Stopped;
|
||||||
|
sampleRate = setSampleRate;
|
||||||
|
channels = (int)setChannels;
|
||||||
|
format = channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16;
|
||||||
|
source = AL.GenSource();
|
||||||
|
|
||||||
|
FrameworkDispatcher.OnUpdate += Tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SubmitBuffer(byte[] buffer)
|
||||||
|
{
|
||||||
|
SubmitBuffer(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SubmitBuffer(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
int bufferHandle = AL.GenBuffer();
|
||||||
|
IntPtr dataHandle;
|
||||||
|
fixed (byte* ptr = &buffer[0])
|
||||||
|
dataHandle = (IntPtr)(ptr + offset);
|
||||||
|
AL.BufferData(bufferHandle, format, dataHandle, count, sampleRate);
|
||||||
|
AL.SourceQueueBuffer(source, bufferHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Play()
|
||||||
|
{
|
||||||
|
if (State != SoundState.Playing)
|
||||||
|
AL.SourcePlay(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
if (State != SoundState.Paused)
|
||||||
|
AL.SourcePause(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop(bool immediate)
|
||||||
|
{
|
||||||
|
// TODO: handle immediate!
|
||||||
|
|
||||||
|
if (State != SoundState.Stopped)
|
||||||
|
AL.SourceStop(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resume()
|
||||||
|
{
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Tick()
|
||||||
|
{
|
||||||
|
if (State != SoundState.Playing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int buffersProcessed;
|
||||||
|
AL.GetSource(source, ALGetSourcei.BuffersProcessed, out buffersProcessed);
|
||||||
|
for (int index = 0; index < buffersProcessed; index++)
|
||||||
|
{
|
||||||
|
int buffer = AL.SourceUnqueueBuffer(source);
|
||||||
|
AL.DeleteBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PendingBufferCount == 0 && BufferNeeded != null)
|
||||||
|
BufferNeeded(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Apply3D(AudioListener[] listeners, AudioEmitter emitter)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (source != -1)
|
||||||
|
{
|
||||||
|
FrameworkDispatcher.OnUpdate -= Tick;
|
||||||
|
AL.DeleteSource(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
source = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -103,8 +103,7 @@ namespace ANX.SoundSystem.PsVita
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CreateSoundEffectInstance
|
#region CreateSoundEffectInstance
|
||||||
public ISoundEffectInstance CreateSoundEffectInstance(
|
public ISoundEffectInstance CreateSoundEffectInstance(ISoundEffect nativeSoundEffect)
|
||||||
ISoundEffect nativeSoundEffect)
|
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
@ -178,10 +177,10 @@ namespace ANX.SoundSystem.PsVita
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance()
|
public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance(int sampleRate, AudioChannels channels)
|
||||||
{
|
{
|
||||||
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
AddInSystemFactory.Instance.PreventSystemChange(AddInType.SoundSystem);
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
|
<Compile Include="XAudioDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="XAudioOggInputStream.cs" />
|
<Compile Include="XAudioOggInputStream.cs" />
|
||||||
<Compile Include="XAudioSong.cs" />
|
<Compile Include="XAudioSong.cs" />
|
||||||
<Compile Include="XAudioSoundEffectInstance.cs" />
|
<Compile Include="XAudioSoundEffectInstance.cs" />
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
|
<Compile Include="XAudioDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="XAudioOggInputStream.cs" />
|
<Compile Include="XAudioOggInputStream.cs" />
|
||||||
<Compile Include="XAudioSong.cs" />
|
<Compile Include="XAudioSong.cs" />
|
||||||
<Compile Include="XAudioSoundEffectInstance.cs" />
|
<Compile Include="XAudioSoundEffectInstance.cs" />
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
|
<Compile Include="XAudioDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="XAudioOggInputStream.cs" />
|
<Compile Include="XAudioOggInputStream.cs" />
|
||||||
<Compile Include="XAudioSong.cs" />
|
<Compile Include="XAudioSong.cs" />
|
||||||
<Compile Include="XAudioSoundEffectInstance.cs" />
|
<Compile Include="XAudioSoundEffectInstance.cs" />
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Creator.cs" />
|
<Compile Include="Creator.cs" />
|
||||||
|
<Compile Include="XAudioDynamicSoundEffectInstance.cs" />
|
||||||
<Compile Include="XAudioOggInputStream.cs" />
|
<Compile Include="XAudioOggInputStream.cs" />
|
||||||
<Compile Include="XAudioSong.cs" />
|
<Compile Include="XAudioSong.cs" />
|
||||||
<Compile Include="XAudioSoundEffectInstance.cs" />
|
<Compile Include="XAudioSoundEffectInstance.cs" />
|
||||||
|
@ -148,13 +148,15 @@ namespace ANX.SoundSystem.Windows.XAudio
|
|||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
return new XAudioSoundEffectInstance(device, nativeSoundEffect as XAudioSoundEffect);
|
return new XAudioSoundEffectInstance(device, nativeSoundEffect as XAudioSoundEffect);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance()
|
#region CreateDynamicSoundEffectInstance
|
||||||
|
public IDynamicSoundEffectInstance CreateDynamicSoundEffectInstance(int sampleRate, AudioChannels channels)
|
||||||
{
|
{
|
||||||
PreventSystemChange();
|
PreventSystemChange();
|
||||||
throw new NotImplementedException();
|
return new XAudioDynamicSoundEffectInstance(device, sampleRate, channels);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
public IMicrophone CreateMicrophone(Microphone managedMicrophone)
|
public IMicrophone CreateMicrophone(Microphone managedMicrophone)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,136 @@
|
|||||||
|
using System;
|
||||||
|
using ANX.Framework.Audio;
|
||||||
|
using ANX.Framework.NonXNA.Development;
|
||||||
|
using ANX.Framework.NonXNA.SoundSystem;
|
||||||
|
using SharpDX;
|
||||||
|
using SharpDX.Multimedia;
|
||||||
|
using SharpDX.XAudio2;
|
||||||
|
|
||||||
|
// 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.Windows.XAudio
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// DynamicSoundEffectInstance supports only PCM 16-bit mono or stereo data.
|
||||||
|
/// </summary>
|
||||||
|
[Developer("AstrorEnales")]
|
||||||
|
public class XAudioDynamicSoundEffectInstance : IDynamicSoundEffectInstance
|
||||||
|
{
|
||||||
|
private SourceVoice source;
|
||||||
|
private float currentPitch;
|
||||||
|
|
||||||
|
public event EventHandler<EventArgs> BufferNeeded;
|
||||||
|
|
||||||
|
public int PendingBufferCount
|
||||||
|
{
|
||||||
|
get { return source.State.BuffersQueued; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLooped
|
||||||
|
{
|
||||||
|
get { throw new NotImplementedException(); }
|
||||||
|
set { throw new NotImplementedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Pan
|
||||||
|
{
|
||||||
|
get { throw new NotImplementedException(); }
|
||||||
|
set { throw new NotImplementedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Pitch
|
||||||
|
{
|
||||||
|
get { return currentPitch; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
currentPitch = value;
|
||||||
|
source.SetFrequencyRatio(value);
|
||||||
|
// TODO: pitch <= 1 is working, but greater isn't
|
||||||
|
if (value > 1f)
|
||||||
|
throw new NotImplementedException("Pitch greater than 1f is currently not implemented for XAudio!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundState State { get; private set; }
|
||||||
|
|
||||||
|
public float Volume
|
||||||
|
{
|
||||||
|
get { return source.Volume; }
|
||||||
|
set { source.SetVolume(value, 0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public XAudioDynamicSoundEffectInstance(XAudio2 device, int sampleRate, AudioChannels channels)
|
||||||
|
{
|
||||||
|
State = SoundState.Stopped;
|
||||||
|
currentPitch = 1f;
|
||||||
|
var format = new WaveFormat(sampleRate, 16, (int)channels);
|
||||||
|
source = new SourceVoice(device, format, true);
|
||||||
|
source.BufferEnd += OnBufferEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBufferEnd(IntPtr handle)
|
||||||
|
{
|
||||||
|
if (source.State.BuffersQueued == 0 && BufferNeeded != null)
|
||||||
|
BufferNeeded(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SubmitBuffer(byte[] buffer)
|
||||||
|
{
|
||||||
|
SubmitBuffer(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SubmitBuffer(byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
var audioBuffer = new AudioBuffer();
|
||||||
|
IntPtr dataHandle;
|
||||||
|
fixed (byte* ptr = &buffer[0])
|
||||||
|
dataHandle = (IntPtr)(ptr + offset);
|
||||||
|
audioBuffer.Stream = new DataStream(dataHandle, count, false, false);
|
||||||
|
source.SubmitSourceBuffer(audioBuffer, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Play()
|
||||||
|
{
|
||||||
|
if (State != SoundState.Playing)
|
||||||
|
source.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
if (State != SoundState.Paused)
|
||||||
|
source.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop(bool immediate)
|
||||||
|
{
|
||||||
|
// TODO: handle immediate
|
||||||
|
|
||||||
|
if (State != SoundState.Stopped)
|
||||||
|
source.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Resume()
|
||||||
|
{
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Apply3D(AudioListener[] listeners, AudioEmitter emitter)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (source != null)
|
||||||
|
{
|
||||||
|
source.BufferEnd -= OnBufferEnd;
|
||||||
|
source.DestroyVoice();
|
||||||
|
source.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
source = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user