actually resample stella's audio

This commit is contained in:
CasualPokePlayer 2024-09-15 23:19:43 -07:00
parent db11df3804
commit 57e24b8f09
3 changed files with 78 additions and 14 deletions

View File

@ -58,6 +58,7 @@ namespace BizHawk.Emulation.Cores.Atari.Stella
public void Dispose()
{
_elf.Dispose();
DisposeSound();
}
}
}

View File

@ -1,12 +1,13 @@
using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Atari.Stella
{
public partial class Stella : ISoundProvider
{
private BlipBuffer _blipL, _blipR;
private int _latchL, _latchR;
private readonly short[] _samples = new short[4096];
private int _nsamp;
@ -20,9 +21,7 @@ namespace BizHawk.Emulation.Cores.Atari.Stella
}
public void DiscardSamples()
{
_nsamp = 0;
}
=> _nsamp = 0;
public void SetSyncMode(SyncSoundMode mode)
{
@ -30,26 +29,89 @@ namespace BizHawk.Emulation.Cores.Atari.Stella
{
throw new NotSupportedException("Async mode is not supported.");
}
}
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
public void GetSamplesAsync(short[] samples)
{
throw new InvalidOperationException("Async mode is not supported.");
}
=> throw new InvalidOperationException("Async mode is not supported.");
private void UpdateAudio()
private unsafe void UpdateAudio()
{
var src = IntPtr.Zero;
Core.stella_get_audio(ref _nsamp, ref src);
var nsamp = 0;
Core.stella_get_audio(ref nsamp, ref src);
if (src != IntPtr.Zero)
{
using (_elf.EnterExit())
{
Marshal.Copy(src, _samples, 0, _nsamp * 2);
var samplePtr = (ushort*)src.ToPointer();
for (uint i = 0; i < nsamp; i++)
{
int sample = *samplePtr++;
if (sample != _latchL)
{
var diff = _latchL - sample;
_latchL = sample;
_blipL.AddDelta(i, diff);
}
sample = *samplePtr++;
if (sample != _latchR)
{
var diff = _latchR - sample;
_latchR = sample;
_blipR.AddDelta(i, diff);
}
}
}
_blipL.EndFrame((uint)nsamp);
_blipR.EndFrame((uint)nsamp);
_nsamp = _blipL.SamplesAvailable();
if (_nsamp != _blipR.SamplesAvailable())
{
throw new InvalidOperationException("Audio processing error");
}
_blipL.ReadSamplesLeft(_samples, _nsamp);
_blipR.ReadSamplesRight(_samples, _nsamp);
}
else
{
_nsamp = 0;
}
}
private void InitSound(int fps)
{
var sampleRate = fps switch
{
60 => 262 * 76 * 60 / 38, // 31440Hz
50 => 312 * 76 * 50 / 38, // 31200Hz
_ => throw new InvalidOperationException()
};
_blipL = new(2048);
_blipL.SetRates(sampleRate, 44100);
_blipR = new(2048);
_blipR.SetRates(sampleRate, 44100);
}
private void DisposeSound()
{
if (_blipL != null)
{
_blipL.Dispose();
_blipL = null;
}
if (_blipR != null)
{
_blipR.Dispose();
_blipR = null;
}
}
}

View File

@ -62,6 +62,8 @@ namespace BizHawk.Emulation.Cores.Atari.Stella
Core.stella_get_frame_rate(out var fps);
InitSound(fps);
var regionId = Core.stella_get_region();
Region = regionId switch
{
@ -85,7 +87,6 @@ namespace BizHawk.Emulation.Cores.Atari.Stella
Core.stella_set_input_callback(_inputCallback);
// Getting cartridge type
var ptr = Core.stella_get_cart_type();
var cartType = Marshal.PtrToStringAnsi(ptr);
Console.WriteLine($"[Stella] Cart type loaded: {cartType}");