Just for overkill, I thought it'd be fun to support the LC7883KM.
I understand that I'm emulating a DAC when both the input and outputs from the emulation are digital, but this is just for fun.
The chip has pins for:
* SOC1,SOC2 -> clock rate (384f, 448f, 392f, 512f): seems to be fixed at one of these with no software control
* EMPH1,EMPH2 -> de-emphasis mode (off, 44.1khz, 32khz, 48khz): can be configured via serial transfer ($ff8034)
* D/N -> 1 = double-rate, 0 = normal-rate: can be configured via serial transfer ($ff8034) [called "spindle speed", but it's not really]
Also there's attenuation bits for a15-a4, but the manual says a4-a5 are ignored so it's only 10-bits
The normal rate mode performs 8x oversampling at 18-bit precision.
The double rate mode performs 4x oversampling at 18-bit precision.
The normal rate filtering is:
Input -> 43rd-order FIR (unknown purpose) -> 1st-order IIR (de-emphasis) -> 11th-order FIR (unknown purpose) -> 3rd-order FIR (attenuator) ->noise shaper (lower 6 bits) -> Output at 16-bit
The double rate filtering is:
Input -> 1st-order IIR (de-emphasis) -> 43rd-order FIR (unknown purpose) -> 3rd-order FIR (attenuator) -> noise shaper (lower 6 bit) -> Output at 16-bit
Each FIR filter doubles the input frequency rate. So the normal rate output is 44.1khz*8=352.8khz, the double rate output is 44.1khz*4=176.4khz.
The IIR filter for de-emphasis is is a high-shelf filter with a gain of -9.477, a slope of 0.5, and a cutoff frequency of 5uS (3.1KHz) + 15uS (10KHz).
I'm using a biquad filter (second-order, but oh well, I don't have a first-order high-shelf algorithm handy) with arithmetic mean, so (10000+3100)/2.0 cutoff.
I presume the Sega CD will feed this DAC 44.1khz audio no matter what, so setting the 48khz and 32khz de-emphasis modes are just going to adjust the output frequency parameter of the IIR filter, which will basically throw off the coefficient calculations and produce the wrong shelf, which is how I'm emulating it for now.
The manual states the attenuator adjustment is: -20 * log((attenuator & ~63) / 256) dB. I'm not sure how to model that, but (sample*attenuator)/0x4000 seems to produce adequate results, although it may be incorrect. I'm also not clear why one would design a 3rd-order FIR filter to do this attenuation ...? Since 0x4000 is the baseline value at reset, it means we can quadruple the input volume with an attenuation of 0xffff, which would probably be fine given the filters internally work at 18-bit. So if we are outputting in normalized floats, we can then do:
int18 output = (4*sample*attenuator)/16384; return output / 131072.0; //-1.0 to +1.0
The attenuator is adjusted by one for each sample period, persumably one input sample at 44.1khz, which also produces adequately sounding results.
The manual does not say anything about what the 43rd-order and 11th-order FIR filters are for, short of for doubling the sampling rates. Without knowledge of this, modeling this step seems pointless. (I know, this whole exercise is pointless, but its fun to support what we can!)
The noise shaper is used to boost the SNR of the output, but again, the algorithm used is unknown. I don't understand why it's 6-bit when the input at this point will be 18-bit. You'd end up with 12-bit of unmodified input. That can't be right.
Finally, the PDF recommends low-pass filters on the final outputs from the DAC, but I don't know if those are present in the Sega CD, or what their cutoffs would be (but I'd bet money they'd be first-order if they were even there.)
I imagine absolutely none of this aside from just the attenuator is ever going to produce any kind of audible difference in the Sega CD output, but oh well.
Obviously, the WonderMega and WonderMega M2 use different DACs with their own peculiarities, but I'm not as interested in them.
If anyone wants to take this absurd tangent any further, let me know, otherwise I think I'll stop with de-emphasis and the attenuator stepping (hopefully) correctly emulated, and the oversampling and noise shaping omitted.