Clean up namespaces for BizHawk.Emulation sound files

This commit is contained in:
adelikat 2013-11-14 19:33:13 +00:00
parent 906c0316a6
commit 25b242ade4
40 changed files with 1442 additions and 1426 deletions

View File

@ -998,7 +998,7 @@ namespace BizHawk.Client.EmuHawk
//avi/wav state //avi/wav state
private IVideoWriter CurrAviWriter; private IVideoWriter CurrAviWriter;
private ISoundProvider AviSoundInput; private ISoundProvider AviSoundInput;
private Emulation.Sound.MetaspuSoundProvider DumpProxy; //an audio proxy used for dumping private MetaspuSoundProvider DumpProxy; //an audio proxy used for dumping
private long SoundRemainder; //audio timekeeping for video dumping private long SoundRemainder; //audio timekeeping for video dumping
private int avwriter_resizew; private int avwriter_resizew;
private int avwriter_resizeh; private int avwriter_resizeh;
@ -1412,7 +1412,7 @@ namespace BizHawk.Client.EmuHawk
if (!Global.Emulator.StartAsyncSound()) if (!Global.Emulator.StartAsyncSound())
{ {
// if the core doesn't support async mode, use a standard vecna wrapper // if the core doesn't support async mode, use a standard vecna wrapper
GlobalWin.Sound.SetAsyncInputPin(new Emulation.Sound.MetaspuAsync(Global.Emulator.SyncSoundProvider, Emulation.Sound.ESynchMethod.ESynchMethod_V)); GlobalWin.Sound.SetAsyncInputPin(new MetaspuAsync(Global.Emulator.SyncSoundProvider, ESynchMethod.ESynchMethod_V));
} }
else else
{ {
@ -2854,10 +2854,10 @@ namespace BizHawk.Client.EmuHawk
// do sound rewire. the plan is to eventually have AVI writing support syncsound input, but it doesn't for the moment // do sound rewire. the plan is to eventually have AVI writing support syncsound input, but it doesn't for the moment
if (!Global.Emulator.StartAsyncSound()) if (!Global.Emulator.StartAsyncSound())
AviSoundInput = new Emulation.Sound.MetaspuAsync(Global.Emulator.SyncSoundProvider, Emulation.Sound.ESynchMethod.ESynchMethod_V); AviSoundInput = new MetaspuAsync(Global.Emulator.SyncSoundProvider, ESynchMethod.ESynchMethod_V);
else else
AviSoundInput = Global.Emulator.SoundProvider; AviSoundInput = Global.Emulator.SoundProvider;
DumpProxy = new Emulation.Sound.MetaspuSoundProvider(Emulation.Sound.ESynchMethod.ESynchMethod_V); DumpProxy = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
SoundRemainder = 0; SoundRemainder = 0;
RewireSound(); RewireSound();
} }

View File

