BizHawk/BizHawk.Emulation.Cores/Sound/IAsyncSoundProvider.cs

132 lines
3.4 KiB
C#
Raw Normal View History

using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Components
{
/// <summary>
/// This interface is for legacy sound implementations in some older cores
/// This needs to go away, but is provided here, for now
/// </summary>
internal interface IAsyncSoundProvider
{
void GetSamples(short[] samples);
void DiscardSamples();
}
/// <summary>
/// TODO: this is a shim for now, and needs to go away
/// turns an <seealso cref="IAsyncSoundProvider"/> 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
/// </summary>
internal class FakeSyncSound : ISoundProvider
{
private readonly IAsyncSoundProvider _source;
private readonly int _spf;
/// <summary>
/// Initializes a new instance of the <see cref="FakeSyncSound"/> class.
/// </summary>
/// <param name="source">The async sound provider</param>
/// <param name="spf">number of sample pairs to request and provide on each GetSamples() call</param>
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();
}
}
}