bsnes/ruby/audio/audio.cpp

285 lines
6.6 KiB
C++
Raw Normal View History

Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#if defined(AUDIO_ALSA)
#include <ruby/audio/alsa.cpp>
#endif
#if defined(AUDIO_AO)
#include <ruby/audio/ao.cpp>
#endif
#if defined(AUDIO_ASIO)
#include <ruby/audio/asio.cpp>
#endif
#if defined(AUDIO_DIRECTSOUND)
#include <ruby/audio/directsound.cpp>
#endif
#if defined(AUDIO_OPENAL)
#include <ruby/audio/openal.cpp>
#endif
#if defined(AUDIO_OSS)
#include <ruby/audio/oss.cpp>
#endif
#if defined(AUDIO_PULSEAUDIO)
#include <ruby/audio/pulseaudio.cpp>
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
#include <ruby/audio/pulseaudiosimple.cpp>
#endif
#if defined(AUDIO_WASAPI)
#include <ruby/audio/wasapi.cpp>
#endif
#if defined(AUDIO_XAUDIO2)
#include <ruby/audio/xaudio2.cpp>
#endif
namespace ruby {
auto Audio::setExclusive(bool exclusive) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->exclusive == exclusive) return true;
if(!instance->hasExclusive()) return false;
if(!instance->setExclusive(instance->exclusive = exclusive)) return false;
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setContext(uintptr context) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->context == context) return true;
if(!instance->hasContext()) return false;
if(!instance->setContext(instance->context = context)) return false;
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setDevice(string device) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->device == device) return true;
if(!instance->hasDevice(device)) return false;
if(!instance->setDevice(instance->device = device)) return false;
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setBlocking(bool blocking) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->blocking == blocking) return true;
if(!instance->hasBlocking()) return false;
if(!instance->setBlocking(instance->blocking = blocking)) return false;
for(auto& resampler : resamplers) resampler.reset(instance->frequency);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setDynamic(bool dynamic) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->dynamic == dynamic) return true;
if(!instance->hasDynamic()) return false;
if(!instance->setDynamic(instance->dynamic = dynamic)) return false;
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setChannels(uint channels) -> bool {
if(resamplers.size() != channels) {
resamplers.reset();
resamplers.resize(channels);
for(auto& resampler : resamplers) resampler.reset(instance->frequency);
}
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->channels == channels) return true;
if(!instance->hasChannels(channels)) return false;
if(!instance->setChannels(instance->channels = channels)) return false;
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setFrequency(uint frequency) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->frequency == frequency) return true;
if(!instance->hasFrequency(frequency)) return false;
if(!instance->setFrequency(instance->frequency = frequency)) return false;
for(auto& resampler : resamplers) resampler.reset(instance->frequency);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
auto Audio::setLatency(uint latency) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(instance->latency == latency) return true;
if(!instance->hasLatency(latency)) return false;
if(!instance->setLatency(instance->latency = latency)) return false;
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
return true;
}
//
auto Audio::clear() -> void {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
for(auto& resampler : resamplers) resampler.reset(instance->frequency);
return instance->clear();
}
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
auto Audio::level() -> double {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
return instance->level();
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
}
auto Audio::output(const double samples[]) -> void {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(!instance->dynamic) return instance->output(samples);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
auto maxDelta = 0.005;
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
double fillLevel = instance->level();
double dynamicFrequency = ((1.0 - maxDelta) + 2.0 * fillLevel * maxDelta) * instance->frequency;
for(auto& resampler : resamplers) {
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
resampler.setInputFrequency(dynamicFrequency);
resampler.write(*samples++);
}
while(resamplers.first().pending()) {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
double samples[instance->channels];
for(uint n : range(instance->channels)) samples[n] = resamplers[n].read();
instance->output(samples);
}
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
}
//
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
auto Audio::create(string driver) -> bool {
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
self.instance.reset();
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
if(!driver) driver = optimalDriver();
#if defined(AUDIO_ALSA)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "ALSA") self.instance = new AudioALSA(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_AO)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "libao") self.instance = new AudioAO(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_ASIO)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "ASIO") self.instance = new AudioASIO(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_DIRECTSOUND)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "DirectSound") self.instance = new AudioDirectSound(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_OPENAL)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "OpenAL") self.instance = new AudioOpenAL(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_OSS)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "OSS") self.instance = new AudioOSS(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_PULSEAUDIO)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "PulseAudio") self.instance = new AudioPulseAudio(*this);
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "PulseAudioSimple") self.instance = new AudioPulseAudioSimple(*this);
#endif
#if defined(AUDIO_WASAPI)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "WASAPI") self.instance = new AudioWASAPI(*this);
#endif
#if defined(AUDIO_XAUDIO2)
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(driver == "XAudio2") self.instance = new AudioXAudio2(*this);
#endif
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
if(!self.instance) self.instance = new AudioDriver(*this);
Update to 20180731 release. byuu says: I've completed moving all the class objects from `unique_pointer<T>` to just T. The one exception is the Emulator::Interface instance. I can absolutely make that a global object, but only in bsnes where there's just the one emulation core. I also moved all the SettingsWindow and ToolsWindow panels out to their own global objects, and fixed a very difficult bug with GTK TabFrame controls. The configuration settings panel is now the emulator settings panel. And I added some spacing between bold label sections on both the emulator and driver settings panels. I gave fixing ComboButtonItem my best shot, given I can't reproduce the crash. Probably won't work, though. Also made a very slight consistency improvement to ruby and renamed driverName() to driver(). ... An important change ... as a result of moving bsnes to global objects, this means that the constructors for all windows run before the presentation window is displayed. Before this change, only the presentation window was constructed first berore displaying it, followed by the construction of the rest of the GUI windows. The upside to this is that as soon as you see the main window, the GUI is ready to go without a period where it's unresponsive. The downside to this is it takes about 1.5 seconds to show the main window, compared to around 0.75 seconds before. I've no intention of changing that back. So if the startup time becomes a problem, then we'll just have to work on optimizing hiro, so that it can construct all the global Window objects quicker. The main way to do that would be to not do calls to the Layout::setGeometry functions for every widget added, and instead wait until the window is displayed. But I don't have an easy way to do that, because you want the widget geometry values to be sane even before the window is visible to help size certain things.
2018-07-31 10:56:45 +00:00
return self.instance->create();
}
auto Audio::hasDrivers() -> vector<string> {
return {
#if defined(AUDIO_ASIO)
"ASIO",
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_WASAPI)
"WASAPI",
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_XAUDIO2)
"XAudio2",
#endif
#if defined(AUDIO_DIRECTSOUND)
"DirectSound",
#endif
#if defined(AUDIO_ALSA)
"ALSA",
#endif
#if defined(AUDIO_OSS)
"OSS",
#endif
#if defined(AUDIO_OPENAL)
"OpenAL",
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
#endif
#if defined(AUDIO_PULSEAUDIO)
"PulseAudio",
#endif
#if defined(AUDIO_PULSEAUDIOSIMPLE)
"PulseAudioSimple",
#endif
#if defined(AUDIO_AO)
"libao",
#endif
"None"};
Update to 20180728 release. byuu says: Sigh, I seem to be spiraling a bit here ... but the work is very important. Hopefully I can get a solid WIP together soon. But for now... I've integrated dynamic rate control into ruby::Audio via setDynamic(bool) for now. It's very demanding, as you would expect. When it's not in use, I realized the OSS driver's performance was pretty bad due to calling write() for every sample for every channel. I implemented a tiny 256-sample buffer and bsnes went from 290fps to 330fps on my FreeBSD desktop. It may be possible to do the same buffering with DRC, but for now, I'm not doing so, and adjusting the audio input frequency on every sample. I also added ruby::Video::setFlush(bool), which is available only in the OpenGL drivers, and this causes glFinish() to be called after swapping display buffers. I really couldn't think of a good name for this, "hard GPU sync" sounds kind of silly. In my view, flush is what commits queued events. Eg fflush(). OpenGL of course treats glFlush differently (I really don't even know what the point of it is even after reading the manual ...), and then has glFinish ... meh, whatever. It's setFlush(bool) until I come up with something better. Also as expected, this one's a big hit to performance. To implement the DRC, I started putting helper functions into the ruby video/audio/input core classes. And then the XVideo driver started crashing. It took hours and hours and hours to track down the problem: you have to clear XSetWindowAttributes to zero before calling XCreateWindow. No amount of `--sync`, `gdb break gdk_x_error`, `-Og`, etc will make Xlib be even remotely helpful in debugging errors like this. The GLX, GLX2, and XVideo drivers basically worked by chance before. If the stack frame had the right memory cleared, it worked. Otherwise it'd crash with BadValue, and my changing things broke that condition on the XVideo driver. So this has been fixed in all three now. Once XVideo was running again, I realized that non-power of two video sizes were completely broken for the YUV formats. It took a while, but I managed to fix all of that as well. At this point, most of ruby is going to be broken outside of FreeBSD, as I still need to finish updating all the drivers.
2018-07-28 11:21:39 +00:00
}
auto Audio::optimalDriver() -> string {
#if defined(AUDIO_ASIO)
return "ASIO";
#elif defined(AUDIO_WASAPI)
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO)
return "PulseAudio";
#elif defined(AUDIO_PULSEAUDIOSIMPLE)
return "PulseAudioSimple";
#elif defined(AUDIO_AO)
return "libao";
#else
return "None";
#endif
}
auto Audio::safestDriver() -> string {
#if defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_WASAPI)
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OSS)
return "OSS";
#elif defined(AUDIO_OPENAL)
return "OpenAL";
#elif defined(AUDIO_PULSEAUDIO)
return "PulseAudio";
#elif defined(AUDIO_PULSEAUDIOSIMPLE)
return "PulseAudioSimple";
#elif defined(AUDIO_AO)
return "libao";
#elif defined(AUDIO_ASIO)
return "ASIO";
#else
return "None";
#endif
}
}