From 9cc83775030067e2dac4ba55c9f8cb4f0a40aa68 Mon Sep 17 00:00:00 2001 From: Alessandro Proto Date: Thu, 16 Feb 2023 21:49:33 +0100 Subject: [PATCH] Added HQ audio channel. Lowered sample rate to 16kHz to normal channels. Arbitrary audio can only be played on the HQ channel --- Capy64/Core/Audio.cs | 33 +++++++++++++++++++++++++++---- Capy64/Runtime/Libraries/Audio.cs | 21 ++++++-------------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/Capy64/Core/Audio.cs b/Capy64/Core/Audio.cs index 4e5d9c9..5e418c3 100644 --- a/Capy64/Core/Audio.cs +++ b/Capy64/Core/Audio.cs @@ -29,12 +29,15 @@ public class Audio : IDisposable Noise } - public const int SampleRate = 48000; + public const int SampleRate = 16000; + public const int HQSampleRate = 48000; public const AudioChannels AudioChannel = AudioChannels.Mono; public const int ChannelsCount = 5; public readonly DynamicSoundEffectInstance[] Channels = new DynamicSoundEffectInstance[ChannelsCount]; private bool[] freeChannels = new bool[ChannelsCount]; + public readonly DynamicSoundEffectInstance HQChannel = new(HQSampleRate, AudioChannel); + private static readonly Random rng = new(); public Audio() { @@ -44,6 +47,19 @@ public class Audio : IDisposable freeChannels[i] = true; Channels[i].BufferNeeded += Audio_BufferNeeded; } + + HQChannel.BufferNeeded += HQChannel_BufferNeeded; + } + + private void HQChannel_BufferNeeded(object sender, EventArgs e) + { + var pending = HQChannel.PendingBufferCount; + Capy64.Instance.LuaRuntime.QueueEvent("audio_need", LK => + { + LK.PushInteger(-1); + LK.PushInteger(pending); + return 2; + }); } private void Audio_BufferNeeded(object sender, EventArgs e) @@ -71,6 +87,9 @@ public class Audio : IDisposable return inp; if (inp == -1) + return -1; + + if (inp == -2) { for (int i = 0; i < ChannelsCount; i++) { @@ -79,8 +98,6 @@ public class Audio : IDisposable } } - // -2 is all? - return -3; } @@ -90,6 +107,8 @@ public class Audio : IDisposable if (resolvedId >= 0) channel = Channels[resolvedId]; + else if (resolvedId == -1) + channel = HQChannel; else channel = null; @@ -106,7 +125,13 @@ public class Audio : IDisposable return channel.GetSampleDuration(buffer.Length); } - public byte[] GenerateWave(DynamicSoundEffectInstance channel, Waveform form, double frequency, TimeSpan time, float volume = 1f) + public TimeSpan SubmitHQ(byte[] buffer) + { + HQChannel.SubmitBuffer(buffer); + return HQChannel.GetSampleDuration(buffer.Length); + } + + public static byte[] GenerateWave(DynamicSoundEffectInstance channel, Waveform form, double frequency, TimeSpan time, float volume = 1f) { var size = channel.GetSampleSizeInBytes(time); var buffer = new byte[size]; diff --git a/Capy64/Runtime/Libraries/Audio.cs b/Capy64/Runtime/Libraries/Audio.cs index 83441e6..0529c17 100644 --- a/Capy64/Runtime/Libraries/Audio.cs +++ b/Capy64/Runtime/Libraries/Audio.cs @@ -114,16 +114,7 @@ public class Audio : IComponent } } - var id = (int)L.OptInteger(2, -1); - - if (!_game.Audio.TryGetChannel(id, out var channel, out var rid)) - { - L.PushBoolean(false); - L.PushString("Channel not available"); - return 2; - } - - if (channel.PendingBufferCount > queueLimit) + if (_game.Audio.HQChannel.PendingBufferCount > queueLimit) { L.PushBoolean(false); L.PushString("queue is full"); @@ -133,10 +124,10 @@ public class Audio : IComponent try { - var ts = _game.Audio.Submit(rid, buffer); + var ts = _game.Audio.SubmitHQ(buffer); - if (channel.State != SoundState.Playing) - channel.Play(); + if (_game.Audio.HQChannel.State != SoundState.Playing) + _game.Audio.HQChannel.Play(); } catch (Exception ex) { @@ -167,7 +158,7 @@ public class Audio : IComponent null, }); - var id = (int)L.OptInteger(5, -1); + var id = (int)L.OptInteger(5, -2); if (!_game.Audio.TryGetChannel(id, out var channel, out var rid)) { @@ -175,7 +166,7 @@ public class Audio : IComponent return 1; } - var buffer = _game.Audio.GenerateWave(channel, (Waveform)form, freq, timespan, volume); + var buffer = GenerateWave(channel, (Waveform)form, freq, timespan, volume); try {