VOGONS


OPLx emulation concerns

Topic actions

First post, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

Frankly I'm a bit surprised that in 2009 we still haven't found the Valhalla of emulation yet. The digital end is pretty straight-forward and emulating an AdLib one would think would be quite possible.

So I guess my question is, is it that the emulation is that difficult or is it that not enough people, with the talent to knock the doors off this, really care about it today?

Emulation is not exactly easy. OPL2 and OPL3 chips (YM3812 and YMF262) have little documentation how they actually do their stuff internally. Most often things go wrong when some parameter is modified after the sound is already playing. I have also tried to gain knowledge how these chips work internally, but I will never be able to achieve same level as Jarek and others who already have made rather good emulators.

My main reason for not creating the most perfect Adlib emulator is lack of time, I have work and family, so maybe other people too.

If however there would be a 100% bit accurate Adlib emulator, the sound would have to be processed to some extent before it goes to soundcard, like resampling from the original 49716 sampling rate. Emulators in DosBox and ScummVM have internal scaling so they create the samples at some wanted frequency, not the original frequency.

My opinion is that a good emulator would first create the original samples at original rate and then resample to whatever is needed.

If the sound generation is done like the original chips do it (via lookup tables) instead of how current implementations do it (multiplication), it would propably use less CPU horsepower too.

So do the FM chip emulator guys hang out here or where can they be reached? I may have some ideas if they are interested.

Reply 1 of 13, by HunterZ

User metadata
Rank l33t++
Rank
l33t++
Jepael wrote:

If however there would be a 100% bit accurate Adlib emulator, the sound would have to be processed to some extent before it goes to soundcard, like resampling from the original 49716 sampling rate. Emulators in DosBox and ScummVM have internal scaling so they create the samples at some wanted frequency, not the original frequency.

My opinion is that a good emulator would first create the original samples at original rate and then resample to whatever is needed.

DOSBox 0.73 added the ability to run its OPL emulators and master mixer at 49716Hz.

Reply 2 of 13, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

DOSBox 0.73 added the ability to run its OPL emulators and master mixer at 49716Hz.

I have to check the emulator code, but running the emulator and mixer at 49716Hz still does not mean the samples are generated 1:1.

In some emulator code, I have seen the internal reference rate been set to 49720 or something to get 1:1 output, so in this case, the emulator and mixer should be set to 49720, which is correct in terms of sound generation, but playback frequency is then off.

Well, okay, I guess you can't say 80 PPM is bad. Most likely the real cards have their sampling rate set by a crystal which for cost reasons can be something like 100 PPM accurate, plus whatever the surrounding components add there. So it may be within 200 PPM.

But 49716 Hz would give something like 2 PPM error only.

Reply 3 of 13, by HunterZ

User metadata
Rank l33t++
Rank
l33t++

You're very skeptical 😀 You should look at the code because I know they're always tweaking it to improve it, so they'd probably be interested to know of any potential improvements that could be made.

Reply 4 of 13, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

Yes, too sceptical :)

Well I took a peek at the code.

First to make all increments 1, the float variable chip->freqbase needs to be initialized to 1.0 exactly.

As this is calculated from chip->clock (oscillator speed used to clock the OPL3) and chip->rate (mixing rate samples are taken from output), we can make freqbase to 1.0 easily.

We know that chip mixrate is clock/288, and clock is 14.318181 MHz in the real world, it makes sampling rate rounded to 49716.

Therefore, as both mixing rate and chip clock are integers, mixing should be done at rate=49716 and clock set to 288*rate=14318208.

This makes the optimal output.

If the mixing rate is something other than 49716, it really does not matter how much things are scaled to generate the wanted mixing frequency anyway. But just for completeness, the chip clock should be rounded to 14318182 instead of 14318180 just for completeness.

But in case mixing rate is set to 49716 (in the config files I suppose, not in code, right?), then OPL3 clock rate should be set to 14318208 in here:

adlib.cpp:
//#define OPL3_INTERNAL_FREQ 14318180 // The OPL3 operates at ~14.3MHz
/*
The OPL3 master clock operates at 4*NTSC colourburst frequency.
Clock = 4*227.5*525*30/1.001 = 14318181.818181818... Hz.
OPL3 mixing rate is Fs=Clock/288=49715.909090909... Hz.
OPL3 emulation core master clock and mixing rate are integers,
so to get 1:1 output mixing rate should be set to 49716 and
master clock rate to 288*49716=14318208.
14318182 should be closer to original anyway.
*/
#define OPL3_INTERNAL_FREQ 14318208

I have not tried this yet - I have to figure out how to compile DosBox in Linux. Last time I compiled it myself was in Windows some four years ago.

