-
Notifications
You must be signed in to change notification settings - Fork 52
PushSamplesRequestBufs() fix #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
… rates. Lower rates still produce issue.
…s errors at lower framethrottled rates. Previously number of samples requested at 10Hz, 20Hz exceeded capacity of buffers. Complex interactions of allegro requests and buffer code make deeper analysis difficult.
…Estimated FPS rate of fskipper needs to be used instead of machine frequency due to lack of allegro timer or other limiters when using unthrottled mode
…mplesRequestBufs errors will occur at low framerates (20Hz and especially 10Hz) due to buffers not being large enough
|
I've reverted the sound buffer sample capacity to 1024 to avoid the unacceptable increase in latency of the fix. One workaround for this could be a variable capacity samples buffer, increase in capacity and latency at just the lower framerates (but the sound lag is still noticeable even here). But this feels like a bit of a kludge. I don't think this constitutes a solution so much a duct tape fix. I will try to think a bit more over the weekend, but this may not be fully solvable without going way deeper than I'm currently able. Edit: It occurs to me that maybe another solution is, instead of increasing the samples generated in the buffer at lower framerates, to instead get allegro consume more samples instead. Not sure if this works for higher framerates, but I will try and see if it at least works. |
…ng extremely low framerates where output delay exceeds sound buffer latency capacity
|
I added a timeout to the allegro wait on the the framerate timer throttle queue, followed by a Sound_Update() call. There are a small number of remaining PushSamplesRequestBufs() errors when loading certain new roms (Sonic 2) and apparently during sound changeover from the bootup logo. Apart from these the results appear stable. I have only tested this on SMS roms. |
|
I usually leave it to Omar to merge here, but it all LGTM |
|
If I try sample playing roms such as "Music Station" or "Alex Kidd: The Lost Stars" the samples are noticeably too highly pitched with this patch. |
Hmm, actually it only happened because I was running emulating a PAL/SECAM system yet having emulator running at 60 Hz. According to this factor: const double emulated_to_output_ratio = g_machine.TV->screen_frequency / (double)output_frequency;Would it make sense to support that use case without effectively pitching the sound? |
Yes. I will need to fix this. The "Music Station" rom is helpful Edit: The pitching is definitely present and increases noticeably as you change framerate.
I don't understand why simply asking for more samples changes the pitch of the sound from the sound unit. It is behaving as if the sound were truly "slowed down", like running a tape at half speed. But why should this be the case if all we did was ask for more sound samples from the sound unit? There must be something complex going on here within the FM chip emulator. Before this change, the output from the sound would causes skips and PushSamplesRequestBufs() errors, but the pitch would be unchanged. I don't currently understand why pitch is affected. I will try to see if there is a setting
Edit 3: This issue affects samples generated by the PSG chip. I'll need to revisit some assumptions and check how these samples are being generated. Edit 4: Recorded sound samples are a tricky case. For ordinary sounds/music, the PSG chip registers are simply set to generate constantly ossillating tones. You then asking for enough samples for a certain output number of seconds are you are done. Pitch remains unchanged. But to generate recorded voice samples, the chip does not use tones. Instead the PSG chip volume is periodically set to a constant (non-ossillating) volume level directly, with volume changes only occurring when registers are changed. This explains the change in pitch when the number of samples was increased at lower framerates(e.g. 30Hz). The volumes were held constant for longer, decreasing the number of volume changes and hence lowering the perceived frequency. But there is another catch with samples. The timing is controlled by the CPU, during calls to SN76489_Write() in Out_SMS() I think. In practice this means that voice samples can only be generated for at maximum 1/60 emulated seconds. In the current master branch, this is the case. At lower framerates, 30Hz say, a voice sample is generated for 1/60th of a second at the correct pitch. But then in the remaining 1/60th of a second fill-in time Allegro needs to fill up with samples in SoundStream_Update(), there is only one large call to PSG_WriteSamples(), during which the PSG tone volume is constant and the voice sample does not play. This is leading to starts and stops in the voice sample playback. This is quite a tricky issue to solve given the fundamentally different ways ordinary music tones and voice sample sounds are generated. Note, it is possible to pitch down regular music as well by using SN76489_SetClock(), but I haven't found a way to do this acceptably. A more drastic option would be to somehow record and repeat the PSG write commands to fill in time during lower framerates, and cut these off at higher framerates, restoring the proper state of the PSG chip when starting the next frame. Maybe something so radical might not be needed if I can figure it out. |
|
I think it is sensible to have the samples pitch change when the system speed is incorrect. |
My current thinking on how to achieve constant pitch time stretching (and possibly allow the chipmunk effect too), is to make the following changes to the sound system. I think this will at least work for the PSG chip.
I believe this method could work to "time extend" the sounds consistently. I think it could also be adjusted at the output stage to produce the "chipmunk" effect as well (by adjusting the number of sample being output for each PSG state change). I'm not 100% if this will work or not, but I'd like to give it a go. |
In theory perhaps but our general UI design + database override (certain games are forced to PAL mode for compatibility, yet speed is still 60 hz, which is somehow nice in some situation, yet somehow incorrect) doesn’t make it very sensible ? I would assume most modern emulators have had to deal with issues like this and there’s probably good code references, if not whole librairies that may be used for it. |
|
I think Meka should be a bit more like Emulicious and have NTSC/60Hz and PAL/50Hz as the "100%" speed, and let people pick relative percentage speeds. But that's a much bigger change than this. So I would say it is fine as it is, and the bigger change can be done separately. |
2nd attempt at a fix for the long standing PushSamplesRequestBufs issue. Fix for #74
The root cause of the issue is the inter-relationships between the sound.cpp code, frame skipper, and allegro.
output_seconds = CORRECTION_RATIO * emulated_secondsThe solution isn't perfect and PushSamplesRequestBufs errors can still be seen when changing the framerate, but in testing at fixed framerates this appears stable.
I'm not confident this solution is truly robust given the complexity of the sound code, but it appears to be a working fix, finally.