2011-01-11 02:55:51 +00:00
|
|
|
|
using System;
|
2013-06-02 00:49:40 +00:00
|
|
|
|
using System.Collections.Generic;
|
2013-11-14 19:33:13 +00:00
|
|
|
|
|
2012-03-12 04:44:34 +00:00
|
|
|
|
#if WINDOWS
|
2011-01-11 02:55:51 +00:00
|
|
|
|
using SlimDX.DirectSound;
|
|
|
|
|
using SlimDX.Multimedia;
|
2012-03-12 04:44:34 +00:00
|
|
|
|
#endif
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
2013-11-04 01:39:19 +00:00
|
|
|
|
using BizHawk.Emulation.Common;
|
2013-11-14 19:33:13 +00:00
|
|
|
|
using BizHawk.Client.Common;
|
2013-10-25 00:57:23 +00:00
|
|
|
|
|
2013-11-03 03:54:37 +00:00
|
|
|
|
namespace BizHawk.Client.EmuHawk
|
2011-01-11 02:55:51 +00:00
|
|
|
|
{
|
2012-03-12 04:44:34 +00:00
|
|
|
|
#if WINDOWS
|
2013-06-02 00:49:40 +00:00
|
|
|
|
public static class SoundEnumeration
|
|
|
|
|
{
|
|
|
|
|
public static DirectSound Create()
|
|
|
|
|
{
|
|
|
|
|
var dc = DirectSound.GetDevices();
|
|
|
|
|
foreach (var dev in dc)
|
|
|
|
|
{
|
|
|
|
|
if (dev.Description == Global.Config.SoundDevice)
|
|
|
|
|
return new DirectSound(dev.DriverGuid);
|
|
|
|
|
}
|
|
|
|
|
return new DirectSound();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static IEnumerable<string> DeviceNames()
|
|
|
|
|
{
|
|
|
|
|
var ret = new List<string>();
|
|
|
|
|
var dc = DirectSound.GetDevices();
|
|
|
|
|
foreach (var dev in dc)
|
|
|
|
|
ret.Add(dev.Description);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-06-11 17:42:16 +00:00
|
|
|
|
public class Sound : IDisposable
|
|
|
|
|
{
|
2013-04-16 00:19:31 +00:00
|
|
|
|
public bool needDiscard;
|
2011-06-11 17:42:16 +00:00
|
|
|
|
|
2013-04-16 00:19:31 +00:00
|
|
|
|
private bool Muted;
|
|
|
|
|
private readonly bool disposed;
|
2011-06-11 17:42:16 +00:00
|
|
|
|
private SecondarySoundBuffer DSoundBuffer;
|
2013-04-16 00:19:31 +00:00
|
|
|
|
private readonly byte[] SoundBuffer;
|
2011-06-11 17:42:16 +00:00
|
|
|
|
private const int BufferSize = 4410 * 2 * 2; // 1/10th of a second, 2 bytes per sample, 2 channels;
|
|
|
|
|
//private int SoundBufferPosition; //TODO: use this
|
2013-04-16 00:19:31 +00:00
|
|
|
|
private readonly BufferedAsync semisync = new BufferedAsync();
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
private ISoundProvider asyncsoundProvider;
|
|
|
|
|
private ISyncSoundProvider syncsoundProvider;
|
|
|
|
|
|
2011-06-11 17:42:16 +00:00
|
|
|
|
public Sound(IntPtr handle, DirectSound device)
|
|
|
|
|
{
|
2012-03-02 03:39:09 +00:00
|
|
|
|
if (device != null)
|
|
|
|
|
{
|
|
|
|
|
device.SetCooperativeLevel(handle, CooperativeLevel.Priority);
|
|
|
|
|
|
2013-04-16 00:19:31 +00:00
|
|
|
|
var format = new WaveFormat
|
|
|
|
|
{
|
|
|
|
|
SamplesPerSecond = 44100,
|
|
|
|
|
BitsPerSample = 16,
|
|
|
|
|
Channels = 2,
|
|
|
|
|
FormatTag = WaveFormatTag.Pcm,
|
|
|
|
|
BlockAlignment = 4
|
|
|
|
|
};
|
2012-03-02 03:39:09 +00:00
|
|
|
|
format.AverageBytesPerSecond = format.SamplesPerSecond * format.Channels * (format.BitsPerSample / 8);
|
|
|
|
|
|
2013-04-16 00:19:31 +00:00
|
|
|
|
var desc = new SoundBufferDescription
|
|
|
|
|
{
|
|
|
|
|
Format = format,
|
|
|
|
|
Flags =
|
|
|
|
|
BufferFlags.GlobalFocus | BufferFlags.Software | BufferFlags.GetCurrentPosition2 | BufferFlags.ControlVolume,
|
|
|
|
|
SizeInBytes = BufferSize
|
|
|
|
|
};
|
2012-03-02 03:39:09 +00:00
|
|
|
|
DSoundBuffer = new SecondarySoundBuffer(device, desc);
|
|
|
|
|
ChangeVolume(Global.Config.SoundVolume);
|
|
|
|
|
}
|
2011-06-11 17:42:16 +00:00
|
|
|
|
SoundBuffer = new byte[BufferSize];
|
|
|
|
|
|
|
|
|
|
disposed = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StartSound()
|
|
|
|
|
{
|
|
|
|
|
if (disposed) throw new ObjectDisposedException("Sound");
|
|
|
|
|
if (Global.Config.SoundEnabled == false) return;
|
2012-03-02 03:39:09 +00:00
|
|
|
|
if (DSoundBuffer == null) return;
|
2011-06-11 17:42:16 +00:00
|
|
|
|
if (IsPlaying)
|
2011-02-20 08:40:22 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2011-03-19 09:12:56 +00:00
|
|
|
|
needDiscard = true;
|
|
|
|
|
|
2011-06-11 17:42:16 +00:00
|
|
|
|
DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer);
|
|
|
|
|
DSoundBuffer.CurrentPlayPosition = 0;
|
|
|
|
|
DSoundBuffer.Play(0, PlayFlags.Looping);
|
|
|
|
|
}
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
2011-02-21 19:06:54 +00:00
|
|
|
|
bool IsPlaying
|
2011-06-11 17:42:16 +00:00
|
|
|
|
{
|
2011-02-21 19:06:54 +00:00
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (DSoundBuffer == null) return false;
|
|
|
|
|
if ((DSoundBuffer.Status & BufferStatus.Playing) != 0) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StopSound()
|
2011-06-11 17:42:16 +00:00
|
|
|
|
{
|
|
|
|
|
if (!IsPlaying)
|
2011-02-20 08:40:22 +00:00
|
|
|
|
return;
|
2011-06-11 17:42:16 +00:00
|
|
|
|
for (int i = 0; i < SoundBuffer.Length; i++)
|
|
|
|
|
SoundBuffer[i] = 0;
|
|
|
|
|
DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer);
|
|
|
|
|
DSoundBuffer.Stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if (disposed) return;
|
|
|
|
|
if (DSoundBuffer != null && DSoundBuffer.Disposed == false)
|
|
|
|
|
{
|
|
|
|
|
DSoundBuffer.Dispose();
|
|
|
|
|
DSoundBuffer = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
public void SetSyncInputPin(ISyncSoundProvider source)
|
|
|
|
|
{
|
|
|
|
|
syncsoundProvider = source;
|
|
|
|
|
asyncsoundProvider = null;
|
|
|
|
|
semisync.DiscardSamples();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetAsyncInputPin(ISoundProvider source)
|
|
|
|
|
{
|
|
|
|
|
syncsoundProvider = null;
|
|
|
|
|
asyncsoundProvider = source;
|
|
|
|
|
semisync.BaseSoundProvider = source;
|
2013-10-27 16:26:37 +00:00
|
|
|
|
semisync.RecalculateMagic(Global.CoreComm.VsyncRate);
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-05 21:25:58 +00:00
|
|
|
|
static int circularDist(int from, int to, int size)
|
|
|
|
|
{
|
2011-06-11 17:42:16 +00:00
|
|
|
|
if (size == 0)
|
2011-02-05 21:25:58 +00:00
|
|
|
|
return 0;
|
|
|
|
|
int diff = (to - from);
|
2011-06-11 17:42:16 +00:00
|
|
|
|
while (diff < 0)
|
2011-02-05 21:25:58 +00:00
|
|
|
|
diff += size;
|
|
|
|
|
return diff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int soundoffset;
|
|
|
|
|
int SNDDXGetAudioSpace()
|
|
|
|
|
{
|
2012-03-02 03:39:09 +00:00
|
|
|
|
if (DSoundBuffer == null) return 0;
|
|
|
|
|
|
2011-02-05 21:25:58 +00:00
|
|
|
|
int playcursor = DSoundBuffer.CurrentPlayPosition;
|
|
|
|
|
int writecursor = DSoundBuffer.CurrentWritePosition;
|
|
|
|
|
|
|
|
|
|
int curToWrite = circularDist(soundoffset, writecursor, BufferSize);
|
|
|
|
|
int curToPlay = circularDist(soundoffset, playcursor, BufferSize);
|
|
|
|
|
|
2011-06-11 17:42:16 +00:00
|
|
|
|
if (curToWrite < curToPlay)
|
2011-02-05 21:25:58 +00:00
|
|
|
|
return 0; // in-between the two cursors. we shouldn't write anything during this time.
|
|
|
|
|
|
|
|
|
|
return curToPlay / 4;
|
|
|
|
|
}
|
|
|
|
|
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
public void UpdateSilence()
|
|
|
|
|
{
|
|
|
|
|
Muted = true;
|
|
|
|
|
UpdateSound();
|
|
|
|
|
Muted = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateSound()
|
2011-06-11 17:42:16 +00:00
|
|
|
|
{
|
2011-03-13 19:30:56 +00:00
|
|
|
|
if (Global.Config.SoundEnabled == false || disposed)
|
2011-03-19 09:12:56 +00:00
|
|
|
|
{
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
if (asyncsoundProvider != null) asyncsoundProvider.DiscardSamples();
|
|
|
|
|
if (syncsoundProvider != null) syncsoundProvider.DiscardSamples();
|
2011-03-19 09:12:56 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
2011-06-11 17:42:16 +00:00
|
|
|
|
int samplesNeeded = SNDDXGetAudioSpace() * 2;
|
2012-10-01 15:20:41 +00:00
|
|
|
|
short[] samples;
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
2013-04-16 00:19:31 +00:00
|
|
|
|
int samplesProvided;
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Muted)
|
|
|
|
|
{
|
|
|
|
|
if (samplesNeeded == 0)
|
|
|
|
|
return;
|
|
|
|
|
samples = new short[samplesNeeded];
|
|
|
|
|
samplesProvided = samplesNeeded;
|
2012-12-09 03:13:47 +00:00
|
|
|
|
|
|
|
|
|
if (asyncsoundProvider != null) asyncsoundProvider.DiscardSamples();
|
|
|
|
|
if (syncsoundProvider != null) syncsoundProvider.DiscardSamples();
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
}
|
|
|
|
|
else if (syncsoundProvider != null)
|
2011-03-19 09:12:56 +00:00
|
|
|
|
{
|
2012-10-01 15:20:41 +00:00
|
|
|
|
if (DSoundBuffer == null) return; // can cause SNDDXGetAudioSpace() = 0
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
int nsampgot;
|
|
|
|
|
|
|
|
|
|
syncsoundProvider.GetSamples(out samples, out nsampgot);
|
2012-10-01 15:20:41 +00:00
|
|
|
|
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
samplesProvided = 2 * nsampgot;
|
|
|
|
|
|
2013-10-27 07:54:00 +00:00
|
|
|
|
if (!Global.ForceNoThrottle)
|
2012-10-11 01:00:36 +00:00
|
|
|
|
while (samplesNeeded < samplesProvided)
|
|
|
|
|
{
|
|
|
|
|
System.Threading.Thread.Sleep((samplesProvided - samplesNeeded) / 88); // let audio clock control sleep time
|
|
|
|
|
samplesNeeded = SNDDXGetAudioSpace() * 2;
|
|
|
|
|
}
|
2011-03-19 09:12:56 +00:00
|
|
|
|
}
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
else if (asyncsoundProvider != null)
|
2012-10-01 15:20:41 +00:00
|
|
|
|
{
|
|
|
|
|
if (samplesNeeded == 0)
|
|
|
|
|
return;
|
|
|
|
|
samples = new short[samplesNeeded];
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
//if (asyncsoundProvider != null && Muted == false)
|
|
|
|
|
//{
|
2012-10-11 01:00:36 +00:00
|
|
|
|
semisync.BaseSoundProvider = asyncsoundProvider;
|
|
|
|
|
semisync.GetSamples(samples);
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
//}
|
|
|
|
|
//else asyncsoundProvider.DiscardSamples();
|
|
|
|
|
samplesProvided = samplesNeeded;
|
2012-10-01 15:20:41 +00:00
|
|
|
|
}
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
else
|
|
|
|
|
return;
|
2012-10-01 15:20:41 +00:00
|
|
|
|
|
2011-02-05 21:25:58 +00:00
|
|
|
|
int cursor = soundoffset;
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
for (int i = 0; i < samplesProvided; i++)
|
2011-02-05 21:25:58 +00:00
|
|
|
|
{
|
|
|
|
|
short s = samples[i];
|
|
|
|
|
SoundBuffer[cursor++] = (byte)(s & 0xFF);
|
|
|
|
|
SoundBuffer[cursor++] = (byte)(s >> 8);
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
2011-02-05 21:25:58 +00:00
|
|
|
|
if (cursor >= SoundBuffer.Length)
|
|
|
|
|
cursor = 0;
|
|
|
|
|
}
|
2011-01-11 02:55:51 +00:00
|
|
|
|
|
2011-06-11 17:42:16 +00:00
|
|
|
|
DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer);
|
2011-02-05 21:25:58 +00:00
|
|
|
|
|
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
|
|
|
|
soundoffset += samplesProvided * 2;
|
2011-02-05 21:25:58 +00:00
|
|
|
|
soundoffset %= BufferSize;
|
2011-06-11 17:42:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Range: 0-100
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="vol"></param>
|
|
|
|
|
public void ChangeVolume(int vol)
|
|
|
|
|
{
|
|
|
|
|
if (vol > 100)
|
|
|
|
|
vol = 100;
|
|
|
|
|
if (vol < 0)
|
|
|
|
|
vol = 0;
|
|
|
|
|
Global.Config.SoundVolume = vol;
|
|
|
|
|
UpdateSoundSettings();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Uses Global.Config.SoundEnabled, this just notifies the object to read it
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void UpdateSoundSettings()
|
|
|
|
|
{
|
|
|
|
|
if (!Global.Config.SoundEnabled || Global.Config.SoundVolume == 0)
|
|
|
|
|
DSoundBuffer.Volume = -5000;
|
|
|
|
|
else
|
|
|
|
|
DSoundBuffer.Volume = 0 - ((100 - Global.Config.SoundVolume) * 15);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-03-12 04:44:34 +00:00
|
|
|
|
#else
|
|
|
|
|
// Dummy implementation for non-Windows platforms for now.
|
|
|
|
|
public class Sound
|
|
|
|
|
{
|
|
|
|
|
public bool Muted = false;
|
|
|
|
|
public bool needDiscard;
|
|
|
|
|
|
|
|
|
|
public Sound()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StartSound()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsPlaying = false;
|
|
|
|
|
|
|
|
|
|
public void StopSound()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SNDDXGetAudioSpace()
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateSound(ISoundProvider soundProvider)
|
|
|
|
|
{
|
|
|
|
|
soundProvider.DiscardSamples();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Range: 0-100
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="vol"></param>
|
|
|
|
|
public void ChangeVolume(int vol)
|
|
|
|
|
{
|
|
|
|
|
Global.Config.SoundVolume = vol;
|
|
|
|
|
UpdateSoundSettings();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Uses Global.Config.SoundEnabled, this just notifies the object to read it
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void UpdateSoundSettings()
|
|
|
|
|
{
|
|
|
|
|
if (Global.Emulator is NES)
|
|
|
|
|
{
|
|
|
|
|
NES n = Global.Emulator as NES;
|
|
|
|
|
if (Global.Config.SoundEnabled == false)
|
|
|
|
|
n.SoundOn = false;
|
|
|
|
|
else
|
|
|
|
|
n.SoundOn = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|