From 9a854506f346227efd5db9f36c7de814cac3f2a7 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 2 Aug 2023 18:26:27 -0700 Subject: [PATCH] documentation + fix some edge cases --- src/Audio/AudioBuffer.cs | 15 +++++++++++++++ src/Audio/AudioDataOgg.cs | 3 +++ src/Audio/AudioDataQoa.cs | 3 +++ src/Audio/AudioDataStreamable.cs | 3 +++ src/Audio/AudioDataWav.cs | 7 ++++++- src/Audio/AudioUtils.cs | 33 -------------------------------- src/Audio/PersistentVoice.cs | 3 +++ src/Audio/ReverbEffect.cs | 4 +++- src/Audio/SoundSequence.cs | 4 +++- src/Audio/SourceVoice.cs | 9 +++++++++ src/Audio/StreamingVoice.cs | 13 +++++++++++-- src/Audio/SubmixVoice.cs | 3 +++ src/Audio/TransientVoice.cs | 5 +++-- 13 files changed, 65 insertions(+), 40 deletions(-) delete mode 100644 src/Audio/AudioUtils.cs diff --git a/src/Audio/AudioBuffer.cs b/src/Audio/AudioBuffer.cs index 306a078..bfdeda7 100644 --- a/src/Audio/AudioBuffer.cs +++ b/src/Audio/AudioBuffer.cs @@ -3,6 +3,10 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { + /// + /// Contains raw audio data in the format specified by Format. + /// Submit this to a SourceVoice to play audio. + /// public class AudioBuffer : AudioResource { IntPtr BufferDataPtr; @@ -24,11 +28,22 @@ namespace MoonWorks.Audio OwnsBufferData = ownsBufferData; } + /// + /// Create another AudioBuffer from this audio buffer. + /// It will not own the buffer data. + /// + /// Offset in bytes from the top of the original buffer. + /// Length in bytes of the new buffer. + /// public AudioBuffer CreateSubBuffer(int offset, uint length) { return new AudioBuffer(Device, Format, BufferDataPtr + offset, length, false); } + /// + /// Create an FAudioBuffer struct from this AudioBuffer. + /// + /// Whether we should set the FAudioBuffer to loop. public FAudio.FAudioBuffer ToFAudioBuffer(bool loop = false) { return new FAudio.FAudioBuffer diff --git a/src/Audio/AudioDataOgg.cs b/src/Audio/AudioDataOgg.cs index d7f1a21..dce9976 100644 --- a/src/Audio/AudioDataOgg.cs +++ b/src/Audio/AudioDataOgg.cs @@ -4,6 +4,9 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { + /// + /// Streamable audio in Ogg format. + /// public class AudioDataOgg : AudioDataStreamable { private IntPtr FileDataPtr = IntPtr.Zero; diff --git a/src/Audio/AudioDataQoa.cs b/src/Audio/AudioDataQoa.cs index 02a5c43..9bf30d6 100644 --- a/src/Audio/AudioDataQoa.cs +++ b/src/Audio/AudioDataQoa.cs @@ -4,6 +4,9 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { + /// + /// Streamable audio in QOA format. + /// public class AudioDataQoa : AudioDataStreamable { private IntPtr QoaHandle = IntPtr.Zero; diff --git a/src/Audio/AudioDataStreamable.cs b/src/Audio/AudioDataStreamable.cs index aab413c..a0b9d60 100644 --- a/src/Audio/AudioDataStreamable.cs +++ b/src/Audio/AudioDataStreamable.cs @@ -1,5 +1,8 @@ namespace MoonWorks.Audio { + /// + /// Use this in conjunction with a StreamingVoice to play back streaming audio data. + /// public abstract class AudioDataStreamable : AudioResource { public Format Format { get; protected set; } diff --git a/src/Audio/AudioDataWav.cs b/src/Audio/AudioDataWav.cs index 5e415ca..4b6c0a3 100644 --- a/src/Audio/AudioDataWav.cs +++ b/src/Audio/AudioDataWav.cs @@ -6,9 +6,14 @@ namespace MoonWorks.Audio { public static class AudioDataWav { - // mostly borrowed from https://github.com/FNA-XNA/FNA/blob/b71b4a35ae59970ff0070dea6f8620856d8d4fec/src/Audio/SoundEffect.cs#L385 + /// + /// Create an AudioBuffer containing all the WAV audio data in a file. + /// + /// public unsafe static AudioBuffer CreateBuffer(AudioDevice device, string filePath) { + // mostly borrowed from https://github.com/FNA-XNA/FNA/blob/b71b4a35ae59970ff0070dea6f8620856d8d4fec/src/Audio/SoundEffect.cs#L385 + // WaveFormatEx data ushort wFormatTag; ushort nChannels; diff --git a/src/Audio/AudioUtils.cs b/src/Audio/AudioUtils.cs deleted file mode 100644 index a9caa2d..0000000 --- a/src/Audio/AudioUtils.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.IO; - -namespace MoonWorks.Audio -{ - public static class AudioUtils - { - public static Format ReadWaveFormat(string filePath, out int dataLength) - { - var fileInfo = new FileInfo(filePath); - using FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); - using BinaryReader br = new BinaryReader(fs); - - fs.Position = 20; - var formatTag = br.ReadInt16(); - fs.Position = 22; - var channels = br.ReadInt16(); - fs.Position = 24; - var sampleRate = br.ReadInt32(); - fs.Position = 34; - var bitsPerSample = br.ReadInt16(); - fs.Position = 40; - dataLength = br.ReadInt32(); - - return new Format - { - Tag = (FormatTag) formatTag, - Channels = (ushort) channels, - SampleRate = (uint) sampleRate, - BitsPerSample = (ushort) bitsPerSample - }; - } - } -} diff --git a/src/Audio/PersistentVoice.cs b/src/Audio/PersistentVoice.cs index 7b54395..5077c15 100644 --- a/src/Audio/PersistentVoice.cs +++ b/src/Audio/PersistentVoice.cs @@ -1,5 +1,8 @@ namespace MoonWorks.Audio { + /// + /// PersistentVoice should be used when you need to maintain a long-term reference to a source voice. + /// public class PersistentVoice : SourceVoice, IPoolable { public PersistentVoice(AudioDevice device, Format format) : base(device, format) diff --git a/src/Audio/ReverbEffect.cs b/src/Audio/ReverbEffect.cs index 064ab72..746e99e 100644 --- a/src/Audio/ReverbEffect.cs +++ b/src/Audio/ReverbEffect.cs @@ -3,7 +3,9 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { - // sound instances can send their audio to this voice to add reverb + /// + /// Use this in conjunction with SourceVoice.SetReverbEffectChain to add reverb to a voice. + /// public unsafe class ReverbEffect : SubmixVoice { public ReverbEffect(AudioDevice audioDevice) : base(audioDevice, 1, audioDevice.DeviceDetails.OutputFormat.Format.nSamplesPerSec) diff --git a/src/Audio/SoundSequence.cs b/src/Audio/SoundSequence.cs index d88177a..466aebf 100644 --- a/src/Audio/SoundSequence.cs +++ b/src/Audio/SoundSequence.cs @@ -1,6 +1,8 @@ namespace MoonWorks.Audio { - // NOTE: all sounds played with a SoundSequence must have the same audio format! + /// + /// Plays back a series of AudioBuffers in sequence. Set the OnSoundNeeded callback to add AudioBuffers dynamically. + /// public class SoundSequence : SourceVoice { public int NeedSoundThreshold = 0; diff --git a/src/Audio/SourceVoice.cs b/src/Audio/SourceVoice.cs index 7ef90e6..9950a28 100644 --- a/src/Audio/SourceVoice.cs +++ b/src/Audio/SourceVoice.cs @@ -10,6 +10,8 @@ namespace MoonWorks.Audio private Format format; public Format Format => format; + protected bool PlaybackInitiated; + /// /// The number of buffers queued in the voice. /// This includes the currently playing voice! @@ -170,6 +172,13 @@ namespace MoonWorks.Audio } } + public override void Reset() + { + Stop(); + PlaybackInitiated = false; + base.Reset(); + } + protected override unsafe void Destroy() { Stop(); diff --git a/src/Audio/StreamingVoice.cs b/src/Audio/StreamingVoice.cs index 03dcd0a..9a1b98f 100644 --- a/src/Audio/StreamingVoice.cs +++ b/src/Audio/StreamingVoice.cs @@ -3,6 +3,9 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { + /// + /// Use in conjunction with an AudioDataStreamable object to play back streaming audio data. + /// public class StreamingVoice : SourceVoice, IPoolable { private const int BUFFER_COUNT = 3; @@ -54,6 +57,12 @@ namespace MoonWorks.Audio } } + public override void Reset() + { + Unload(); + base.Reset(); + } + public override void Update() { lock (StateLock) @@ -67,7 +76,7 @@ namespace MoonWorks.Audio } } - protected void QueueBuffers() + private void QueueBuffers() { int buffersNeeded = BUFFER_COUNT - (int) BuffersQueued; // don't get got by uint underflow! for (int i = 0; i < buffersNeeded; i += 1) @@ -76,7 +85,7 @@ namespace MoonWorks.Audio } } - protected unsafe void AddBuffer() + private unsafe void AddBuffer() { var buffer = buffers[nextBufferIndex]; nextBufferIndex = (nextBufferIndex + 1) % BUFFER_COUNT; diff --git a/src/Audio/SubmixVoice.cs b/src/Audio/SubmixVoice.cs index e442a80..b681024 100644 --- a/src/Audio/SubmixVoice.cs +++ b/src/Audio/SubmixVoice.cs @@ -2,6 +2,9 @@ using System; namespace MoonWorks.Audio { + /// + /// SourceVoices can send audio to a SubmixVoice for convenient effects processing. + /// public class SubmixVoice : Voice { public SubmixVoice( diff --git a/src/Audio/TransientVoice.cs b/src/Audio/TransientVoice.cs index 1dbc4c2..9c747b6 100644 --- a/src/Audio/TransientVoice.cs +++ b/src/Audio/TransientVoice.cs @@ -1,7 +1,8 @@ namespace MoonWorks.Audio { /// - /// These voices are intended for playing one-off sound effects that don't have a long term reference. + /// TransientVoice is intended for playing one-off sound effects that don't have a long term reference. + /// It will be automatically returned to the source voice pool once it is done playing back. /// public class TransientVoice : SourceVoice, IPoolable { @@ -18,7 +19,7 @@ namespace MoonWorks.Audio { lock (StateLock) { - if (BuffersQueued == 0) + if (PlaybackInitiated && BuffersQueued == 0) { Return(); }