188 lines
4.6 KiB
C#
188 lines
4.6 KiB
C#
using System;
|
|
|
|
namespace MoonWorks.Audio
|
|
{
|
|
/// <summary>
|
|
/// Emits audio from submitted audio buffers.
|
|
/// </summary>
|
|
public class SourceVoice : Voice
|
|
{
|
|
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 handle,
|
|
ref fAudioFormat,
|
|
FAudio.FAUDIO_VOICE_USEFILTER,
|
|
FAudio.FAUDIO_DEFAULT_FREQ_RATIO,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero, // default sends to mastering voice!
|
|
IntPtr.Zero
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Starts consumption and processing of audio by the voice.
|
|
/// Delivers the result to any connected submix or mastering voice.
|
|
/// </summary>
|
|
/// <param name="syncGroup">Optional. Denotes that the operation will be pending until AudioDevice.TriggerSyncGroup is called.</param>
|
|
public void Play(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_Start(Handle, 0, syncGroup);
|
|
|
|
State = SoundState.Playing;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pauses playback.
|
|
/// All source buffers that are queued on the voice and the current cursor position are preserved.
|
|
/// </summary>
|
|
/// <param name="syncGroup">Optional. Denotes that the operation will be pending until AudioDevice.TriggerSyncGroup is called.</param>
|
|
public void Pause(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_Stop(Handle, 0, syncGroup);
|
|
|
|
State = SoundState.Paused;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops looping the voice when it reaches the end of the current loop region.
|
|
/// If the cursor for the voice is not in a loop region, ExitLoop does nothing.
|
|
/// </summary>
|
|
/// <param name="syncGroup">Optional. Denotes that the operation will be pending until AudioDevice.TriggerSyncGroup is called.</param>
|
|
public void ExitLoop(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_ExitLoop(Handle, syncGroup);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops playback and removes all pending audio buffers from the voice queue.
|
|
/// </summary>
|
|
/// <param name="syncGroup">Optional. Denotes that the operation will be pending until AudioDevice.TriggerSyncGroup is called.</param>
|
|
public void Stop(uint syncGroup = FAudio.FAUDIO_COMMIT_NOW)
|
|
{
|
|
lock (StateLock)
|
|
{
|
|
FAudio.FAudioSourceVoice_Stop(Handle, 0, syncGroup);
|
|
FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle);
|
|
|
|
State = SoundState.Stopped;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a static sound to the voice queue.
|
|
/// The voice processes and plays back the buffers in its queue in the order that they were submitted.
|
|
/// </summary>
|
|
/// <param name="sound">The sound to submit to the voice.</param>
|
|
/// <param name="loop">Designates that the voice will loop the submitted buffer.</param>
|
|
public void Submit(StaticSound sound, bool loop = false)
|
|
{
|
|
if (loop)
|
|
{
|
|
sound.Buffer.LoopCount = FAudio.FAUDIO_LOOP_INFINITE;
|
|
}
|
|
else
|
|
{
|
|
sound.Buffer.LoopCount = 0;
|
|
}
|
|
|
|
Submit(sound.Buffer);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an FAudio buffer to the voice queue.
|
|
/// The voice processes and plays back the buffers in its queue in the order that they were submitted.
|
|
/// </summary>
|
|
/// <param name="buffer">The buffer to submit to the voice.</param>
|
|
public void Submit(FAudio.FAudioBuffer buffer)
|
|
{
|
|
FAudio.FAudioSourceVoice_SubmitSourceBuffer(
|
|
Handle,
|
|
ref buffer,
|
|
IntPtr.Zero
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Designates that this source voice will return to the voice pool once all its buffers are exhausted.
|
|
/// </summary>
|
|
public void ReturnWhenIdle()
|
|
{
|
|
Device.ReturnWhenIdle(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns this source voice to the voice pool.
|
|
/// </summary>
|
|
public void Return()
|
|
{
|
|
Stop();
|
|
Reset();
|
|
Device.Return(this);
|
|
}
|
|
|
|
protected override unsafe void Destroy()
|
|
{
|
|
Stop();
|
|
base.Destroy();
|
|
}
|
|
}
|
|
}
|