bsnes vsync development thread

Archived bsnes development news, feature requests and bug reports. Forum is now located at http://board.byuu.org/
byuu

Post by byuu »

Can we adjust the interface a bit, for efficiency/simplicity? Basically, I'm thinking you don't need "samples_pending", just a way to read as many samples as are available into the caller's buffer.

Code: Select all

class Resampler {
public:
    // Sets output sample rate and removes all samples from buffer
    void set_rate( int sample_rate );
   
    // Writes pair of samples, each 16-bit signed
    void write( int left, int right );
   
    // Reads at most n sample pairs to *out and returns number actually written
    int read( uint32_t* out, int n );
};
Hah, was just about to post my revision to that.

I came up with:

Code: Select all

class resampler {
public:
  //if buffer is too full, it can 'drop' samples in the extreme case
  void sample(uint16_t left, uint16_t right);

  //audio driver will ask for the samples needed to complete one block
  //resampler can return NULL in extreme cases
  uint32_t* read(unsigned samples);

  //setup routine, also used to clear buffer (eg for system reset)
  void init(unsigned frequency, optional unsigned latency_in_ms, optional unsigned samples_per_block);
};
Yours looks better, as you require the caller to specify the buffer to write to. I like the names more, too. More descriptive.

I don't know if it'd help much to tell the resampler that it'll be working with blocks of n samples or not. Maybe, maybe not.

But for the read() function, it would need to get the same number of samples it asks for (excepting for extreme cases where audio will fail anyway, of course.)

For both DirectSound and OpenAL at least, I basically query the play cursor to determine the current block. There are three blocks, one for playback, one for writing new samples, and one to make sure that playback doesn't cross over into the write buffer. What I do is once one block has been completely played, I write it with the new block. Right now, I just simply lock the emulation once I have one whole block and wait for the play cursor to complete a block before returning control. Each block is basically 1/3rd of the audio latency total, so with the average being ~60ms, you're looking at me requesting ~20ms worth of audio at a time, but it'd be a consistent value every time, whereas the input samples will vary by as much as ~5-10ms each time I ask for output (I can run some tests at home to be more specific on the variance, if needed.) Overall, of course, you'll be getting almost exactly 32040 samples per second worth of input. They'd just be coming in at sporadic intervals.

So ideally, the resampler should be able to compensate for the largest possible difference in samples, obviously increasing in range as requested latency rises. Given the insane overhead of bsnes, not even 4-tap hermite phases it in the slightest, so the resampling algorithm can be as intense as it needs to be.

Also, bsnes currently works by setting the audio card frequency to the speed of emulation, eg 2x will set playback to 64khz. Ideally, it'd probably be best if we could just give it a constant, user-specified frequency for all emulation speed settings ... but the frequency change works perfectly fine for now, anyway.
Last edited by byuu on Wed Aug 13, 2008 6:43 pm, edited 1 time in total.
blargg
Regular
Posts: 327
Joined: Thu Jun 30, 2005 1:54 pm
Location: USA
Contact:

Post by blargg »

byuu wrote:Yours looks a bit better, as you require the caller to specify the buffer to write to. I don't know if it'd help much to tell the resampler that it'll be working with blocks of n samples or not. Maybe, maybe not.
Yes, returning a pointer to an internal buffer is just asking for trouble, since the caller could use it beyond its validity, and the caller often already has a place for the samples to go. And it certainly helps the resampler, since it can convert multiple samples in a loop very efficiently.
byuu wrote:But for the read() function, it would need to get the same number of samples it asks for (excepting for extreme cases where audio will fail anyway, of course.)
What if that many samples just aren't available? Or do you mean it can't get more than requested? That much is obvious.
byuu

Post by byuu »

Added minor revisions to my above post.
What if that many samples just aren't available?
Then we are essentially out of luck. Nothing we can really do. Maybe use the extra space to fade out the audio as best we can (fade length would obviously vary based on how close we were to filling the whole buffer), so that it doesn't crackle so bad? This would basically only happen when emulation dips below 60fps, and there's nothing we can really do in that case. I've never heard of an emulator that really gracefully handles that case.

