C64: Start SID Filtering
Set up infrastructure Still a lot to do.
This commit is contained in:
parent
e2d76149d4
commit
86629319c4
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue