2012-11-27 05:11:40 +00:00
|
|
|
|
using System;
|
2013-11-14 19:33:13 +00:00
|
|
|
|
|
2013-11-04 00:36:15 +00:00
|
|
|
|
using BizHawk.Common;
|
2013-11-14 19:33:13 +00:00
|
|
|
|
using BizHawk.Emulation.Common;
|
2012-11-27 05:11:40 +00:00
|
|
|
|
|
2013-10-27 17:07:37 +00:00
|
|
|
|
#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 219 //adelikat: Disable dumb warnings until this file is complete
|
|
|
|
|
|
2014-10-03 21:04:37 +00:00
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
2012-11-27 05:11:40 +00:00
|
|
|
|
{
|
2013-08-24 17:30:46 +00:00
|
|
|
|
sealed public partial class Sid
|
2012-11-27 05:11:40 +00:00
|
|
|
|
{
|
2012-11-30 06:41:02 +00:00
|
|
|
|
|
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
2013-11-14 19:33:13 +00:00
|
|
|
|
public SpeexResampler resampler;
|
2012-12-10 22:51:02 +00:00
|
|
|
|
|
2013-08-24 17:30:46 +00:00
|
|
|
|
static int[] syncNextTable = new int[] { 1, 2, 0 };
|
|
|
|
|
static int[] syncPrevTable = new int[] { 2, 0, 1 };
|
|
|
|
|
|
2013-11-14 19:33:13 +00:00
|
|
|
|
int cachedCycles;
|
2013-08-24 17:30:46 +00:00
|
|
|
|
bool disableVoice3;
|
|
|
|
|
int[] envelopeOutput;
|
|
|
|
|
Envelope[] envelopes;
|
|
|
|
|
bool[] filterEnable;
|
|
|
|
|
int filterFrequency;
|
|
|
|
|
int filterResonance;
|
|
|
|
|
bool filterSelectBandPass;
|
|
|
|
|
bool filterSelectLoPass;
|
|
|
|
|
bool filterSelectHiPass;
|
2013-11-14 19:33:13 +00:00
|
|
|
|
int mixer;
|
|
|
|
|
int potCounter;
|
2013-08-24 17:30:46 +00:00
|
|
|
|
int potX;
|
2013-11-14 19:33:13 +00:00
|
|
|
|
int potY;
|
|
|
|
|
short sample;
|
|
|
|
|
int[] voiceOutput;
|
2013-08-24 17:30:46 +00:00
|
|
|
|
Voice[] voices;
|
|
|
|
|
int volume;
|
|
|
|
|
int[][] waveformTable;
|
2012-11-30 06:41:02 +00:00
|
|
|
|
|
2012-12-05 21:07:51 +00:00
|
|
|
|
public Func<byte> ReadPotX;
|
|
|
|
|
public Func<byte> ReadPotY;
|
|
|
|
|
|
2015-09-28 21:52:23 +00:00
|
|
|
|
public Sid(int[][] newWaveformTable, uint sampleRate, uint cyclesNum, uint cyclesDen)
|
2012-11-30 06:41:02 +00:00
|
|
|
|
{
|
|
|
|
|
waveformTable = newWaveformTable;
|
|
|
|
|
|
|
|
|
|
envelopes = new Envelope[3];
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
envelopes[i] = new Envelope();
|
2012-12-11 06:27:00 +00:00
|
|
|
|
envelopeOutput = new int[3];
|
2012-11-30 06:41:02 +00:00
|
|
|
|
|
|
|
|
|
voices = new Voice[3];
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
2012-11-30 21:12:23 +00:00
|
|
|
|
voices[i] = new Voice(newWaveformTable);
|
2012-12-11 06:27:00 +00:00
|
|
|
|
voiceOutput = new int[3];
|
2012-11-30 06:41:02 +00:00
|
|
|
|
|
|
|
|
|
filterEnable = new bool[3];
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
filterEnable[i] = false;
|
2012-12-08 16:05:00 +00:00
|
|
|
|
|
2013-11-14 19:33:13 +00:00
|
|
|
|
resampler = new SpeexResampler(0, cyclesNum, sampleRate * cyclesDen, cyclesNum, sampleRate * cyclesDen, null, null);
|
2012-11-27 05:11:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-10 22:51:02 +00:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if (resampler != null)
|
|
|
|
|
{
|
|
|
|
|
resampler.Dispose();
|
|
|
|
|
resampler = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-27 05:11:40 +00:00
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
|
|
|
|
public void HardReset()
|
|
|
|
|
{
|
2012-11-30 06:41:02 +00:00
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
envelopes[i].HardReset();
|
|
|
|
|
voices[i].HardReset();
|
|
|
|
|
}
|
|
|
|
|
potCounter = 0;
|
|
|
|
|
potX = 0;
|
|
|
|
|
potY = 0;
|
2012-11-27 05:11:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------
|
|
|
|
|
|
2013-11-14 19:33:13 +00:00
|
|
|
|
public void ExecutePhase2()
|
|
|
|
|
{
|
|
|
|
|
cachedCycles++;
|
|
|
|
|
|
|
|
|
|
// potentiometer values refresh every 512 cycles
|
|
|
|
|
if (potCounter == 0)
|
|
|
|
|
{
|
|
|
|
|
potCounter = 512;
|
|
|
|
|
potX = ReadPotX();
|
|
|
|
|
potY = ReadPotY();
|
|
|
|
|
Flush(); //this is here unrelated to the pots, just to keep the buffer somewhat loaded
|
|
|
|
|
}
|
|
|
|
|
potCounter--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Flush()
|
2012-11-27 05:11:40 +00:00
|
|
|
|
{
|
2013-11-14 19:33:13 +00:00
|
|
|
|
while (cachedCycles > 0)
|
|
|
|
|
{
|
|
|
|
|
// process voices and envelopes
|
|
|
|
|
voices[0].ExecutePhase2();
|
|
|
|
|
voices[1].ExecutePhase2();
|
|
|
|
|
voices[2].ExecutePhase2();
|
|
|
|
|
envelopes[0].ExecutePhase2();
|
|
|
|
|
envelopes[1].ExecutePhase2();
|
|
|
|
|
envelopes[2].ExecutePhase2();
|
|
|
|
|
|
|
|
|
|
// process sync
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
voices[i].Synchronize(voices[syncNextTable[i]], voices[syncPrevTable[i]]);
|
|
|
|
|
|
|
|
|
|
// get output
|
|
|
|
|
voiceOutput[0] = voices[0].Output(voices[2]);
|
|
|
|
|
voiceOutput[1] = voices[1].Output(voices[0]);
|
|
|
|
|
voiceOutput[2] = voices[2].Output(voices[1]);
|
|
|
|
|
envelopeOutput[0] = envelopes[0].Level;
|
|
|
|
|
envelopeOutput[1] = envelopes[1].Level;
|
|
|
|
|
envelopeOutput[2] = envelopes[2].Level;
|
|
|
|
|
|
|
|
|
|
mixer = ((voiceOutput[0] * envelopeOutput[0]) >> 7);
|
|
|
|
|
mixer += ((voiceOutput[1] * envelopeOutput[1]) >> 7);
|
|
|
|
|
mixer += ((voiceOutput[2] * envelopeOutput[2]) >> 7);
|
|
|
|
|
mixer = (mixer * volume) >> 4;
|
|
|
|
|
|
|
|
|
|
sample = (short)mixer;
|
|
|
|
|
resampler.EnqueueSample(sample, sample);
|
|
|
|
|
cachedCycles--;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-27 05:11:40 +00:00
|
|
|
|
|
2012-12-03 08:38:12 +00:00
|
|
|
|
// ----------------------------------
|
|
|
|
|
|
2013-11-14 19:33:13 +00:00
|
|
|
|
public void SyncState(Serializer ser)
|
2012-12-03 08:38:12 +00:00
|
|
|
|
{
|
2013-11-14 19:33:13 +00:00
|
|
|
|
SaveState.SyncObject(ser, this);
|
|
|
|
|
ser.BeginSection("env0");
|
2012-12-03 08:38:12 +00:00
|
|
|
|
envelopes[0].SyncState(ser);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
ser.BeginSection("wav0");
|
|
|
|
|
voices[0].SyncState(ser);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
ser.BeginSection("env1");
|
|
|
|
|
envelopes[1].SyncState(ser);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
ser.BeginSection("wav1");
|
|
|
|
|
voices[1].SyncState(ser);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
ser.BeginSection("env2");
|
|
|
|
|
envelopes[2].SyncState(ser);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
ser.BeginSection("wav2");
|
|
|
|
|
voices[2].SyncState(ser);
|
|
|
|
|
ser.EndSection();
|
|
|
|
|
}
|
2012-11-27 05:11:40 +00:00
|
|
|
|
}
|
|
|
|
|
}
|