More improvements to SameBoy audio interface for Super Game Boy.
Added a fix for a very rare crashing issue with SDL 2.0 joypad support.
This commit is contained in:
byuu 2019-10-06 10:14:30 +09:00
parent 1698533774
commit e22167cf82
8 changed files with 42 additions and 20 deletions

View File

@ -55,6 +55,7 @@ struct Filter {
struct Stream {
auto reset(uint channels, double inputFrequency, double outputFrequency) -> void;
auto reset() -> void;
auto frequency() const -> double;
auto setFrequency(double inputFrequency, maybe<double> outputFrequency = nothing) -> void;
@ -63,7 +64,7 @@ struct Stream {
auto addLowPassFilter(double cutoffFrequency, Filter::Order order, uint passes = 1) -> void;
auto addHighPassFilter(double cutoffFrequency, Filter::Order order, uint passes = 1) -> void;
auto pending() const -> bool;
auto pending() const -> uint;
auto read(double samples[]) -> uint;
auto write(const double samples[]) -> void;

View File

@ -9,6 +9,12 @@ auto Stream::reset(uint channelCount, double inputFrequency, double outputFreque
setFrequency(inputFrequency, outputFrequency);
}
auto Stream::reset() -> void {
for(auto& channel : channels) {
channel.resampler.reset(this->inputFrequency, this->outputFrequency);
}
}
auto Stream::frequency() const -> double {
return inputFrequency;
}
@ -81,8 +87,9 @@ auto Stream::addHighPassFilter(double cutoffFrequency, Filter::Order order, uint
}
}
auto Stream::pending() const -> bool {
return channels && channels[0].resampler.pending();
auto Stream::pending() const -> uint {
if(!channels) return 0;
return channels[0].resampler.pending();
}
auto Stream::read(double samples[]) -> uint {

View File

@ -29,7 +29,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "bsnes";
static const string Version = "111";
static const string Version = "111.1";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org";

View File

@ -40,6 +40,7 @@ namespace SameBoy {
float left = sample->left / 32768.0f;
float right = sample->right / 32768.0f;
icd.apuWrite(left, right);
//print(dsp.stream->pending(), " ", icd.stream->pending(), "\n");
}
static auto vblank(GB_gameboy_t*) -> void {
@ -63,7 +64,7 @@ auto ICD::main() -> void {
step(clocks >> 1);
} else { //DMG halted
apuWrite(0.0, 0.0);
step(256);
step(128);
}
synchronizeCPU();
}
@ -75,16 +76,15 @@ auto ICD::step(uint clocks) -> void {
auto ICD::load() -> bool {
information = {};
//todo: connect to SFC random enable setting
//GB_random_set_enabled(false);
GB_random_set_enabled(configuration.hacks.entropy != "None");
if(Frequency == 0) {
GB_init(&sameboy, GB_MODEL_SGB_NO_SFC);
GB_load_boot_rom_from_buffer(&sameboy, (const unsigned char*)&SGB1BootROM[0], 256);
GB_set_sample_rate(&sameboy, uint(system.cpuFrequency() / 5.0 / 128.0));
GB_set_sample_rate(&sameboy, 32768);
} else {
GB_init(&sameboy, GB_MODEL_SGB2_NO_SFC);
GB_load_boot_rom_from_buffer(&sameboy, (const unsigned char*)&SGB2BootROM[0], 256);
GB_set_sample_rate(&sameboy, uint(Frequency / 5.0 / 128.0));
GB_set_sample_rate(&sameboy, 32000);
}
GB_set_highpass_filter_mode(&sameboy, GB_HIGHPASS_ACCURATE);
GB_set_icd_hreset_callback(&sameboy, &SameBoy::hreset);
@ -138,11 +138,12 @@ auto ICD::unload() -> void {
}
auto ICD::power(bool reset) -> void {
uint frequency = (Frequency ? Frequency : system.cpuFrequency()) / 5.0;
//SGB1 uses CPU oscillator; SGB2 uses dedicated oscillator
create(ICD::Enter, (Frequency ? Frequency : system.cpuFrequency()) / 5.0);
if(!reset) {
stream = Emulator::audio.createStream(2, uint((Frequency ? Frequency : system.cpuFrequency()) / 5.0 / 128.0));
}
create(ICD::Enter, frequency);
if(!reset) stream = Emulator::audio.createStream(2, frequency / 128);
dsp.stream->reset();
icd.stream->reset();
for(auto& packet : this->packet) packet = {};
packetSize = 0;

View File

@ -19,7 +19,9 @@ auto DSP::main() -> void {
int count = spc_dsp.sample_count();
if(count > 0) {
for(uint n = 0; n < count; n += 2) {
stream->sample(samplebuffer[n + 0] / 32768.0f, samplebuffer[n + 1] / 32768.0f);
float left = samplebuffer[n + 0] / 32768.0f;
float right = samplebuffer[n + 1] / 32768.0f;
stream->sample(left, right);
}
spc_dsp.set_output(samplebuffer, 8192);
}

View File

@ -170,13 +170,23 @@ auto InputMapping::Binding::icon() -> image {
}
auto InputMapping::Binding::name() -> string {
if(device && device->isKeyboard()) {
//if ruby drivers cannot report accurate vendor/product IDs (eg SDL),
//and the user closes the emulator, changes gamepads, and restarts it,
//it is possible the wrong device will now be mapped to the input IDs.
//that could potentially make the group/input IDs go out of bounds.
if(!device) return {};
if(group >= device->size()) return {};
if(input >= device->group(group).size()) return {};
if(device->isKeyboard()) {
return device->group(group).input(input).name();
}
if(device && device->isMouse()) {
if(device->isMouse()) {
return device->group(group).input(input).name();
}
if(device && device->isJoypad()) {
if(device->isJoypad()) {
string name{Hash::CRC16(string{device->id()}).digest().upcase()};
name.append(" ", device->group(group).name());
name.append(" ", device->group(group).input(input).name());
@ -185,6 +195,7 @@ auto InputMapping::Binding::name() -> string {
if(qualifier == Qualifier::Rumble) name.append(" Rumble");
return name;
}
return {};
}

View File

@ -8,7 +8,7 @@ namespace nall::DSP::Resampler {
struct Cubic {
inline auto reset(double inputFrequency, double outputFrequency = 0, uint queueSize = 0) -> void;
inline auto setInputFrequency(double inputFrequency) -> void;
inline auto pending() const -> bool;
inline auto pending() const -> uint;
inline auto read() -> double;
inline auto write(double sample) -> void;
@ -37,7 +37,7 @@ auto Cubic::setInputFrequency(double inputFrequency) -> void {
ratio = inputFrequency / outputFrequency;
}
auto Cubic::pending() const -> bool {
auto Cubic::pending() const -> uint {
return samples.pending();
}

View File

@ -41,7 +41,7 @@ struct queue {
template<typename U = T> auto capacity() const -> uint { return _capacity * sizeof(T) / sizeof(U); }
template<typename U = T> auto size() const -> uint { return _size * sizeof(T) / sizeof(U); }
auto empty() const -> bool { return _size == 0; }
auto pending() const -> bool { return _size > 0; }
auto pending() const -> uint { return _size; }
auto full() const -> bool { return _size >= (int)_capacity; }
auto underflow() const -> bool { return _size < 0; }
auto overflow() const -> bool { return _size > (int)_capacity; }