sound sync (wrong number of samples)

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Anes
Posts: 621
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

sound sync (wrong number of samples)

Post by Anes » Tue Mar 09, 2021 4:11 pm

Hi everyone:

I rewrote my emu in C++ OOP and can't sync sound to 48000 Khz 16 bit samples.
I'm using a DirectSound interface that Disch wrote sometime ago and works fine.
We all know that NES doesn't sync to 60hz exactly, but PCs do.
So what i did was simple:

Code: Select all

48000 / 60 = 800 Samples per frame
So we got:

Code: Select all

- 29780.5 x 60 = 1786830 Cpu Clocks
Then i get the sound every:

Code: Select all

1786830 / 48000 = 37.225625 cpu clocks
The thing is that my emu frame can't generate 800 samples always. It generates 799 or 800 or 801 samples.

My "frame" code looks like this:

Code: Select all

*** GLOBAL ***
frame_cycles = 89342;
*****************
do {
	***STUFF HERE***
	cpu_cc = cpu->Run();
	ppu_cc += cpu_cc * 3;
}
while (ppu_cc < frame_cycles)
ppu_cc -= frame_cycles;
frame_toggle = !frame_toggle;
if (bg_enable)
{
	if (frame_toggle)
		frame_cycles = 89341;
	else
		frame_cycles = 89342;
]	
sound->Out();  <<------ here i call that actually writes to directSound buffer
I have tested a lot of different things, but no luck. I even made the "sound frame" routine in a separate task but no luck.
One thing a think is that getting 799 is no so bad, since i can run the sound rutine to get one more APU sample. But what about the 801?
The emu alrady got that sample.

As you can see there is a sync problem. I'm stuck here from more than 2 weeks. Tried a lot of things: no luck.

The question: any clues?
I beg help becouse im really stuck.
Thxs in advance.
ANes

User avatar
Dwedit
Posts: 4427
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: sound sync (wrong number of samples)

Post by Dwedit » Tue Mar 09, 2021 5:08 pm

Syncing is hard.

You have the NES generating a picture at ~60.0985 FPS (omitting the first pixel from the prerender line about half of every frame)
You have the NES generating audio at ~1.7898 MHz.

Your video card will output at the monitor's refresh rate, which could be anything from 59.5Hz to 60.499Hz, as the "60Hz" you see in Windows is a number which has been rounded.
You need to fill the sound API's buffer for a given sample rate of your choice, and that rate will be in KHz rather than MHz.

Possible ways to get 60.0985 FPS onto your monitor's refresh rate:

Way 1: Change the game speed to match your monitor.
- Pros: You can see every frame generated, no extra frames are introduced, no frames are dropped
- Cons: You can't do fair 2 hour speedrun races, because time drifts.

Way 2: Hold a fully buffered frame at all times, and depending on how far behind real time we are, either skip that frame, or present it twice.
- Pros: Game speed matches exactly
- Cons: One frame added input lag*, and picture may have occasional stuttering. About 6 frames are dropped every minute with 60.098FPS vs 60FPS.

Way 3: Screen Tearing
- Pros: Game speed matches
- Cons: It looks horrible

Way 4: Have the user reconfigure their monitor to 60.098FPS using something like Custom Resolution Utility.
- Pros: Drastically improves syncing to monitor refresh rate (Way 1) or holding buffered frames (Way 2).
- Cons: Hard to do, and might not work on all monitors.

*Windows itself is already adding 3 frames of input lag from desktop composition. If you are in exclusive Fullscreen mode, this does not happen.

And that's it for visuals. One of these choices will be end up being used, regardless if you know you've picked it or not.

Next: Audio (to post later)
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

User avatar
Anes
Posts: 621
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: sound sync (wrong number of samples)

Post by Anes » Tue Mar 09, 2021 7:02 pm

I did it!! I don't know how and why by took the emulated cpu to 1776000 mhz.
So now it takes sound every exactly 32 (integer) clocks.

Since there are many variables (cpu speed, sound hz, clocks, etc) the thing seems not to be desyncing sound enymore.

thxs for the help
ANes

User avatar
Anes
Posts: 621
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Re: sound sync (wrong number of samples)

Post by Anes » Tue Mar 09, 2021 8:22 pm

You have the NES generating a picture at ~60.0985 FPS
But, why they not sync EXACTLY at 60 hz??
Is it an electricity/electronic thing?
ANes

lidnariq
Posts: 10463
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: sound sync (wrong number of samples)

Post by lidnariq » Tue Mar 09, 2021 8:36 pm

Because the picture must be an integer division of the color frequency.

US video always uses the frequency 3.579545MHz to generate color
NTSC NES multiples that by 1.5 to get the pixel rate
Each horizontal row of pixels is (almost) always 341 pixels
Each vertical set of rows is always 262 pixels.
All that together gets 60.0985 Hz.

Original black-and-white video in the US was exactly 60 Hz.
But when they went to add color, they discovered they had to fix a design flaw.
It turns out that to not get interference between audio and video, the audio channel must be an integer multiple of the horizontal row frequency.
The audio channel couldn't be moved, so it was still at 4.5MHz.
The horizontal row frequency had to be slowed down by a tiny bit so that there were exactly 286 audio channel periods per horizontal row.
The number of rows didn't change.
This slowed down video in the US by 0.1%.

Post Reply