fix dynamic looping

main
cosmonaut 2021-01-20 10:55:15 -08:00
parent 2c828e52b3
commit 4c89c9173b
5 changed files with 48 additions and 28 deletions

View File

@ -44,9 +44,9 @@ namespace MoonWorks.Audio
}; };
} }
public DynamicSoundInstance CreateInstance() public DynamicSoundInstance CreateInstance(bool loop = false)
{ {
var instance = new DynamicSoundInstance(Device, this, false); var instance = new DynamicSoundInstance(Device, this, false, loop);
Device.AddDynamicSoundInstance(instance); Device.AddDynamicSoundInstance(instance);
return instance; return instance;
} }

View File

@ -19,8 +19,9 @@ namespace MoonWorks.Audio
internal DynamicSoundInstance( internal DynamicSoundInstance(
AudioDevice device, AudioDevice device,
DynamicSound parent, DynamicSound parent,
bool is3D bool is3D,
) : base(device, parent, is3D) bool loop
) : base(device, parent, is3D, loop)
{ {
queuedBuffers = new List<IntPtr>(); queuedBuffers = new List<IntPtr>();
queuedSizes = new List<uint>(); queuedSizes = new List<uint>();
@ -32,17 +33,14 @@ namespace MoonWorks.Audio
public void Play() public void Play()
{ {
Update();
if (State == SoundState.Playing) if (State == SoundState.Playing)
{ {
return; return;
} }
QueueBuffers();
FAudio.FAudioSourceVoice_Start(Handle, 0, 0);
State = SoundState.Playing; State = SoundState.Playing;
Update();
FAudio.FAudioSourceVoice_Start(Handle, 0, 0);
} }
public void Pause() public void Pause()
@ -54,12 +52,16 @@ namespace MoonWorks.Audio
} }
} }
public void Stop() public void Stop(bool immediate = true)
{ {
FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); if (immediate)
FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); {
FAudio.FAudioSourceVoice_Stop(Handle, 0, 0);
FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle);
ClearBuffers();
}
State = SoundState.Stopped; State = SoundState.Stopped;
ClearBuffers();
} }
internal void Update() internal void Update()
@ -80,8 +82,9 @@ namespace MoonWorks.Audio
{ {
Marshal.FreeHGlobal(queuedBuffers[0]); Marshal.FreeHGlobal(queuedBuffers[0]);
queuedBuffers.RemoveAt(0); queuedBuffers.RemoveAt(0);
queuedSizes.RemoveAt(0);
} }
QueueBuffers();
} }
private void QueueBuffers() private void QueueBuffers()
@ -104,7 +107,7 @@ namespace MoonWorks.Audio
Marshal.FreeHGlobal(buf); Marshal.FreeHGlobal(buf);
} }
queuedBuffers.Clear(); queuedBuffers.Clear();
queuedBuffers.Clear(); queuedSizes.Clear();
} }
} }
@ -112,6 +115,7 @@ namespace MoonWorks.Audio
{ {
var parent = (DynamicSound) Parent; var parent = (DynamicSound) Parent;
/* NOTE: this function returns samples per channel, not total samples */
var samples = FAudio.stb_vorbis_get_samples_float_interleaved( var samples = FAudio.stb_vorbis_get_samples_float_interleaved(
parent.FileHandle, parent.FileHandle,
parent.Info.channels, parent.Info.channels,
@ -119,13 +123,14 @@ namespace MoonWorks.Audio
buffer.Length buffer.Length
); );
IntPtr next = Marshal.AllocHGlobal(buffer.Length * sizeof(float)); var sampleCount = samples * parent.Info.channels;
Marshal.Copy(buffer, 0, next, buffer.Length); var lengthInBytes = (uint) sampleCount * sizeof(float);
IntPtr next = Marshal.AllocHGlobal((int) lengthInBytes);
Marshal.Copy(buffer, 0, next, sampleCount);
lock (queuedBuffers) lock (queuedBuffers)
{ {
var lengthInBytes = (uint) buffer.Length * sizeof(float);
queuedBuffers.Add(next); queuedBuffers.Add(next);
if (State != SoundState.Stopped) if (State != SoundState.Stopped)
{ {
@ -151,6 +156,19 @@ namespace MoonWorks.Audio
queuedSizes.Add(lengthInBytes); queuedSizes.Add(lengthInBytes);
} }
} }
/* We have reached the end of the file, what do we do? */
if (sampleCount < buffer.Length)
{
if (Loop)
{
FAudio.stb_vorbis_seek_start(parent.FileHandle);
}
else
{
Stop(false);
}
}
} }
} }
} }

View File

@ -8,6 +8,8 @@ namespace MoonWorks.Audio
protected AudioDevice Device { get; } protected AudioDevice Device { get; }
internal IntPtr Handle { get; } internal IntPtr Handle { get; }
public Sound Parent { get; } public Sound Parent { get; }
public bool Loop { get; }
protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings; protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings;
protected bool is3D; protected bool is3D;
@ -171,7 +173,8 @@ namespace MoonWorks.Audio
public SoundInstance( public SoundInstance(
AudioDevice device, AudioDevice device,
Sound parent, Sound parent,
bool is3D bool is3D,
bool loop
) { ) {
Device = device; Device = device;
Parent = parent; Parent = parent;
@ -203,6 +206,8 @@ namespace MoonWorks.Audio
handle, handle,
ref Device.ReverbSends ref Device.ReverbSends
); );
Loop = loop;
} }
private void InitDSPSettings(uint srcChannels) private void InitDSPSettings(uint srcChannels)

View File

@ -78,9 +78,9 @@ namespace MoonWorks.Audio
LoopLength = 0; LoopLength = 0;
} }
public StaticSoundInstance CreateInstance() public StaticSoundInstance CreateInstance(bool loop = false)
{ {
return new StaticSoundInstance(Device, this, false, true); return new StaticSoundInstance(Device, this, false, loop);
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)

View File

@ -4,8 +4,6 @@ namespace MoonWorks.Audio
{ {
public class StaticSoundInstance : SoundInstance public class StaticSoundInstance : SoundInstance
{ {
public bool Loop { get; }
private SoundState _state = SoundState.Stopped; private SoundState _state = SoundState.Stopped;
public override SoundState State public override SoundState State
{ {
@ -30,14 +28,13 @@ namespace MoonWorks.Audio
} }
} }
public StaticSoundInstance( internal StaticSoundInstance(
AudioDevice device, AudioDevice device,
StaticSound parent, StaticSound parent,
bool is3D, bool is3D,
bool loop = false bool loop
) : base(device, parent, is3D) ) : base(device, parent, is3D, loop)
{ {
Loop = loop;
State = SoundState.Stopped; State = SoundState.Stopped;
} }