@ -1,13 +1,13 @@
using System; using System;
using BizHawk.Emulation.Sound;
using System.Collections.Generic; using System.Collections.Generic;
#if WINDOWS #if WINDOWS
using SlimDX.DirectSound; using SlimDX.DirectSound;
using SlimDX.Multimedia; using SlimDX.Multimedia;
#endif #endif
using BizHawk.Client.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk namespace BizHawk.Client.EmuHawk
{ {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
using System; using System;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common;
#pragma warning disable 649 //adelikat: Disable dumb warnings until this file is complete #pragma warning disable 649 //adelikat: Disable dumb warnings until this file is complete
#pragma warning disable 169 //adelikat: Disable dumb warnings until this file is complete #pragma warning disable 169 //adelikat: Disable dumb warnings until this file is complete
@ -14,12 +16,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
// ------------------------------------ // ------------------------------------
public Sound.Utilities.SpeexResampler resampler; public SpeexResampler resampler;
static int[] syncNextTable = new int[] { 1, 2, 0 }; static int[] syncNextTable = new int[] { 1, 2, 0 };
static int[] syncPrevTable = new int[] { 2, 0, 1 }; static int[] syncPrevTable = new int[] { 2, 0, 1 };
int cachedCycles; int cachedCycles;
bool disableVoice3; bool disableVoice3;
int[] envelopeOutput; int[] envelopeOutput;
Envelope[] envelopes; Envelope[] envelopes;
@ -29,12 +31,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
bool filterSelectBandPass; bool filterSelectBandPass;
bool filterSelectLoPass; bool filterSelectLoPass;
bool filterSelectHiPass; bool filterSelectHiPass;
int mixer; int mixer;
int potCounter; int potCounter;
int potX; int potX;
int potY; int potY;
short sample; short sample;
int[] voiceOutput; int[] voiceOutput;
Voice[] voices; Voice[] voices;
int volume; int volume;
int[][] waveformTable; int[][] waveformTable;
@ -45,15 +47,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
public Sid(int[][] newWaveformTable, int newSampleRate, Region newRegion) public Sid(int[][] newWaveformTable, int newSampleRate, Region newRegion)
{ {
uint cyclesPerSec = 0; uint cyclesPerSec = 0;
uint cyclesNum; uint cyclesNum;
uint cyclesDen; uint cyclesDen;
uint sampleRate = 44100; uint sampleRate = 44100;
switch (newRegion) switch (newRegion)
{ {
case Region.NTSC: cyclesNum = 14318181; cyclesDen = 14; break; case Region.NTSC: cyclesNum = 14318181; cyclesDen = 14; break;
case Region.PAL: cyclesNum = 17734472; cyclesDen = 18; break; case Region.PAL: cyclesNum = 17734472; cyclesDen = 18; break;
default: return; default: return;
} }
waveformTable = newWaveformTable; waveformTable = newWaveformTable;
@ -72,7 +74,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
filterEnable[i] = false; filterEnable[i] = false;
resampler = new Sound.Utilities.SpeexResampler(0, cyclesNum, sampleRate * cyclesDen, cyclesNum, sampleRate * cyclesDen, null, null); resampler = new SpeexResampler(0, cyclesNum, sampleRate * cyclesDen, cyclesNum, sampleRate * cyclesDen, null, null);
} }
public void Dispose() public void Dispose()
@ -100,55 +102,55 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
// ------------------------------------ // ------------------------------------
public void ExecutePhase2() public void ExecutePhase2()
{ {
cachedCycles++; cachedCycles++;
// potentiometer values refresh every 512 cycles // potentiometer values refresh every 512 cycles
if (potCounter == 0) if (potCounter == 0)
{ {
potCounter = 512; potCounter = 512;
potX = ReadPotX(); potX = ReadPotX();
potY = ReadPotY(); potY = ReadPotY();
Flush(); //this is here unrelated to the pots, just to keep the buffer somewhat loaded Flush(); //this is here unrelated to the pots, just to keep the buffer somewhat loaded
} }
potCounter--; potCounter--;
} }
public void Flush() public void Flush()
{ {
while (cachedCycles > 0) while (cachedCycles > 0)
{ {
// process voices and envelopes // process voices and envelopes
voices[0].ExecutePhase2(); voices[0].ExecutePhase2();
voices[1].ExecutePhase2(); voices[1].ExecutePhase2();
voices[2].ExecutePhase2(); voices[2].ExecutePhase2();
envelopes[0].ExecutePhase2(); envelopes[0].ExecutePhase2();
envelopes[1].ExecutePhase2(); envelopes[1].ExecutePhase2();
envelopes[2].ExecutePhase2(); envelopes[2].ExecutePhase2();
// process sync // process sync
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]); voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]);
// get output // get output
voiceOutput[0] = voices[0].Output(voices[2]); voiceOutput[0] = voices[0].Output(voices[2]);
voiceOutput[1] = voices[1].Output(voices[0]); voiceOutput[1] = voices[1].Output(voices[0]);
voiceOutput[2] = voices[2].Output(voices[1]); voiceOutput[2] = voices[2].Output(voices[1]);
envelopeOutput[0] = envelopes[0].Level; envelopeOutput[0] = envelopes[0].Level;
envelopeOutput[1] = envelopes[1].Level; envelopeOutput[1] = envelopes[1].Level;
envelopeOutput[2] = envelopes[2].Level; envelopeOutput[2] = envelopes[2].Level;
mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7); mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7);
mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7); mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7);
mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7); mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7);
mixer = (mixer * volume) >> 4; mixer = (mixer * volume) >> 4;
sample = (short)mixer; sample = (short)mixer;
resampler.EnqueueSample(sample, sample); resampler.EnqueueSample(sample, sample);
cachedCycles--; cachedCycles--;
} }
} }
// ------------------------------------ // ------------------------------------
@ -172,7 +174,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
case 0x1A: case 0x1A:
case 0x1B: case 0x1B:
case 0x1C: case 0x1C:
Flush(); Flush();
result = ReadRegister(addr); result = ReadRegister(addr);
break; break;
} }
@ -280,7 +282,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
); );
break; break;
case 0x19: result = (byte)potX; break; case 0x19: result = (byte)potX; break;
case 0x1A: result = (byte)potY; break; case 0x1A: result = (byte)potY; break;
case 0x1B: result = (byte)(voiceOutput[2] >> 4); break; case 0x1B: result = (byte)(voiceOutput[2] >> 4); break;
case 0x1C: result = (byte)(envelopeOutput[2]); break; case 0x1C: result = (byte)(envelopeOutput[2]); break;
} }
@ -303,7 +305,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
// can't write to these // can't write to these
break; break;
default: default:
Flush(); Flush();
WriteRegister(addr, val); WriteRegister(addr, val);
break; break;
} }
@ -360,10 +362,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
// ---------------------------------- // ----------------------------------
public void SyncState(Serializer ser) public void SyncState(Serializer ser)
{ {
SaveState.SyncObject(ser, this); SaveState.SyncObject(ser, this);
ser.BeginSection("env0"); ser.BeginSection("env0");
envelopes[0].SyncState(ser); envelopes[0].SyncState(ser);
ser.EndSection(); ser.EndSection();
ser.BeginSection("wav0"); ser.BeginSection("wav0");

View File

@ -1,6 +1,7 @@
using System; using System;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components.M6502; using BizHawk.Emulation.Common.Components.M6502;
@ -12,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public MOS6502X cpu; public MOS6502X cpu;
public M6532 m6532; public M6532 m6532;
public TIA tia; public TIA tia;
public Emulation.Sound.Utilities.DCFilter dcfilter; public DCFilter dcfilter;
public byte[] ram = new byte[128]; public byte[] ram = new byte[128];
public MapperBase mapper; public MapperBase mapper;
@ -183,7 +184,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
//tia = new TIA(this, frameBuffer); //tia = new TIA(this, frameBuffer);
tia = new TIA(this); tia = new TIA(this);
// dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles // dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
dcfilter = Emulation.Sound.Utilities.DCFilter.AsISoundProvider(tia, 256); dcfilter = DCFilter.AsISoundProvider(tia, 256);
// Setup 6532 // Setup 6532
m6532 = new M6532(this); m6532 = new M6532(this);

View File

@ -344,16 +344,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
// really shouldn't happen (after init), but if it does, we're ready // really shouldn't happen (after init), but if it does, we're ready
if (resampler != null) if (resampler != null)
resampler.Dispose(); resampler.Dispose();
resampler = new Emulation.Sound.Utilities.SpeexResampler(3, newsamplerate, 44100, newsamplerate, 44100, null, null); resampler = new SpeexResampler(3, newsamplerate, 44100, newsamplerate, 44100, null, null);
samplerate = newsamplerate; samplerate = newsamplerate;
dcfilter = Emulation.Sound.Utilities.DCFilter.DetatchedMode(256); dcfilter = DCFilter.DetatchedMode(256);
} }
} }
uint samplerate; uint samplerate;
int[] vidbuffer; int[] vidbuffer;
Emulation.Sound.Utilities.SpeexResampler resampler; SpeexResampler resampler;
Emulation.Sound.Utilities.DCFilter dcfilter; DCFilter dcfilter;
public void FillFrameBuffer() public void FillFrameBuffer()
{ {

View File

@ -4,8 +4,8 @@ using System.IO;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components;
using BizHawk.Emulation.Common.Components.Z80; using BizHawk.Emulation.Common.Components.Z80;
using BizHawk.Emulation.Sound;
namespace BizHawk.Emulation.Cores.ColecoVision namespace BizHawk.Emulation.Cores.ColecoVision
{ {

View File

@ -826,10 +826,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
int latchaudio = 0; int latchaudio = 0;
//Sound.Utilities.SpeexResampler resampler; //SpeexResampler resampler;
//Sound.Utilities.DCFilter dcfilter; //DCFilter dcfilter;
Sound.Utilities.BlipBuffer blip; BlipBuffer blip;
void ProcessSound() void ProcessSound()
{ {
@ -862,7 +862,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
//dcfilter = Sound.Utilities.DCFilter.AsISyncSoundProvider(resampler, 65536); //dcfilter = Sound.Utilities.DCFilter.AsISyncSoundProvider(resampler, 65536);
// lowpass filtering on an actual GB was probably pretty aggressive? // lowpass filtering on an actual GB was probably pretty aggressive?
//dcfilter = Sound.Utilities.DCFilter.AsISyncSoundProvider(resampler, 2048); //dcfilter = Sound.Utilities.DCFilter.AsISyncSoundProvider(resampler, 2048);
blip = new Sound.Utilities.BlipBuffer(1024); blip = new BlipBuffer(1024);
blip.SetRates(2097152, 44100); blip.SetRates(2097152, 44100);
} }

View File

@ -60,8 +60,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
LagCount = 0; LagCount = 0;
IsLagFrame = false; IsLagFrame = false;
blip_left = new Sound.Utilities.BlipBuffer(1024); blip_left = new BlipBuffer(1024);
blip_right = new Sound.Utilities.BlipBuffer(1024); blip_right = new BlipBuffer(1024);
blip_left.SetRates(2097152 * 2, 44100); blip_left.SetRates(2097152 * 2, 44100);
blip_right.SetRates(2097152 * 2, 44100); blip_right.SetRates(2097152 * 2, 44100);
@ -357,9 +357,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
// i tried using the left and right buffers and then mixing them together... it was kind of a mess of code, and slow // i tried using the left and right buffers and then mixing them together... it was kind of a mess of code, and slow
Sound.Utilities.BlipBuffer blip_left; BlipBuffer blip_left;
Sound.Utilities.BlipBuffer blip_right; BlipBuffer blip_right;
short[] LeftBuffer = new short[(35112 + 2064) * 2]; short[] LeftBuffer = new short[(35112 + 2064) * 2];
short[] RightBuffer = new short[(35112 + 2064) * 2]; short[] RightBuffer = new short[(35112 + 2064) * 2];

View File

@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
public int BackgroundColor { get { return 0; } } public int BackgroundColor { get { return 0; } }
public Sound.Utilities.SpeexResampler resampler; public SpeexResampler resampler;
public ISoundProvider SoundProvider { get { return null; } } public ISoundProvider SoundProvider { get { return null; } }
public ISyncSoundProvider SyncSoundProvider { get { return resampler; } } public ISyncSoundProvider SyncSoundProvider { get { return resampler; } }

View File

@ -5,6 +5,8 @@ using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.N64 namespace BizHawk.Emulation.Cores.Nintendo.N64
{ {
public class mupen64plusApi : IDisposable public class mupen64plusApi : IDisposable
@ -515,7 +517,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
// Set up the resampler // Set up the resampler
m64pSamplingRate = (uint)AudGetAudioRate(); m64pSamplingRate = (uint)AudGetAudioRate();
bizhawkCore.resampler = new Sound.Utilities.SpeexResampler(6, m64pSamplingRate, 44100, m64pSamplingRate, 44100, null, null); bizhawkCore.resampler = new SpeexResampler(6, m64pSamplingRate, 44100, m64pSamplingRate, 44100, null, null);
AttachedCore = this; AttachedCore = this;
} }

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Sound;
//http://wiki.nesdev.com/w/index.php/APU_Mixer_Emulation //http://wiki.nesdev.com/w/index.php/APU_Mixer_Emulation
//http://wiki.nesdev.com/w/index.php/APU //http://wiki.nesdev.com/w/index.php/APU

View File

@ -2,6 +2,7 @@
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components;
//simplifications/approximations: //simplifications/approximations:
//* "Note that no commercial games rely on this mirroring -- therefore you can take the easy way out and simply give all MMC5 games 64k PRG-RAM." //* "Note that no commercial games rely on this mirroring -- therefore you can take the easy way out and simply give all MMC5 games 64k PRG-RAM."
@ -38,7 +39,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
int wram_bank; int wram_bank;
byte[] EXRAM = new byte[1024]; byte[] EXRAM = new byte[1024];
byte multiplicand, multiplier; byte multiplicand, multiplier;
Sound.MMC5Audio audio; MMC5Audio audio;
//regeneratable state //regeneratable state
IntBuffer a_banks_1k = new IntBuffer(8); IntBuffer a_banks_1k = new IntBuffer(8);
IntBuffer b_banks_1k = new IntBuffer(8); IntBuffer b_banks_1k = new IntBuffer(8);
@ -119,7 +120,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
PoweronState(); PoweronState();
if (NES.apu != null) if (NES.apu != null)
audio = new Sound.MMC5Audio(NES.apu.ExternalQueue, (e) => { irq_audio = e; SyncIRQ(); }); audio = new MMC5Audio(NES.apu.ExternalQueue, (e) => { irq_audio = e; SyncIRQ(); });
return true; return true;
} }

View File

@ -1,4 +1,5 @@
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common.Components;
namespace BizHawk.Emulation.Cores.Nintendo.NES namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
@ -7,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
public sealed class Sunsoft_5 : Sunsoft_FME7 public sealed class Sunsoft_5 : Sunsoft_FME7
{ {
Sound.Sunsoft5BAudio audio; Sunsoft5BAudio audio;
public override bool Configure(NES.EDetectionOrigin origin) public override bool Configure(NES.EDetectionOrigin origin)
{ {
@ -23,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
BaseConfigure(); BaseConfigure();
if (NES.apu != null) if (NES.apu != null)
audio = new Sound.Sunsoft5BAudio(NES.apu.ExternalQueue); audio = new Sunsoft5BAudio(NES.apu.ExternalQueue);
return true; return true;
} }

View File

@ -1,5 +1,7 @@
using System; using System;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Nintendo.NES namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
@ -116,15 +118,15 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
ser.Sync("ch", ref ch); ser.Sync("ch", ref ch);
} }
Sound.Utilities.SpeexResampler resampler; SpeexResampler resampler;
Sound.Utilities.DCFilter dc; DCFilter dc;
Sound.MetaspuAsync metaspu; MetaspuAsync metaspu;
public Namco163Audio() public Namco163Audio()
{ {
resampler = new Sound.Utilities.SpeexResampler(2, 119318, 44100, 119318, 44100, null, null); resampler = new SpeexResampler(2, 119318, 44100, 119318, 44100, null, null);
dc = Sound.Utilities.DCFilter.DetatchedMode(4096); dc = DCFilter.DetatchedMode(4096);
metaspu = new Sound.MetaspuAsync(resampler, Sound.ESynchMethod.ESynchMethod_V); metaspu = new MetaspuAsync(resampler, ESynchMethod.ESynchMethod_V);
} }
public void ApplyCustomAudio(short[] samples) public void ApplyCustomAudio(short[] samples)

View File

@ -1,5 +1,7 @@
using System; using System;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common.Components;
namespace BizHawk.Emulation.Cores.Nintendo.NES namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
@ -12,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
bool newer_variant; bool newer_variant;
//Sound.VRC6 VRC6Sound = new Sound.VRC6(); //Sound.VRC6 VRC6Sound = new Sound.VRC6();
Sound.VRC6Alt VRC6Sound; VRC6Alt VRC6Sound;
//state //state
int prg_bank_16k, prg_bank_8k; int prg_bank_16k, prg_bank_8k;
@ -96,7 +98,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
SetMirrorType(EMirrorType.Vertical); SetMirrorType(EMirrorType.Vertical);
if (NES.apu != null) // don't start up sound when in configurator if (NES.apu != null) // don't start up sound when in configurator
VRC6Sound = new Sound.VRC6Alt((uint)NES.cpuclockrate, NES.apu.ExternalQueue); VRC6Sound = new VRC6Alt((uint)NES.cpuclockrate, NES.apu.ExternalQueue);
return true; return true;
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common.Components;
namespace BizHawk.Emulation.Cores.Nintendo.NES namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
@ -14,7 +15,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
Func<int, int> remap; Func<int, int> remap;
//state //state
BizHawk.Emulation.Sound.YM2413 fm; //= new Sound.YM2413(Sound.YM2413.ChipType.VRC7); YM2413 fm; //= new Sound.YM2413(Sound.YM2413.ChipType.VRC7);
ByteBuffer prg_banks_8k = new ByteBuffer(4); ByteBuffer prg_banks_8k = new ByteBuffer(4);
ByteBuffer chr_banks_1k = new ByteBuffer(8); ByteBuffer chr_banks_1k = new ByteBuffer(8);
@ -94,7 +95,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
// presumably the only reason a homebrew would use mapper085 is for the sound? // presumably the only reason a homebrew would use mapper085 is for the sound?
// so initialize like lagrange point // so initialize like lagrange point
remap = (addr) => ((addr & 0xF000) | ((addr & 0x30) >> 4)); remap = (addr) => ((addr & 0xF000) | ((addr & 0x30) >> 4));
fm = new Sound.YM2413(Sound.YM2413.ChipType.VRC7); fm = new YM2413(YM2413.ChipType.VRC7);
break; break;
case "KONAMI-VRC-7": case "KONAMI-VRC-7":
AssertPrg(128, 512); AssertChr(0, 128); AssertVram(0, 8); AssertWram(0, 8); AssertPrg(128, 512); AssertChr(0, 128); AssertVram(0, 8); AssertWram(0, 8);
@ -109,7 +110,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
//lagrange point //lagrange point
remap = (addr) => ((addr & 0xF000) | ((addr & 0x30) >> 4)); remap = (addr) => ((addr & 0xF000) | ((addr & 0x30) >> 4));
fm = new Sound.YM2413(Sound.YM2413.ChipType.VRC7); fm = new YM2413(YM2413.ChipType.VRC7);
} }
else else
throw new Exception("Unknown PCB type for VRC7"); throw new Exception("Unknown PCB type for VRC7");

