150 lines
2.9 KiB
C#
150 lines
2.9 KiB
C#
using System;
|
|
|
|
namespace MoonWorks.Audio
|
|
{
|
|
public class SourceVoice : SendableVoice
|
|
{
|
|
private Format format;
|
|
public Format Format => format;
|
|
|
|
protected object StateLock = new object();
|
|
|
|
public uint BuffersQueued
|
|
{
|
|
get
|
|
{
|
|
FAudio.FAudioSourceVoice_GetState(
|
|
Handle,
|
|
out var state,
|
|
FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED
|
|
);
|
|
|
|
return state.BuffersQueued;
|
|
}
|
|
}
|
|
|
|
private SoundState state;
|
|
public SoundState State
|
|
{
|
|
get
|
|
{
|
|
if (BuffersQueued == 0)
|
|
{
|
|
Stop();
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
internal set
|
|
{
|
|
state = value;
|
|
}
|
|
}
|
|
|
|
public delegate void OnUpdateFunc();
|
|
public OnUpdateFunc OnUpdate; // called by AudioDevice thread
|
|
|
|
public SourceVoice(
|
|
AudioDevice device,
|
|
Format format
|
|
) : base(device, format.Channels, device.DeviceDetails.OutputFormat.Format.nChannels)
|
|
{
|
|
this.format = format;
|
|
var fAudioFormat = format.ToFAudioFormat();
|
|
|
|
FAudio.FAudio_CreateSourceVoice(
|
|
device.Handle,
|
|
out var Handle,
|
|
ref fAudioFormat,
|
|
FAudio.FAUDIO_VOICE_USEFILTER,
|
|
FAudio.FAUDIO_DEFAULT_FREQ_RATIO,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero, // default sends to mastering voice!
|
|
IntPtr.Zero
|
|
);
|
|
}
|
|
|
|
public void Play(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_Start(Handle, 0, syncGroup);
|
|
|
|
State = SoundState.Playing;
|
|
}
|
|
}
|
|
|
|
public void Pause(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_Stop(Handle, 0, syncGroup);
|
|
|
|
State = SoundState.Paused;
|
|
}
|
|
}
|
|
|
|
public void ExitLoop(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_ExitLoop(Handle, syncGroup);
|
|
}
|
|
}
|
|
|
|
public void Stop(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_Stop(Handle, 0, syncGroup);
|
|
FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle);
|
|
|
|
State = SoundState.Stopped;
|
|
}
|
|
}
|
|
|
|
public void SubmitBuffer(FAudio.FAudioBuffer buffer)
|
|
{
|
|
FAudio.FAudioSourceVoice_SubmitSourceBuffer(
|
|
Handle,
|
|
ref buffer,
|
|
IntPtr.Zero
|
|
);
|
|
}
|
|
|
|
// FIXME: maybe this is bad
|
|
// NOTE: SourceVoices obtained this way will be returned to the voice pool when stopped!
|
|
public static SourceVoice ObtainSourceVoice(AudioDevice device, Format format)
|
|
{
|
|
return device.ObtainSourceVoice(format);
|
|
}
|
|
|
|
// intended for short-lived sound effects
|
|
public static SourceVoice PlayStaticSound(AudioDevice device, StaticSound sound, SubmixVoice sendVoice = null)
|
|
{
|
|
var voice = ObtainSourceVoice(device, sound.Format);
|
|
|
|
if (sendVoice == null)
|
|
{
|
|
voice.SetOutputVoice(device.MasteringVoice);
|
|
}
|
|
else
|
|
{
|
|
voice.SetOutputVoice(sendVoice);
|
|
}
|
|
|
|
voice.SubmitBuffer(sound.Handle);
|
|
voice.Play();
|
|
|
|
return voice;
|
|
}
|
|
|
|
protected override unsafe void Destroy()
|
|
{
|
|
Stop();
|
|
base.Destroy();
|
|
}
|
|
}
|
|
}
|