using System; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Components { /// /// This interface is for legacy sound implementations in some older cores /// This needs to go away, but is provided here, for now /// internal interface IAsyncSoundProvider { void GetSamples(short[] samples); void DiscardSamples(); } /// /// TODO: this is a shim for now, and needs to go away /// turns an into a full ISoundProvider /// This is used in cores that have an async only sound implementation /// better is implement a sync sound option in those cores without the need for /// this class or an IAsyncSoundProvider interface /// internal class FakeSyncSound : ISoundProvider { private readonly IAsyncSoundProvider _source; private readonly int _spf; /// /// Initializes a new instance of the class. /// /// The async sound provider /// number of sample pairs to request and provide on each GetSamples() call public FakeSyncSound(IAsyncSoundProvider source, int spf) { _source = source; _spf = spf; SyncMode = SyncSoundMode.Sync; } public void GetSamplesSync(out short[] samples, out int nsamp) { if (SyncMode != SyncSoundMode.Sync) { throw new InvalidOperationException("Must be in sync mode to call a sync method"); } short[] ret = new short[_spf * 2]; _source.GetSamples(ret); samples = ret; nsamp = _spf; } public void DiscardSamples() { _source.DiscardSamples(); } public void GetSamplesAsync(short[] samples) { if (SyncMode != SyncSoundMode.Async) { throw new InvalidOperationException("Must be in async mode to call an async method"); } _source.GetSamples(samples); } public bool CanProvideAsync => true; public SyncSoundMode SyncMode { get; private set; } public void SetSyncMode(SyncSoundMode mode) { SyncMode = mode; } } // An async sound provider // This class needs to go away, it takes an IAsyncSoundProvider // and is only used by legacy sound implementations internal class MetaspuSoundProvider : ISoundProvider { private readonly short[] _pullBuffer = new short[1470]; public MetaspuSoundProvider(ESynchMethod method) { Buffer = Metaspu.MetaspuConstruct(method); } public ISynchronizingAudioBuffer Buffer { get; } public MetaspuSoundProvider() : this(ESynchMethod.Vecna) { } public void PullSamples(IAsyncSoundProvider source) { Array.Clear(_pullBuffer, 0, 1470); source.GetSamples(_pullBuffer); Buffer.EnqueueSamples(_pullBuffer, 735); } public bool CanProvideAsync => true; public SyncSoundMode SyncMode => SyncSoundMode.Async; public void SetSyncMode(SyncSoundMode mode) { if (mode != SyncSoundMode.Async) { throw new NotSupportedException("Only Async mode is supported."); } } public void GetSamplesSync(out short[] samples, out int nsamp) { throw new InvalidOperationException("Sync mode is not supported."); } public void GetSamplesAsync(short[] samples) { Buffer.OutputSamples(samples, samples.Length / 2); } public void DiscardSamples() { Buffer.Clear(); } } }