I think it is a good thing that mixing rate and chip clock are separate numbers, but the output best matches the original when ratio is 1. I think it is done in a way that does not affect CPU performance, so there is no point to remove the feature completely.

I have been thinking about if it would increase CPU performance and/or sound quality, if OPL core output is always at 49716 mixing rate and then the output is downsampled to some mixing rate that is sent to sound card.

Does this make any sense? Should this be forked into separate thread already?

Reply 6 of 13, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

be sure to check all 3 opl cores.

Water flows down the stream
How to ask questions the smart way!

Reply 7 of 13, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

Sorry for the trouble splitting the thread, thanks so it has better visibility.

More cores, eh? Let's see!

opl.h:
#define INTFREQU ((fltype)(14318180.0 / 288.0)) // clocking of the chip

opl.cpp:
generator_add = (Bit32u)(INTFREQU*FIXEDPT/int_samplerate);

So Ken Silverman's emulation core is best when INTREQU define and int_samplerate (mixing frequency set when initializing) are same, making generator_add equal to FIXEDPT which is 65536.

I am not absolutely sure about in which order the result is calculated or is it rounded or truncated, but in any case it would be best to define INTFREQ directly to 49716.0, or if the original notation is nicer, then 14318208.0/288.0. I assume that mixing rate in config file can be set to integers only, right?

If results are truncated, then mixer rate of 49715 would try to run the opl core a bit faster, 65537/65536, and mixer rate of 49716 would try to run the opl core a bit slower, 65535/65536.

If resuts are rounded, then 49715 is still 65537/65536, but 49716 will round up perfectly to 65536/65536.

Again this assumes the mixing rate is 49716. If mixing rate is something else, the define can be set as close to original frequency as needed by the 16-bit fixed point math, like 14318181.82 or 14318181.818 - oh let's just add enough decimals there - 14318181.81818181818181.

Reply 8 of 13, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

What's your point?

Reply 9 of 13, by HunterZ

User metadata
Rank l33t++
Rank
l33t++

Shouldn't that be 14318181.81818181818182? 😉

Reply 10 of 13, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

One more core YM3812, similar to YMF262 core values.

adlib.cpp (again)
#define OPL2_INTERNAL_FREQ 3579545

fmopl.cpp:
OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0;

Again, freqbase should be exactly 1 when integer mixingrate is 49716. Thus OPL2_INTERNAL_FREQ should be 72*49716 = 3579552.

If mixing rate is not 49716, then for best accuracy, OPL2_INTERNAL_FREQ should be 35795454.54545454.

I propose all the cores would consider 49716 as the perfect integer approximation of the real rate, and adjust their internal scalings to 1x if mixer works at 49716. If the mixing rate is not exactly 49716, then the cores would use the exact real rate of 49715.90909090 to perform the scaling.

This however creates problems for people who would like to run the mixer at say half or other integer division of the opl core sampling rate - the code should try to see this too so it can work out the internal scaling to 2x,3x,4x etc of the original. As it turns out, 49716 divides nicely to 24858, 16572, and 12429.

We could also cheat and provide integer internal scaling for a range of mixer frequencies. For example any mixer frequency between 49710 and 49720 instead of just 49716 could also be considered to go with 1x scaling, with the expense of the generated tones being a bit out of tune. I guess no one can hear 0.02% frequency difference which is 200ppm. For the note, the sound cards may have their own crystal for generating the master clock, and they most likely are the least accurate crystals available (around 100ppm plus whatever inaccuracies the oscillator electronics can throw it to). Another notable fact is that an OPL4 sound card I have uses a ceramic resonator (I think), which are even more inaccurate than crystals, but also OPL4 FM output is resampled to 44100.

Reply 11 of 13, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

What's your point?

Why do you ask?

Improve the current emulation to the world's best and accurate OPL emulation cores, almost to the level of real chips.

Or if you think they are already so good that there is no room for improvement, please say now so I'll stop.

For example, the following tables presented here http://docs.google.com/Doc?id=dd8kqn9f_13cqjkf4gp are true. A few simple algorithms using those two lookup tables create identical output to real YMF262 chip - verified with a logic analyser. Nobody uses those yet in OPL emulation.

Reply 12 of 13, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

I don't care about bitperfect emulation of the digital part of a digital/analogue system.
Use/improve mame's logic if you care, and feel free to provide USEFUL patches against
dosbox if the difference is audible.

Nobody uses those yet in OPL emulation.

How do you know?

Reply 13 of 13, by Jepael

User metadata
Rank Oldbie
Rank
Oldbie

Shouldn't that be 14318181.81818181818182? Wink

Let's put 4.0*227.5*525.0*30.0/1.001 then :)

#define F_NTSC (227.5*525.0*30.0/1.001)
#define F_4xNTSC (4.0*F_NTSC)