Software Support > GroovyMAME

Theoretical versus real refresh rates

(1/3) > >>

Dr.Venom:
Hi Calamity,

While testing I noticed two possible "issues" with refresh rates that might negatively impact GM's (sound synchronization) accuracy. The first is about the refresh rate that GM seems to calculate from the dynamically created modelines and the second is about the modelines' theoretical refresh rates versus their real refresh rates.

1 - Refresh rate rate calculation

When running Snowbros, Genesis and SNES, GM generates the following 3 modelines 'on the fly' (it's dynamically creating them from the installed 'static' soft15khz modelines, which are at 62Hz and 63Hz refresh rates):

Modeline "256x240_57 15.64KHz 57.50Hz" 5.26 256 272 296 336 240 247 250 272 -hsync -vsync
Modeline "320x240_60 15.78KHz 60.00Hz" 6.56 320 336 368 416 240 241 244 263 -hsync -vsync
Modeline "512x240_60 15.63KHz 60.10Hz" 10.38 512 536 584 664 240 241 244 260 -hsync -vsync

According to GM the refresh rates of these dynamically created modelines are respectively 57.50Hz, 60.00Hz and 60.10Hz. But, when I calculate the refresh rates from the above modelines myself (given pixelclock and pixel/line x/y timing values), they should respectively be (cut to 4 decimals)  57.5543Hz, 59.9591Hz and 60.1251Hz. Any idea what's the reason for this difference?


2 - Theoretical versus real refresh rate

On my HD 4850, actual refresh rates will differ by about 0.01 to 0.05Hz from their modelines theoretical values. I'm quite certain you're already aware of this issue, but nonetheless I thought it would be good to bring it up.

I've taken the three modelines generated by GM 'on the fly', as mentioned above, and installed them as 'static' modelines with soft15Khz, just so that I can measure their real refresh rate.

To test the refresh rates I'm using the tool "Freqtest.exe" version 1.6 (not 2.1), which is available from here: http://www.mediafire.com/?lycrjcm55j37n.


--- Code: ---Resolution     Theoretical      Real
                 refresh       refresh
                   (Hz)         (Hz)
256x240          57.5543       57.5821
320x240          59.9591       59.9753
512x250          60.1251       60.1075

--- End code ---
 

Interestingly the real refresh rates are differing by about 0.02 to 0.03Hz in either direction from their theoretical modeline values. I've tested this for other screenmodes also, and the deviations are seemingly random positive and negative by about 0.01 to 0.05Hz.

I'm guessing these differences between the theoretical modeline and real refresh rates might be negatively impacting the (sound) sync timing In GM? If that's the case, would it then be an idea to add the possibility to GM to use a custom user specified refresh rate (with high granularity, freqtest provides 6 decimals), instead of the modeline theoretical value?


*Edit: clarified that I'm talking about the 'on the fly' created modelines under point 1.

matrigs:
I think that Calamity might have answered this question in my topic below:


--- Quote from: Calamity on January 07, 2013, 03:01:04 pm ---But unless you're using the 'static' mode list method, you won't get the 57.55 Hz refresh, because everything is normalized to 60 Hz in order to reduce the list as much as possible, and GM recalculates the right refresh later.

--- End quote ---


--- Quote from: Calamity on January 07, 2013, 04:15:17 pm ---
--- Quote from: matrigs on January 07, 2013, 03:16:07 pm ---So as long as i have any 320x240 resolution in modeline.txt, no matter the refresh rate, GM will still show the game at the right refresh rate later on right?

--- End quote ---

Yes.
--- End quote ---

So i understand that no matter what the modelines say about the refresh rate, GM calculates the correct refresh rates on the fly.

That would also explain the differences that you pointed out using soft 15khz. Soft 15 khz is using a static modeline and you will never be able to have an exact refresh ratio as at some point some degree of rounding the numbers is used.

As far as i understand GM, it is trying to generate the nearest possible modeline, and later uses throttle to speed up/down the game to make it perfectly smooth.

Please someone correct me if i have given any false informations.

Dr.Venom:

--- Quote from: matrigs on January 08, 2013, 09:21:52 am ---I think that Calamity might have answered this question in my topic below:
--- End quote ---

No, sorry, you're talking about a different topic. My post is about the -dynamically- created nearest possible modeline (refresh rate) that GM generates 'on the fly' and whether or not the two issues I raised are negatively affecting, however small, the sound synchronization. 


--- Quote from: Calamity on January 07, 2013, 04:15:17 pm ---
--- Quote from: matrigs on January 07, 2013, 03:16:07 pm ---So as long as i have any 320x240 resolution in modeline.txt, no matter the refresh rate, GM will still show the game at the right refresh rate later on right?

--- End quote ---

Yes.
--- End quote ---

So to be clear, the "right refresh rate" in above quote might be more of an "nearly right refresh rate", which would possibly result in a nearly accurate (but not 100%) sound synchronization, because of the issues I mentioned.

But, let's see what Calamity has to say about it.

Calamity:
Hi Dr.Venom,

There are two different issues going on there, each has its own explanation. I'm going to focus on one of your modelines as an example, the same applies to all of them.


--- Quote ---1 - Refresh rate rate calculation

Modeline "256x240_57 15.64KHz 57.50Hz" 5.26 256 272 296 336 240 247 250 272 -hsync -vsync

--- End quote ---

So if you calculate the refresh out of the above values, you get: 5.26 * 1000000 / 336 / 272 = 57.5543 Hz (diff = 0.0543 Hz)

The key here is that the dotclock is calculated as a real number, but in order to pass it to the ATI drivers we need to round it to just two decimal figures, because that's the best precission that the drivers admit. So that's where the 5.26 value comes from.

If you tried the lower inmediate possible value, you'd get: 5.25 * 1000000 / 336 / 272 = 57.5449 Hz (diff = -0.0551 Hz)
So the absolute difference is bigger in this case and 5.26 MHz is selected as best possible dotclock.

Now this is the theoretical refresh due to the limitations imposed by the drivers. What about the real refresh obtained?



--- Quote ---2 - Theoretical versus real refresh rate

256x240          57.5543       57.5821

--- End quote ---

So let's assume the refresh returned by the Freqtest program is accurate enough (I believe so). We do the opposite operation:

real_dotclock = 57.5821 * 336 * 272 =  5.2625432832 MHz (vs 5.26)

This value is the best approximation that the drivers can obtain for our requested value of 5.26 MHz.

You can easily see where I want to go: it's impossible to get an *exact* match for a given refresh for these two reasons:

- Dotclock granularity
- Dotclock uncertainty

While we can't do anything about the granularity (unless you created your own drivers), there's a way to reduce or eliminate the uncertainty: we can measure ALL possible real dotclocks and create a dotclock look-up table instead of assuming theoretical values. I did implement this for VMMaker and the Radeon 9250. There's a file named Ati9250.txt that contains all measured dotclocks.

However, this is just one part of the problem: it allows you to predict how much off you're going to be, but doesn't help to get any closer. So what else can we do to gain precission:

real_dotclock = 57.5821 * 336 * 272

We shouldn't play with Horizontal-total because that would ruin our geometry. On the other hand, adding extra lines to Vertical-Total is not going to change the geometry, it will only raise the horizontal frequency a bit. So we can try again with 273, 274, 275, etc. lines, just in case the our *real* precalculated dotclocks required for that combination happens to produce a value which is closer to the target refresh. This is implemented in VMMaker with an option named 'Iterations'. By doing this, you can get values that are just 0.02 Hz off or less, most of the times.

Before you ask, GroovyMAME does not implement this feature. The reason is that you need to create an unique dotclock look-up table for your specific card and drivers, and I should write some software to assist people doing this. Considering most users find it hard to figure out the porch values of their monitors with Arcade_OSD, leave apart understanding how these affect the picture, which is the ABC of the whole thing, I honestly don't believe it's worth the effort to create the required software for doing this and supporting this feature, being the only benefit that the obtained refresh is 0.03 Hz closer. (http://en.wikipedia.org/wiki/Diminishing_returns ;)) I consider myself very obsessed with this stuff and I can't truly notice the difference.

Anyway, Arcade_OSD let's you play with the involved values and measure the real refresh rate (just like FreqTest), so you can come up with a modeline that's more accurate. GroovyMAME will allow you to enter a raw modeline in the near feature, so you will be able to use your own tweaked modelines.

Finally, regarding how this affects the sound accuracy, GM doesn't need to know the exact refresh in order to adjust the sound. It just uses the core speed percentage that's recalculated on the fly which has a precission of 1/1000 (1000 = 100%, 999 = 99.9 %), so that means that for a 60 Hz typical refresh the accuracy is only 0.06 Hz. This factor is applied to the sound buffer when doing the final mix. However, I need to clarify that this is NOT applied when the new -frame_delay option is enabled. The reason is that modifying the core speed made the -frame_delay code to go crazy and produce an erratic speed.

Dr.Venom:
Hi Calamity,

Many thanks for your thorough explanation, that's truly appreciated and made for a good read also.


--- Quote ---Anyway, Arcade_OSD let's you play with the involved values and measure the real refresh rate (just like FreqTest), so you can come up with a modeline that's more accurate. GroovyMAME will allow you to enter a raw modeline in the near feature, so you will be able to use your own tweaked modelines.
--- End quote ---

That sounds like a valuable option. I'll also give Arcade_OSD a go, but from what I remember it would somehow not work fully on my Win 7 / dual gfx-card setup. I'll let you know.


--- Quote ---Finally, regarding how this affects the sound accuracy, GM doesn't need to know the exact refresh in order to adjust the sound. It just uses the core speed percentage that's recalculated on the fly which has a precission of 1/1000 (1000 = 100%, 999 = 99.9 %), so that means that for a 60 Hz typical refresh the accuracy is only 0.06 Hz. This factor is applied to the sound buffer when doing the final mix. However, I need to clarify that this is NOT applied when the new -frame_delay option is enabled. The reason is that modifying the core speed made the -frame_delay code to go crazy and produce an erratic speed.
--- End quote ---

The low accuracy (1/1000) on the sound buffer adjustment is what's worrying me. I agree that when it's about the perception of *video* speed that a 0.03Hz difference most probably will go unnoticed. "Unfortunately" in MAME we have to deal with video + audio sync and the mechanisms in MAME/UME to do that. It seems to me that *without* the proper audio rate adjustment (< 0.06Hz threshold), a mismatch between the video and audio rate will make the emulation to either regularly discard videoframes or drop samples from the audio buffer to keep audio and video in sync.

I'm almost certain the following isn't correct in the context of MAME/UME and am not even fully sure it would work this way, but for discussion sake it will do. 

Suppose we're running the SNES driver in UME. The SNES runs at (rounded) 60.10Hz. Because of the Dotclock granularity and uncertainty we've come up with a 512x240 resolution for the SNES running at 60.13Hz (+0.03Hz versus SNES core). This is below the +/- 0.06Hz threshold for the sound speed adjustment that's built into UME.

When at 100% the SNES audio runs at 32040 samples per second, or say 533 samples per frame. But, in above case the video is running at a factor 60.13/60.10=1.000499 faster. This means the emulation should be providing 32040*1.000499=32056 samples per second, but it's doing 32040. So we're underrunning by 16 samples per second. Since one frame is 533 samples, sound will be lagging by a full frame after 533/16=33 seconds. This is most probably where UME decides to discard a *video* frame to keep video and audio better in lockstep. This cycle of discarding a video frame then repeats every 33 seconds! It can easily get worse when there's a +0.05%Hz difference in targeted versus real refresh rate. That difference still sits under the radar of the audio adjustment and would mean UME needs to discard a frame every 20 seconds!

I've been looking in the documentation and there I found "By default MAME tries to keep the DirectSound audio buffer between 1/5 and 2/5 full." So I'm not sure how this will impact above hypothetical case, but my best guess is that a difference of +/-0.03Hz in targeted versus real refresh rate is causing serious loss of emulation accuracy; basically because you just can't get around the fact of either discarding video frames or (in the opposite case of real refresh being lower than target?) dropping samples from the buffer as the main video/audio sync mechanism. Of course this would be purely because of the fact that audio isn't properly adjusted for refresh rate differences below the 0.06Hz threshold (in case we're talking of a typical 60Hz refresh), and the "simple" solution would be to increase the granularity on the 'core speed percentage that is calculated on the fly'. The big question then is: how simple would it be to make that granularity adjustment?
 
Of course the above is hypothesizing mainly. Hopefully you have some more insight in how the adjustment mechanism for the video-audio sync actually works in MAME, especially in the special case where the target and real refresh differ by less than 0.06Hz (or more precisely the difference stays under the 1/1000 granularity radar).

Navigation

[0] Message Index

[#] Next page

Go to full version