C64: Start SID Filtering

Set up infrastructure
Still a lot to do.
This commit is contained in:
alyosha-tas 2017-05-22 16:44:27 -04:00 committed by GitHub
parent e2d76149d4
commit 86629319c4
2 changed files with 122 additions and 19 deletions

View File

@ -49,9 +49,14 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void GetSamplesSync(out short[] samples, out int nsamp)
{
Flush();
nsamp = _outputBufferIndex;
samples = _outputBuffer;
nsamp = _outputBufferIndex >> 1;
_outputBufferIndex = 0;
last_index = 0;
}
}
}

View File

@ -40,11 +40,15 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
private bool _filterSelectHiPass;
private int _mixer;
private readonly short[] _outputBuffer;
private int[] _outputBuffer_filtered;
private int[] _outputBuffer_not_filtered;
private int _outputBufferIndex;
private int last_index;
private int filter_index;
private int _potCounter;
private int _potX;
private int _potY;
private short _sample;
private int _sample;
private int _voiceOutput0;
private int _voiceOutput1;
private int _voiceOutput2;
@ -57,6 +61,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public Func<int> ReadPotX;
public Func<int> ReadPotY;
public RealFFT fft;
private readonly int _cpuCyclesNum;
private int _sampleCyclesNum;
private readonly int _sampleCyclesDen;
@ -87,6 +93,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_filterEnable[i] = false;
_outputBuffer = new short[sampleRate];
_outputBuffer_filtered = new int[sampleRate];
_outputBuffer_not_filtered = new int[sampleRate];
}
// ------------------------------------
@ -145,39 +153,129 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
_envelopeOutput1 = _envelope1.Level;
_envelopeOutput2 = _envelope2.Level;
int temp_v0 = (_voiceOutput0 * _envelopeOutput0);
int temp_v1 = (_voiceOutput1 * _envelopeOutput1);
int temp_v2 = (_voiceOutput2 * _envelopeOutput2);
int temp_filtered = 0;
int temp_not_filtered = 0;
//note that voice 3 disable is relevent only if it is not going to the filter
// see block diargam http://archive.6502.org/datasheets/mos_6581_sid.pdf
if (!_filterEnable[2] && _disableVoice3)
temp_v2 = 0;
// break sound into filtered and non-filtered output
// we need to process the filtered parts in bulk, so let's do it here
if (_filterEnable[0])
temp_filtered += temp_v0;
else
temp_not_filtered += temp_v0;
if (_filterEnable[1])
temp_filtered += temp_v1;
else
temp_not_filtered += temp_v1;
if (_filterEnable[2])
temp_filtered += temp_v2;
else
temp_not_filtered += temp_v2;
_sampleCyclesNum += _sampleCyclesDen;
if (_sampleCyclesNum >= _cpuCyclesNum)
{
_sampleCyclesNum -= _cpuCyclesNum;
_mixer = (_voiceOutput0 * _envelopeOutput0) >> 7;
_mixer += (_voiceOutput1 * _envelopeOutput1) >> 7;
_mixer += (_voiceOutput2 * _envelopeOutput2) >> 7;
_mixer = (_mixer * _volume) >> 4;
_mixer -= _volume << 8;
if (_mixer > 0x7FFF)
{
_mixer = 0x7FFF;
}
if (_mixer < -0x8000)
{
_mixer = -0x8000;
}
_sample = unchecked((short)_mixer);
if (_outputBufferIndex < _sampleRate)
{
_outputBuffer[_outputBufferIndex++] = _sample;
_outputBuffer[_outputBufferIndex++] = _sample;
_outputBuffer_not_filtered[_outputBufferIndex] = temp_not_filtered;
_outputBuffer_filtered[filter_index] = temp_filtered;
_outputBufferIndex++;
filter_index++;
}
}
}
//here we need to apply filtering to the samples and add them back to the buffer
filter_operator();
for (int i = last_index; i < _outputBufferIndex; i++)
{
_mixer = _outputBuffer_not_filtered[i] + _outputBuffer_filtered[i-last_index];
_mixer = _mixer >> 7;
_mixer = (_mixer * _volume) >> 4;
_mixer -= _volume << 8;
if (_mixer > 0x7FFF)
{
_mixer = 0x7FFF;
}
if (_mixer < -0x8000)
{
_mixer = -0x8000;
}
_outputBuffer[i * 2] = (short)_mixer;
_outputBuffer[i * 2 + 1] = (short)_mixer;
}
last_index = _outputBufferIndex;
filter_index = 0;
}
public void filter_operator()
{
double loc_filterFrequency = ((_filterFrequency + 30) * 2000) / 0x7FF;
double attenuation;
int nsamp = filter_index;
// pass the list of filtered samples to the FFT
// TODO
// for each element in the frequency list, attenuate it according to the specs
//for (...
/*
// low pass filter
if (_filterSelectLoPass && current_voice_freq > loc_filterFrequency)
{
//attenuated at 12db per octave
attenuation = Math.Log(current_voice_freq / loc_filterFrequency, 2);
//temp_voice = temp_voice - 12 * attenuation;
attenuation = 12 * attenuation;
temp_voice = temp_voice * Math.Pow(2, -attenuation/10);
}
// High pass filter
if (_filterSelectHiPass && current_voice_freq < _filterFrequency)
{
//attenuated at 12db per octave
attenuation = Math.Log(current_voice_freq / _filterFrequency, 2);
//temp_voice = temp_voice - 12 * Math.Abs(attenuation);
}
// Band pass filter
if (_filterSelectBandPass)
{
//attenuated at 6db per octave
attenuation = Math.Log(current_voice_freq / _filterFrequency, 2);
//temp_voice = temp_voice - 6 * Math.Abs(attenuation);
}
*/
// now transform back into time space and reassemble the attenuated frequency components
// TODO
}
// ----------------------------------
public void SyncState(Serializer ser)
{
ser.Sync("last index", ref last_index);
ser.Sync("_databus", ref _databus);
ser.Sync("_cachedCycles", ref _cachedCycles);
ser.Sync("_disableVoice3", ref _disableVoice3);