110 lines
3.6 KiB
C#
110 lines
3.6 KiB
C#
using System;
|
|
using BizHawk.Emulation.Sound;
|
|
using SlimDX.DirectSound;
|
|
using SlimDX.Multimedia;
|
|
|
|
namespace BizHawk.MultiClient
|
|
{
|
|
public class Sound : IDisposable
|
|
{
|
|
public bool SoundEnabled = true;
|
|
public bool Muted = false;
|
|
private bool disposed = false;
|
|
|
|
private SecondarySoundBuffer DSoundBuffer;
|
|
private byte[] SoundBuffer;
|
|
private const int BufferSize = 4410 * 2 * 2; // 1/10th of a second, 2 bytes per sample, 2 channels;
|
|
private int SoundBufferPosition;
|
|
|
|
private BufferedAsync semisync = new BufferedAsync();
|
|
|
|
public Sound(IntPtr handle, DirectSound device)
|
|
{
|
|
device.SetCooperativeLevel(handle, CooperativeLevel.Priority);
|
|
|
|
var format = new WaveFormat();
|
|
format.SamplesPerSecond = 44100;
|
|
format.BitsPerSample = 16;
|
|
format.Channels = 2;
|
|
format.FormatTag = WaveFormatTag.Pcm;
|
|
format.BlockAlignment = 4;
|
|
format.AverageBytesPerSecond = format.SamplesPerSecond * format.Channels * (format.BitsPerSample / 8);
|
|
|
|
var desc = new SoundBufferDescription();
|
|
desc.Format = format;
|
|
desc.Flags = BufferFlags.GlobalFocus | BufferFlags.Software | BufferFlags.GetCurrentPosition2;
|
|
desc.SizeInBytes = BufferSize;
|
|
|
|
DSoundBuffer = new SecondarySoundBuffer(device, desc);
|
|
SoundBuffer = new byte[BufferSize];
|
|
|
|
disposed = false;
|
|
}
|
|
|
|
public void StartSound()
|
|
{
|
|
if (disposed) throw new ObjectDisposedException("Sound");
|
|
if (SoundEnabled == false) return;
|
|
|
|
DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer);
|
|
|
|
DSoundBuffer.CurrentPlayPosition = 0;
|
|
DSoundBuffer.Play(0, PlayFlags.Looping);
|
|
}
|
|
|
|
public void StopSound()
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
public void UpdateSound(ISoundProvider soundProvider)
|
|
{
|
|
if (SoundEnabled == false || disposed)
|
|
return;
|
|
|
|
int PlayPos = DSoundBuffer.CurrentPlayPosition / 2;
|
|
int WritePos = SoundBufferPosition / 2;
|
|
int TargetPos = PlayPos + 2204;
|
|
|
|
int samplesNeeded = TargetPos - WritePos;
|
|
if (samplesNeeded < 0)
|
|
samplesNeeded += 8820;
|
|
|
|
if (samplesNeeded >= 8820)
|
|
samplesNeeded -= 8820;
|
|
|
|
short[] samples = new short[samplesNeeded];
|
|
|
|
if (soundProvider != null && Muted == false)
|
|
{
|
|
semisync.BaseSoundProvider = soundProvider;
|
|
semisync.GetSamples(samples);
|
|
}
|
|
|
|
for (int i = 0; i < samples.Length; i++)
|
|
{
|
|
short s = samples[i];
|
|
SoundBuffer[SoundBufferPosition++] = (byte)(s & 0xFF);
|
|
SoundBuffer[SoundBufferPosition++] = (byte)(s >> 8);
|
|
|
|
if (SoundBufferPosition >= SoundBuffer.Length)
|
|
SoundBufferPosition = 0;
|
|
}
|
|
|
|
DSoundBuffer.Write(SoundBuffer, 0, LockFlags.EntireBuffer);
|
|
}
|
|
}
|
|
} |