How about we make read() return a boolean result to say if it was successful in generating enough samples, so when it's false, the emulator can optionally do things like raise the frameskipping or mute the audio entirely or something?

I would still recommend padding out the read buffer with fading, or just zeroes.
Snark
Trooper
Posts: 376
Joined: Tue Oct 31, 2006 7:17 pm

Post by Snark »

FitzRoy wrote:If you don't have the cash ready, you don't make the commitment. If you don't have paypal, you don't make the commitment. And there is no bounty yet because nobody has a clue what the conditions are.
Commitment off then...
-_-'''' and cmon..if I didn't have at least 20$ ready to spare I'd be in DEEP financial shit..and the first thing I'd do is cancel my high speed internet connection.

...I was thinking more like a fund "pool"..you give money and that money is used whenever a bounty comes up. This is basically the way M.A.M.E and the dumping project works. It's more convenient for people imo because they can donate whenever they want. I just don't want being bound by a promise to donate as I don't want to check the board every day/weeks just to make sure.
I want to fry~~ Sky Hiiiiiiiiigh~
Let's go-o-o-O~ togeda~
Verdauga Greeneyes
Regular
Posts: 347
Joined: Tue Mar 07, 2006 10:32 am
Location: The Netherlands

Post by Verdauga Greeneyes »

byuu wrote:Overall, of course, you'll be getting almost exactly 32040 samples per second worth of input. They'd just be coming in at sporadic intervals.
What's the biggest this interval can get? At the moment bsnes sends any samples to the sound card as soon as they're ready, right? So if you set the sound latency/buffer length for any driver to a value that's lower than the biggest synchronisation interval, even if the OS and hardware had no latency at all you would still get gaps in the audio.
I suppose a better question is: what's the maximum number of samples the buffer will ever need to hold?
neviksti
Lurker
Posts: 122
Joined: Thu Jul 29, 2004 6:15 am

Post by neviksti »

I'm not quite following here. It sounds like the overarching problem here is that video sync was given up for audio sync, and a possible solution is to get a better audio resampler?

So if it just comes down to an audio resampler, and the previous attempts did the following:
byuu wrote:This results in nice speedups that make up for the speed hit of the green thread switching, but it also means that you get very unusual amounts of audio samples per emulated frame.

...

I tried to compensate for this: the more buffer I used, the worse the latency. The less buffer I used, the more dramatic the resampling to different numbers of samples became. And even with ~200ms latency, you could still audibly detect the block resampling very clearly.
This doesn't make sense to me. Why would it matter at all how much the emulation spits out at a time? All that should matter is the minimum amount of "held audio data" (basically your data buffer for latency) the code can expect. Right? (am I missing something?)

The only thing I can figure that would cause the problems you describe is that you were resampling each chunk the emulator output seperately and sticking that in the "to play" audio buffer. Or equivalently, resampling the audio in chunks (like your buffer split into three segments you described) in any manner. You will probably hear problems on the boundary of every chunk.

It sounds like all you need is a kind of "moving window" resampler (which cubic spline, or truncated sinc, etc are), where the resampler only depends on a fixed number of samples in either direction. You probably even already have these functions. Just don't "reset" them with every chunk.
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

I think it's pretty clear that if the operating system APIs are able to buffer and play back in a continuous fashion, it's quite possible to buffer and output a continuous stream in software too. I'm sure byuu just overlooked some silly detail or was subject to some kind of silly bug when he tried to do this previously, and naturally got fed up with it. I think blargg described it pretty well conceptually in an earlier thread here.

Resampling doesn't magically solve the vsync problem of course. If you don't want sample loss you'll have to sync to audio anyway. It merely allows you to get the ratio between sound blocking time per frame and the video blocking time per frame pretty close to 1 (slightly above 1 is usually preferable since that will only result in occasional video chops rather than sound buffer underruns). Adjusting the resampling ratio accordingly isn't trivial though since we usually neither know the exact refresh rate nor the exact sample rate (a second as seen by the sound card isn't necessarily equal to a second as seen by the monitor/video card or CPU/chipset).
Last edited by sinamas on Thu Aug 14, 2008 12:59 am, edited 1 time in total.
byuu

Post by byuu »

This doesn't make sense to me. Why would it matter at all how much the emulation spits out at a time?
It doesn't make sense to me, either. I tried buffering up to 200ms, I cant get a steady input to output ratio of samples that doesn't result in drastic pitch shifts when I resample to fit into the output window, no matter what I try.

I will have to make some logs of what samples I'm getting and how I resample, maybe that will help explain the problem I'm having.
The only thing I can figure that would cause the problems you describe is that you were resampling each chunk the emulator output seperately and sticking that in the "to play" audio buffer.
I had another buffer involved to even out the chunk sizes given as input each time.
It sounds like all you need is a kind of "moving window" resampler (which cubic spline, or truncated sinc, etc are), where the resampler only depends on a fixed number of samples in either direction. You probably even already have these functions. Just don't "reset" them with every chunk.
That's easy enough to make, at least. A fixed input + size + output sampler that only spits out samples when ready, so you don't end up sampling {0 - 15}, then {16 - 31}, but rather {0,1,2,3}, {1,2,3,4}, {2,3,4,5}, etc. But obviously over fractional samples. Simple 1D interpolation, in other words.
Resampling doesn't magically solve the vsync problem of course. If you don't want sample loss you'll have to sync to audio anyway. It merely allows you to get the ratio between sound blocking time per frame and the video blocking time per frame pretty close to 1 (slightly above 1 is usually preferable since that will only result in occasional video chops rather than sound buffer underruns).
That's just it, I want zero video frame loss. We should be able to get the tearing under control and the audio dropping to stop with a sample rate of ~32100hz, as that would be more audio samples than video frames. Thus, you'd get the same frame twice on occasion, and miss one on occasion as well.

But I don't want the video to ever stutter. Video is infinitely more noticeable than audio, so we should be resampling audio to fit into the audio buffer. Obviously the video refresh rate and the sound card playback rate factor into how many samples you get, but it should still be close enough that you have a near-constant rate of input samples per second to output samples per second.

The major issue I'm having is that even up to 200ms, the input to output ratio keeps changing too drastically, and you can hear the pitch changes every time that happens, and it sounds absolutely dreadful.

There seems to be an exceptionally low tolerance to resampling the audio, like ~1-3 samples per frame of ~530 samples. If they differ much more, you hear it.

And obviously, yes, I'm doing something wrong. The theory on how to do this is sound. I understand the theory, I just don't seem to be able to pull it off in practice.
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

byuu wrote:
Resampling doesn't magically solve the vsync problem of course. If you don't want sample loss you'll have to sync to audio anyway. It merely allows you to get the ratio between sound blocking time per frame and the video blocking time per frame pretty close to 1 (slightly above 1 is usually preferable since that will only result in occasional video chops rather than sound buffer underruns).
That's just it, I want zero video frame loss. We should be able to get the tearing under control and the audio dropping to stop with a sample rate of ~32100hz, as that would be more audio samples than video frames. Thus, you'd get the same frame twice on occasion, and miss one on occasion as well.

But I don't want the video to ever stutter. Video is infinitely more noticeable than audio, so we should be resampling audio to fit into the audio buffer. Obviously the video refresh rate and the sound card playback rate factor into how many samples you get, but it should still be close enough that you have a near-constant rate of input samples per second to output samples per second.

The major issue I'm having is that even up to 200ms, the input to output ratio keeps changing too drastically, and you can hear the pitch changes every time that happens, and it sounds absolutely dreadful.

There seems to be an exceptionally low tolerance to resampling the audio, like ~1-3 samples per frame of ~530 samples. If they differ much more, you hear it.

And obviously, yes, I'm doing something wrong. The theory on how to do this is sound. I understand the theory, I just don't seem to be able to pull it off in practice.
Zero frame duplication by dynamically adjusting pitch is pretty hard to achieve even with big (output side) buffers (smaller if you can poll play cursor accurately), and I actually think sample loss is more annoying than very occasional duplicate video frames anyway. Using exponential weighted moving averages and adjusting the ratio by a tiny amount based on play cursor position changes can get you pretty close, but it's hard to do reliably especially since getting accurate play cursor position isn't common, and I suspect it'll become rarer and rarer as sound servers like pulse audio are becoming more common. It's a bit easier to aim for dynamically adjusting the pitch so that it only causes frame duplication occasionally.

The stream of raw input samples from the emulator per frame shouldn't be hard to get constant (within one sample) with some buffering of course, as blargg described earlier. You shouldn't base the resampling ratio on that anyway, that's a (real) constant as far as calculations go.

EDIT: I don't see how frame _loss_ would occur when sound output blocks (consistently) longer per frame than video output does.
Last edited by sinamas on Thu Aug 14, 2008 2:13 am, edited 1 time in total.
Fes
Rookie
Posts: 11
Joined: Thu Apr 10, 2008 12:19 am

Post by Fes »

I'm not terribly experienced with this kind of thing, but I definitely agree that steady v-sync makes a world of difference in the experience of a game, so to my mind it's a worthy goal to push through this wall. I'll try to help in my own meager way, and to that end, here's my thoughts.

As has been established, the video and audio subsystems of a general purpose pc are just too disjoint to be able to sync to both, so we have to pick one and compensate for the other. My initial thought was that staying synced to audio and making the video output asynchronous so that vsync doesn't block the emulator (I thought that was the whole point of triple buffering, but trying it in opengl and direct3d still resulted in audio stutter, so I'm not sure what's up there). Having a rendering thread and using a buffer ring to pass the frames through seems like it would do the trick.

For many people I think this would be "good enough" to have the occasional hitch in exchange for rampant shearing, and if this was the way it was now, I probably would be satisfied. I suspect, though obviously can't confirm, that other emulators do this as well. I know the CVS build of VBA-M I downloaded has triple buffering support that works like a charm and it's great.

Having said that, I think the goal of trying to sync to video and do it the other way has promise, and if pulled off could yield an even better experience. So, on with the show...
I can easily run one processor for a really long time with no need to break out and sync the other, so long as they aren't talking to each other.
This is interesting indeed. I might be misunderstanding or misinterpreting this, but an idea that came to mind when I read that was: would it be possible then to make the sound chip more "aggressive" in its execution, and run as far as it can as soon as it can, in order to get samples to the resampler sooner? I think we can agree that the sooner samples get into the resampler buffers, the more leeway we have.

Next, as it stands, as my first order of business after getting bsnes to build was to going to be to try and collect data about sample generation distribution. However, if byuu has a plan in motion for doing this I'm sure it would be more comprehensive than what I'd get.

Anyway, after this data is in hand, we KNOW that there are 32040 samples per "second" coming out of the system in some distrubtion or other (unless I misunderstand what I've read in other threads), so it seems natural to me to want to know the average coming in every frame, and if at all possible, get the standard deviation of that down as much as possible. Once we have this, I think the resampler should target the average amount. If there are currently an excess of samples, it shouldn't necessarily try to resample them down into a smaller chunk, because likely there will be a deficit later in accordance with the average. The trick would be buffering enough frames in advance so that a run of deficits doesn't underrun and force more extreme compensation.

Anyway, just some thoughts. A fascinating topic to be sure.
byuu

Post by byuu »

With 250,000 clock CPU <> SMP max drifting:

Code: Select all

generated   960 samples whilst sound card played   800 samples
generated   640 samples whilst sound card played   800 samples
generated   928 samples whilst sound card played   800 samples
generated   672 samples whilst sound card played   800 samples
generated   944 samples whilst sound card played   800 samples
generated   656 samples whilst sound card played   800 samples
generated   960 samples whilst sound card played   800 samples
generated   640 samples whilst sound card played   800 samples
generated   960 samples whilst sound card played   800 samples
generated   640 samples whilst sound card played   800 samples
generated   928 samples whilst sound card played   800 samples
generated   672 samples whilst sound card played   800 samples
This is at 32khz, the buffer is frequency / 40 -> 800 samples. Note how they all add up to 800 in the end.

If I force synchronization every cycle, I get:

Code: Select all

generated   848 samples whilst sound card played   800 samples
generated   720 samples whilst sound card played   800 samples
generated   880 samples whilst sound card played   800 samples
generated   720 samples whilst sound card played   800 samples
generated   880 samples whilst sound card played   800 samples
generated   736 samples whilst sound card played   800 samples
generated   864 samples whilst sound card played   800 samples
It's still way too sporadic.

---

With a "capacitor-like" class, I can get smooth audio with a massive latency of ~1050ms, and it lasts for about one full minute before the difference overflows:

Code: Select all

//ignore the class name, obviously not a resampler (yet)
class Resampler {
public:
  void write(uint16_t l, uint16_t r) {
    counters++;

    buffer[writeoffset++] = l + (r << 16);
    writeoffset &= 65535;
  }

  uint32_t* read(unsigned length) {
    counterb++;

    unsigned count;
    if(writeoffset >= readoffset) count = writeoffset - readoffset;
    else count = 65536 - (readoffset - writeoffset);
    //printf("* buffered = %d -- average = %I64d vs %I64d (%f)\n", count, counters, counterb * length, double(counterb * length) / double(counters));
    if(count >= length * 16) {
      //printf("* depleting %d samples\n", length);
      for(unsigned i = 0; i < length; i++) output[i] = buffer[(readoffset + i) & 65535];
      readoffset += length;
      readoffset &= 65535;
    } else {
      printf("* miss %d\n", counterb);
      for(unsigned i = 0; i < length; i++) output[i] = 0;
    }
    return output;
  }

  void init() {
    readoffset  = 0;
    writeoffset = 0;
    counters = 0;
    counterb = 0;
  }

  uint32_t buffer[65536];
  uint32_t output[65536];
  unsigned readoffset, writeoffset;
  uint64_t counters, counterb;
} resampler;
---

And some logs of it in action:

Code: Select all

* want to read  3200 samples, generated  3162 samples; skew = 0.988125
* want to read  3200 samples, generated  3196 samples; skew = 0.998750
* want to read  3200 samples, generated  3196 samples; skew = 0.998750
* want to read  3200 samples, generated  3213 samples; skew = 1.004063
* want to read  3200 samples, generated  3196 samples; skew = 0.998750
* want to read  3200 samples, generated  3196 samples; skew = 0.998750
* want to read  3200 samples, generated  3196 samples; skew = 0.998750
* want to read  3200 samples, generated  3213 samples; skew = 1.004063
* want to read  3200 samples, generated  3179 samples; skew = 0.993438
* want to read  3200 samples, generated  3196 samples; skew = 0.998750
byuu

Post by byuu »

Alright, blargg was a huge help this evening in getting a bit better understanding down.

It seems the generated samples delay is more due to the video card's vsync + blit taking different amounts of time, and of course the CPU <> SMP drifting. If I turn off the out-of-order execution entirely (~10-15% speed hit), I can get the same results as forcefully feeding 533 samples all at once right before calling SNES::video.update(). It still see-saws, but that's nothing a bit of buffering won't address. The important part is that the rate is relataively constant.

Now, what we were able to do was skew the audio output rate, such that it's always greater than the video refresh rate (eg 32100hz vs 60.09hz), disable the out-of-order stuff, and then greatly expand the latency to ~120ms, and we were able to get smooth audio and mostly smooth video (every few seconds the same frame would display twice, causing a tiny stuttering effect.)

Obviously, it requires 60hz monitor to look good, PAL goes straight to hell (but would look okay I guess at 100hz), you literally cannot get the emulator to run faster than 60hz anymore, and slower speeds are really choppy like PAL. All of that is really obvious, though.

So from here, going to start by trying to get an audio resampler going to upscale 32040hz emulated to 32100hz output, so that we don't have to visibly affect emulation by faking the S-SMP clock rate to generate those extra samples. From there, we can leave the audio rate at 32khz.

From there, we still have the issues of greater system requirements, more latency, and occasional doubled frames, but it's a huge step forward at least. I would still like to manage no dropped video frames if at all possible, but one thing at a time ...
My initial thought was that staying synced to audio and making the video output asynchronous so that vsync doesn't block the emulator (I thought that was the whole point of triple buffering, but trying it in opengl and direct3d still resulted in audio stutter, so I'm not sure what's up there).
That likewise makes zero sense to me. You'd think triple buffering's whole point was to be non-blocking, but it just ends up blocking once you have two frames in queue anyway. You might as well just save the memory and use double buffering for all it's good for. Obviously, it's trying to prevent you from ever dropping a frame, but that's exactly what we want it to do in our case ...

What's worse is, even if you try querying the scanline position / vblank status and flipping then, the accuracy of the polling is so bad that you end up tearing anyway.

It's terribly frustrating.
DancemasterGlenn
Veteran
Posts: 637
Joined: Sat Apr 21, 2007 8:05 pm

Post by DancemasterGlenn »

Wow. That's definitely huge progress... congrats to you, and thanks to blargg for helping byuu out. I think the speed hit is totally worth finally overcoming this long-standing problem.

And thanks to fitzroy for making his views clear in his full reply. I of course understand the frustration in having the windows port held back (so to speak) because of the way the emulator is coded, but I very much appreciate byuu's practices. The linux build problems could so easily be forgotten once platform-specific fixes start getting implemented, obviously, so it's a nice feeling not to see such fixes slip by on a linux build. That kind of attention doesn't happen very often.
I bring the trouble.
FirebrandX
Trooper
Posts: 376
Joined: Tue Apr 19, 2005 11:08 pm
Location: DFW area, TX USA
Contact:

Post by FirebrandX »

Hey byuu,

Any chance there will be a wip release of that progress? This has always been #1 issue for me and would love to test it out on my system. Even if you decide you don't like the speed hits when all is said and done, it would still be great to have such a version around for those with computers than can handle it.
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

byuu wrote:Now, what we were able to do was skew the audio output rate, such that it's always greater than the video refresh rate (eg 32100hz vs 60.09hz), disable the out-of-order stuff, and then greatly expand the latency to ~120ms, and we were able to get smooth audio and mostly smooth video (every few seconds the same frame would display twice, causing a tiny stuttering effect.)
Under good conditions I've been able to dynamically adjust the resampling ratio to achieve a frame duplication frequency of once every few minutes or so. If you don't want to try to calculate this dynamically, you could supply an advanced configuration tunable that controls the overproduction of samples. This way it would be possible, but inconvenient, to tune it to your system and refresh rate (what works well for 60.5 Hz is unlikely to work well for 59.5 Hz).
tetsuo55
Regular
Posts: 307
Joined: Sat Mar 04, 2006 3:17 pm

Post by tetsuo55 »

So this current version works great for NTSC but makes PAL unplayable?
tetsuo55
Regular
Posts: 307
Joined: Sat Mar 04, 2006 3:17 pm

Post by tetsuo55 »

This GPL resampler code claims that:

-It's the best resampler on the market
-" Arbitrary in this case means that the ratio of input and output sample rates can be an irrational number. "

look here:
http://www.mega-nerd.com/SRC

Not sure if it helps at all, but i saw it in the mame forums. and according to some of the posters it dramatically increases audio quality (read prevent conversion errors, it doesnt add anything that wasnt there)
blargg
Regular
Posts: 327
Joined: Thu Jun 30, 2005 1:54 pm
Location: USA
Contact:

Post by blargg »

Once byuu gets linear resampling working well, I'm going to send over a fast polyphase FIR-based resampler, which is the same thing SRC uses.
tetsuo55
Regular
Posts: 307
Joined: Sat Mar 04, 2006 3:17 pm

Post by tetsuo55 »

blargg wrote:Once byuu gets linear resampling working well, I'm going to send over a fast polyphase FIR-based resampler, which is the same thing SRC uses.
blargg FTW!
byuu

Post by byuu »

I think the speed hit is totally worth finally overcoming this long-standing problem.
I'm not finished optimizing yet. Right now the CPU and SMP can execute up to 10 frames out of sync. In reality, few games will sync that infrequently anyway, and going from six thread switches a second to sixty should not hurt. Probably not even to 600. I was adding in 1,024,000 syncs to get the ~10% speed hit with blargg's DSP, which I've since converted back to a state machine to avoid.
I may want to solve all problems with my cothread hammer, but not all problems are nails ... sigh :/

I can probably find a happy medium that only has a small speed hit of 2-3%, yet gives a much smaller difference in emulated samples per emulated frame.
Under good conditions I've been able to dynamically adjust the resampling ratio to achieve a frame duplication frequency of once every few minutes or so.
That's honestly very acceptable. Not perfect, but it doesn't look like perfect is realistic. And really close is certainly better than nothing ...
If you don't want to try to calculate this dynamically, you could supply an advanced configuration tunable that controls the overproduction of samples. This way it would be possible, but inconvenient, to tune it to your system and refresh rate (what works well for 60.5 Hz is unlikely to work well for 59.5 Hz).
That's the problem I had, that it would be inconvenient to make the end user fine tune it. Obviously, use safe defaults with more latency and more frame doubling for people who don't care as much.

Fine tuning it in the emulator would be hard, as it would require basically running the monitor for ~2-10 seconds to get an estimate of the monitor refresh rate, and then compute what the minimum safe resample rate skew would be.

Could always provide a complementary program that computes this stuff for you to plug in to the emulator. Then I won't have to hook calibration controls into my video and audio libraries.
So this current version works great for NTSC but makes PAL unplayable?
It's playable, just that every six frames it duplicates. It makes it feel blocky, but it's not really worse than the tearing you get now -- just different. You could run the emulator at 100hz to get around that. Or run your monitor at 300hz if you want both NTSC and PAL to work without ever changing the refresh rate. What, your monitor can't do 300hz? Psssh. This is bsnes, not Shoney's all you can emulate buffet, top of the line equipment or get out of line :P
Or 295245e+12hz if you want all speed regulations for both modes to look good.
Once byuu gets linear resampling working well, I'm going to send over a fast polyphase FIR-based resampler, which is the same thing SRC uses.
Neat, thanks! :D
I was going to add 4-tap hermite, but your sounds even cooler! Longer name = better, every time.

Also, I'm going to make the emulator use one sampling rate for all modes to keep resampling simple, and so that we don't have to destroy the audio context entirely (required by the suckier audio APIs) to switch playback modes. I'll let the end user choose the base audio rate for the purists who think 96KHz makes a difference, or want to pretend that their audio card isn't resampling 32KHz to 44KHz internally anyway :P
Last edited by byuu on Thu Aug 14, 2008 10:32 pm, edited 3 times in total.
I.S.T.
Zealot
Posts: 1325
Joined: Tue Nov 27, 2007 7:03 am

Post by I.S.T. »

byuu wrote:
Once byuu gets linear resampling working well, I'm going to send over a fast polyphase FIR-based resampler, which is the same thing SRC uses.
Neat, thanks! :D
I was going to add 4-tap hermite, but your sounds even cooler! Longer name = better, every time.
:lol:
mudlord
has wat u liek
Posts: 559
Joined: Tue Sep 11, 2007 2:54 pm
Location: Banland.

Post by mudlord »

choose the base audio rate for the purists who think 96KHz makes a difference, or want to pretend that their audio card isn't resampling 32KHz to 44KHz internally anyway :P
So, your catering to the placebo crowd? :P
byuu

Post by byuu »

So, your catering to the placebo crowd? :P
Why not, if it's completely transparent? Maybe I'll modify the requested frequency rate so that 96KHz really plays at 16KHz. Would be all the more fun when they brag about how much better it sounds, heheh.
Snark
Trooper
Posts: 376
Joined: Tue Oct 31, 2006 7:17 pm

Post by Snark »

Wow if this issue get finally resolved big thanks in advance to blargg and all those who helped!
I want to fry~~ Sky Hiiiiiiiiigh~
Let's go-o-o-O~ togeda~
creaothceann
Seen it all
Posts: 2302
Joined: Mon Jan 03, 2005 5:04 pm
Location: Germany
Contact:

Post by creaothceann »

byuu wrote:You could run the emulator at 100hz to get around that.
Are there TFTs that support that? :?

Eh, not worth the trouble anyway.
vSNES | Delphi 10 BPLs
bsnes launcher with recent files list
Locked