Quake2 snd_dma and long server times

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Quake2 snd_dma and long server times

Post by jitspoe »

Noticed this issue when connecting to a server that had been running the same map for a few days:

int snd_dma.c, S_StartSound():

start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;

These were the values I had:
cl.frame.servertime 110254500
dma.speed 48000
s_beginofs 1578529

cl.frame.servertime * 0.001 * dma.speed + s_beginofs 5293794529.0000000

That overflows the max int value, and you end up with:
(int)(cl.frame.servertime * 0.001 * dma.speed + s_beginofs) -2147483648

I tried making start and s_beginofs double's a while back, but it seems there may be reduced performance doing that. What do you think the proper way to fix this is?


Edit: I think the performance issue was just a fluke. Sometimes the framerate will vary even when I haven't changed anything. Really annoying when I'm trying to test optimizations. Using doubles is probably the correct thing to do.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Quake2 snd_dma and long server times

Post by Spike »

the bigger the float gets, the less precision it has.
qc programmers will know that floats can only hold about 24 bits (mantissa is 23 bits) before it starts forgetting bits.
meaning it can no longer hold 48khz precision after ((1<<24)/48000) seconds. Which comes out at about ~5.82 mins.
simply put, you do NOT want to store absolute audio sample times in a float.
you really ought to rewrite it to calculate an offset instead of an absolute time.

what is s_beginofs anyway? the audio time the client would have used when servertime was 0? that's really nasty, no wonder its wrapping.
jitspoe
Posts: 217
Joined: Mon Jan 17, 2005 5:27 am

Re: Quake2 snd_dma and long server times

Post by jitspoe »

It does use an offset instead of absolute time, but it calculates that offset using the server time. It works fine, as far as I can tell. The only problem is the overflow, which I'm not sure is actually a problem in practice. I just noticed it because I had some floating point exceptions enabled, and they triggered on that line.

On a side note, this can be pretty useful if you're trying to track down qnan's and other garbage float values:

Code: Select all

#ifdef DEBUG_FLOATS // jitdebug trying to catch bad floating point values..
	_clearfp();
	_controlfp(_controlfp(0, 0) & ~(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW), _MCW_EM);
#endif
Post Reply