Bad, vile and meaningless: Sidplay2 update from Alan's clob

SIDplay2 advances

I got the Catweasel Mk4 running from Linux.

Catweasel Mk4 contains a hardware FIFO and a driver which can write commands to the SID chip very precisely and without main CPU interaction. Using cycle-exact emulation it should be possible to obtain perfectly identical playback that doesn't suffer from scheduling latencies that you would get with HardSID-based cards. This is especially important for getting good sample playback through the Catweasel.

To do this you need to use the experimental hardsid driver for the Catweasel. Simon White tells that he will first make HardSID driver on Linux use the realtime stuff if/when it gets merged in the linux kernel, and then bypass it for the Catweasel's special case. But in the meantime, you can just go nuts with the mk4 experimental branch.

I caution it's not fully stable but I hope Simon can spend some time on it to fix the most obvious annoyances.

Software emulation improvements

I have now conducted a set of measurements using a python script that programs the SID chip, and some ALSA recording utilities and more Python analysis programs. I extracted 66 points for getting the right center frequency register to physical frequency mapping (for this particular 6581 which is a R4 model, generally regarded as the best-sounding 6581 chip). The measured data is here, lifted from my sidplay.ini:

[Emulation]
ClockSpeed    =
ForceSongSpeed=
MOS8580       =
UseFilter     =
OptimiseLevel =0
Filter6581    =Filter6581R4
Filter8580    =
SidSamples    =

[Filter6581R4]
type=1
points=68
point1=0,207
point2=32,196
point3=64,191
point4=96,201
point5=128,207
point6=160,212
point7=192,212
point8=224,207
point9=256,223
point10=288,212
point11=320,223
point12=352,223
point13=384,239
point14=416,234
point15=448,244
point16=480,250
point17=512,261
point18=544,277
point19=576,271
point20=608,277
point21=640,304
point22=672,325
point23=704,368
point24=736,357
point25=768,417
point26=800,473
point27=832,514
point28=864,584
point29=896,667
point30=928,802
point31=960,966
point32=992,1195
point33=1023,1571
point34=1023,1571
point35=1024,1003
point36=1024,1003
point37=1056,1321
point38=1088,1483
point39=1120,1765
point40=1152,2048
point41=1184,2400
point42=1216,2783
point43=1248,3310
point44=1280,3499
point45=1312,4013
point46=1344,4317
point47=1376,4952
point48=1408,5743
point49=1440,6252
point50=1472,7170
point51=1504,7690
point52=1536,7945
point53=1568,8586
point54=1600,9323
point55=1632,10260
point56=1664,10938
point57=1696,11670
point58=1728,12220
point59=1760,12761
point60=1792,13781
point61=1824,14653
point62=1856,14855
point63=1888,16117
point64=1920,16214
point65=1952,17398
point66=1984,18034
point67=2016,19196
point68=2047,20163

Standard sidplay is not able to handle this data set because it repeats the filter center frequency points 1023 and 1024 in order to deal with the discontinuity in the filter curve. You will get this data to work by changing the first 1023 to 1022 and the latter 1024 to 1025 so that the values follow in monotonic fashion. (This bug has been reported to Dag Lem.)

I included the "Emulation" section as well, because you need to set OptimiseLevel to 0 in order for the filter emulation to not suck, and to point the Filter6581 to the section name Filter6581R4.

There seems to be virtually no documentation about the format of the filter cutoff file. I had to dig this up through reading the source of sidplay-utils.

Voice nonlinearity improvements

It seems that there's a nonlinearity after the voice oscillator get modulated by the envelope generator. The nonlinearity seems to be modelled reasonably well by this piecewise defined waveshaper:

f(x) = x       , when x >= 0
f(x) = x - x/3, when x < 0

This assumes that the full dynamic range of the waveform is -1 to 1. At the negative side we find that f(0) = 0, f(1) = 2/3, thus losing 1/6th of full dynamic range. Additionally, f'(0) = 1 and f'(1) = 0; hence there are no discontinuities in the first derivate. By measurements it seems that f indeed appears to fully "saturate" near f(1) which is modelled by the derivate falling to zero.

Filter nonlinearity improvements

I believe that I have discovered a workable model for the filter distortion. First of all, we probably have to forget nonlinearity simulation for the OptimiseLevel != 0 case because the filter is easily driven into unstable state and stepping a cycle at a time is probably a requirement for acceptable emulation.

I mentioned in the earlier entry that the lowpass, bandpass and highpass outputs are mixed significantly attenuated compared to the unfiltered signal. I believe the source of the changed mixing volume is the nonlinear behaviour of the SID filter amplifiers themselves. The most promising model for the nonlinearity simulation involves biasing some suitable nonlinear function (such as tanh or atan) slightly off its center value, and then correcting for the "bias" with some well-chosen factors. Right now I'm trying a function like this:

Vlp = (atan(Vlp - bias) + bias) / (1 / (1 + bias ** 2))

The latter part is the derivate of atan, which is atan'(x) = 1 / (1 + x ** 2). It may be necessary to choose a different bias factor for the derivate.

Unfortunately, scaling the filter outputs even slightly tend to drive the filter quickly into unstable condition. I still need to get that problem fixed somehow.