From 35ff15f83e4e4239a0f791c9ed4cf119074a204b Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 21 Jul 2018 21:06:40 +1000 Subject: [PATCH] Update to v106r50 release. byuu says: Changelog: - emulator/video,audio: various cleanups - emulator/audio: removed reverb effect (it breaks very badly on high-frequency systems) - emulator/audio: the Nyquist anti-aliasing lowpass filter is now generated automatically instead of set per-core - at 44.1KHz output, it's set to 22KHz; at 48KHz, it's set to 22KHz; at 96KHz, it's set to 25KHz - this filter now takes the bsnes emulation speed setting into account - all system/video.cpp files removed; inlined in System::power() and Interface::set() instead - sfc/cpu: pre-compute `HTIME` as `HTIME+1<<2` for faster comparisons of HIRQs - sfc/cpu: re-add check to block IRQs on the last dot of each frame (minor speed hit) - hiro/gtk3: fixed headers for Linux compilation finally - hiro/gtk,qt: fixed settings.cpp logic so initial values are used when no settings.bml file exists - hiro/gtk: started a minor experiment to specify theming information in settings.bml files - nall/dsp: allow the precision type (double) to be overridden (to float) - nall: add some helpers for generating pre-compiled headers - it was a failure to try using them for higan, however ... - nall: add some helpers for reading fallback values from empty `Markup::Node[search]` statements Todo: - CRITICAL: a lot of my IRQ/NMI/HDMA timing tests are failing with the fast PPU ... need to figure out why - space between Emulator::video functions and Emulator::audio functions in gb/system/system.cpp - remove Audio/Reverb/Enable from settings.bml in target-bsnes --- higan/GNUmakefile | 2 +- higan/audio/audio.cpp | 40 +++++------------------- higan/audio/audio.hpp | 11 +++---- higan/audio/stream.cpp | 20 +++++++++++- higan/emulator/emulator.hpp | 2 +- higan/fc/apu/apu.cpp | 1 - higan/fc/interface/interface.cpp | 2 +- higan/fc/system/system.cpp | 10 ++---- higan/fc/system/system.hpp | 4 --- higan/fc/system/video.cpp | 6 ---- higan/gb/apu/apu.cpp | 1 - higan/gb/interface/interface.cpp | 6 ++-- higan/gb/system/system.cpp | 12 +++---- higan/gb/system/video.cpp | 9 ------ higan/gba/apu/apu.cpp | 1 - higan/gba/interface/interface.cpp | 6 ++-- higan/gba/system/system.cpp | 12 +++---- higan/gba/system/system.hpp | 4 --- higan/gba/system/video.cpp | 8 ----- higan/md/psg/psg.cpp | 1 - higan/md/system/system.cpp | 6 ++-- higan/md/ym2612/ym2612.cpp | 1 - higan/ms/psg/psg.cpp | 1 - higan/ms/system/system.cpp | 6 ++-- higan/pce/psg/psg.cpp | 1 - higan/pce/system/system.cpp | 6 ++-- higan/sfc/coprocessor/icd/icd.cpp | 3 +- higan/sfc/cpu/cpu.hpp | 4 +-- higan/sfc/cpu/io.cpp | 12 ++++--- higan/sfc/cpu/irq.cpp | 5 +-- higan/sfc/cpu/serialization.cpp | 4 +-- higan/sfc/system/system.cpp | 6 ++-- higan/target-bsnes/program/audio.cpp | 3 -- higan/target-bsnes/program/game.cpp | 4 +-- higan/target-bsnes/settings/audio.cpp | 6 ---- higan/target-bsnes/settings/settings.hpp | 1 - higan/target-higan/program/medium.cpp | 5 ++- higan/target-higan/program/utility.cpp | 3 -- higan/target-higan/settings/audio.cpp | 4 --- higan/target-higan/settings/settings.cpp | 1 - higan/target-higan/settings/settings.hpp | 1 - higan/video/video.cpp | 11 +++---- higan/video/video.hpp | 4 +-- higan/ws/apu/apu.cpp | 1 - higan/ws/interface/interface.cpp | 6 ++-- higan/ws/system/system.cpp | 12 +++---- higan/ws/system/system.hpp | 4 --- higan/ws/system/video.cpp | 8 ----- hiro/gtk/header.hpp | 10 ++++-- hiro/gtk/settings.cpp | 33 ++++++++++++------- hiro/gtk/settings.hpp | 5 +++ hiro/gtk/widget/table-view.cpp | 4 +-- hiro/qt/settings.cpp | 27 +++++++++------- hiro/qt/window.cpp | 1 - nall/GNUmakefile | 14 +++++++-- nall/dsp/dsp.hpp | 11 +++++++ nall/dsp/iir/biquad.hpp | 36 +++++++++++---------- nall/dsp/iir/one-pole.hpp | 20 ++++++------ nall/dsp/resampler/cubic.hpp | 31 +++++++++--------- nall/string/markup/node.hpp | 6 ++++ 60 files changed, 218 insertions(+), 267 deletions(-) delete mode 100644 higan/fc/system/video.cpp delete mode 100644 higan/gb/system/video.cpp delete mode 100644 higan/gba/system/video.cpp delete mode 100644 higan/ws/system/video.cpp create mode 100644 nall/dsp/dsp.hpp diff --git a/higan/GNUmakefile b/higan/GNUmakefile index 2463cf03..63c5a6d3 100644 --- a/higan/GNUmakefile +++ b/higan/GNUmakefile @@ -47,5 +47,5 @@ include $(ui)/GNUmakefile -include obj/*.d clean: - $(call delete,out/*) $(call delete,obj/*) + $(call delete,out/*) diff --git a/higan/audio/audio.cpp b/higan/audio/audio.cpp index 8fb963a6..22132005 100644 --- a/higan/audio/audio.cpp +++ b/higan/audio/audio.cpp @@ -5,30 +5,14 @@ namespace Emulator { #include "stream.cpp" Audio audio; -auto Audio::reset(maybe channels_, maybe frequency_) -> void { - interface = nullptr; - - if(channels_) channels = channels_(); - if(frequency_) frequency = frequency_(); - - streams.reset(); - reverb.reset(); - - reverb.resize(channels); - for(auto c : range(channels)) { - reverb[c].resize(7); - reverb[c][0].resize(1229); - reverb[c][1].resize(1559); - reverb[c][2].resize(1907); - reverb[c][3].resize(4057); - reverb[c][4].resize(8117); - reverb[c][5].resize(8311); - reverb[c][6].resize(9931); - } +Audio::~Audio() { + reset(nullptr); } -auto Audio::setInterface(Interface* interface) -> void { +auto Audio::reset(Interface* interface) -> void { this->interface = interface; + streams.reset(); + channels = 0; } auto Audio::setFrequency(double frequency) -> void { @@ -46,11 +30,8 @@ auto Audio::setBalance(double balance) -> void { this->balance = balance; } -auto Audio::setReverb(bool enabled) -> void { - this->reverbEnable = enabled; -} - auto Audio::createStream(uint channels, double frequency) -> shared_pointer { + this->channels = max(this->channels, channels); shared_pointer stream = new Stream; stream->reset(channels, frequency, this->frequency); streams.append(stream); @@ -67,7 +48,7 @@ auto Audio::process() -> void { for(auto& sample : samples) sample = 0.0; for(auto& stream : streams) { - double buffer[16]; + double buffer[channels]; uint length = stream->read(buffer), offset = 0; for(auto& sample : samples) { @@ -78,13 +59,6 @@ auto Audio::process() -> void { for(auto c : range(channels)) { samples[c] = max(-1.0, min(+1.0, samples[c] * volume)); - - if(reverbEnable) { - samples[c] *= 0.125; - for(auto n : range(7)) samples[c] += 0.125 * reverb[c][n].last(); - for(auto n : range(7)) reverb[c][n].write(samples[c]); - samples[c] *= 8.000; - } } if(channels == 2) { diff --git a/higan/audio/audio.hpp b/higan/audio/audio.hpp index ca027f3a..7597e256 100644 --- a/higan/audio/audio.hpp +++ b/higan/audio/audio.hpp @@ -12,13 +12,12 @@ struct Filter; struct Stream; struct Audio { - auto reset(maybe channels = nothing, maybe frequency = nothing) -> void; - auto setInterface(Interface* interface) -> void; + ~Audio(); + auto reset(Interface* interface) -> void; auto setFrequency(double frequency) -> void; auto setVolume(double volume) -> void; auto setBalance(double balance) -> void; - auto setReverb(bool enabled) -> void; auto createStream(uint channels, double frequency) -> shared_pointer; @@ -29,14 +28,11 @@ private: vector> streams; uint channels = 0; - double frequency = 0.0; + double frequency = 48000.0; double volume = 1.0; double balance = 0.0; - bool reverbEnable = false; - vector>> reverb; - friend class Stream; }; @@ -68,6 +64,7 @@ struct Stream { private: struct Channel { vector filters; + vector nyquist; DSP::Resampler::Cubic resampler; }; vector channels; diff --git a/higan/audio/stream.cpp b/higan/audio/stream.cpp index 547db942..d036cf41 100644 --- a/higan/audio/stream.cpp +++ b/higan/audio/stream.cpp @@ -16,13 +16,28 @@ auto Stream::setFrequency(double inputFrequency, maybe outputFrequency) if(outputFrequency) this->outputFrequency = outputFrequency(); for(auto& channel : channels) { + channel.nyquist.reset(); channel.resampler.reset(this->inputFrequency, this->outputFrequency); } + + if(this->inputFrequency >= this->outputFrequency * 2) { + //add a low-pass filter to prevent aliasing during resampling + double cutoffFrequency = min(25000.0, this->outputFrequency / 2.0 - 2000.0); + for(auto& channel : channels) { + uint passes = 3; + for(uint pass : range(passes)) { + DSP::IIR::Biquad filter; + double q = DSP::IIR::Biquad::butterworth(passes * 2, pass); + filter.reset(DSP::IIR::Biquad::Type::LowPass, cutoffFrequency, this->inputFrequency, q); + channel.nyquist.append(filter); + } + } + } } auto Stream::addFilter(Filter::Order order, Filter::Type type, double cutoffFrequency, uint passes) -> void { for(auto& channel : channels) { - for(auto pass : range(passes)) { + for(uint pass : range(passes)) { Filter filter{order}; if(order == Filter::Order::First) { @@ -63,6 +78,9 @@ auto Stream::write(const double samples[]) -> void { case Filter::Order::Second: sample = filter.biquad.process(sample); break; } } + for(auto& filter : channels[c].nyquist) { + sample = filter.process(sample); + } channels[c].resampler.write(sample); } diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 689b2d6a..7b6083da 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -13,7 +13,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.49"; + static const string Version = "106.50"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/fc/apu/apu.cpp b/higan/fc/apu/apu.cpp index c35d6adb..433cfba2 100644 --- a/higan/fc/apu/apu.cpp +++ b/higan/fc/apu/apu.cpp @@ -77,7 +77,6 @@ auto APU::power(bool reset) -> void { stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 90.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 440.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 14000.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); pulse[0].power(); pulse[1].power(); diff --git a/higan/fc/interface/interface.cpp b/higan/fc/interface/interface.cpp index 7fc12e0f..2e49241d 100644 --- a/higan/fc/interface/interface.cpp +++ b/higan/fc/interface/interface.cpp @@ -177,7 +177,7 @@ auto Interface::get(const string& name) -> any { auto Interface::set(const string& name, const any& value) -> bool { if(name == "Color Emulation" && value.is()) { settings.colorEmulation = value.get(); - system.configureVideoPalette(); + Emulator::video.setPalette(); return true; } if(name == "Scanline Emulation" && value.is()) return settings.scanlineEmulation = value.get(), true; diff --git a/higan/fc/system/system.cpp b/higan/fc/system/system.cpp index 4f297d52..9ebee864 100644 --- a/higan/fc/system/system.cpp +++ b/higan/fc/system/system.cpp @@ -2,7 +2,6 @@ namespace Famicom { -#include "video.cpp" #include "serialization.cpp" System system; Scheduler scheduler; @@ -63,13 +62,10 @@ auto System::unload() -> void { } auto System::power(bool reset) -> void { - Emulator::video.reset(); - Emulator::video.setInterface(interface); - configureVideoPalette(); - configureVideoEffects(); + Emulator::video.reset(interface); + Emulator::video.setPalette(); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); scheduler.reset(); cartridge.power(); diff --git a/higan/fc/system/system.hpp b/higan/fc/system/system.hpp index 9d666b3f..689a502b 100644 --- a/higan/fc/system/system.hpp +++ b/higan/fc/system/system.hpp @@ -16,10 +16,6 @@ struct System { auto init() -> void; auto term() -> void; - //video.cpp - auto configureVideoPalette() -> void; - auto configureVideoEffects() -> void; - //serialization.cpp auto serialize() -> serializer; auto unserialize(serializer&) -> bool; diff --git a/higan/fc/system/video.cpp b/higan/fc/system/video.cpp deleted file mode 100644 index 66d09298..00000000 --- a/higan/fc/system/video.cpp +++ /dev/null @@ -1,6 +0,0 @@ -auto System::configureVideoPalette() -> void { - Emulator::video.setPalette(); -} - -auto System::configureVideoEffects() -> void { -} diff --git a/higan/gb/apu/apu.cpp b/higan/gb/apu/apu.cpp index b9f7498d..a91afb1a 100644 --- a/higan/gb/apu/apu.cpp +++ b/higan/gb/apu/apu.cpp @@ -56,7 +56,6 @@ auto APU::power() -> void { if(!Model::SuperGameBoy()) { stream = Emulator::audio.createStream(2, frequency()); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); } for(uint n = 0xff10; n <= 0xff3f; n++) bus.mmio[n] = this; diff --git a/higan/gb/interface/interface.cpp b/higan/gb/interface/interface.cpp index 3d0a41f6..1fb71003 100644 --- a/higan/gb/interface/interface.cpp +++ b/higan/gb/interface/interface.cpp @@ -100,13 +100,15 @@ auto Interface::get(const string& name) -> any { auto Interface::set(const string& name, const any& value) -> bool { if(name == "Blur Emulation" && value.is()) { settings.blurEmulation = value.get(); - system.configureVideoEffects(); + if(Model::SuperGameBoy()) return true; + Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); return true; } if(name == "Color Emulation" && value.is()) { settings.colorEmulation = value.get(); - system.configureVideoPalette(); + if(Model::SuperGameBoy()) return true; + Emulator::video.setPalette(); return true; } diff --git a/higan/gb/system/system.cpp b/higan/gb/system/system.cpp index b02e3457..8b0996c2 100644 --- a/higan/gb/system/system.cpp +++ b/higan/gb/system/system.cpp @@ -2,7 +2,6 @@ namespace GameBoy { -#include "video.cpp" #include "serialization.cpp" System system; Scheduler scheduler; @@ -83,13 +82,10 @@ auto System::unload() -> void { auto System::power() -> void { if(model() != Model::SuperGameBoy) { - Emulator::video.reset(); - Emulator::video.setInterface(interface); - configureVideoPalette(); - configureVideoEffects(); - - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::video.reset(interface); + Emulator::video.setPalette(); + Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); + Emulator::audio.reset(interface); } scheduler.reset(); diff --git a/higan/gb/system/video.cpp b/higan/gb/system/video.cpp deleted file mode 100644 index 5fd57461..00000000 --- a/higan/gb/system/video.cpp +++ /dev/null @@ -1,9 +0,0 @@ -auto System::configureVideoPalette() -> void { - if(model() == Model::SuperGameBoy) return; - Emulator::video.setPalette(); -} - -auto System::configureVideoEffects() -> void { - if(model() == Model::SuperGameBoy) return; - Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); -} diff --git a/higan/gba/apu/apu.cpp b/higan/gba/apu/apu.cpp index 230a9bad..61aa3a56 100644 --- a/higan/gba/apu/apu.cpp +++ b/higan/gba/apu/apu.cpp @@ -78,7 +78,6 @@ auto APU::power() -> void { create(APU::Enter, system.frequency()); stream = Emulator::audio.createStream(2, frequency() / 64.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); clock = 0; square1.power(); diff --git a/higan/gba/interface/interface.cpp b/higan/gba/interface/interface.cpp index dabffd16..696cade0 100644 --- a/higan/gba/interface/interface.cpp +++ b/higan/gba/interface/interface.cpp @@ -131,19 +131,19 @@ auto Interface::get(const string& name) -> any { auto Interface::set(const string& name, const any& value) -> bool { if(name == "Blur Emulation" && value.is()) { settings.blurEmulation = value.get(); - system.configureVideoEffects(); + Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); return true; } if(name == "Color Emulation" && value.is()) { settings.colorEmulation = value.get(); - system.configureVideoPalette(); + Emulator::video.setPalette(); return true; } if(name == "Rotate Display" && value.is()) { settings.rotateLeft = value.get(); - system.configureVideoEffects(); + Emulator::video.setEffect(Emulator::Video::Effect::RotateLeft, settings.rotateLeft); return true; } diff --git a/higan/gba/system/system.cpp b/higan/gba/system/system.cpp index f6eb9e11..02b51390 100644 --- a/higan/gba/system/system.cpp +++ b/higan/gba/system/system.cpp @@ -5,7 +5,6 @@ namespace GameBoyAdvance { System system; Scheduler scheduler; #include "bios.cpp" -#include "video.cpp" #include "serialization.cpp" auto System::init() -> void { @@ -15,13 +14,12 @@ auto System::term() -> void { } auto System::power() -> void { - Emulator::video.reset(); - Emulator::video.setInterface(interface); - configureVideoPalette(); - configureVideoEffects(); + Emulator::video.reset(interface); + Emulator::video.setPalette(); + Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); + Emulator::video.setEffect(Emulator::Video::Effect::RotateLeft, settings.rotateLeft); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); scheduler.reset(); bus.power(); diff --git a/higan/gba/system/system.hpp b/higan/gba/system/system.hpp index b9236ada..7feb4722 100644 --- a/higan/gba/system/system.hpp +++ b/higan/gba/system/system.hpp @@ -27,10 +27,6 @@ struct System { auto run() -> void; auto runToSave() -> void; - //video.cpp - auto configureVideoPalette() -> void; - auto configureVideoEffects() -> void; - //serialization.cpp auto serialize() -> serializer; auto unserialize(serializer&) -> bool; diff --git a/higan/gba/system/video.cpp b/higan/gba/system/video.cpp deleted file mode 100644 index 33c13fab..00000000 --- a/higan/gba/system/video.cpp +++ /dev/null @@ -1,8 +0,0 @@ -auto System::configureVideoPalette() -> void { - Emulator::video.setPalette(); -} - -auto System::configureVideoEffects() -> void { - Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); - Emulator::video.setEffect(Emulator::Video::Effect::RotateLeft, settings.rotateLeft); -} diff --git a/higan/md/psg/psg.cpp b/higan/md/psg/psg.cpp index 752e14a8..f9f6b6ca 100644 --- a/higan/md/psg/psg.cpp +++ b/higan/md/psg/psg.cpp @@ -39,7 +39,6 @@ auto PSG::power(bool reset) -> void { stream = Emulator::audio.createStream(1, frequency() / 16.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); select = 0; for(auto n : range(15)) { diff --git a/higan/md/system/system.cpp b/higan/md/system/system.cpp index 7dd250e6..30d1be43 100644 --- a/higan/md/system/system.cpp +++ b/higan/md/system/system.cpp @@ -62,12 +62,10 @@ auto System::unload() -> void { } auto System::power(bool reset) -> void { - Emulator::video.reset(); - Emulator::video.setInterface(interface); + Emulator::video.reset(interface); Emulator::video.setPalette(); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); scheduler.reset(); cartridge.power(); diff --git a/higan/md/ym2612/ym2612.cpp b/higan/md/ym2612/ym2612.cpp index efd6fc84..c3bf5fde 100644 --- a/higan/md/ym2612/ym2612.cpp +++ b/higan/md/ym2612/ym2612.cpp @@ -159,7 +159,6 @@ auto YM2612::power(bool reset) -> void { stream = Emulator::audio.createStream(2, frequency() / 144.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); io = {}; lfo = {}; diff --git a/higan/ms/psg/psg.cpp b/higan/ms/psg/psg.cpp index 4c7248d6..770d76c4 100644 --- a/higan/ms/psg/psg.cpp +++ b/higan/ms/psg/psg.cpp @@ -45,7 +45,6 @@ auto PSG::power() -> void { create(PSG::Enter, system.colorburst() / 16.0); stream = Emulator::audio.createStream(2, frequency()); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); select = 0; for(auto n : range(15)) { diff --git a/higan/ms/system/system.cpp b/higan/ms/system/system.cpp index 835b5edc..ad46185b 100644 --- a/higan/ms/system/system.cpp +++ b/higan/ms/system/system.cpp @@ -59,12 +59,10 @@ auto System::unload() -> void { } auto System::power() -> void { - Emulator::video.reset(); - Emulator::video.setInterface(interface); + Emulator::video.reset(interface); Emulator::video.setPalette(); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); scheduler.reset(); cartridge.power(); diff --git a/higan/pce/psg/psg.cpp b/higan/pce/psg/psg.cpp index f69b73e0..934aab24 100644 --- a/higan/pce/psg/psg.cpp +++ b/higan/pce/psg/psg.cpp @@ -53,7 +53,6 @@ auto PSG::power() -> void { create(PSG::Enter, system.colorburst()); stream = Emulator::audio.createStream(2, frequency()); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); io = {}; for(auto C : range(6)) channel[C].power(C); diff --git a/higan/pce/system/system.cpp b/higan/pce/system/system.cpp index e64a2017..8cbdd25a 100644 --- a/higan/pce/system/system.cpp +++ b/higan/pce/system/system.cpp @@ -49,12 +49,10 @@ auto System::unload() -> void { } auto System::power() -> void { - Emulator::video.reset(); - Emulator::video.setInterface(interface); + Emulator::video.reset(interface); Emulator::video.setPalette(); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); scheduler.reset(); cartridge.power(); diff --git a/higan/sfc/coprocessor/icd/icd.cpp b/higan/sfc/coprocessor/icd/icd.cpp index 69d3d23f..7467018d 100644 --- a/higan/sfc/coprocessor/icd/icd.cpp +++ b/higan/sfc/coprocessor/icd/icd.cpp @@ -47,7 +47,6 @@ auto ICD::power() -> void { create(ICD::Enter, (Frequency ? Frequency : system.cpuFrequency()) / 5.0); stream = Emulator::audio.createStream(2, frequency() / 2.0); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); r6003 = 0x00; r6004 = 0xff; @@ -91,7 +90,7 @@ auto ICD::reset() -> void { writeAddress = 0; packetSize = 0; - joypID = 0; + joypID = 3; joyp15Lock = 0; joyp14Lock = 0; pulseLock = true; diff --git a/higan/sfc/cpu/cpu.hpp b/higan/sfc/cpu/cpu.hpp index 19a67cf8..2d883653 100644 --- a/higan/sfc/cpu/cpu.hpp +++ b/higan/sfc/cpu/cpu.hpp @@ -139,8 +139,8 @@ private: uint8 wrdivb = 0xff; //$4207-$420a - uint9 hirqPos = 0x1ff; - uint9 virqPos = 0x1ff; + uint12 htime = 0x1ff + 1 << 2; + uint9 vtime = 0x1ff; //$420d uint romSpeed = 8; diff --git a/higan/sfc/cpu/io.cpp b/higan/sfc/cpu/io.cpp index 84771498..b976ecd2 100644 --- a/higan/sfc/cpu/io.cpp +++ b/higan/sfc/cpu/io.cpp @@ -174,19 +174,23 @@ auto CPU::writeCPU(uint24 addr, uint8 data) -> void { return; case 0x4207: //HTIMEL - io.hirqPos.bits(0,7) = data; + io.htime = (io.htime >> 2) - 1; + io.htime.bits(0,7) = data; + io.htime = (io.htime + 1) << 2; return; case 0x4208: //HTIMEH - io.hirqPos.bit(8) = data.bit(0); + io.htime = (io.htime >> 2) - 1; + io.htime.bit(8) = data.bit(0); + io.htime = (io.htime + 1) << 2; return; case 0x4209: //VTIMEL - io.virqPos.bits(0,7) = data; + io.vtime.bits(0,7) = data; return; case 0x420a: //VTIMEH - io.virqPos.bit(8) = data.bit(0); + io.vtime.bit(8) = data.bit(0); return; case 0x420b: //DMAEN diff --git a/higan/sfc/cpu/irq.cpp b/higan/sfc/cpu/irq.cpp index 6153b389..e4937445 100644 --- a/higan/sfc/cpu/irq.cpp +++ b/higan/sfc/cpu/irq.cpp @@ -18,8 +18,9 @@ auto CPU::pollInterrupts() -> void { //IRQ test if(status.irqValid.raise(io.irqEnable - && (!io.virqEnable || vcounter(10) == io.virqPos) - && (!io.hirqEnable || hcounter(10) == io.hirqPos + 1 << 2) + && (!io.virqEnable || vcounter(10) == io.vtime) + && (!io.hirqEnable || hcounter(10) == io.htime) + && (vcounter(6) || hcounter(6)) //IRQs cannot trigger on last dot of fields )) status.irqLine = status.irqHold = true; //hold /IRQ for four cycles } diff --git a/higan/sfc/cpu/serialization.cpp b/higan/sfc/cpu/serialization.cpp index 0050baa0..e010be4e 100644 --- a/higan/sfc/cpu/serialization.cpp +++ b/higan/sfc/cpu/serialization.cpp @@ -65,8 +65,8 @@ auto CPU::serialize(serializer& s) -> void { s.integer(io.wrdiva); s.integer(io.wrdivb); - s.integer(io.hirqPos); - s.integer(io.virqPos); + s.integer(io.htime); + s.integer(io.vtime); s.integer(io.romSpeed); diff --git a/higan/sfc/system/system.cpp b/higan/sfc/system/system.cpp index e74aea7e..365a308f 100644 --- a/higan/sfc/system/system.cpp +++ b/higan/sfc/system/system.cpp @@ -91,12 +91,10 @@ auto System::power(bool reset) -> void { hacks.fastPPU = settings.fastPPU; hacks.fastDSP = settings.fastDSP; - Emulator::video.reset(); - Emulator::video.setInterface(interface); + Emulator::video.reset(interface); Emulator::video.setPalette(); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); random.entropy(Random::Entropy::Low); diff --git a/higan/target-bsnes/program/audio.cpp b/higan/target-bsnes/program/audio.cpp index 55e6e5c4..2a864e9f 100644 --- a/higan/target-bsnes/program/audio.cpp +++ b/higan/target-bsnes/program/audio.cpp @@ -72,7 +72,4 @@ auto Program::updateAudioEffects() -> void { double balance = max(-1.0, min(+1.0, (settings["Audio/Balance"].integer() - 50) / 50.0)); Emulator::audio.setBalance(balance); - - bool reverb = settings["Audio/Reverb"].boolean(); - Emulator::audio.setReverb(reverb); } diff --git a/higan/target-bsnes/program/game.cpp b/higan/target-bsnes/program/game.cpp index 04c567fa..94ad89a8 100644 --- a/higan/target-bsnes/program/game.cpp +++ b/higan/target-bsnes/program/game.cpp @@ -4,9 +4,7 @@ auto Program::load() -> void { for(auto& media : emulator->media) { if(media.type != "sfc") continue; - Emulator::audio.reset(2, audio->frequency()); if(emulator->load(media.id)) { - gameQueue = {}; screenshot = {}; frameAdvance = false; if(!verified() && settingsWindow->advanced.warnOnUnverifiedGames.checked()) { @@ -56,6 +54,8 @@ auto Program::load() -> void { break; } + + gameQueue = {}; } auto Program::loadFile(string location) -> vector { diff --git a/higan/target-bsnes/settings/audio.cpp b/higan/target-bsnes/settings/audio.cpp index 35c7450c..33c0da9e 100644 --- a/higan/target-bsnes/settings/audio.cpp +++ b/higan/target-bsnes/settings/audio.cpp @@ -52,12 +52,6 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { balanceValue.setText(value); program->updateAudioEffects(); }).doChange(); - reverb.setText("Reverb").setChecked(settings["Audio/Reverb"].boolean()).onToggle([&] { - settings["Audio/Reverb"].setValue(reverb.checked()); - program->updateAudioEffects(); - }); - //todo: does not work properly with Super Game Boy - reverb.setVisible(false); } auto AudioSettings::updateDevice() -> void { diff --git a/higan/target-bsnes/settings/settings.hpp b/higan/target-bsnes/settings/settings.hpp index e8d595de..428e592c 100644 --- a/higan/target-bsnes/settings/settings.hpp +++ b/higan/target-bsnes/settings/settings.hpp @@ -55,7 +55,6 @@ public: Label balanceLabel{&effectsLayout, Size{0, 0}}; Label balanceValue{&effectsLayout, Size{50, 0}}; HorizontalSlider balanceSlider{&effectsLayout, Size{~0, 0}}; - CheckLabel reverb{&layout, Size{~0, 0}}; }; struct InputSettings : TabFrameItem { diff --git a/higan/target-higan/program/medium.cpp b/higan/target-higan/program/medium.cpp index bcaa39ec..e30a47b9 100644 --- a/higan/target-higan/program/medium.cpp +++ b/higan/target-higan/program/medium.cpp @@ -19,17 +19,16 @@ auto Program::loadMedium(Emulator::Interface& interface, const Emulator::Interfa mediumPaths.append(locate({"systems/", medium.name, ".sys/"})); - Emulator::audio.reset(2, audio->frequency()); inputManager->bind(emulator = &interface); if(!emulator->load(medium.id)) { emulator = nullptr; mediumPaths.reset(); return; } - updateAudioDriver(); - updateAudioEffects(); connectDevices(); emulator->power(); + updateAudioDriver(); + updateAudioEffects(); presentation->resizeViewport(); presentation->setTitle(emulator->title()); diff --git a/higan/target-higan/program/utility.cpp b/higan/target-higan/program/utility.cpp index 76918ff7..ef9990dd 100644 --- a/higan/target-higan/program/utility.cpp +++ b/higan/target-higan/program/utility.cpp @@ -171,9 +171,6 @@ auto Program::updateAudioEffects() -> void { auto balance = max(-1.0, min(1.0, (settings["Audio/Balance"].integer() - 50) / 50.0)); Emulator::audio.setBalance(balance); - - auto reverbEnable = settings["Audio/Reverb/Enable"].boolean(); - Emulator::audio.setReverb(reverbEnable); } auto Program::focused() -> bool { diff --git a/higan/target-higan/settings/audio.cpp b/higan/target-higan/settings/audio.cpp index d989759f..362fdb9c 100644 --- a/higan/target-higan/settings/audio.cpp +++ b/higan/target-higan/settings/audio.cpp @@ -48,8 +48,6 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) { balanceValue.setAlignment(0.5); balanceSlider.setLength(101).setPosition(settings["Audio/Balance"].natural()).onChange([&] { updateEffects(); }); - reverbEnable.setText("Reverb").setChecked(settings["Audio/Reverb/Enable"].boolean()).onToggle([&] { updateEffects(); }); - updateDevice(); updateEffects(true); } @@ -79,7 +77,5 @@ auto AudioSettings::updateEffects(bool initializing) -> void { settings["Audio/Balance"].setValue(balanceSlider.position()); balanceValue.setText({balanceSlider.position(), "%"}); - settings["Audio/Reverb/Enable"].setValue(reverbEnable.checked()); - if(!initializing) program->updateAudioEffects(); } diff --git a/higan/target-higan/settings/settings.cpp b/higan/target-higan/settings/settings.cpp index 13385a65..39db1ecc 100644 --- a/higan/target-higan/settings/settings.cpp +++ b/higan/target-higan/settings/settings.cpp @@ -58,7 +58,6 @@ Settings::Settings() { set("Audio/Mute", false); set("Audio/Volume", 100); set("Audio/Balance", 50); - set("Audio/Reverb/Enable", false); set("Input/Driver", ruby::Input::safestDriver()); set("Input/Frequency", 5); diff --git a/higan/target-higan/settings/settings.hpp b/higan/target-higan/settings/settings.hpp index 46bbd459..d5511ef7 100644 --- a/higan/target-higan/settings/settings.hpp +++ b/higan/target-higan/settings/settings.hpp @@ -109,7 +109,6 @@ struct AudioSettings : TabFrameItem { Label balanceLabel{&balanceLayout, Size{80, 0}}; Label balanceValue{&balanceLayout, Size{50, 0}}; HorizontalSlider balanceSlider{&balanceLayout, Size{~0, 0}}; - CheckLabel reverbEnable{&layout, Size{~0, 0}}; auto updateDevice() -> void; auto updateEffects(bool initializing = false) -> void; diff --git a/higan/video/video.cpp b/higan/video/video.cpp index b5a31568..7ddbd09f 100644 --- a/higan/video/video.cpp +++ b/higan/video/video.cpp @@ -6,11 +6,12 @@ namespace Emulator { Video video; Video::~Video() { - reset(); + reset(nullptr); } -auto Video::reset() -> void { - interface = nullptr; +auto Video::reset(Interface* interface) -> void { + this->interface = interface; + sprites.reset(); delete buffer; buffer = nullptr; @@ -25,10 +26,6 @@ auto Video::reset() -> void { effects.rotateLeft = false; } -auto Video::setInterface(Interface* interface) -> void { - this->interface = interface; -} - auto Video::setPalette() -> void { if(!interface) return; diff --git a/higan/video/video.hpp b/higan/video/video.hpp index dd97d505..7c71155d 100644 --- a/higan/video/video.hpp +++ b/higan/video/video.hpp @@ -14,9 +14,7 @@ struct Video { }; ~Video(); - - auto reset() -> void; - auto setInterface(Interface* interface) -> void; + auto reset(Interface* interface) -> void; auto setPalette() -> void; auto setSaturation(double saturation) -> void; diff --git a/higan/ws/apu/apu.cpp b/higan/ws/apu/apu.cpp index d7dd6e59..322a1f5a 100644 --- a/higan/ws/apu/apu.cpp +++ b/higan/ws/apu/apu.cpp @@ -68,7 +68,6 @@ auto APU::power() -> void { create(APU::Enter, 3'072'000); stream = Emulator::audio.createStream(2, frequency()); stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0); - stream->addFilter(Emulator::Filter::Order::Second, Emulator::Filter::Type::LowPass, 20000.0, 3); bus.map(this, 0x004a, 0x004c); bus.map(this, 0x004e, 0x0050); diff --git a/higan/ws/interface/interface.cpp b/higan/ws/interface/interface.cpp index fa9c2992..c57a1b39 100644 --- a/higan/ws/interface/interface.cpp +++ b/higan/ws/interface/interface.cpp @@ -106,19 +106,19 @@ auto Interface::get(const string& name) -> any { auto Interface::set(const string& name, const any& value) -> bool { if(name == "Blur Emulation" && value.is()) { settings.blurEmulation = value.get(); - system.configureVideoEffects(); + Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); return true; } if(name == "Color Emulation" && value.is()) { settings.colorEmulation = value.get(); - system.configureVideoPalette(); + Emulator::video.setPalette(); return true; } if(name == "Rotate Display" && value.is()) { settings.rotateLeft = value.get(); - system.configureVideoEffects(); + Emulator::video.setEffect(Emulator::Video::Effect::RotateLeft, settings.rotateLeft); return true; } diff --git a/higan/ws/system/system.cpp b/higan/ws/system/system.cpp index 60a80561..dfb53408 100644 --- a/higan/ws/system/system.cpp +++ b/higan/ws/system/system.cpp @@ -6,7 +6,6 @@ System system; Scheduler scheduler; Cheat cheat; #include "io.cpp" -#include "video.cpp" #include "serialization.cpp" auto System::init() -> void { @@ -61,13 +60,12 @@ auto System::unload() -> void { } auto System::power() -> void { - Emulator::video.reset(); - Emulator::video.setInterface(interface); - configureVideoPalette(); - configureVideoEffects(); + Emulator::video.reset(interface); + Emulator::video.setPalette(); + Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); + Emulator::video.setEffect(Emulator::Video::Effect::RotateLeft, settings.rotateLeft); - Emulator::audio.reset(); - Emulator::audio.setInterface(interface); + Emulator::audio.reset(interface); scheduler.reset(); bus.power(); diff --git a/higan/ws/system/system.hpp b/higan/ws/system/system.hpp index 136ecd7c..71258b80 100644 --- a/higan/ws/system/system.hpp +++ b/higan/ws/system/system.hpp @@ -22,10 +22,6 @@ struct System : IO { auto portRead(uint16 addr) -> uint8 override; auto portWrite(uint16 addr, uint8 data) -> void override; - //video.cpp - auto configureVideoPalette() -> void; - auto configureVideoEffects() -> void; - //serialization.cpp auto serializeInit() -> void; auto serialize() -> serializer; diff --git a/higan/ws/system/video.cpp b/higan/ws/system/video.cpp deleted file mode 100644 index 33c13fab..00000000 --- a/higan/ws/system/video.cpp +++ /dev/null @@ -1,8 +0,0 @@ -auto System::configureVideoPalette() -> void { - Emulator::video.setPalette(); -} - -auto System::configureVideoEffects() -> void { - Emulator::video.setEffect(Emulator::Video::Effect::InterframeBlending, settings.blurEmulation); - Emulator::video.setEffect(Emulator::Video::Effect::RotateLeft, settings.rotateLeft); -} diff --git a/hiro/gtk/header.hpp b/hiro/gtk/header.hpp index 26ad5d00..3b7787fa 100644 --- a/hiro/gtk/header.hpp +++ b/hiro/gtk/header.hpp @@ -43,9 +43,13 @@ #include #include #if defined(Hiro_SourceEdit) - #include - #include - #include + #if HIRO_GTK==2 + #include + #include + #include + #elif HIRO_GTK==3 + #include + #endif #endif #include #endif diff --git a/hiro/gtk/settings.cpp b/hiro/gtk/settings.cpp index 7062b2ae..a24e7ebf 100644 --- a/hiro/gtk/settings.cpp +++ b/hiro/gtk/settings.cpp @@ -8,16 +8,20 @@ Settings::Settings() { auto document = BML::unserialize(file::read({path, "gtk3.bml"})); #endif - auto get = [&](string_view name) { - return document[name]; - }; + #define get(name, type, value) \ + if(auto node = document[name]) value = node.type() - geometry.frameX = get("Geometry/FrameX").integer(); - geometry.frameY = get("Geometry/FrameY").integer(); - geometry.frameWidth = get("Geometry/FrameWidth").integer(); - geometry.frameHeight = get("Geometry/FrameHeight").integer(); - geometry.menuHeight = get("Geometry/MenuHeight").integer(); - geometry.statusHeight = get("Geometry/StatusHeight").integer(); + get("Geometry/FrameX", integer, geometry.frameX); + get("Geometry/FrameY", integer, geometry.frameY); + get("Geometry/FrameWidth", integer, geometry.frameWidth); + get("Geometry/FrameHeight", integer, geometry.frameHeight); + get("Geometry/MenuHeight", integer, geometry.menuHeight); + get("Geometry/StatusHeight", integer, geometry.statusHeight); + + get("Theme/ActionIcons", boolean, theme.actionIcons); + get("Theme/WidgetColors", boolean, theme.widgetColors); + + #undef get } Settings::~Settings() { @@ -25,9 +29,9 @@ Settings::~Settings() { directory::create(path, 0755); Markup::Node document; - auto set = [&](string_view name, string_view value) { - document(name).setValue(value); - }; + + #define set(name, value) \ + document(name).setValue(value) set("Geometry/FrameX", geometry.frameX); set("Geometry/FrameY", geometry.frameY); @@ -36,6 +40,11 @@ Settings::~Settings() { set("Geometry/MenuHeight", geometry.menuHeight); set("Geometry/StatusHeight", geometry.statusHeight); + set("Theme/ActionIcons", theme.actionIcons); + set("Theme/WidgetColors", theme.widgetColors); + + #undef set + #if HIRO_GTK==2 file::write({path, "gtk2.bml"}, BML::serialize(document)); #elif HIRO_GTK==3 diff --git a/hiro/gtk/settings.hpp b/hiro/gtk/settings.hpp index 24fc0126..ed17252a 100644 --- a/hiro/gtk/settings.hpp +++ b/hiro/gtk/settings.hpp @@ -14,6 +14,11 @@ struct Settings { int menuHeight = 8; int statusHeight = 4; } geometry; + + struct Theme { + bool actionIcons = true; + bool widgetColors = true; + } theme; }; static Settings settings; diff --git a/hiro/gtk/widget/table-view.cpp b/hiro/gtk/widget/table-view.cpp index 24be583b..e0e957ff 100644 --- a/hiro/gtk/widget/table-view.cpp +++ b/hiro/gtk/widget/table-view.cpp @@ -257,14 +257,14 @@ auto pTableView::_doDataFunc(GtkTreeViewColumn* gtkColumn, GtkCellRenderer* rend pango_font_description_free(font); if(auto color = cell->foregroundColor(true)) { auto gdkColor = CreateColor(color); - g_object_set(G_OBJECT(renderer), "foreground-gdk", &gdkColor, nullptr); + if(settings.theme.widgetColors) g_object_set(G_OBJECT(renderer), "foreground-gdk", &gdkColor, nullptr); } else { g_object_set(G_OBJECT(renderer), "foreground-set", false, nullptr); } } if(auto color = cell->backgroundColor(true)) { auto gdkColor = CreateColor(color); - g_object_set(G_OBJECT(renderer), "cell-background-gdk", &gdkColor, nullptr); + if(settings.theme.widgetColors) g_object_set(G_OBJECT(renderer), "cell-background-gdk", &gdkColor, nullptr); } else { g_object_set(G_OBJECT(renderer), "cell-background-set", false, nullptr); } diff --git a/hiro/qt/settings.cpp b/hiro/qt/settings.cpp index e3c27f5a..abb316ae 100644 --- a/hiro/qt/settings.cpp +++ b/hiro/qt/settings.cpp @@ -8,16 +8,17 @@ Settings::Settings() { auto document = BML::unserialize(file::read({path, "qt5.bml"})); #endif - auto get = [&](string_view name) { - return document[name]; - }; + #define get(name, type, value) \ + if(auto node = document[name]) value = node.type() - geometry.frameX = get("Geometry/FrameX").integer(); - geometry.frameY = get("Geometry/FrameY").integer(); - geometry.frameWidth = get("Geometry/FrameWidth").integer(); - geometry.frameHeight = get("Geometry/FrameHeight").integer(); - geometry.menuHeight = get("Geometry/MenuHeight").integer(); - geometry.statusHeight = get("Geometry/StatusHeight").integer(); + get("Geometry/FrameX", integer, geometry.frameX); + get("Geometry/FrameY", integer, geometry.frameY); + get("Geometry/FrameWidth", integer, geometry.frameWidth); + get("Geometry/FrameHeight", integer, geometry.frameHeight); + get("Geometry/MenuHeight", integer, geometry.menuHeight); + get("Geometry/StatusHeight", integer, geometry.statusHeight); + + #undef get } Settings::~Settings() { @@ -25,9 +26,9 @@ Settings::~Settings() { directory::create(path, 0755); Markup::Node document; - auto set = [&](string_view name, string_view value) { - document(name).setValue(value); - }; + + #define set(name, value) \ + document(name).setValue(value) set("Geometry/FrameX", geometry.frameX); set("Geometry/FrameY", geometry.frameY); @@ -36,6 +37,8 @@ Settings::~Settings() { set("Geometry/MenuHeight", geometry.menuHeight); set("Geometry/StatusHeight", geometry.statusHeight); + #undef set + #if HIRO_QT==4 file::write({path, "qt4.bml"}, BML::serialize(document)); #elif HIRO_QT==5 diff --git a/hiro/qt/window.cpp b/hiro/qt/window.cpp index 7fac0a21..f16b23f5 100644 --- a/hiro/qt/window.cpp +++ b/hiro/qt/window.cpp @@ -164,7 +164,6 @@ auto pWindow::setMaximumSize(Size size) -> void { static auto maximumSize = qtWindow->maximumSize(); if(size) { - //once this is called, no matter what the size is, Qt will no longer allow the window to be maximized qtWindow->setMaximumSize(size.width(), size.height() + _menuHeight() + _statusHeight()); } else { qtWindow->setMaximumSize(maximumSize); diff --git a/nall/GNUmakefile b/nall/GNUmakefile index 7d006cb6..4a11b3c5 100644 --- a/nall/GNUmakefile +++ b/nall/GNUmakefile @@ -40,7 +40,9 @@ ifeq ($(platform),) endif flags.c = -x c -std=c11 +flags.h = -x c-header -std=c11 flags.cpp = -x c++ -std=c++14 +flags.hpp = -x c++-header -std=c++14 flags.objc = -x objective-c -std=c11 flags.objcpp = -x objective-c++ -std=c++14 flags.deps = -MMD -MP -MF $(@:.o=.d) @@ -50,6 +52,7 @@ ifeq ($(compiler),) ifeq ($(platform),windows) compiler := g++ flags.cpp := -x c++ -std=gnu++14 + flags.hpp := -x c++-header -std=gnu++14 else ifeq ($(platform),macos) compiler := clang++ else ifeq ($(platform),linux) @@ -133,7 +136,10 @@ endif # paths prefix := $(HOME)/.local -object.path := obj + +ifeq ($(object.path),) + object.path := obj +endif # rules default: all; @@ -155,7 +161,11 @@ compile = \ $(compiler) $(flags.c) $(flags.deps) $(flags) $1 -c $< -o $@ \ ,$(if $(filter %.cpp,$<), \ $(compiler) $(flags.cpp) $(flags.deps) $(flags) $1 -c $< -o $@ \ - )) \ + ,$(if $(filter %.h,$<), \ + $(compiler) $(flags.h) $(flags) $1 -c $< -o $@ \ + ,$(if $(filter %.hpp,$<), \ + $(compiler) $(flags.hpp) $(flags) $1 -c $< -o $@ \ + )))) \ ) # function rwildcard(directory, pattern) diff --git a/nall/dsp/dsp.hpp b/nall/dsp/dsp.hpp new file mode 100644 index 00000000..3bf21127 --- /dev/null +++ b/nall/dsp/dsp.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace nall { namespace DSP { + +#if defined(NALL_DSP_PRECISION) +using real = NALL_DSP_PRECISION; +#else +using real = double; +#endif + +}} diff --git a/nall/dsp/iir/biquad.hpp b/nall/dsp/iir/biquad.hpp index 81ea432f..5bc63043 100644 --- a/nall/dsp/iir/biquad.hpp +++ b/nall/dsp/iir/biquad.hpp @@ -1,5 +1,7 @@ #pragma once +#include + //transposed direct form II biquadratic second-order IIR filter namespace nall { namespace DSP { namespace IIR { @@ -15,22 +17,22 @@ struct Biquad { HighShelf, }; - inline auto reset(Type type, double cutoffFrequency, double samplingFrequency, double quality, double gain = 0.0) -> void; - inline auto process(double in) -> double; //normalized sample (-1.0 to +1.0) + inline auto reset(Type type, real cutoffFrequency, real samplingFrequency, real quality, real gain = 0.0) -> void; + inline auto process(real in) -> real; //normalized sample (-1.0 to +1.0) - inline static auto butterworth(uint order, uint phase) -> double; + inline static auto butterworth(uint order, uint phase) -> real; private: Type type; - double cutoffFrequency; - double samplingFrequency; - double quality; //frequency response quality - double gain; //peak gain - double a0, a1, a2, b1, b2; //coefficients - double z1, z2; //second-order IIR + real cutoffFrequency; + real samplingFrequency; + real quality; //frequency response quality + real gain; //peak gain + real a0, a1, a2, b1, b2; //coefficients + real z1, z2; //second-order IIR }; -auto Biquad::reset(Type type, double cutoffFrequency, double samplingFrequency, double quality, double gain) -> void { +auto Biquad::reset(Type type, real cutoffFrequency, real samplingFrequency, real quality, real gain) -> void { this->type = type; this->cutoffFrequency = cutoffFrequency; this->samplingFrequency = samplingFrequency; @@ -40,10 +42,10 @@ auto Biquad::reset(Type type, double cutoffFrequency, double samplingFrequency, z1 = 0.0; z2 = 0.0; - double v = pow(10, fabs(gain) / 20.0); - double k = tan(Math::Pi * cutoffFrequency / samplingFrequency); - double q = quality; - double n = 0.0; + real v = pow(10, fabs(gain) / 20.0); + real k = tan(Math::Pi * cutoffFrequency / samplingFrequency); + real q = quality; + real n = 0.0; switch(type) { @@ -140,15 +142,15 @@ auto Biquad::reset(Type type, double cutoffFrequency, double samplingFrequency, } } -auto Biquad::process(double in) -> double { - double out = in * a0 + z1; +auto Biquad::process(real in) -> real { + real out = in * a0 + z1; z1 = in * a1 + z2 - b1 * out; z2 = in * a2 - b2 * out; return out; } //compute Q values for N-order butterworth filtering -auto Biquad::butterworth(uint order, uint phase) -> double { +auto Biquad::butterworth(uint order, uint phase) -> real { return -0.5 / cos(Math::Pi * (phase + order + 0.5) / order); } diff --git a/nall/dsp/iir/one-pole.hpp b/nall/dsp/iir/one-pole.hpp index e678c999..74effc0c 100644 --- a/nall/dsp/iir/one-pole.hpp +++ b/nall/dsp/iir/one-pole.hpp @@ -1,5 +1,7 @@ #pragma once +#include + //one-pole first-order IIR filter namespace nall { namespace DSP { namespace IIR { @@ -10,24 +12,24 @@ struct OnePole { HighPass, }; - inline auto reset(Type type, double cutoffFrequency, double samplingFrequency) -> void; - inline auto process(double in) -> double; //normalized sample (-1.0 to +1.0) + inline auto reset(Type type, real cutoffFrequency, real samplingFrequency) -> void; + inline auto process(real in) -> real; //normalized sample (-1.0 to +1.0) private: Type type; - double cutoffFrequency; - double samplingFrequency; - double a0, b1; //coefficients - double z1; //first-order IIR + real cutoffFrequency; + real samplingFrequency; + real a0, b1; //coefficients + real z1; //first-order IIR }; -auto OnePole::reset(Type type, double cutoffFrequency, double samplingFrequency) -> void { +auto OnePole::reset(Type type, real cutoffFrequency, real samplingFrequency) -> void { this->type = type; this->cutoffFrequency = cutoffFrequency; this->samplingFrequency = samplingFrequency; z1 = 0.0; - double x = cos(2.0 * Math::Pi * cutoffFrequency / samplingFrequency); + real x = cos(2.0 * Math::Pi * cutoffFrequency / samplingFrequency); if(type == Type::LowPass) { b1 = +2.0 - x - sqrt((+2.0 - x) * (+2.0 - x) - 1); a0 = 1.0 - b1; @@ -37,7 +39,7 @@ auto OnePole::reset(Type type, double cutoffFrequency, double samplingFrequency) } } -auto OnePole::process(double in) -> double { +auto OnePole::process(real in) -> real { return z1 = in * a0 + z1 * b1; } diff --git a/nall/dsp/resampler/cubic.hpp b/nall/dsp/resampler/cubic.hpp index df379776..8d6ee7e7 100644 --- a/nall/dsp/resampler/cubic.hpp +++ b/nall/dsp/resampler/cubic.hpp @@ -1,26 +1,27 @@ #pragma once #include +#include namespace nall { namespace DSP { namespace Resampler { struct Cubic { - inline auto reset(double inputFrequency, double outputFrequency, uint queueSize = 0) -> void; + inline auto reset(real inputFrequency, real outputFrequency, uint queueSize = 0) -> void; inline auto pending() const -> bool { return samples.pending(); } - inline auto read() -> double { return samples.read(); } - inline auto write(double sample) -> void; + inline auto read() -> real { return samples.read(); } + inline auto write(real sample) -> void; private: - double inputFrequency; - double outputFrequency; + real inputFrequency; + real outputFrequency; - double ratio; - double fraction; - double history[4]; - queue samples; + real ratio; + real fraction; + real history[4]; + queue samples; }; -auto Cubic::reset(double inputFrequency, double outputFrequency, uint queueSize) -> void { +auto Cubic::reset(real inputFrequency, real outputFrequency, uint queueSize) -> void { this->inputFrequency = inputFrequency; this->outputFrequency = outputFrequency; if(!queueSize) queueSize = outputFrequency * 0.02; //20ms @@ -31,7 +32,7 @@ auto Cubic::reset(double inputFrequency, double outputFrequency, uint queueSize) samples.resize(queueSize); } -auto Cubic::write(double sample) -> void { +auto Cubic::write(real sample) -> void { auto& mu = fraction; auto& s = history; @@ -41,10 +42,10 @@ auto Cubic::write(double sample) -> void { s[3] = sample; while(mu <= 1.0) { - double A = s[3] - s[2] - s[0] + s[1]; - double B = s[0] - s[1] - A; - double C = s[2] - s[0]; - double D = s[1]; + real A = s[3] - s[2] - s[0] + s[1]; + real B = s[0] - s[1] - A; + real C = s[2] - s[0]; + real D = s[1]; samples.write(A * mu * mu * mu + B * mu * mu + C * mu + D); mu += ratio; diff --git a/nall/string/markup/node.hpp b/nall/string/markup/node.hpp index c0fa03c4..5cbe06c1 100644 --- a/nall/string/markup/node.hpp +++ b/nall/string/markup/node.hpp @@ -63,6 +63,12 @@ struct Node { auto natural() const -> uintmax { return text().natural(); } auto real() const -> double { return text().real(); } + auto text(const string& fallback) const -> string { return bool(*this) ? text() : fallback; } + auto boolean(bool fallback) const -> bool { return bool(*this) ? boolean() : fallback; } + auto integer(intmax fallback) const -> intmax { return bool(*this) ? integer() : fallback; } + auto natural(uintmax fallback) const -> uintmax { return bool(*this) ? natural() : fallback; } + auto real(double fallback) const -> double { return bool(*this) ? real() : fallback; } + auto setName(const string& name = "") -> Node& { shared->_name = name; return *this; } auto setValue(const string& value = "") -> Node& { shared->_value = value; return *this; }