C64: Filtering

First Draft, sounds better but needs peeking effect
This commit is contained in:
alyosha-tas 2017-05-24 14:45:07 -04:00 committed by GitHub
parent 19dde8018a
commit 2d5c4ce893
2 changed files with 80 additions and 37 deletions

View File

@ -21,16 +21,18 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
addr &= 0x1F;
var result = _databus;
switch (addr)
{
case 0x19:
case 0x1A:
case 0x1B:
case 0x1C:
Flush();
//Flush(); not needed
result = ReadRegister(addr);
break;
}
return result;
}
@ -125,6 +127,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
{
addr &= 0x1F;
_databus = val;
switch (addr)
{
case 0x19:
@ -137,7 +140,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
// can't write to these
break;
default:
Flush();
Flush();
WriteRegister(addr, val);
break;
}
@ -168,12 +171,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
case 0x12: _voice2.Control = val; _envelope2.Gate = (val & 0x01) != 0; break;
case 0x13: _envelope2.Attack = val >> 4; _envelope2.Decay = val & 0xF; break;
case 0x14: _envelope2.Sustain = val >> 4; _envelope2.Release = val & 0xF; break;
case 0x15: _filterFrequency &= 0x3FF; _filterFrequency |= val & 0x7; break;
case 0x15: _filterFrequency &= 0x7F8; _filterFrequency |= val & 0x7; break;
case 0x16: _filterFrequency &= 0x7; _filterFrequency |= val << 3; break;
case 0x17:
_filterEnable[0] = (val & 0x1) != 0;
_filterEnable[1] = (val & 0x2) != 0;
_filterEnable[2] = (val & 0x4) != 0;
_filterResonance = val >> 4;
break;
case 0x18:

View File

@ -129,6 +129,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
public void Flush()
{
while (_cachedCycles > 0)
{
_cachedCycles--;
@ -182,7 +184,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
else
temp_not_filtered += temp_v2;
_sampleCyclesNum += _sampleCyclesDen;
if (_sampleCyclesNum >= _cpuCyclesNum)
{
@ -197,10 +198,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
}
}
}
//here we need to apply filtering to the samples and add them back to the buffer
filter_operator();
if (_filterEnable[0] | _filterEnable[1] | _filterEnable[2])
if (filter_index >= 2)
filter_operator();
for (int i = last_index; i < _outputBufferIndex; i++)
{
_mixer = _outputBuffer_not_filtered[i] + _outputBuffer_filtered[i-last_index];
@ -226,49 +229,85 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
filter_index = 0;
}
public void filter_operator()
{
double loc_filterFrequency = ((_filterFrequency + 30) * 2000) / 0x7FF;
double loc_filterFrequency = (double)(_filterFrequency<<2);
double attenuation;
int nsamp = filter_index;
// pass the list of filtered samples to the FFT
// TODO
// but needs to be a power of 2, so find the next highest power of 2 and re-sample
int nsamp_2 = 2;
bool test = true;
while(test)
{
nsamp_2 *= 2;
if (nsamp_2>nsamp)
{
test = false;
}
}
fft = new RealFFT(nsamp_2);
double[] temp_buffer = new double[nsamp_2];
// linearly interpolate the original sample set into the new denser sample set
for (double i = 0; i < nsamp_2; i++)
{
temp_buffer[(int)i] = _outputBuffer_filtered[(int)Math.Floor((i / (nsamp_2-1) * (filter_index - 1)))];
}
// now we have everything we need to perform the FFT
fft.ComputeForward(temp_buffer);
// for each element in the frequency list, attenuate it according to the specs
//for (...
/*
// low pass filter
if (_filterSelectLoPass && current_voice_freq > loc_filterFrequency)
for (int i = 0; i < nsamp_2; i++)
{
//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);
double freq = i * ((double)(880*50)/filter_index);
// low pass filter
if (_filterSelectLoPass && freq > loc_filterFrequency)
{
//attenuated at 12db per octave
attenuation = Math.Log(freq / loc_filterFrequency, 2);
attenuation = 12 * attenuation;
temp_buffer[i] = temp_buffer[i] * Math.Pow(2, -attenuation / 10);
}
// High pass filter
if (_filterSelectHiPass && freq < _filterFrequency)
{
//attenuated at 12db per octave
attenuation = Math.Log(freq / _filterFrequency, 2);
attenuation = 12 * attenuation;
temp_buffer[i] = temp_buffer[i] * Math.Pow(2, -attenuation / 10);
}
// Band pass filter
if (_filterSelectBandPass)
{
//attenuated at 6db per octave
attenuation = Math.Log(freq / _filterFrequency, 2);
temp_buffer[i] = temp_buffer[i] - 6 * Math.Abs(attenuation);
}
}
// 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
fft.ComputeReverse(temp_buffer);
//re-sample back down to the original number of samples
for (double i = 0; i < filter_index; i++)
{
_outputBuffer_filtered[(int)i] = (int)(temp_buffer[(int)Math.Floor((i / (filter_index-1) * (nsamp_2 - 1)))]/(nsamp/2));
if (loc_filterFrequency==0)
{
_outputBuffer_filtered[(int)i] = 0;
}
}
}
// ----------------------------------