When working on SMPSPlay and DEPlay there was always one thing that bothered me: the DAC frequency It's something I couldn't just get right, so I decided to do some research. I startet with Oerg866's SMPS Player, which uses jman2050's DAC driver: At first I made an SMPS file that plays a few DAC sounds and made each sound play the same sample, but with different DAC rates. Then I used MESS to make a VGM of it. (MESS because MAME's timing system is extremely accurate.) After that I wrote a small tool in VB that reads that VGM and calculated the frequency of each sound. Finally I made another small VB tool that recalculated the formula FreqHz = BaseVal / (RateBase + DACRate) for the DAC rates I logged. With this tool I tested values for RateBase until I found a perfect one. (I made it recalculate BaseVal with the tested frequency of rate 01 and RateBase.) Then I did the same with plain Sonic 1, Sonic 2, and Barver Battle Saga (because I already had its pointers) for the Data East driver. And here are my results: (The columns are DACRate, logged DAC samples, length of the DAC sound in VGM ticks (44100 Hz), DAC samples per VGM sample, DAC frequency.) Code (Text): jman2050's DAC driver --------------------- 01 8,238 11,940 1.45 30,426.784 02 8,238 13,275 1.61 27,366.915 03 8,238 14,600 1.77 24,883.274 04 8,238 15,937 1.93 22,795.746 05 8,238 17,268 2.10 21,038.673 06 8,238 18,602 2.26 19,529.932 07 8,238 19,938 2.42 18,221.276 08 8,238 21,265 2.58 17,084.213 0C 8,238 26,598 3.23 13,658.764 10 8,238 31,926 3.88 11,379.308 20 8,238 53,243 6.46 6,823.353 30 8,238 74,561 9.05 4,872.464 40 8,082 94,060 11.64 3,789.243 80 4,278 94,054 21.99 2,005.867 C0 2,908 94,020 32.33 1,363.995 FF 2,212 94,038 42.51 1,037.338 00 8,238 352,309 42.77 1,031.185 -> FreqHz = 272624 / (7.96 + DACRate) Calculating with (8 + prim) is still a good approximation. (DACSmpl/VGMSmpl variance is <0.2 for rates <= 80) Sonic 1 DAC driver ------------------ 01 8,236 15,517 1.88 23,407.076 02 8,236 16,846 2.05 21,560.465 03 8,236 18,190 2.21 19,967.433 04 8,236 19,530 2.37 18,597.419 05 8,236 20,866 2.53 17,406.671 06 8,236 22,209 2.70 16,354.073 07 8,236 23,550 2.86 15,422.828 08 8,236 24,882 3.02 14,597.203 0C 8,236 30,252 3.67 12,006.069 10 8,236 35,602 4.32 10,201.888 20 8,236 57,041 6.93 6,367.483 40 8,236 99,906 12.13 3,635.493 80 8,236 185,658 22.54 1,956.326 C0 5,710 188,159 32.95 1,338.288 FF 4,354 188,077 43.20 1,020.919 00 8,236 357,141 43.36 1,016.987 -> FreqHz = 271053 / (10.58 + DACRate) Sonic 2 DAC driver ------------------ [without gaps] 01 5,994 10,634 1.77 24,857.570 02 5,994 11,593 1.93 22,801.294 03 5,994 12,550 2.09 21,062.582 04 5,994 13,505 2.25 19,573.151 05 5,994 14,464 2.41 18,275.401 06 5,994 15,442 2.58 17,117.951 07 5,994 16,400 2.74 16,118.012 08 5,994 17,349 2.89 15,236.348 0C 5,994 21,209 3.54 12,463.360 10 5,994 25,016 4.17 10,566.653 20 5,994 40,424 6.74 6,539.071 40 5,994 71,112 11.86 3,717.170 80 4,384 96,853 22.09 1,996.163 C0 3,014 97,425 32.32 1,364.305 FF 2,312 98,042 42.41 1,039.954 00 5,994 255,585 42.64 1,034.237 -> FreqHz = 275173 / (10.07 + DACRate) [with gaps] 01 5,994 11,152 1.86 23,702.959 02 5,994 12,146 2.03 21,763.165 03 5,994 13,140 2.19 20,116.849 04 5,994 14,163 2.36 18,663.800 05 5,994 15,155 2.53 17,442.125 06 5,994 16,181 2.70 16,336.160 07 5,994 17,175 2.87 15,390.707 08 5,994 18,178 3.03 14,541.501 0C 5,994 22,193 3.70 11,910.756 10 5,994 26,203 4.37 10,087.982 20 5,994 42,327 7.06 6,245.078 40 5,994 74,027 12.35 3,570.797 80 4,384 100,639 22.96 1,921.068 C0 3,014 100,638 33.39 1,320.748 FF 2,312 99,898 43.21 1,020.633 00 5,994 259,097 43.23 1,020.218 -> FreqHz = 265473 / (10.20 + DACRate) Data East DAC driver -------------------- 01 5,309 14,714 2.77 15,911.846 02 5,309 15,768 2.97 14,848.231 03 5,309 16,817 3.17 13,922.037 04 5,309 17,866 3.37 13,104.607 05 5,309 18,906 3.56 12,383.735 06 5,309 19,951 3.76 11,735.096 07 5,309 21,006 3.96 11,145.716 08 5,309 22,077 4.16 10,605.014 0C 5,309 26,261 4.95 8,915.384 10 5,309 30,457 5.74 7,687.129 20 5,309 47,284 8.91 4,951.504 40 5,309 80,941 15.25 2,892.562 80 5,309 148,154 27.91 1,580.294 C0 5,309 215,537 40.60 1,086.249 FF 5,309 281,543 53.03 831.585 00 5,309 282,774 53.26 827.965 -> FreqHz = 222766 / (13 + prim) All formulas are accurate enough that the difference between tested and recauculated (DAC samples per VGM sample) is <= 0.2 for all rates. (except for Sonic 2 with gaps) The Sonic 2 driver does all work on the Z80, so it needs to interrupt the DAC stream every frame to do update the music engine. [without gaps] means, that I removed the small delays that occur because of this, [with gaps] means that I just took the approximate frequency including these delays. The next update of SMPSPlay and DEPlay with feature perfect DAC rates. (For SMPSPlay they're adjustable via ini-files.)
For what is worth, the DAC playback loops in the S3, S&K and S3D sound drivers take the exact same number of cycles as the equivalent code in the S2 driver, so the formula without gaps should be equal for both.
Sega was stupid and told developers that they needed to halt the Z80 when reading controllers and performing DMA, so all official games have interrupted DAC. Plus, DAC is played with a CPU loop, and some things (like GEMS) don't even use a loop... this is to say, this is great, but IDK how far this method can be pushed
Something I should note is, that I made sure that the sound driver has absolutely nothing to do but playing a DAC sound every few seconds. The few drivers I checked had a quite consistent stream of DAC data. They just stopped it for a few samples every frame (both Sonic 2 and Data East). Sonic 1 didn't interrupt the stream at all. The method worked well with 2 sound engines, and I think it should also work with other ones. (Maybe in some distant future, we can listen to Ristar songs with clean samples.) btw: I did the Sonic 2 [with gaps] table just to see the differences between the averaged and 'real' frequencies. Don't take it too serious.
What about the differences between NTSC and PAL? There should be timing differences even with a busy loop, since the Z80 speed also changes between both systems.
NTSC vs. PAL is actually a good idea, so I made another test. Also I recalculated the jman2050 and Sonic 1 DAC frequencies with removed gaps. (The gaps had ~6 samples in Sonic 1, but ~30 in Sonic 2.) Code (Text): jman2050's DAC driver --------------------- 01 8,238 11,811 1.43 30,759.106 02 8,238 13,151 1.60 27,624.956 03 8,238 14,486 1.76 25,079.097 04 8,238 15,804 1.92 22,987.585 05 8,238 17,108 2.08 21,235.434 06 8,238 18,424 2.24 19,718.617 07 8,238 19,768 2.40 18,377.975 08 8,238 21,082 2.56 17,232.511 0C 8,238 26,330 3.20 13,797.790 10 8,238 31,618 3.84 11,490.158 20 8,238 52,786 6.41 6,882.427 30 8,238 73,877 8.97 4,917.577 40 8,082 93,281 11.54 3,820.887 80 4,278 93,219 21.79 2,023.834 C0 2,908 93,158 32.04 1,376.616 FF 2,212 93,169 42.12 1,047.013 00 8,238 349,322 42.40 1,040.003 -> FreqHz = 275320 / (7.96 + DACRate) Calculating with (8 + DACRate) is still a good approximation, (DACSmpl/VGMSmpl variance is <0.2 for rates <= 80) Sonic 1 DAC driver ------------------ 01 8,236 15,278 1.86 23,773.243 02 8,236 16,670 2.02 21,788.098 03 8,236 18,116 2.20 20,048.995 04 8,236 19,437 2.36 18,686.402 05 8,236 20,697 2.51 17,548.804 06 8,236 22,112 2.68 16,425.814 07 8,236 23,355 2.84 15,551.599 08 8,236 24,672 3.00 14,721.449 0C 8,236 30,030 3.65 12,094.825 10 8,236 35,194 4.27 10,320.157 20 8,236 56,326 6.84 6,448.312 40 8,236 98,566 11.97 3,684.918 80 8,236 182,903 22.21 1,985.794 C0 5,710 185,336 32.46 1,358.673 FF 4,354 185,301 42.56 1,036.214 00 8,236 351,896 42.73 1,032.145 -> FreqHz = 275300 / (10.68 + DACRate) [PAL version] 01 8,236 15,550 1.89 23,357.402 02 8,236 16,841 2.04 21,566.867 03 8,236 18,207 2.21 19,948.789 04 8,236 19,561 2.38 18,567.946 05 8,236 20,910 2.54 17,370.043 06 8,236 22,242 2.70 16,329.808 07 8,236 23,513 2.85 15,447.097 08 8,236 24,906 3.02 14,583.137 0C 8,236 30,227 3.67 12,015.999 10 8,236 35,577 4.32 10,209.056 20 8,236 56,783 6.89 6,396.414 30 8,236 78,154 9.49 4,647.332 40 8,236 99,445 12.07 3,652.347 80 8,236 184,592 22.41 1,967.624 C0 6,806 223,024 32.77 1,345.795 FF 5,192 222,947 42.94 1,027.003 00 8,236 355,891 43.21 1,020.559 -> FreqHz = 272853 / (10.68 + DACRate) Sonic 2 DAC driver ------------------ [without gaps] 01 5,994 10,634 1.77 24,857.570 02 5,994 11,593 1.93 22,801.294 03 5,994 12,550 2.09 21,062.582 04 5,994 13,505 2.25 19,573.151 05 5,994 14,464 2.41 18,275.401 06 5,994 15,442 2.58 17,117.951 07 5,994 16,400 2.74 16,118.012 08 5,994 17,349 2.89 15,236.348 0C 5,994 21,209 3.54 12,463.360 10 5,994 25,016 4.17 10,566.653 20 5,994 40,424 6.74 6,539.071 40 5,994 71,112 11.86 3,717.170 80 4,384 96,853 22.09 1,996.163 C0 3,014 97,425 32.32 1,364.305 FF 2,312 98,042 42.41 1,039.954 00 5,994 255,585 42.64 1,034.237 -> FreqHz = 275680 / (10.09 + DACRate) [with gaps] 01 5,994 11,152 1.86 23,702.959 02 5,994 12,146 2.03 21,763.165 03 5,994 13,140 2.19 20,116.849 04 5,994 14,163 2.36 18,663.800 05 5,994 15,155 2.53 17,442.125 06 5,994 16,181 2.70 16,336.160 07 5,994 17,175 2.87 15,390.707 08 5,994 18,178 3.03 14,541.501 0C 5,994 22,193 3.70 11,910.756 10 5,994 26,203 4.37 10,087.982 20 5,994 42,327 7.06 6,245.078 40 5,994 74,027 12.35 3,570.797 80 4,384 100,639 22.96 1,921.068 C0 3,014 100,638 33.39 1,320.748 FF 2,312 99,898 43.21 1,020.633 00 5,994 259,097 43.23 1,020.218 -> FreqHz = 270978 / (10.50 + DACRate) Data East DAC driver -------------------- 01 5,309 14,714 2.77 15,911.846 02 5,309 15,768 2.97 14,848.231 03 5,309 16,817 3.17 13,922.037 04 5,309 17,866 3.37 13,104.607 05 5,309 18,906 3.56 12,383.735 06 5,309 19,951 3.76 11,735.096 07 5,309 21,006 3.96 11,145.716 08 5,309 22,077 4.16 10,605.014 0C 5,309 26,261 4.95 8,915.384 10 5,309 30,457 5.74 7,687.129 20 5,309 47,284 8.91 4,951.504 40 5,309 80,941 15.25 2,892.562 80 5,309 148,154 27.91 1,580.294 C0 5,309 215,537 40.60 1,086.249 FF 5,309 281,543 53.03 831.585 00 5,309 282,774 53.26 827.965 -> FreqHz = 222865 / (13 + DACRate) The NTSC Z80 clock is 3579545, the PAL clock is 3546895, so PAL should be 99.088% NTSC speed. The ratio of the Sonic 1 frequency base values is 272853 / 275300 = 99.11 %, which is quite close.