whscullin / apple2js

An Apple II emulator originally written in Javascript, now being converted to TypeScript
http://www.scullinsteel.com/apple2/
MIT License
438 stars 57 forks source link

Option to slow acceleration during audio playback #171

Open inexorabletash opened 1 year ago

inexorabletash commented 1 year ago

Feature request: an option that can be passed via the query string that would slow acceleration during audio playback.

Context:

Many hardware accelerators (e.g. FASTChip, ZIP Chip, etc) and other emulators (e.g. Virtual ][) have settings to slow acceleration to 1MHz temporarily during audio playback. The duration of the slowdown is a heuristic; I don't know if there's a universally agreed upon value. 1-5ms maybe?

This was reported as an issue when using Apple II DeskTop with //jse - the alert sounds pay as quick chirps. You can try this out on a2desktop.com - click the "Try it now with Apple //jse" button, use the Apple menu > Control Panels > Sounds, click various options.

NB: The sound code does slow some hardware accelerators that don't auto-slow for audio (IIgs, Mac IIe Card, Laser 128). I don't think that's a good route to go down for //jse, though.

iflan commented 1 year ago

That's very interesting. It made me think about different ways of approaching it.

The way you suggest is mostly straightforward. The only minor problem is that the emulator doesn't (currently) have code that supports delayed actions, like going back into accelerated mode, except by using browser timers. But the browser timers are in real-time, regardless of what the emulator is doing.

I wonder if it is possible to just slow down the sound output instead of actually slowing down the emulation by changing how _calcSampleRate works. I'm guessing that this would work fine because few (if any) programs that make sound count on the accelerator. (And if they did count on the accelerator, then they would have to account for the difference between the FASTChip, ZIP Chip and others.

Thoughts?

inexorabletash commented 1 year ago

For long sounds (eg Electric Duet) the buffer would get very large. For short SFX it might work.

whscullin commented 1 year ago

For the most part the way cycles are handled hasn't been updated since it was a struggle to get 1/30th of a second's worth of CPU into the gap between frames. Having a conditional or any additional code during the run loop was troublesome. Now we can do 60fps with room to spare, so it might be reasonable add code to count fast and slow cycles and handle frames that are mix. We'd have to think about how we'd want to do that.