Some interesting comments in the source code :
Code:
//And now, the combined waveforms. The resid source simply uses 4kbyte 8bit
// samples from wavetable arrays, says these waveforms are mystic due to the
// analog behaviour.
//It's true, the analog things inside SID play a significant role in how the
// combined waveforms look like, but process variations are not so huge that
// cause much differences in SIDs.
// After checking these waveforms by eyes, it turned out for me that these
// waveform are fractal-like, recursively approachable waveforms.
//My 1st thought and trial was to store only a portion of the waveforms in
// table, and magnify them depending on phase-accumulator's state.
//But I wanted to understand how these waveforms are produced. I felt from the
// waveform-diagrams that the bits of the waveforms affect each other,
//hence the recursive look. A short C code proved by assumption, I could
// generate something like a pulse+saw combined waveform.
//Recursive calculations were not feasible for MCU of SwinSID, but for jsSID I
//could utilize what I found out and code below generates the combined waveforms
// into wavetables.
// To approach the combined waveforms as much as possible, I checked out the
// SID schematic that can be found at some reverse-engineering sites...
//The SID's R-2R ladder WAVE DAC is driven by operation-amplifier like
// complementary FET output drivers, so that's not the place where I first
// thought the magic happens.
// These 'opamps' (for all 12 wave-bits) have single FETs as inputs, and they
// switch on above a certain level of input-voltage, causing 0 or 1 bit as R-2R
// DAC input.
// So the first keyword for the workings is THRESHOLD. These FET inputs are
// driven through serial switch FETs (wave-selector) that normally enables one
//waveform at a time.
// The phase-accumulator's output is brought to 3 kinds of circuitries for the
// 3 basic waveforms. The pulse simply drives
// all wave-selector inputs with a 0/1 depending on pulsewidth, the sawtooth
// has a XOR for triangle/ringmod generation, but what
// is common for all waveforms, they have an open-drain driver before the wave-
// selector, which has FETs towards GND and 'FET resistor' towards the power-
// supply rail.
// These outputs are clearly not designed to drive high loads, and normally
// they only have to drive the FETs input mentioned above.
// But when more of these output drivers are switched together by the switch-
// FETs in the wave-selector, they affect each other by loading each other.
// The pulse waveform, when selected, connects all of them together through a
// fairly strong connection, and its signal also affects the analog level (pulls
// below the treshold)...
// The farther a specific DAC bit driver is from the other, the less it affects
// its output. It turned out it's not powers of 2 but something else,
//that creates similar combined waveforms to that of real SID's...
// The analog levels that get generated by the various bit drivers, that pull
// each other up/down depends on the resistances the components inside the SID
// have.
// And finally, what is output on the DAC depends on whether these analog
// levels are below or above the FET gate's threshold-level,
// That's how the combined waveform is generated. Maybe I couldn't explain
// well enough, but the code below is simple enough to understand the mechanism
// algoritmically.
//This simplified schematic example might make it easier to understand
//sawtooth+pulse combination (must be observed with monospace fonts):
// _____ |- .--------------. /\/\--.
// Vsupply / .----| |---------*---|- / Vsupply ! R ! As can be seen on this schematic,
// ------. other ! ! _____ ! TRES \ \ ! / the pulse wave-selector FETs
// ! saw bit *--!----| |---------' HOLD / ! |- 2R \ connect the neighbouring sawtooth
// / output ! ! ! |------|- / outputs with a fairly strong
// Rd \ |- !WAVEFORM-SELECTOR *--*---|- ! R ! connection to each other through
// / |- !SWITCHING FETs ! ! ! *---/\/\--* their own wave-selector FETs.
// ! saw-bit ! _____ |- ! --- ! ! So the adjacent sawtooth outputs
// *------------------!-----| |-----------*-----|- ! |- / pull each other upper/lower
// ! (weak drive,so ! saw switch !THRES-! `----------|- 2R \ depending on their low/high state and
// |- can be shifted ! ! HOLD ! ! / distance from each other, causing
// -----|- by neighbours ! _____ ! ! ! R ! the resulting analog level that
// ! up or down) *-----| |-----------' --- --- /\/\-* will either turn the output on or not.
// GND --- ! pulse switch ! (Depending on their relation to treshold.)
//
//(As triangle waveform connects adjacent bits by default, the above explained effect becomes even stronger, that's why combined waveforms with thriangle are at 0 level most of the time.)
function combinedWF(channel,wfarray,index,differ6581) { //on 6581 most combined waveforms are essentially halved 8580-like waves
if(differ6581 && SID_model==6581.0)
index&=0x7FF;
combiwf = (wfarray[index]+prevwavdata[channel])/2;
prevwavdata[channel]=wfarray[index];
return combiwf;
}
function createCombinedWF(wfarray,bitmul,bitstrength,treshold) { //I found out how the combined waveform works (neighboring bits affect each other recursively)
for (var i=0; i<4096; i++) {
wfarray[i]=0; //neighbour-bit strength and DAC MOSFET treshold is approximately set by ears'n'trials
for (var j=0; j<12;j++) {
var bitlevel=0;
for (var k=0; k<12; k++) {
bitlevel += ( bitmul/Math.pow(bitstrength,Math.abs(k-j)) ) * (((i>>k)&1)-0.5) ;
}
wfarray[i] += (bitlevel>=treshold)? Math.pow(2,j) : 0;
}
wfarray[i]*=12; }
}