WIP: SoLoud audio system, make Sound be in 16-bit PCM.
This commit is contained in:
BIN
TestGame/Resources/sounds/test_sound_mono.ogg
Normal file
BIN
TestGame/Resources/sounds/test_sound_mono.ogg
Normal file
Binary file not shown.
@@ -34,6 +34,7 @@ public class TestGame : Game
|
||||
}
|
||||
|
||||
ResourceManager.TryLoad("icon.png", out _icon);
|
||||
ResourceManager.TryLoad("sounds/test_sound_mono.ogg", out _sound);
|
||||
|
||||
if (!ResourceManager.TryLoad("fire_effect.toml", out _fireEffect))
|
||||
{
|
||||
@@ -52,8 +53,9 @@ public class TestGame : Game
|
||||
{
|
||||
if (Input.IsActionPressed("reload"))
|
||||
{
|
||||
ResourceManager.Reload();
|
||||
_particleSystem!.RestartEmitter(_emitterId);
|
||||
// ResourceManager.Reload();
|
||||
// _particleSystem!.RestartEmitter(_emitterId);
|
||||
AudioSystem.PlaySound(_sound.Value);
|
||||
}
|
||||
|
||||
if (Input.KeyboardKeyJustPressed(KeyboardKey.One))
|
||||
@@ -106,5 +108,6 @@ public class TestGame : Game
|
||||
private int _emitterId;
|
||||
private ResourceRef<ParticleEmitterSettingsResource> _fireEffect;
|
||||
private ResourceRef<Font> _font;
|
||||
private ResourceRef<Sound> _sound;
|
||||
private ResourceRef<Texture2d> _icon;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Voile
|
||||
{
|
||||
public class AudioBus
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Voile
|
||||
{
|
||||
public class AudioEffect { }
|
||||
|
||||
public class AudioEffectReverb : AudioEffect
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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>(T effect, string bus = "Master") where T : AudioEffect;
|
||||
|
||||
|
||||
private LehmerRandom _random = new LehmerRandom();
|
||||
}
|
||||
@@ -5,11 +5,6 @@ namespace Voile.Audio
|
||||
/// </summary>
|
||||
public class DummyAudioSystem : AudioSystem
|
||||
{
|
||||
public override void AddBusEffect<T>(T effect, string bus = "Master")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public override void CreateBus(string busName)
|
||||
{
|
||||
return;
|
||||
|
||||
64
Voile/Source/Audio/StandardAudioSystem.cs
Normal file
64
Voile/Source/Audio/StandardAudioSystem.cs
Normal file
@@ -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<short> 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;
|
||||
}
|
||||
@@ -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
|
||||
/// </summary>
|
||||
protected RenderSystem? Renderer { get; set; }
|
||||
|
||||
protected AudioSystem? AudioSystem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of this game. Also used as a default window title.
|
||||
/// </summary>
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using StbVorbisSharp;
|
||||
using Voile.VFS;
|
||||
|
||||
namespace Voile.Resources
|
||||
{
|
||||
@@ -6,7 +7,7 @@ namespace Voile.Resources
|
||||
{
|
||||
public override IEnumerable<string> 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)
|
||||
{
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
namespace Voile
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents raw audio samples.
|
||||
/// Represents raw audio samples in 16-bit PCM format.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user