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 { /// /// DynamicSoundEffectInstance supports only PCM 16-bit mono or stereo data. /// [Developer("AstrorEnales")] public class XAudioDynamicSoundEffectInstance : IDynamicSoundEffectInstance { private SourceVoice source; private float currentPitch; public event EventHandler 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; } } }