Add sound output to sound card while dumping is occurring. Uses a proxy ISoundProvider (DualSound.cs) to guarantee emulation sound core and dumping routine are unaffected, while sending "best effort" sound to system output. Doesn't sound great, but simple and functional.

This commit is contained in:
goyuken 2012-05-09 20:21:23 +00:00
parent 35a9edc018
commit a313d3910d
3 changed files with 136 additions and 7 deletions

View File

@ -295,6 +295,7 @@
<Compile Include="Properties\svnrev.cs" />
<Compile Include="QuickCollections.cs" />
<Compile Include="Sound\CDAudio.cs" />
<Compile Include="Sound\Utilities\DualSound.cs" />
<Compile Include="Sound\Utilities\Equalizer.cs" />
<Compile Include="Sound\YM2612.IO.cs" />
<Compile Include="Sound\YM2612.Channel.cs" />

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Sound.Utilities
{
/// <summary>
/// provides pass-through sound for the dumping tool to use, while making a "best effort"
/// to have something available for audio output
/// </summary>
public class DualSound : ISoundProvider
{
/// <summary>
/// implementation of a "slave" ISoundProvider that recieves best effort audio
/// </summary>
class SecondPin : ISoundProvider
{
/// <summary>
/// the source to draw from
/// </summary>
DualSound master;
public SecondPin(DualSound master)
{
this.master = master;
}
public void GetSamples(short[] samples)
{
int i;
for (i = 0; i < Math.Min(samples.Length, master.ringbuffer.Count); i++)
samples[i] = master.ringbuffer.Dequeue();
for (; i < samples.Length; i++)
// underflow
samples[i] = 0;
}
public void DiscardSamples()
{
master.ringbuffer.Clear();
}
public int MaxVolume
{
// ignored
get;
set;
}
}
/// <summary>
/// original input source
/// </summary>
ISoundProvider input;
/// <summary>
/// threshold at which to discard samples
/// </summary>
int killsize;
/// <summary>
/// storage of samples waiting to go to second pin
/// </summary>
Queue<short> ringbuffer;
/// <summary>
/// get the slave pin
/// </summary>
public ISoundProvider secondpin
{
get;
private set;
}
/// <summary>
/// default constructor
/// </summary>
/// <param name="input">the ISoundProvider to use as input</param>
/// <param name="buffsize">how many sample pairs to save for the second pin</param>
public DualSound(ISoundProvider input, int buffsize)
{
this.input = input;
killsize = buffsize * 2;
ringbuffer = new Queue<short>(killsize);
secondpin = new SecondPin(this);
}
public void GetSamples(short[] samples)
{
input.GetSamples(samples);
if (ringbuffer.Count >= killsize)
ringbuffer.Clear();
foreach (var sample in samples)
ringbuffer.Enqueue(sample);
}
public void DiscardSamples()
{
throw new Exception("Dumpers should never discard samples!");
}
public int MaxVolume
{
get { return input.MaxVolume; }
set { input.MaxVolume = value; }
}
}
}

View File

@ -33,6 +33,11 @@ namespace BizHawk.MultiClient
//avi/wav state
IVideoWriter CurrAviWriter = null;
/// <summary>
/// an audio proxy used for dumping
/// </summary>
Emulation.Sound.Utilities.DualSound DumpProxy = null;
//runloop control
bool exit;
@ -1874,8 +1879,9 @@ namespace BizHawk.MultiClient
//TODO - this will stray over time! have AviWriter keep an accumulation!
int samples = (int)(44100 / Global.Emulator.CoreOutputComm.VsyncRate);
short[] temp = new short[samples * 2];
Global.Emulator.SoundProvider.GetSamples(temp);
genSound = false;
//Global.Emulator.SoundProvider.GetSamples(temp);
DumpProxy.GetSamples(temp);
//genSound = false;
CurrAviWriter.AddFrame(Global.Emulator.VideoProvider);
CurrAviWriter.AddSamples(temp);
@ -1891,10 +1897,16 @@ namespace BizHawk.MultiClient
PressFrameAdvance = false;
}
if (genSound)
Global.Sound.UpdateSound(Global.Emulator.SoundProvider);
else
Global.Sound.UpdateSound(NullSound.SilenceProvider);
if (genSound)
{
// change audio path if dumping is occuring
if (DumpProxy != null)
Global.Sound.UpdateSound(DumpProxy.secondpin);
else
Global.Sound.UpdateSound(Global.Emulator.SoundProvider);
}
else
Global.Sound.UpdateSound(NullSound.SilenceProvider);
}
/// <summary>
@ -2704,16 +2716,23 @@ namespace BizHawk.MultiClient
aw.Dispose();
throw;
}
// buffersize here is entirely guess
DumpProxy = new Emulation.Sound.Utilities.DualSound(Global.Emulator.SoundProvider, 8192);
}
public void StopAVI()
{
if (CurrAviWriter == null) return;
if (CurrAviWriter == null)
{
DumpProxy = null;
return;
}
CurrAviWriter.CloseFile();
CurrAviWriter = null;
Global.OSD.AddMessage("AVI capture stopped");
AVIStatusLabel.Image = BizHawk.MultiClient.Properties.Resources.Blank;
AVIStatusLabel.ToolTipText = "";
DumpProxy = null; // return to normal sound output
}
private void SwapBackupSavestate(string path)