From e51d28ce89e01541689181e7cbbae9f6588d88f0 Mon Sep 17 00:00:00 2001 From: dnesov Date: Mon, 28 Oct 2024 23:13:14 +0100 Subject: [PATCH] WIP: SoLoud audio system, make Sound be in 16-bit PCM. --- TestGame/Resources/sounds/test_sound_mono.ogg | Bin 0 -> 8430 bytes TestGame/TestGame.cs | 7 +- Voile/Source/Audio/AudioBus.cs | 7 -- Voile/Source/Audio/AudioEffect.cs | 9 --- Voile/Source/Audio/AudioSystem.cs | 4 -- Voile/Source/Audio/DummyAudioSystem.cs | 5 -- Voile/Source/Audio/StandardAudioSystem.cs | 64 ++++++++++++++++++ Voile/Source/Game.cs | 11 +++ Voile/Source/Resources/Loaders/SoundLoader.cs | 22 +++--- Voile/Source/Resources/Sound.cs | 6 +- 10 files changed, 91 insertions(+), 44 deletions(-) create mode 100644 TestGame/Resources/sounds/test_sound_mono.ogg delete mode 100644 Voile/Source/Audio/AudioBus.cs delete mode 100644 Voile/Source/Audio/AudioEffect.cs create mode 100644 Voile/Source/Audio/StandardAudioSystem.cs diff --git a/TestGame/Resources/sounds/test_sound_mono.ogg b/TestGame/Resources/sounds/test_sound_mono.ogg new file mode 100644 index 0000000000000000000000000000000000000000..0ac7c52044bf03d5c0abe378e2c269a9e8977328 GIT binary patch literal 8430 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 _fireEffect; private ResourceRef _font; + private ResourceRef _sound; private ResourceRef _icon; } \ No newline at end of file diff --git a/Voile/Source/Audio/AudioBus.cs b/Voile/Source/Audio/AudioBus.cs deleted file mode 100644 index c27fded..0000000 --- a/Voile/Source/Audio/AudioBus.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Voile -{ - public class AudioBus - { - - } -} \ No newline at end of file diff --git a/Voile/Source/Audio/AudioEffect.cs b/Voile/Source/Audio/AudioEffect.cs deleted file mode 100644 index 8deec24..0000000 --- a/Voile/Source/Audio/AudioEffect.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Voile -{ - public class AudioEffect { } - - public class AudioEffectReverb : AudioEffect - { - - } -} \ No newline at end of file diff --git a/Voile/Source/Audio/AudioSystem.cs b/Voile/Source/Audio/AudioSystem.cs index 3195ea4..e0d3eda 100644 --- a/Voile/Source/Audio/AudioSystem.cs +++ b/Voile/Source/Audio/AudioSystem.cs @@ -22,7 +22,6 @@ public abstract class AudioSystem : IStartableSystem, IUpdatableSystem, IDisposa public abstract void SetBusVolume(string busName, float volume); public abstract float GetBusVolume(string busName); - // SOUND public abstract void PlaySound(Sound sound, float pitch, float volume, string bus = "Master"); public void PlaySound(Sound sound, string bus = "Master") => PlaySound(sound, 1.0f, 1.0f, bus); @@ -32,9 +31,6 @@ public abstract class AudioSystem : IStartableSystem, IUpdatableSystem, IDisposa return instance; } - // EFFECTS - public abstract void AddBusEffect(T effect, string bus = "Master") where T : AudioEffect; - private LehmerRandom _random = new LehmerRandom(); } \ No newline at end of file diff --git a/Voile/Source/Audio/DummyAudioSystem.cs b/Voile/Source/Audio/DummyAudioSystem.cs index f7b1d21..323b0e4 100644 --- a/Voile/Source/Audio/DummyAudioSystem.cs +++ b/Voile/Source/Audio/DummyAudioSystem.cs @@ -5,11 +5,6 @@ namespace Voile.Audio /// public class DummyAudioSystem : AudioSystem { - public override void AddBusEffect(T effect, string bus = "Master") - { - return; - } - public override void CreateBus(string busName) { return; diff --git a/Voile/Source/Audio/StandardAudioSystem.cs b/Voile/Source/Audio/StandardAudioSystem.cs new file mode 100644 index 0000000..e99209a --- /dev/null +++ b/Voile/Source/Audio/StandardAudioSystem.cs @@ -0,0 +1,64 @@ +using System.Runtime.CompilerServices; +using Raylib_cs; +using SoLoud; + +namespace Voile.Audio; + +public class StandardAudioSystem : AudioSystem +{ + public StandardAudioSystem() + { + _engine = new Soloud(); + } + protected override void Initialize() + { + _engine.init(); + } + + public override void CreateBus(string busName) + { + throw new NotImplementedException(); + } + + public override float GetBusVolume(string busName) + { + throw new NotImplementedException(); + } + + public override void PlaySound(Sound sound, float pitch, float volume, string bus = "Master") + { + PlayUnsafe(sound.Buffer, sound.BufferSize, sound.SampleRate, sound.Channel); + } + + public override void SetBusVolume(string busName, float volume) + { + throw new NotImplementedException(); + } + + protected override void Shutdown() + { + _engine!.deinit(); + } + + protected override void Update() + { + + } + + private void PlayUnsafe(ReadOnlyMemory soundBuffer, long length, int sampleRate, SoundChannel channels) + { + var wav = new Wav(); + + int channelCount = channels == SoundChannel.Stereo ? 2 : 1; + + unsafe + { + nint ptr = (nint)soundBuffer.Pin().Pointer; + wav.loadRawWave16(ptr, (uint)length, sampleRate, (uint)channelCount); + } + + _engine.play(wav); + } + + private Soloud _engine; +} \ No newline at end of file diff --git a/Voile/Source/Game.cs b/Voile/Source/Game.cs index b4b4102..4599f06 100644 --- a/Voile/Source/Game.cs +++ b/Voile/Source/Game.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using Voile.Audio; using Voile.Input; using Voile.Rendering; using Voile.Resources; @@ -42,6 +43,8 @@ namespace Voile /// protected RenderSystem? Renderer { get; set; } + protected AudioSystem? AudioSystem { get; set; } + /// /// Name of this game. Also used as a default window title. /// @@ -113,6 +116,13 @@ namespace Voile Input = new RaylibInputSystem(); } + if (AudioSystem is null) + { + AudioSystem = new StandardAudioSystem(); + } + + AudioSystem.Start(); + Input.Start(); InitializeRenderer(); } @@ -121,6 +131,7 @@ namespace Voile { Input?.Dispose(); Renderer?.Dispose(); + AudioSystem?.Dispose(); ResourceManager.Dispose(); } diff --git a/Voile/Source/Resources/Loaders/SoundLoader.cs b/Voile/Source/Resources/Loaders/SoundLoader.cs index 1729d4e..56e92f7 100644 --- a/Voile/Source/Resources/Loaders/SoundLoader.cs +++ b/Voile/Source/Resources/Loaders/SoundLoader.cs @@ -1,4 +1,5 @@ using StbVorbisSharp; +using Voile.VFS; namespace Voile.Resources { @@ -6,7 +7,7 @@ namespace Voile.Resources { public override IEnumerable SupportedExtensions => new string[] { - "ogg" + ".ogg" }; protected override Sound LoadResource(string path) @@ -14,9 +15,11 @@ namespace Voile.Resources Vorbis vorbis; Sound result; - var fileBuffer = File.ReadAllBytes(path); - vorbis = Vorbis.FromMemory(fileBuffer); + using var stream = VirtualFileSystem.Read(path); + byte[] fileBuffer = new byte[stream.Length]; + int bytesRead = stream.Read(fileBuffer, 0, fileBuffer.Length); + vorbis = Vorbis.FromMemory(fileBuffer); vorbis.SubmitBuffer(); if (vorbis.Decoded == 0) @@ -27,18 +30,9 @@ namespace Voile.Resources var audioShort = vorbis.SongBuffer; int length = vorbis.Decoded * vorbis.Channels; - byte[] audioData = new byte[length * 2]; - for (int i = 0; i < length; i++) - { - if (i * 2 >= audioData.Length) break; - - var b1 = (byte)(audioShort[i] >> 8); - var b2 = (byte)(audioShort[i] & 256); - - audioData[i * 2] = b2; - audioData[i * 2 + 1] = b1; - } + short[] audioData = new short[length]; + Array.Copy(audioShort, audioData, length); result = new Sound(path, audioData) { diff --git a/Voile/Source/Resources/Sound.cs b/Voile/Source/Resources/Sound.cs index f3433c5..cd18555 100644 --- a/Voile/Source/Resources/Sound.cs +++ b/Voile/Source/Resources/Sound.cs @@ -1,17 +1,17 @@ namespace Voile { /// - /// Represents raw audio samples. + /// Represents raw audio samples in 16-bit PCM format. /// public class Sound : Resource { public SoundChannel Channel { get; set; } public int SampleRate { get; set; } - public byte[]? Buffer { get; private set; } + public short[]? Buffer { get; private set; } public long BufferSize { get; set; } - public Sound(string path, byte[] buffer) : base(path) + public Sound(string path, short[] buffer) : base(path) { Buffer = buffer; }