155 lines
4.4 KiB
C#
155 lines
4.4 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|