View File

@ -66,7 +66,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
class MagicSoundProvider : ISoundProvider, ISyncSoundProvider, IDisposable class MagicSoundProvider : ISoundProvider, ISyncSoundProvider, IDisposable
{ {
Sound.Utilities.BlipBuffer blip; BlipBuffer blip;
NES nes; NES nes;
const int blipbuffsize = 4096; const int blipbuffsize = 4096;
@ -75,7 +75,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{ {
this.nes = nes; this.nes = nes;
blip = new Sound.Utilities.BlipBuffer(blipbuffsize); blip = new BlipBuffer(blipbuffsize);
blip.SetRates(infreq, 44100); blip.SetRates(infreq, 44100);
//var actualMetaspu = new Sound.MetaspuSoundProvider(Sound.ESynchMethod.ESynchMethod_V); //var actualMetaspu = new Sound.MetaspuSoundProvider(Sound.ESynchMethod.ESynchMethod_V);

View File

@ -975,11 +975,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
#region audio stuff #region audio stuff
Sound.Utilities.SpeexResampler resampler; SpeexResampler resampler;
void InitAudio() void InitAudio()
{ {
resampler = new Sound.Utilities.SpeexResampler(6, 64081, 88200, 32041, 44100); resampler = new SpeexResampler(6, 64081, 88200, 32041, 44100);
} }
void snes_audio_sample(ushort left, ushort right) void snes_audio_sample(ushort left, ushort right)

View File

@ -1,5 +1,4 @@
using System; using System;
using BizHawk.Emulation.Sound;
using System.IO; using System.IO;
using System.Globalization; using System.Globalization;

View File

@ -5,9 +5,9 @@ using System.IO;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components;
using BizHawk.Emulation.Common.Components.H6280; using BizHawk.Emulation.Common.Components.H6280;
using BizHawk.Emulation.DiscSystem; using BizHawk.Emulation.DiscSystem;
using BizHawk.Emulation.Sound;
namespace BizHawk.Emulation.Cores.PCEngine namespace BizHawk.Emulation.Cores.PCEngine
{ {

View File

@ -3,8 +3,8 @@ using System.IO;
using System.Globalization; using System.Globalization;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.DiscSystem; using BizHawk.Emulation.DiscSystem;
using BizHawk.Emulation.Sound;
namespace BizHawk.Emulation.Cores.PCEngine namespace BizHawk.Emulation.Cores.PCEngine
{ {

View File

@ -7,12 +7,11 @@ using System.Runtime.InteropServices;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components;
using BizHawk.Emulation.Common.Components.M68000; using BizHawk.Emulation.Common.Components.M68000;
using BizHawk.Emulation.Common.Components.Z80; using BizHawk.Emulation.Common.Components.Z80;
using BizHawk.Emulation.Sound;
using Native68000; using Native68000;
namespace BizHawk.Emulation.Cores.Sega.Genesis namespace BizHawk.Emulation.Cores.Sega.Genesis
{ {
public sealed partial class Genesis : IEmulator public sealed partial class Genesis : IEmulator

View File

@ -5,8 +5,8 @@ using System.IO;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components;
using BizHawk.Emulation.Common.Components.Z80; using BizHawk.Emulation.Common.Components.Z80;
using BizHawk.Emulation.Sound;
/***************************************************** /*****************************************************

View File

@ -9,7 +9,7 @@ using BizHawk.Emulation.DiscSystem;
// I decided not to let the perfect be the enemy of the good. // I decided not to let the perfect be the enemy of the good.
// It can always be refactored. It's at least deterministic. // It can always be refactored. It's at least deterministic.
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common
{ {
public sealed class CDAudio : ISoundProvider public sealed class CDAudio : ISoundProvider
{ {

View File

@ -6,7 +6,7 @@ using System.IO;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
// Emulates PSG audio unit of a PC Engine / Turbografx-16 / SuperGrafx. // Emulates PSG audio unit of a PC Engine / Turbografx-16 / SuperGrafx.
// It is embedded on the CPU and doesn't have its own part number. None the less, it is emulated separately from the 6280 CPU. // It is embedded on the CPU and doesn't have its own part number. None the less, it is emulated separately from the 6280 CPU.

View File

@ -5,7 +5,7 @@ using System.Text;
using BizHawk.Common; using BizHawk.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
public class MMC5Audio public class MMC5Audio
{ {

View File

@ -5,11 +5,13 @@ using System.IO;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
// Emulates a Texas Instruments SN76489
// TODO the freq->note translation should be moved to a separate utility class. // TODO the freq->note translation should be moved to a separate utility class.
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
/// <summary>
/// Emulates a Texas Instruments SN76489
/// </summary>
public sealed class SN76489 : ISoundProvider public sealed class SN76489 : ISoundProvider
{ {
public sealed class Channel public sealed class Channel

View File

@ -5,11 +5,13 @@ using System.Text;
using BizHawk.Common; using BizHawk.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
// YM2149F variant /// <summary>
// this implementation is quite incomplete /// YM2149F variant
// http://wiki.nesdev.com/w/index.php/Sunsoft_5B_audio /// this implementation is quite incomplete
/// http://wiki.nesdev.com/w/index.php/Sunsoft_5B_audio
/// </summary>
public class Sunsoft5BAudio public class Sunsoft5BAudio
{ {
class Pulse class Pulse

View File

@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace BizHawk.Emulation.Sound.Utilities namespace BizHawk.Emulation.Common
{ {
/// <summary> /// <summary>
/// wrapper around blargg's unmanaged blip_buf /// wrapper around blargg's unmanaged blip_buf

View File

@ -2,18 +2,18 @@
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common
{ {
// Generates SEMI-synchronous sound, or "buffered asynchronous" sound. // Generates SEMI-synchronous sound, or "buffered asynchronous" sound.
// This class will try as hard as it can to request the correct number of samples on each frame and then // This class will try as hard as it can to request the correct number of samples on each frame and then
// send them out to the sound card as it needs them. // send them out to the sound card as it needs them.
// However, it has minimum/maximum buffer targets and will request smaller or larger frames if it has to. // However, it has minimum/maximum buffer targets and will request smaller or larger frames if it has to.
// The ultimate goal of this strategy is to make MOST frames 100% correct, and if errors must occur, // The ultimate goal of this strategy is to make MOST frames 100% correct, and if errors must occur,
// concentrate it on a single frame, rather than distribute small errors across most frames, as // concentrate it on a single frame, rather than distribute small errors across most frames, as
// distributing error to most frames tends to result in persistently distorted audio, especially when // distributing error to most frames tends to result in persistently distorted audio, especially when
// sample playback is involved. // sample playback is involved.
/* /*
@ -30,15 +30,15 @@ namespace BizHawk.Emulation.Sound
* that and then bypass the BufferedAsync. * that and then bypass the BufferedAsync.
*/ */
public sealed class BufferedAsync : ISoundProvider public sealed class BufferedAsync : ISoundProvider
{ {
public ISoundProvider BaseSoundProvider; public ISoundProvider BaseSoundProvider;
Queue<short> buffer = new Queue<short>(4096); Queue<short> buffer = new Queue<short>(4096);
int SamplesInOneFrame = 1470; int SamplesInOneFrame = 1470;
int TargetExtraSamples = 882; int TargetExtraSamples = 882;
const int MaxExcessSamples = 4096; const int MaxExcessSamples = 4096;
/// <summary> /// <summary>
/// recalculates some internal parameters based on the IEmulator's framerate /// recalculates some internal parameters based on the IEmulator's framerate
@ -52,31 +52,31 @@ namespace BizHawk.Emulation.Sound
public void DiscardSamples() public void DiscardSamples()
{ {
if(BaseSoundProvider != null) if (BaseSoundProvider != null)
BaseSoundProvider.DiscardSamples(); BaseSoundProvider.DiscardSamples();
} }
public int MaxVolume { get; set; } public int MaxVolume { get; set; }
public void GetSamples(short[] samples) public void GetSamples(short[] samples)
{ {
int samplesToGenerate = SamplesInOneFrame; int samplesToGenerate = SamplesInOneFrame;
if (buffer.Count > samples.Length + MaxExcessSamples) if (buffer.Count > samples.Length + MaxExcessSamples)
samplesToGenerate = 0; samplesToGenerate = 0;
if (buffer.Count - samples.Length < TargetExtraSamples) if (buffer.Count - samples.Length < TargetExtraSamples)
samplesToGenerate += SamplesInOneFrame; samplesToGenerate += SamplesInOneFrame;
if (samplesToGenerate + buffer.Count < samples.Length) if (samplesToGenerate + buffer.Count < samples.Length)
samplesToGenerate = samples.Length - buffer.Count; samplesToGenerate = samples.Length - buffer.Count;
var mySamples = new short[samplesToGenerate]; var mySamples = new short[samplesToGenerate];
BaseSoundProvider.GetSamples(mySamples); BaseSoundProvider.GetSamples(mySamples);
for (int i = 0; i < mySamples.Length; i++) for (int i = 0; i < mySamples.Length; i++)
buffer.Enqueue(mySamples[i]); buffer.Enqueue(mySamples[i]);
for (int i = 0; i < samples.Length; i++) for (int i = 0; i < samples.Length; i++)
samples[i] = buffer.Dequeue(); samples[i] = buffer.Dequeue();
} }
} }
} }

View File

@ -5,7 +5,7 @@ using System.Text;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound.Utilities namespace BizHawk.Emulation.Common
{ {
/// <summary> /// <summary>
/// implements a DC block filter on top of an ISoundProvider. rather simple. /// implements a DC block filter on top of an ISoundProvider. rather simple.

View File

@ -5,94 +5,94 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common
{ {
public sealed class Equalizer public sealed class Equalizer
{ {
double lowFilter; double lowFilter;
double lowFilterPole0; double lowFilterPole0;
double lowFilterPole1; double lowFilterPole1;
double lowFilterPole2; double lowFilterPole2;
double lowFilterPole3; double lowFilterPole3;
double highFilter; double highFilter;
double highFilterPole0; double highFilterPole0;
double highFilterPole1; double highFilterPole1;
double highFilterPole2; double highFilterPole2;
double highFilterPole3; double highFilterPole3;
double sampleDataMinus1; double sampleDataMinus1;
double sampleDataMinus2; double sampleDataMinus2;
double sampleDataMinus3; double sampleDataMinus3;
double lowGain; double lowGain;
double midGain; double midGain;
double highGain; double highGain;
const double sampleRate = 44100.0; const double sampleRate = 44100.0;
const double verySmallAmount = (1.0 / 4294967295.0); const double verySmallAmount = (1.0 / 4294967295.0);
double lowfreq; double lowfreq;
public double LowFreqCutoff public double LowFreqCutoff
{ {
get { return lowfreq; } get { return lowfreq; }
set set
{ {
lowfreq = value; lowfreq = value;
lowFilter = 2 * Math.Sin(Math.PI * (lowfreq / sampleRate)); lowFilter = 2 * Math.Sin(Math.PI * (lowfreq / sampleRate));
} }
} }
double highfreq; double highfreq;
public double HighFreqCutoff public double HighFreqCutoff
{ {
get { return highfreq; } get { return highfreq; }
set set
{ {
highfreq = value; highfreq = value;
highFilter = 2 * Math.Sin(Math.PI * (highfreq / sampleRate)); highFilter = 2 * Math.Sin(Math.PI * (highfreq / sampleRate));
} }
} }
public Equalizer(double lowFreq=880, double highFreq=5000) public Equalizer(double lowFreq = 880, double highFreq = 5000)
{ {
lowGain = 1.3; lowGain = 1.3;
midGain = 0.9; midGain = 0.9;
highGain = 1.3; highGain = 1.3;
LowFreqCutoff = lowFreq; LowFreqCutoff = lowFreq;
HighFreqCutoff = highFreq; HighFreqCutoff = highFreq;
} }
public short EqualizeSample(short sample) public short EqualizeSample(short sample)
{ {
lowFilterPole0 += (lowFilter * (sample - lowFilterPole0)) + verySmallAmount; lowFilterPole0 += (lowFilter * (sample - lowFilterPole0)) + verySmallAmount;
lowFilterPole1 += lowFilter * (lowFilterPole0 - lowFilterPole1); lowFilterPole1 += lowFilter * (lowFilterPole0 - lowFilterPole1);
lowFilterPole2 += lowFilter * (lowFilterPole1 - lowFilterPole2); lowFilterPole2 += lowFilter * (lowFilterPole1 - lowFilterPole2);
lowFilterPole3 += lowFilter * (lowFilterPole2 - lowFilterPole3); lowFilterPole3 += lowFilter * (lowFilterPole2 - lowFilterPole3);
double l = lowFilterPole3; double l = lowFilterPole3;
highFilterPole0 += (highFilter * (sample - highFilterPole0)) + verySmallAmount; highFilterPole0 += (highFilter * (sample - highFilterPole0)) + verySmallAmount;
highFilterPole1 += highFilter * (highFilterPole0 - highFilterPole1); highFilterPole1 += highFilter * (highFilterPole0 - highFilterPole1);
highFilterPole2 += highFilter * (highFilterPole1 - highFilterPole2); highFilterPole2 += highFilter * (highFilterPole1 - highFilterPole2);
highFilterPole3 += highFilter * (highFilterPole2 - highFilterPole3); highFilterPole3 += highFilter * (highFilterPole2 - highFilterPole3);
double h = sampleDataMinus3 - highFilterPole3; double h = sampleDataMinus3 - highFilterPole3;
double m = sample - (h + l); double m = sample - (h + l);
l *= lowGain; l *= lowGain;
m *= midGain; m *= midGain;
h *= highGain; h *= highGain;
sampleDataMinus3 = sampleDataMinus2; sampleDataMinus3 = sampleDataMinus2;
sampleDataMinus2 = sampleDataMinus1; sampleDataMinus2 = sampleDataMinus1;
sampleDataMinus1 = sample; sampleDataMinus1 = sample;
return (short) (l + m + h); return (short)(l + m + h);
} }
public void Equalize(short[] samples) public void Equalize(short[] samples)
{ {
for (int i = 0; i < samples.Length; i++) for (int i = 0; i < samples.Length; i++)
samples[i] = EqualizeSample(samples[i]); samples[i] = EqualizeSample(samples[i]);
} }
} }
} }

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common
{ {
/// <summary> /// <summary>
/// uses Metaspu to have an ISyncSoundProvider input to a ISoundProvider /// uses Metaspu to have an ISyncSoundProvider input to a ISoundProvider
@ -36,8 +36,6 @@ namespace BizHawk.Emulation.Sound
public int MaxVolume { get; set; } public int MaxVolume { get; set; }
} }
public class MetaspuSoundProvider : ISoundProvider public class MetaspuSoundProvider : ISoundProvider
{ {
public ISynchronizingAudioBuffer buffer; public ISynchronizingAudioBuffer buffer;
@ -46,17 +44,18 @@ namespace BizHawk.Emulation.Sound
buffer = Metaspu.metaspu_construct(method); buffer = Metaspu.metaspu_construct(method);
} }
public MetaspuSoundProvider() : this(ESynchMethod.ESynchMethod_V) public MetaspuSoundProvider()
: this(ESynchMethod.ESynchMethod_V)
{ {
} }
short[] pullBuffer = new short[1470]; short[] pullBuffer = new short[1470];
public void PullSamples(ISoundProvider source) public void PullSamples(ISoundProvider source)
{ {
Array.Clear(pullBuffer, 0, 1470); Array.Clear(pullBuffer, 0, 1470);
source.GetSamples(pullBuffer); source.GetSamples(pullBuffer);
buffer.enqueue_samples(pullBuffer, 735); buffer.enqueue_samples(pullBuffer, 735);
} }
public void GetSamples(short[] samples) public void GetSamples(short[] samples)
{ {
@ -68,8 +67,8 @@ namespace BizHawk.Emulation.Sound
buffer.clear(); buffer.clear();
} }
public int MaxVolume { get; set; } public int MaxVolume { get; set; }
} }
public interface ISynchronizingAudioBuffer public interface ISynchronizingAudioBuffer
{ {
@ -90,7 +89,7 @@ namespace BizHawk.Emulation.Sound
ESynchMethod_N, //nitsuja's ESynchMethod_N, //nitsuja's
ESynchMethod_Z, //zero's ESynchMethod_Z, //zero's
//ESynchMethod_P, //PCSX2 spu2-x //ohno! not available yet in c# //ESynchMethod_P, //PCSX2 spu2-x //ohno! not available yet in c#
ESynchMethod_V // vecna ESynchMethod_V // vecna
}; };
public static class Metaspu public static class Metaspu
@ -103,8 +102,8 @@ namespace BizHawk.Emulation.Sound
return new ZeromusSynchronizer(); return new ZeromusSynchronizer();
case ESynchMethod.ESynchMethod_N: case ESynchMethod.ESynchMethod_N:
return new NitsujaSynchronizer(); return new NitsujaSynchronizer();
case ESynchMethod.ESynchMethod_V: case ESynchMethod.ESynchMethod_V:
return new VecnaSynchronizer(); return new VecnaSynchronizer();
default: default:
return new NitsujaSynchronizer(); return new NitsujaSynchronizer();
} }
@ -151,7 +150,7 @@ namespace BizHawk.Emulation.Sound
//returns the number of samples actually supplied, which may not match the number requested //returns the number of samples actually supplied, which may not match the number requested
public int output_samples(short[] buf, int samples_requested) public int output_samples(short[] buf, int samples_requested)
{ {
int ctr=0; int ctr = 0;
int done = 0; int done = 0;
if (!mixqueue_go) if (!mixqueue_go)
{ {
@ -208,7 +207,7 @@ namespace BizHawk.Emulation.Sound
size = 0; size = 0;
} }
public void enqueue(short left, short right) public void enqueue(short left, short right)
{ {
buffer.Enqueue(left); buffer.Enqueue(left);
buffer.Enqueue(right); buffer.Enqueue(right);
@ -232,13 +231,15 @@ namespace BizHawk.Emulation.Sound
//static int ctr=0; ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate); //static int ctr=0; ctr++; if((ctr&127)==0) printf("avg size: %f curr size: %d rate: %f\n",averageSize,size,rate);
{ {
float targetRate; float targetRate;
if(averageSize < targetLatency) if (averageSize < targetLatency)
{ {
targetRate = 1.0f - (targetLatency-averageSize)/kAverageSize; targetRate = 1.0f - (targetLatency - averageSize) / kAverageSize;
} }
else if(averageSize > targetLatency) { else if (averageSize > targetLatency)
targetRate = 1.0f + (averageSize-targetLatency)/kAverageSize; {
} else targetRate = 1.0f; targetRate = 1.0f + (averageSize - targetLatency) / kAverageSize;
}
else targetRate = 1.0f;
//rate = moveValueTowards(rate,targetRate,0.001f); //rate = moveValueTowards(rate,targetRate,0.001f);
rate = targetRate; rate = targetRate;
@ -253,11 +254,13 @@ namespace BizHawk.Emulation.Sound
{ {
left = right = 0; left = right = 0;
addStatistic(); addStatistic();
if(size==0) { return; } if (size == 0) { return; }
cursor += rate; cursor += rate;
while(cursor>1.0f) { while (cursor > 1.0f)
{
cursor -= 1.0f; cursor -= 1.0f;
if(size>0) { if (size > 0)
{
curr[0] = buffer.Dequeue(); curr[0] = buffer.Dequeue();
curr[1] = buffer.Dequeue(); curr[1] = buffer.Dequeue();
size--; size--;
@ -282,9 +285,9 @@ namespace BizHawk.Emulation.Sound
// returns values going between 0 and y-1 in a saw wave pattern, based on x // returns values going between 0 and y-1 in a saw wave pattern, based on x
static int pingpong(int x, int y) static int pingpong(int x, int y)
{ {
x %= 2*y; x %= 2 * y;
if(x >= y) if (x >= y)
x = 2*y - x - 1; x = 2 * y - x - 1;
return x; return x;
// in case we want to switch to odd buffer sizes for more sharpness // in case we want to switch to odd buffer sizes for more sharpness
@ -294,11 +297,11 @@ namespace BizHawk.Emulation.Sound
//return x; //return x;
} }
static ssamp crossfade (ssamp lhs, ssamp rhs, int cur, int start, int end) static ssamp crossfade(ssamp lhs, ssamp rhs, int cur, int start, int end)
{ {
if(cur <= start) if (cur <= start)
return lhs; return lhs;
if(cur >= end) if (cur >= end)
return rhs; return rhs;
// in case we want sine wave interpolation instead of linear here // in case we want sine wave interpolation instead of linear here
@ -312,7 +315,7 @@ namespace BizHawk.Emulation.Sound
int lrv = ((int)lhs.l * outNum + (int)rhs.l * inNum) / denom; int lrv = ((int)lhs.l * outNum + (int)rhs.l * inNum) / denom;
int rrv = ((int)lhs.r * outNum + (int)rhs.r * inNum) / denom; int rrv = ((int)lhs.r * outNum + (int)rhs.r * inNum) / denom;
return new ssamp((short)lrv,(short)rrv); return new ssamp((short)lrv, (short)rrv);
} }
public void clear() public void clear()
@ -328,8 +331,8 @@ namespace BizHawk.Emulation.Sound
static void emit_samples(short[] outbuf, ref int outcursor, ssamp[] samplebuf, int incursor, int samples) static void emit_samples(short[] outbuf, ref int outcursor, ssamp[] samplebuf, int incursor, int samples)
{ {
for(int i=0;i<samples;i++) for (int i = 0; i < samples; i++)
emit_sample(outbuf,ref outcursor, samplebuf[i+incursor]); emit_sample(outbuf, ref outcursor, samplebuf[i + incursor]);
} }
static short abs(short value) static short abs(short value)
@ -347,345 +350,347 @@ namespace BizHawk.Emulation.Sound
public void enqueue_samples(short[] buf, int samples_provided) public void enqueue_samples(short[] buf, int samples_provided)
{ {
int cursor = 0; int cursor = 0;
for(int i=0;i<samples_provided;i++) for (int i = 0; i < samples_provided; i++)
{ {
sampleQueue.Add(new ssamp(buf[cursor+0],buf[cursor+1])); sampleQueue.Add(new ssamp(buf[cursor + 0], buf[cursor + 1]));
cursor += 2; cursor += 2;
} }
} }
public void enqueue_sample(short left, short right) public void enqueue_sample(short left, short right)
{ {
sampleQueue.Add(new ssamp(left,right)); sampleQueue.Add(new ssamp(left, right));
} }
public int output_samples(short[] buf, int samples_requested) public int output_samples(short[] buf, int samples_requested)
{ {
Console.WriteLine("{0} {1}", samples_requested, sampleQueue.Count); //add this line Console.WriteLine("{0} {1}", samples_requested, sampleQueue.Count); //add this line
int bufcursor = 0; int bufcursor = 0;
int audiosize = samples_requested; int audiosize = samples_requested;
int queued = sampleQueue.Count; int queued = sampleQueue.Count;
// I am too lazy to deal with odd numbers // I am too lazy to deal with odd numbers
audiosize &= ~1; audiosize &= ~1;
queued &= ~1; queued &= ~1;
if(queued > 0x200 && audiosize > 0) // is there any work to do? if (queued > 0x200 && audiosize > 0) // is there any work to do?
{
// are we going at normal speed?
// or more precisely, are the input and output queues/buffers of similar size?
if(queued > 900 || audiosize > queued * 2)
{ {
// not normal speed. we have to resample it somehow in this case. // are we going at normal speed?
if(audiosize <= queued) // or more precisely, are the input and output queues/buffers of similar size?
if (queued > 900 || audiosize > queued * 2)
{ {
// fast forward speed // not normal speed. we have to resample it somehow in this case.
// this is the easy case, just crossfade it and it sounds ok if (audiosize <= queued)
for(int i = 0; i < audiosize; i++)
{ {
int j = i + queued - audiosize; // fast forward speed
ssamp outsamp = crossfade(sampleQueue[i],sampleQueue[j], i,0,audiosize); // this is the easy case, just crossfade it and it sounds ok
emit_sample(buf,ref bufcursor,outsamp); for (int i = 0; i < audiosize; i++)
}
}
else
{
// slow motion speed
// here we take a very different approach,
// instead of crossfading it, we select a single sample from the queue
// and make sure that the index we use to select a sample is constantly moving
// and that it starts at the first sample in the queue and ends on the last one.
//
// hopefully the index doesn't move discontinuously or we'll get slight crackling
// (there might still be a minor bug here that causes this occasionally)
//
// here's a diagram of how the index we sample from moves:
//
// queued (this axis represents the index we sample from. the top means the end of the queue)
// ^
// | --> audiosize (this axis represents the output index we write to, right meaning forward in output time/position)
// | A C C end
// A A B C C C
// A A A B C C C
// A A A B C C
// A A C
// start
//
// yes, this means we are spending some stretches of time playing the sound backwards,
// but the stretches are short enough that this doesn't sound weird.
// this lets us avoid most crackling problems due to the endpoints matching up.
// first calculate a shorter-than-full window
// that has minimal slope at the endpoints
// (to further reduce crackling, especially in sine waves)
int beststart = 0, extraAtEnd = 0;
{
int bestend = queued;
const int worstdiff = 99999999;
int beststartdiff = worstdiff;
int bestenddiff = worstdiff;
for(int i = 0; i < 128; i+=2)
{ {
int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r); int j = i + queued - audiosize;
if(diff < beststartdiff) ssamp outsamp = crossfade(sampleQueue[i], sampleQueue[j], i, 0, audiosize);
{ emit_sample(buf, ref bufcursor, outsamp);
beststartdiff = diff;
beststart = i;
}
} }
for(int i = queued-3; i > queued-3-128; i-=2) }
else
{
// slow motion speed
// here we take a very different approach,
// instead of crossfading it, we select a single sample from the queue
// and make sure that the index we use to select a sample is constantly moving
// and that it starts at the first sample in the queue and ends on the last one.
//
// hopefully the index doesn't move discontinuously or we'll get slight crackling
// (there might still be a minor bug here that causes this occasionally)
//
// here's a diagram of how the index we sample from moves:
//
// queued (this axis represents the index we sample from. the top means the end of the queue)
// ^
// | --> audiosize (this axis represents the output index we write to, right meaning forward in output time/position)
// | A C C end
// A A B C C C
// A A A B C C C
// A A A B C C
// A A C
// start
//
// yes, this means we are spending some stretches of time playing the sound backwards,
// but the stretches are short enough that this doesn't sound weird.
// this lets us avoid most crackling problems due to the endpoints matching up.
// first calculate a shorter-than-full window
// that has minimal slope at the endpoints
// (to further reduce crackling, especially in sine waves)
int beststart = 0, extraAtEnd = 0;
{ {
int diff = abs(sampleQueue[i].l - sampleQueue[i+1].l) + abs(sampleQueue[i].r - sampleQueue[i+1].r); int bestend = queued;
if(diff < bestenddiff) const int worstdiff = 99999999;
int beststartdiff = worstdiff;
int bestenddiff = worstdiff;
for (int i = 0; i < 128; i += 2)
{ {
bestenddiff = diff; int diff = abs(sampleQueue[i].l - sampleQueue[i + 1].l) + abs(sampleQueue[i].r - sampleQueue[i + 1].r);
bestend = i+1; if (diff < beststartdiff)
{
beststartdiff = diff;
beststart = i;
}
}
for (int i = queued - 3; i > queued - 3 - 128; i -= 2)
{
int diff = abs(sampleQueue[i].l - sampleQueue[i + 1].l) + abs(sampleQueue[i].r - sampleQueue[i + 1].r);
if (diff < bestenddiff)
{
bestenddiff = diff;
bestend = i + 1;
}
}
extraAtEnd = queued - bestend;
queued = bestend - beststart;
int oksize = queued;
while (oksize + queued * 2 + beststart + extraAtEnd <= samples_requested)
oksize += queued * 2;
audiosize = oksize;
for (int x = 0; x < beststart; x++)
{
emit_sample(buf, ref bufcursor, sampleQueue[x]);
}
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart);
sampleQueue.RemoveRange(0, beststart);
//zero 08-nov-2010: did i do this right?
}
int midpointX = audiosize >> 1;
int midpointY = queued >> 1;
// all we need to do here is calculate the X position of the leftmost "B" in the above diagram.
// TODO: we should calculate it with a simple equation like
// midpointXOffset = min(something,somethingElse);
// but it's a little difficult to work it out exactly
// so here's a stupid search for the value for now:
int prevA = 999999;
int midpointXOffset = queued / 2;
while (true)
{
int a = abs(pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset;
if (((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999)
{
if (((a + prevA) & 1) != 0) // there's some sort of off-by-one problem with this search since we're moving diagonally...
midpointXOffset++; // but this fixes it most of the time...
break; // found it
}
prevA = a;
midpointXOffset--;
if (midpointXOffset < 0)
{
midpointXOffset = 0;
break; // failed to find it. the two sides probably meet exactly in the center.
} }
} }
extraAtEnd = queued - bestend; int leftMidpointX = midpointX - midpointXOffset;
queued = bestend - beststart; int rightMidpointX = midpointX + midpointXOffset;
int leftMidpointY = pingpong(leftMidpointX, queued);
int rightMidpointY = (queued - 1) - pingpong((int)audiosize - 1 - rightMidpointX + queued * 2, queued);
int oksize = queued; // output the left almost-half of the sound (section "A")
while(oksize + queued*2 + beststart + extraAtEnd <= samples_requested) for (int x = 0; x < leftMidpointX; x++)
oksize += queued*2;
audiosize = oksize;
for(int x = 0; x < beststart; x++)
{ {
emit_sample(buf,ref bufcursor,sampleQueue[x]); int i = pingpong(x, queued);
emit_sample(buf, ref bufcursor, sampleQueue[i]);
} }
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart);
sampleQueue.RemoveRange(0, beststart);
//zero 08-nov-2010: did i do this right?
}
// output the middle stretch (section "B")
int y = leftMidpointY;
int dyMidLeft = (leftMidpointY < midpointY) ? 1 : -1;
int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1;
for (int x = leftMidpointX; x < midpointX; x++, y += dyMidLeft)
emit_sample(buf, ref bufcursor, sampleQueue[y]);
for (int x = midpointX; x < rightMidpointX; x++, y += dyMidRight)
emit_sample(buf, ref bufcursor, sampleQueue[y]);
int midpointX = audiosize >> 1; // output the end of the queued sound (section "C")
int midpointY = queued >> 1; for (int x = rightMidpointX; x < audiosize; x++)
// all we need to do here is calculate the X position of the leftmost "B" in the above diagram.
// TODO: we should calculate it with a simple equation like
// midpointXOffset = min(something,somethingElse);
// but it's a little difficult to work it out exactly
// so here's a stupid search for the value for now:
int prevA = 999999;
int midpointXOffset = queued/2;
while(true)
{
int a = abs(pingpong(midpointX - midpointXOffset, queued) - midpointY) - midpointXOffset;
if(((a > 0) != (prevA > 0) || (a < 0) != (prevA < 0)) && prevA != 999999)
{ {
if(((a + prevA)&1)!=0) // there's some sort of off-by-one problem with this search since we're moving diagonally... int i = (queued - 1) - pingpong((int)audiosize - 1 - x + queued * 2, queued);
midpointXOffset++; // but this fixes it most of the time... emit_sample(buf, ref bufcursor, sampleQueue[i]);
break; // found it
} }
prevA = a;
midpointXOffset--; for (int x = 0; x < extraAtEnd; x++)
if(midpointXOffset < 0)
{ {
midpointXOffset = 0; int i = queued + x;
break; // failed to find it. the two sides probably meet exactly in the center. emit_sample(buf, ref bufcursor, sampleQueue[i]);
} }
} queued += extraAtEnd;
audiosize += beststart + extraAtEnd;
} //end else
int leftMidpointX = midpointX - midpointXOffset;
int rightMidpointX = midpointX + midpointXOffset;
int leftMidpointY = pingpong(leftMidpointX, queued);
int rightMidpointY = (queued-1) - pingpong((int)audiosize-1 - rightMidpointX + queued*2, queued);
// output the left almost-half of the sound (section "A")
for(int x = 0; x < leftMidpointX; x++)
{
int i = pingpong(x, queued);
emit_sample(buf,ref bufcursor,sampleQueue[i]);
}
// output the middle stretch (section "B")
int y = leftMidpointY;
int dyMidLeft = (leftMidpointY < midpointY) ? 1 : -1;
int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1;
for(int x = leftMidpointX; x < midpointX; x++, y+=dyMidLeft)
emit_sample(buf,ref bufcursor,sampleQueue[y]);
for(int x = midpointX; x < rightMidpointX; x++, y+=dyMidRight)
emit_sample(buf, ref bufcursor, sampleQueue[y]);
// output the end of the queued sound (section "C")
for(int x = rightMidpointX; x < audiosize; x++)
{
int i = (queued-1) - pingpong((int)audiosize-1 - x + queued*2, queued);
emit_sample(buf,ref bufcursor,sampleQueue[i]);
}
for(int x = 0; x < extraAtEnd; x++)
{
int i = queued + x;
emit_sample(buf,ref bufcursor,sampleQueue[i]);
}
queued += extraAtEnd;
audiosize += beststart + extraAtEnd;
} //end else
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
sampleQueue.RemoveRange(0, queued);
//zero 08-nov-2010: did i do this right?
return audiosize;
}
else
{
// normal speed
// just output the samples straightforwardly.
//
// at almost-full speeds (like 50/60 FPS)
// what will happen is that we rapidly fluctuate between entering this branch
// and entering the "slow motion speed" branch above.
// but that's ok! because all of these branches sound similar enough that we can get away with it.
// so the two cases actually complement each other.
if(audiosize >= queued)
{
emit_samples(buf,ref bufcursor, sampleQueue.ToArray(),0,queued);
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); //sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
sampleQueue.RemoveRange(0, queued); sampleQueue.RemoveRange(0, queued);
//zero 08-nov-2010: did i do this right? //zero 08-nov-2010: did i do this right?
return queued; return audiosize;
} }
else else
{ {
emit_samples(buf,ref bufcursor, sampleQueue.ToArray(),0,audiosize); // normal speed
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize); // just output the samples straightforwardly.
sampleQueue.RemoveRange(0, audiosize); //
//zero 08-nov-2010: did i do this right? // at almost-full speeds (like 50/60 FPS)
return audiosize; // what will happen is that we rapidly fluctuate between entering this branch
} // and entering the "slow motion speed" branch above.
// but that's ok! because all of these branches sound similar enough that we can get away with it.
// so the two cases actually complement each other.
} //end normal speed if (audiosize >= queued)
{
emit_samples(buf, ref bufcursor, sampleQueue.ToArray(), 0, queued);
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
sampleQueue.RemoveRange(0, queued);
//zero 08-nov-2010: did i do this right?
return queued;
}
else
{
emit_samples(buf, ref bufcursor, sampleQueue.ToArray(), 0, audiosize);
//sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize);
sampleQueue.RemoveRange(0, audiosize);
//zero 08-nov-2010: did i do this right?
return audiosize;
}
} //end if there is any work to do } //end normal speed
else
} //end if there is any work to do
else
{
return 0;
}
} //output_samples
}; //NitsujaSynchronizer
class VecnaSynchronizer : ISynchronizingAudioBuffer
{
// vecna's attempt at a fully synchronous sound provider.
// It's similar in philosophy to my "BufferedAsync" provider, but BufferedAsync is not
// fully synchronous.
// Like BufferedAsync, it tries to make most frames 100% correct and just suck it up
// periodically and have a big bad-sounding mistake frame if it has to.
// It is significantly less ambitious and elaborate than the other methods.
// We'll see if it works better or not!
// It has a min and maximum amount of excess buffer to deal with minor overflows.
// When fastforwarding, it will discard samples above the maximum excess buffer.
// When underflowing, it will attempt to resample to a certain threshhold.
// If it underflows beyond that threshhold, it will give up and output silence.
// Since it has done this, it will go ahead and generate some excess silence in order
// to restock its excess buffer.
struct Sample
{ {
return 0; public short left, right;
public Sample(short l, short r)
{
left = l;
right = r;
}
} }
} //output_samples Queue<Sample> buffer;
Sample[] resampleBuffer;
const int SamplesInOneFrame = 735;
const int MaxExcessSamples = 2048;
}; //NitsujaSynchronizer public VecnaSynchronizer()
{
buffer = new Queue<Sample>(2048);
resampleBuffer = new Sample[2730]; // 2048 * 1.25
class VecnaSynchronizer : ISynchronizingAudioBuffer // Give us a little buffer wiggle-room
{ for (int i = 0; i < 367; i++)
// vecna's attempt at a fully synchronous sound provider. buffer.Enqueue(new Sample(0, 0));
// It's similar in philosophy to my "BufferedAsync" provider, but BufferedAsync is not }
// fully synchronous.
// Like BufferedAsync, it tries to make most frames 100% correct and just suck it up public void enqueue_samples(short[] buf, int samples_provided)
// periodically and have a big bad-sounding mistake frame if it has to. {
int ctr = 0;
for (int i = 0; i < samples_provided; i++)
{
short left = buf[ctr++];
short right = buf[ctr++];
enqueue_sample(left, right);
}
}
// It is significantly less ambitious and elaborate than the other methods. public void enqueue_sample(short left, short right)
// We'll see if it works better or not! {
if (buffer.Count >= MaxExcessSamples - 1)
{
// if buffer is overfull, dequeue old samples to make room for new samples.
buffer.Dequeue();
}
buffer.Enqueue(new Sample(left, right));
}
// It has a min and maximum amount of excess buffer to deal with minor overflows. public void clear()
// When fastforwarding, it will discard samples above the maximum excess buffer. {
buffer.Clear();
}
// When underflowing, it will attempt to resample to a certain threshhold. public int output_samples(short[] buf, int samples_requested)
// If it underflows beyond that threshhold, it will give up and output silence. {
// Since it has done this, it will go ahead and generate some excess silence in order if (samples_requested > buffer.Count)
// to restock its excess buffer. {
// underflow!
if (buffer.Count > samples_requested * 3 / 4)
{
// if we're within 75% of target, then I guess we suck it up and resample.
// we sample in a goofy way, we could probably do it a bit smarter, if we cared more.
struct Sample int samples_available = buffer.Count;
{ for (int i = 0; buffer.Count > 0; i++)
public short left, right; resampleBuffer[i] = buffer.Dequeue();
public Sample(short l, short r)
{
left = l;
right = r;
}
}
Queue<Sample> buffer; int index = 0;
Sample[] resampleBuffer; for (int i = 0; i < samples_requested; i++)
{
const int SamplesInOneFrame = 735; Sample sample = resampleBuffer[i * samples_available / samples_requested];
const int MaxExcessSamples = 2048; buf[index++] += sample.left;
buf[index++] += sample.right;
public VecnaSynchronizer() }
{ }
buffer = new Queue<Sample>(2048); else
resampleBuffer = new Sample[2730]; // 2048 * 1.25 {
// we're outside of a "reasonable" underflow. Give up and output silence.
// Give us a little buffer wiggle-room // Do nothing. The whole frame will be excess buffer.
for (int i=0; i<367; i++) }
buffer.Enqueue(new Sample(0,0)); }
} else
{
public void enqueue_samples(short[] buf, int samples_provided) // normal operation
{ //Console.WriteLine("samples in buffer {0}, requested {1}", buffer.Count, samples_requested);
int ctr = 0; int index = 0;
for (int i = 0; i < samples_provided; i++) for (int i = 0; i < samples_requested && buffer.Count > 0; i++)
{ {
short left = buf[ctr++]; Sample sample = buffer.Dequeue();
short right = buf[ctr++]; buf[index++] += sample.left;
enqueue_sample(left, right); buf[index++] += sample.right;
} }
} }
return samples_requested;
public void enqueue_sample(short left, short right) }
{ }
if (buffer.Count >= MaxExcessSamples - 1)
{
// if buffer is overfull, dequeue old samples to make room for new samples.
buffer.Dequeue();
}
buffer.Enqueue(new Sample(left, right));
}
public void clear()
{
buffer.Clear();
}
public int output_samples(short[] buf, int samples_requested)
{
if (samples_requested > buffer.Count)
{
// underflow!
if (buffer.Count > samples_requested * 3 / 4)
{
// if we're within 75% of target, then I guess we suck it up and resample.
// we sample in a goofy way, we could probably do it a bit smarter, if we cared more.
int samples_available = buffer.Count;
for (int i = 0; buffer.Count > 0; i++)
resampleBuffer[i] = buffer.Dequeue();
int index = 0;
for (int i = 0; i<samples_requested; i++)
{
Sample sample = resampleBuffer[i*samples_available/samples_requested];
buf[index++] += sample.left;
buf[index++] += sample.right;
}
} else {
// we're outside of a "reasonable" underflow. Give up and output silence.
// Do nothing. The whole frame will be excess buffer.
}
}
else
{
// normal operation
//Console.WriteLine("samples in buffer {0}, requested {1}", buffer.Count, samples_requested);
int index = 0;
for (int i = 0; i < samples_requested && buffer.Count > 0; i++)
{
Sample sample = buffer.Dequeue();
buf[index++] += sample.left;
buf[index++] += sample.right;
}
}
return samples_requested;
}
}
} }

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common
{ {
// This is a straightforward class to mix/chain multiple ISoundProvider sources. // This is a straightforward class to mix/chain multiple ISoundProvider sources.

View File

@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound.Utilities namespace BizHawk.Emulation.Common
{ {
/// <summary> /// <summary>
/// junk wrapper around LibSpeexDSP. quite inefficient. will be replaced /// junk wrapper around LibSpeexDSP. quite inefficient. will be replaced

View File

@ -1,53 +1,53 @@
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common
{ {
public static class Waves public static class Waves
{ {
public static short[] SquareWave; public static short[] SquareWave;
public static short[] ImperfectSquareWave; public static short[] ImperfectSquareWave;
public static short[] NoiseWave; public static short[] NoiseWave;
public static short[] PeriodicWave16; public static short[] PeriodicWave16;
public static void InitWaves() public static void InitWaves()
{ {
SquareWave = new short[] SquareWave = new short[]
{ {
-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767
}; };
ImperfectSquareWave = new short[] ImperfectSquareWave = new short[]
{ {
-32768,-30145,-27852,-26213,-24902,-23592,-22282,-20971,-19988,-19005,-18350,-17694,-17366,-17039,-16711,-16711, -32768,-30145,-27852,-26213,-24902,-23592,-22282,-20971,-19988,-19005,-18350,-17694,-17366,-17039,-16711,-16711,
32767, 30145, 27852, 26213, 24902, 23592, 22282, 20971, 19988, 19005, 18350, 17694, 17366, 17039, 16711, 16711 32767, 30145, 27852, 26213, 24902, 23592, 22282, 20971, 19988, 19005, 18350, 17694, 17366, 17039, 16711, 16711
}; };
PeriodicWave16 = new short[] { 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; PeriodicWave16 = new short[] { 32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
NoiseWave = new short[0x1000]; NoiseWave = new short[0x1000];
var rnd = new System.Random(unchecked((int)0xDEADBEEF)); var rnd = new System.Random(unchecked((int)0xDEADBEEF));
for (int i = 0; i < NoiseWave.Length; i++) for (int i = 0; i < NoiseWave.Length; i++)
{ {
int r = rnd.Next(); int r = rnd.Next();
if ((r & 1) > 0) if ((r & 1) > 0)
NoiseWave[i] = short.MaxValue; NoiseWave[i] = short.MaxValue;
} }
/*TriangleWave = new short[512]; /*TriangleWave = new short[512];
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
TriangleWave[i] = (short)((ushort.MaxValue*i/256)-short.MinValue); TriangleWave[i] = (short)((ushort.MaxValue*i/256)-short.MinValue);
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
TriangleWave[256+i] = TriangleWave[256-i]; TriangleWave[256+i] = TriangleWave[256-i];
TriangleWave[256] = short.MaxValue; TriangleWave[256] = short.MaxValue;
SawWave = new short[512]; SawWave = new short[512];
for (int i = 0; i < 512; i++) for (int i = 0; i < 512; i++)
SawWave[i] = (short)((ushort.MaxValue * i / 512) - short.MinValue); SawWave[i] = (short)((ushort.MaxValue * i / 512) - short.MinValue);
SineWave = new short[1024]; SineWave = new short[1024];
for (int i=0; i<1024; i++) for (int i=0; i<1024; i++)
{ {
SineWave[i] = (short) (Math.Sin(i*Math.PI*2/1024d)*32767); SineWave[i] = (short) (Math.Sin(i*Math.PI*2/1024d)*32767);
}*/ }*/
} }
} }
} }

View File

@ -5,7 +5,7 @@ using System.Text;
using BizHawk.Common; using BizHawk.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
public class VRC6Alt public class VRC6Alt
{ {

View File

@ -1,16 +1,15 @@
using System; // Credits:
// Credits:
// Original emulator written by Mitsutaka Okazaki 2001. // Original emulator written by Mitsutaka Okazaki 2001.
// Original conversion to C# by Ben Ryves. // Original conversion to C# by Ben Ryves.
// TODO The savestate support here is very simplistic and incomplete. However, this does not result in desyncs as the YM2413 is write-only. // TODO The savestate support here is very simplistic and incomplete. However, this does not result in desyncs as the YM2413 is write-only.
// TODO This should eventually be replaced, due to 1) uncertain licensing terms 2) This is not a native C# implementation, but a naive port. // TODO This should eventually be replaced, due to 1) uncertain licensing terms 2) This is not a native C# implementation, but a naive port.
using System;
using BizHawk.Common; using BizHawk.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
public sealed class YM2413 : ISoundProvider public sealed class YM2413 : ISoundProvider
{ {

View File

@ -5,7 +5,7 @@ using System.IO;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Sound namespace BizHawk.Emulation.Common.Components
{ {
// ====================================================================== // ======================================================================
// Yamaha YM2612 Emulation Core // Yamaha YM2612 Emulation Core