ludo
ludo copied to clipboard
Refactored audio stack with PortAudio
Built with OpenAL, Ludo has audible audio latency (hundreds of milliseconds!), which is unbearable for retro gaming. I managed to refactor it with PortAudio, which is as much portable as OpenAL, and has much lower latency.
Awesome, will try it asap...
Can you replace openal-soft by portaudio in the osx sections of ci.yml and cd.yml?
I think I know what's wrong with the test on OSX. Not sure why it happens on this PR and not on others though.
Doing this in SetPixelFormat seems to workaround the bug. There is a division by 0 or of 0.
// PixelStorei also needs to be updated whenever bpp changes
defer func() {
if video.pitch != 0 && video.bpp != 0 {
gl.PixelStorei(gl.UNPACK_ROW_LENGTH, video.pitch/video.bpp)
}
}()
Edit: forget what I said, the test did fail on something portaudio related, in portaudio.(*Stream).Close(0x0) in audio.Reconfigure(0xac44) in audio.go:112
You can just call audio.Init() after Init(&video.Video{}) in Test_coreLoadGame
BTW is there any package manager other than choco in windows env of github workflow?
There may be another one, I see portaudio on a package manager called vcpkg here https://github.com/PortAudio/portaudio/issues/578
I tried your branch on OSX, I noticed 2 things:
- the audio is crackling a little bit, but noticeably
- the implementation doesn't use blocking audio, but it's usually good to block on audio in emulation, and portaudio documentation does mention a way of doing it
I think the crackling occurrs when the core sends data slower than sample rate, causing 0 filled in the interval. Also, since the condition of cores is not expectable, using blocking may cause serious gliches like repeating or unsyncing, I guess.
Here' how mine work: write() convert and put samples into paBuf and push paPtr ahead, and blocks the core if it goes too fast, preventing the not-played data in paBuf from being overwrited like in the classic snake game :) paCallback() is called by portaudio, which get samples from paBuf and push paPlayPtr ahead, which always chases paPtr. if paPlayPtr is not smaller than paPtr, the playback stops by receiving zeros.
Hmm.. Hey, maybe we can just turn off blocking in write() when it is fast-forwarding, instead of returning size and letting it muted. And volume may be reduced when fast-forwarding.
Weird enough... Only right channel is played even though PA stream opened with 2 channels. I'll go to stackoverflow <:-/
Okay finally it is stereo now :-)
BTW I want to know if the patch will pass ci/cd now :-)
It seems that github workflow env has no audio device, causing the failure 'cause portaudio works with audio hardware. We have to do something to the tests <:-/