diff --git a/sdl2-hyper-sonic-drivers/CMakeLists.txt b/sdl2-hyper-sonic-drivers/CMakeLists.txt index dd240443..a6cee6a5 100644 --- a/sdl2-hyper-sonic-drivers/CMakeLists.txt +++ b/sdl2-hyper-sonic-drivers/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required (VERSION 3.21) find_package(SDL2 CONFIG REQUIRED) -find_package(rtmidi CONFIG REQUIRED) find_package(MT32emu CONFIG REQUIRED) set(CMAKE_CXX_STANDARD 20) @@ -96,14 +95,10 @@ target_sources(${LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/IDevice.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/Opl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/Adlib.cpp - - ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/midi/MidiNative.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/midi/MidiOpl.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/midi/MidiAdlib.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/midi/MidiSbPro.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/midi/MidiSbPro2.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/midi/MidiMT32.cpp - # --- # + ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/SbPro.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/SbPro2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/devices/MT32.cpp + # --- # ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/drivers/PCMDriver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/drivers/MIDDriver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/HyperSonicDrivers/drivers/westwood/ADLDriver.cpp @@ -177,7 +172,6 @@ target_sources(${LIB_NAME} PRIVATE target_link_libraries(${LIB_NAME} PUBLIC ${LIB_SDL2} - RtMidi::rtmidi MT32Emu::mt32emu ) if(NOT (WITH_SDL2_STATIC)) diff --git a/sdl2-hyper-sonic-drivers/examples/CMakeLists.txt b/sdl2-hyper-sonic-drivers/examples/CMakeLists.txt index 71155cb2..d757635a 100644 --- a/sdl2-hyper-sonic-drivers/examples/CMakeLists.txt +++ b/sdl2-hyper-sonic-drivers/examples/CMakeLists.txt @@ -98,16 +98,6 @@ macro_example( NONE ) -macro_example( - EXE RtMidi_example - FILE "rtmidi-example.cpp" - DEPS hyper-sonic-drivers-static - LINKS ${LIB_SDL2main} hyper-sonic-drivers-static spdlog::spdlog - FIXTURES - "../test/fixtures/midifile_sample.mid" - NONE -) - macro_example( EXE MIDexample FILE "mid-example.cpp" diff --git a/sdl2-hyper-sonic-drivers/examples/adl-example.cpp b/sdl2-hyper-sonic-drivers/examples/adl-example.cpp index 7d44c13f..eb84f565 100644 --- a/sdl2-hyper-sonic-drivers/examples/adl-example.cpp +++ b/sdl2-hyper-sonic-drivers/examples/adl-example.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include #include @@ -24,16 +27,31 @@ using files::westwood::ADLFile; using drivers::westwood::ADLDriver; -void adl_test(const OplEmulator emu, const OplType type, std::shared_ptr mixer, const std::string& filename, const int track) +void adl_test(const OplEmulator emu, const OplType type, std::shared_ptr mixer, const std::string& filename, const uint8_t track) { - auto opl = OPLFactory::create(emu, type, mixer); - if (opl == nullptr) - return; + using devices::make_device; auto adlFile = std::make_shared(filename); - ADLDriver adlDrv(opl, audio::mixer::eChannelGroup::Music); + std::shared_ptr device; + switch (type) + { + using enum OplType; + + case OPL2: + device = make_device(mixer, emu); + break; + case DUAL_OPL2: + device = make_device(mixer, emu); + break; + case OPL3: + device = make_device(mixer, emu); + break; + + } + + ADLDriver adlDrv(device, audio::mixer::eChannelGroup::Music); adlDrv.setADLFile(adlFile); - adlDrv.play(track, 0xFF); + adlDrv.play(track); if(!mixer->isReady()) { spdlog::error("mixer not ready yet.."); diff --git a/sdl2-hyper-sonic-drivers/examples/mid-example.h b/sdl2-hyper-sonic-drivers/examples/mid-example.h index 63c5af31..68163f87 100644 --- a/sdl2-hyper-sonic-drivers/examples/mid-example.h +++ b/sdl2-hyper-sonic-drivers/examples/mid-example.h @@ -3,13 +3,10 @@ #include #include -#include -#include -#include -#include -#include -#include - +#include +#include +#include +#include #include #include @@ -24,14 +21,17 @@ using namespace HyperSonicDrivers; +using audio::mixer::eChannelGroup; using hardware::opl::OPLFactory; using hardware::opl::OplEmulator; using hardware::opl::OplType; + void mid_test_run(drivers::MIDDriver& midDrv, const std::shared_ptr& midi) { auto start_time = std::chrono::system_clock::now(); - midDrv.play(midi); + midDrv.setMidi(midi); + midDrv.play(0); while (midDrv.isPlaying()) { utils::delayMillis(1000); } @@ -44,26 +44,27 @@ void mid_test_run(drivers::MIDDriver& midDrv, const std::shared_ptr void scummvm_mid_test(const OplEmulator emu, const OplType type, const std::shared_ptr& mixer, const std::shared_ptr midi) { - std::shared_ptr midi_device; + + std::shared_ptr device; switch (type) { using enum OplType; using namespace devices; case OPL2: - midi_device = make_midi_device(mixer, audio::mixer::eChannelGroup::Music, emu); + device = make_device(mixer, emu); break; case DUAL_OPL2: - midi_device = make_midi_device(mixer, audio::mixer::eChannelGroup::Music, emu); + device = make_device(mixer, emu); break; case OPL3: - midi_device = make_midi_device(mixer, audio::mixer::eChannelGroup::Music, emu); + device = make_device(mixer, emu); break; default: throw std::runtime_error("?"); } - drivers::MIDDriver midDrv(/*mixer,*/ midi_device); + drivers::MIDDriver midDrv(device, eChannelGroup::Music); spdlog::info(std::format("playing midi (OPL type={})...", type)); mid_test_run(midDrv, midi); } @@ -72,47 +73,42 @@ void mid_test(const OplEmulator emu, const OplType type, const std::shared_ptr midi) { auto op2file = files::dmx::OP2File("GENMIDI.OP2"); - std::shared_ptr midi_device; + std::shared_ptr device; switch (type) { using enum OplType; using namespace devices; case OPL2: - midi_device = make_midi_device(mixer, op2file.getBank(), audio::mixer::eChannelGroup::Music, emu); + device = make_device(mixer, emu); break; case DUAL_OPL2: - midi_device = make_midi_device(mixer, op2file.getBank(), audio::mixer::eChannelGroup::Music, emu); + device = make_device(mixer, emu); break; case OPL3: - midi_device = make_midi_device(mixer, op2file.getBank(), audio::mixer::eChannelGroup::Music, emu); + device = make_device(mixer, emu); break; default: throw std::runtime_error("?"); } - drivers::MIDDriver midDrv(/*mixer,*/ midi_device); + drivers::MIDDriver midDrv(/*mixer,*/ device, eChannelGroup::Music); + if (!midDrv.loadBankOP2(op2file.getBank())) + { + spdlog::error("can't load BankOP2"); + return; + } + spdlog::info(std::format("playing midi (OPL type={})...", type)); mid_test_run(midDrv, midi); } -void mid_test_native(/*const std::shared_ptr& mixer,*/ - const std::shared_ptr& midi) -{ - auto nativeMidi = std::make_shared(); - - drivers::MIDDriver mid_drv(/*mixer,*/ nativeMidi); - - spdlog::info("playing midi..."); - mid_test_run(mid_drv, midi); -} - int run(const std::shared_ptr& midi, const bool use_opldrv) { auto mixer = audio::make_mixer(8, 44100, 1024); if (!mixer->init()) { - std::cerr << "can't init the mixer" << std::endl; + spdlog::error("can't init the mixer"); return 1; } @@ -160,11 +156,5 @@ int run(const std::shared_ptr& midi, const bool use_opldrv) } } - // Native Midi - for (const auto& c : colors) { - spdlog::info(fmt::format(fg(c), m, "Native", "MIDI")); - } - mid_test_native(/*mixer,*/ midi); - return 0; } diff --git a/sdl2-hyper-sonic-drivers/examples/rtmidi-example.cpp b/sdl2-hyper-sonic-drivers/examples/rtmidi-example.cpp deleted file mode 100644 index ccde0f68..00000000 --- a/sdl2-hyper-sonic-drivers/examples/rtmidi-example.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include - -using namespace HyperSonicDrivers; - -using std::cout; -using std::endl; - -int main(int argc, char* argv[]) -{ - // TODO: as this example shows rtMidi is outside the mixer - // it implies it can be muted, stopped panned, chnage volume, etc.. - // like other music/sounds going through the mixer. - // Check if it can be wired to the mixer - // Otherwise this device Native and rtMidi dependency must be optional (or even removed or not official) - - std::shared_ptr midiout; - - try { - midiout = std::make_shared(); - } - catch (RtMidiError& error) { - // Handle the exception here - error.printMessage(); - } - - // Check outputs. - unsigned int nPorts = midiout->getPortCount(); - std::string portName; - std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n"; - for (unsigned int i = 0; i < nPorts; i++) { - try { - portName = midiout->getPortName(i); - } - catch (RtMidiError& error) { - error.printMessage(); - } - std::cout << " Output Port #" << i + 1 << ": " << portName << endl; - } - std::cout << endl; - - cout << "Midi note test..."; - // Open first available port. - midiout->openPort(0); - // Send out a series of MIDI messages. - std::vector message; - // Program change: 192, 5 - message.push_back(192); - message.push_back(5); - midiout->sendMessage(&message); - // Control Change: 176, 7, 100 (volume) - message[0] = 176; - message[1] = 7; - message.push_back(100); - midiout->sendMessage(&message); - // Note On: 144, 64, 90 - message[0] = 144; - message[1] = 64; - message[2] = 90; - midiout->sendMessage(&message); - utils::delayMillis(1000); - // Note Off: 128, 64, 40 - message[0] = 128; - message[1] = 64; - message[2] = 40; - midiout->sendMessage(&message); - - cout << "OK" << endl; - midiout->closePort(); - - // Device Native is using RtMidi - auto native = std::make_shared(); - drivers::MIDDriver middrv(native); - auto midi = files::MIDFile("midifile_sample.mid").getMIDI(); - middrv.play(midi); - - return 0; -} diff --git a/sdl2-hyper-sonic-drivers/sdl2-hyper-sonic-drivers.cpp b/sdl2-hyper-sonic-drivers/sdl2-hyper-sonic-drivers.cpp index 4a3d3b3b..baa11674 100644 --- a/sdl2-hyper-sonic-drivers/sdl2-hyper-sonic-drivers.cpp +++ b/sdl2-hyper-sonic-drivers/sdl2-hyper-sonic-drivers.cpp @@ -23,10 +23,7 @@ #include #include -#include -#include -#include #include #include @@ -34,7 +31,6 @@ #include #include #include -#include using namespace std; using namespace HyperSonicDrivers; @@ -326,250 +322,21 @@ int song() // return 0; //} -int midi_adlib() -{ - using hardware::opl::OPLFactory; - using hardware::opl::OplEmulator; - using hardware::opl::OplType; - - auto mixer = audio::make_mixer(8, 44100, 1024); - mixer->init(); - auto emu = OplEmulator::NUKED; - auto type = OplType::OPL3; - - //spdlog::set_level(spdlog::level::debug); - std::shared_ptr midFile = std::make_shared("test/fixtures/MI_intro.mid"); - //auto midFile = std::make_shared("test/fixtures/midifile_sample.mid"); - auto midi = midFile->getMIDI(); - auto scumm_midi = std::make_shared(mixer, audio::mixer::eChannelGroup::Music); - - //files::dmx::OP2File op2f("test/fixtures/GENMIDI.OP2"); - //auto scumm_midi = std::make_shared(mixer, op2f.getBank(), audio::mixer::eChannelGroup::Music); - drivers::MIDDriver midDrv(scumm_midi); - - //spdlog::info("playing midi..."); - midDrv.play(midi); - while (midDrv.isPlaying()) - utils::delayMillis(1000); - //spdlog::info("end."); - return 0; -} -int midi_adlib_mus_file_CONCURRENCY_ERROR_ON_SAME_DEVICE() -{ - using hardware::opl::OPLFactory; - using hardware::opl::OplEmulator; - using hardware::opl::OplType; - auto mixer = audio::make_mixer(8, 44100, 1024); - auto emu = OplEmulator::MAME; - auto type = OplType::OPL2; - - //spdlog::set_level(spdlog::level::debug); - auto midFile = std::make_shared("test/fixtures/MI_intro.mid"); - auto musFile = std::make_shared("test/fixtures/D_E1M1.MUS"); - auto midi = musFile->getMIDI(); - auto scumm_midi = std::make_shared(mixer, audio::mixer::eChannelGroup::Music); - //spdlog::info("isAquired: {}", scumm_midi->isAcquired()); - drivers::MIDDriver midDrv(scumm_midi); - // TODO: declare a same driver with the device shouldn't be possible. - // bring the device aquire to the constructor? - // so no other will be declared? - // but if it is acquired should throw.. - // i am keepig at is for now. - drivers::MIDDriver midDrv2(scumm_midi); - - //spdlog::info("playing midi D_E1M1.MUS..."); - midDrv.play(midi); - //spdlog::info("isAquired: {}", scumm_midi->isAcquired()); - utils::delayMillis(1000); - //spdlog::info("playing midi2 D_E1M1.MUS... (this should not be possible with the same device)"); - midDrv2.play(midFile->getMIDI()); - //spdlog::info("isAquired: {}", scumm_midi->isAcquired()); - //spdlog::info("end."); - while (midDrv.isPlaying() || midDrv2.isPlaying()) - { - utils::delayMillis(1000); - } - return 0; -} -int midi_adlib_mus_op2_file() -{ - using hardware::opl::OPLFactory; - using hardware::opl::OplEmulator; - using hardware::opl::OplType; - //spdlog::set_level(spdlog::level::debug); - auto mixer = audio::make_mixer(8, 44100, 1024); - auto emu = OplEmulator::DOS_BOX; - auto type = OplType::OPL2; - - //spdlog::set_level(spdlog::level::debug); - auto op2File = std::make_shared("test/fixtures/GENMIDI.OP2"); - auto musFile = std::make_shared("test/fixtures/D_E1M1.MUS"); - auto midi = musFile->getMIDI(); - - { - auto opl = OPLFactory::create(emu, type, mixer); - if (opl.get() == nullptr) - return -1; - - auto adlib_midi = std::make_shared(mixer, op2File->getBank(), audio::mixer::eChannelGroup::Music, emu); - drivers::MIDDriver midDrv(adlib_midi); - //spdlog::info("playing midi (OPL2) D_E1M1.MUS..."); - midDrv.play(midi); - //utils::delayMillis(1200); - //midDrv.pause(); - //utils::delayMillis(2000); - //midDrv.resume(); - while (midDrv.isPlaying()) - utils::delayMillis(1000); - } - { - auto sbpro_midi = std::make_shared(mixer, op2File->getBank(), audio::mixer::eChannelGroup::Music, emu); - drivers::MIDDriver midDrv(sbpro_midi); - - //spdlog::info("playing midi (OPL3) D_E1M1.MUS..."); - midDrv.play(midi); - //auto handle = *opl->getSoundHandle(); - //auto volume = mixer->getChannelVolume(handle); - //spdlog::info("Volumne: {:d}", volume); - utils::delayMillis(1250); - midDrv.pause(); - utils::delayMillis(2000); - midDrv.resume(); - while (midDrv.isPlaying()) { - utils::delayMillis(1000); - // TODO: the volume should also be set through the MIDDrv for simplicity - // at that point the mixer will be useful - // TODO: the volume should be set through the Device interface too - // as the device/OPL has its own dedicated channel and therefore - // it is like its own volume - //mixer->setChannelVolume(handle, volume / 2); - //mixer->pauseHandle(handle); // TODO this will do it too for pause the music i guess. - } - } - - return 0; -} - - -int midi_adlib_xmi() -{ - // NOT Working but in a reduced way as there are specific XMI midi messages not interpreted - // also it has been hacked through the xmifile get midi to build a single track midi - - using hardware::opl::OPLFactory; - using hardware::opl::OplEmulator; - using hardware::opl::OplType; - - auto mixer = audio::make_mixer(8, 44100, 1024); - - auto emu = OplEmulator::MAME; - auto type = OplType::OPL2; - - //spdlog::set_level(spdlog::level::debug); - auto xmiFile = std::make_shared("test/fixtures/AIL2_14_DEMO.XMI"); - auto m = xmiFile->getMIDI(); - auto midi = std::make_shared(audio::midi::MIDI_FORMAT::SINGLE_TRACK, 1, m->division); - midi->addTrack(m->getTrack(0)); - - auto scumm_midi = std::make_shared(mixer, audio::mixer::eChannelGroup::Music, emu); - files::dmx::OP2File op2File("test/fixtures/GENMIDI.OP2"); - auto opl_midi = std::make_shared(mixer, op2File.getBank(), audio::mixer::eChannelGroup::Music, emu); - //drivers::MIDDriver midDrv(mixer, scumm_midi); - drivers::MIDDriver midDrv(opl_midi); - - //spdlog::info("playing midi AIL2_14_DEMO..."); - midDrv.play(midi); - - while (midDrv.isPlaying()) - { - //spdlog::info("playing..."); - utils::delayMillis(1000); - } - return 0; -} - -void testMultiOpl() -{ - using hardware::opl::OplEmulator; - using hardware::opl::OplType; - using audio::mixer::eChannelGroup; - using utils::ILogger; - - ILogger::instance->setLevelAll(ILogger::eLevel::Info); - - auto mixer = audio::make_mixer(8, 44100, 1024); - if (!mixer->init()) - std::cerr << "can't init mixer"; - - auto opl_a = hardware::opl::OPLFactory::create(OplEmulator::AUTO, OplType::OPL2, mixer); - auto opl_b = hardware::opl::OPLFactory::create(OplEmulator::AUTO, OplType::OPL2, mixer); - - auto af = std::make_shared< files::westwood::ADLFile>("test/fixtures/DUNE0.ADL"); - auto drv1 = drivers::westwood::ADLDriver(opl_a, eChannelGroup::Music); - drv1.setADLFile(af); - auto drv2 = drivers::westwood::ADLDriver(opl_b, eChannelGroup::Sfx); - drv2.setADLFile(af); - - std::cout << af->getNumTracks() << std::endl; - - drv2.play(2); - utils::delayMillis(2000); - drv1.play(4); - - while(drv1.isPlaying() || drv2.isPlaying()) - utils::delayMillis(1000); -} - -void testMOplMultiDrv() -{ - // NOTE more driver on the same OPL won't work. - // in MIDDrv an acquire lock mechanism has been performed - // not for ADL. - using hardware::opl::OplEmulator; - using hardware::opl::OplType; - using audio::mixer::eChannelGroup; - using utils::ILogger; - - ILogger::instance->setLevelAll(ILogger::eLevel::Info); - - auto mixer = audio::make_mixer(8, 44100, 1024); - if (!mixer->init()) - std::cerr << "can't init mixer"; - - auto opl_a = hardware::opl::OPLFactory::create(OplEmulator::AUTO, OplType::OPL2, mixer); - auto adlib = devices::Adlib(mixer, OplEmulator::AUTO); - - auto af = std::make_shared< files::westwood::ADLFile>("test/fixtures/DUNE0.ADL"); - //auto drv1 = drivers::westwood::ADLDriver(opl_a, eChannelGroup::Music); - //auto drv2 = drivers::westwood::ADLDriver(opl_a, eChannelGroup::Sfx); - auto drv1 = drivers::westwood::ADLDriver(adlib, eChannelGroup::Music); - auto drv2 = drivers::westwood::ADLDriver(adlib, eChannelGroup::Music); - drv1.setADLFile(af); - drv2.setADLFile(af); - - std::cout << af->getNumTracks() << std::endl; - - //drv2.play(2); - utils::delayMillis(2000); - drv1.play(4); - - while (drv1.isPlaying() || drv2.isPlaying()) - utils::delayMillis(1000); -} void rendererADL() { + // TODO: need to be re-tested using hardware::opl::OplEmulator; using hardware::opl::OplType; using audio::mixer::eChannelGroup; @@ -582,12 +349,12 @@ void rendererADL() auto mixer = r.getMixer(); - auto adlib = devices::Adlib(mixer, OplEmulator::AUTO); + auto adlib = devices::make_device(mixer, OplEmulator::AUTO); auto drv1 = drivers::westwood::ADLDriver(adlib, eChannelGroup::Music); auto af = std::make_shared("test/fixtures/DUNE0.ADL"); drv1.setADLFile(af); - auto eo = adlib.getOpl(); + auto eo = adlib->getOpl(); drv1.play(4); while(drv1.isPlaying()) r.renderBuffer(eo); @@ -625,26 +392,26 @@ void rendererMIDI() using utils::ILogger; using hardware::opl::OPL; - audio::sdl2::Renderer r(44100, 1024); + //audio::sdl2::Renderer r(44100, 1024); - r.setOutputFile("renderer_midi.wav"); + //r.setOutputFile("renderer_midi.wav"); - auto mixer = r.getMixer(); - auto op2f = files::dmx::OP2File("test/fixtures/GENMIDI.OP2"); - auto midi_adlib = std::make_shared(mixer, op2f.getBank(), audio::mixer::eChannelGroup::Music); - auto mid_drv = drivers::MIDDriver(midi_adlib); - auto mus = files::dmx::MUSFile("test/fixtures/D_E1M1.mus"); - mid_drv.play(mus.getMIDI()); - auto eo = midi_adlib->getOpl(); - - // TODO: doesn't work, due to the driver internal timing - while (mid_drv.isPlaying()) - r.renderBuffer(eo); + //auto mixer = r.getMixer(); + //auto op2f = files::dmx::OP2File("test/fixtures/GENMIDI.OP2"); + //auto midi_adlib = std::make_shared(mixer, audio::mixer::eChannelGroup::Music); + //auto mid_drv = drivers::MIDDriver(midi_adlib); + //auto mus = files::dmx::MUSFile("test/fixtures/D_E1M1.mus"); + //mid_drv.play(mus.getMIDI()); + //auto eo = midi_adlib->getOpl(); - r.releaseOutputFile(); + //// TODO: doesn't work, due to the driver internal timing + //while (mid_drv.isPlaying()) + // r.renderBuffer(eo); - files::WAVFile w("renderer.wav"); - auto sound = w.getSound(); + //r.releaseOutputFile(); + + //files::WAVFile w("renderer.wav"); + //auto sound = w.getSound(); } void testMT32() @@ -657,14 +424,14 @@ void testMT32() auto mixer = audio::make_mixer(8, 44100, 1024); if (!mixer->init()) std::cerr << "can't init mixer" << std::endl; - auto midi_mt32 = devices::make_midi_device(mixer, cr, pr); + //auto midi_mt32 = devices::make_midi_device(mixer, cr, pr); std::shared_ptr midFile = std::make_shared("test/fixtures/MI_intro.mid"); - drivers::MIDDriver midDrv(midi_mt32); + //drivers::MIDDriver midDrv(midi_mt32); - midDrv.play(midFile->getMIDI()); - while (midDrv.isPlaying()) - utils::delayMillis(1000); + //midDrv.play(midFile->getMIDI()); + //while (midDrv.isPlaying()) + // utils::delayMillis(1000); } int main(int argc, char* argv[]) diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.hpp index 5368d6a2..5ce9de82 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/IMixer.hpp @@ -61,10 +61,11 @@ namespace HyperSonicDrivers::audio virtual void setChannelVolumePan(const uint8_t id, const uint8_t volume, const int8_t pan) noexcept = 0; + virtual mixer::eChannelGroup getChannelGroup(const uint8_t id) const noexcept = 0; + uint8_t getChannelGroupVolume(const mixer::eChannelGroup group) const noexcept; void setChannelGroupVolume(const mixer::eChannelGroup group, const uint8_t volume) noexcept; - // TODO: these 3 methods are useless if those 3 vars are consts... inline uint32_t getOutputRate() const noexcept { return m_sampleRate; }; inline uint16_t getBufferSize() const noexcept { return m_samples; }; @@ -72,7 +73,7 @@ namespace HyperSonicDrivers::audio inline uint8_t getMasterVolume() const noexcept { return m_master_volume; }; virtual void setMasterVolume(const uint8_t master_volume) noexcept = 0; - + inline void toggleReverseStereo() noexcept { m_reverseStereo = !m_reverseStereo; }; const uint8_t max_channels; diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp index 6eecb631..cf7a86f5 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.cpp @@ -179,6 +179,11 @@ namespace HyperSonicDrivers::audio::sdl2 m_channels[id]->setVolumePan(volume, pan); } + mixer::eChannelGroup Mixer::getChannelGroup(const uint8_t id) const noexcept + { + return m_channels[id]->getChannelGroup(); + } + void Mixer::setMasterVolume(const uint8_t master_volume) noexcept { std::scoped_lock lck(m_mutex); diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.hpp index 60043ed1..899c8968 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/audio/sdl2/Mixer.hpp @@ -54,6 +54,8 @@ namespace HyperSonicDrivers::audio::sdl2 void setChannelVolumePan(const uint8_t id, const uint8_t volume, const int8_t pan) noexcept override; + mixer::eChannelGroup getChannelGroup(const uint8_t id) const noexcept override; + void setMasterVolume(const uint8_t master_volume) noexcept override; private: diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.cpp index b2b6c61f..d1b346ee 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.cpp @@ -1,8 +1,5 @@ #include -#include #include -#include -#include namespace HyperSonicDrivers::devices { diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.hpp index c10a7dd6..75a7d552 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Adlib.hpp @@ -12,19 +12,9 @@ namespace HyperSonicDrivers::devices { - // TODO: the Adlib sound card for SFX should use PCSpeaker. - // as it was not able to play digi-sound (sfx, speech) - // but..... anyway. - // just create a Sound Blaster that was adlib (OPL2) with digi sound - // beside not sure to do this kind of sound card reproduction - // better keep PCM separated and for MIDI/ADL/emulated sound use the card class Adlib : public Opl { public: - Adlib(Adlib&) = delete; - Adlib(Adlib&&) = delete; - Adlib& operator=(Adlib&) = delete; - explicit Adlib( const std::shared_ptr& mixer, const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.cpp index 85cfc483..0e01a66b 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.cpp @@ -2,11 +2,39 @@ namespace HyperSonicDrivers::devices { - IDevice::IDevice(const std::shared_ptr& mixer) : - m_mixer(mixer) + IDevice::IDevice(const std::shared_ptr& mixer, const bool isOpl) : + m_mixer(mixer), m_isOpl(isOpl) { } + bool IDevice::acquire(drivers::IMusicDriver* owner) + { + if (!m_acquired) + { + if (!init()) + return false; + + m_acquired = true; + m_owner = owner; + return true; + } + + return isOwned(owner); + } + + bool IDevice::release(const drivers::IMusicDriver* owner) + { + if (isOwned(owner)) + { + shutdown(); + m_acquired = false; + m_owner = nullptr; + return true; + } + + return !isAcquired(); + } + void IDevice::setVolume(const uint8_t volume) { auto ch = getChannelId(); diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.hpp index 58fe17cc..3dcf8ba1 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IDevice.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include namespace HyperSonicDrivers::devices { @@ -12,15 +15,21 @@ namespace HyperSonicDrivers::devices **/ class IDevice { - protected: - IDevice(IDevice&) = delete; - IDevice(IDevice&&) = delete; - IDevice& operator=(IDevice&) = delete; - - IDevice(const std::shared_ptr& mixer); + public: + IDevice(const std::shared_ptr& mixer, const bool isOpl = false); virtual ~IDevice() = default; - virtual std::optional getChannelId() const noexcept = 0; + virtual bool init() noexcept = 0; + inline bool isInit() const noexcept { return m_init; }; + virtual bool shutdown() noexcept = 0; + + std::optional getChannelId() const noexcept { return m_hardware->getChannelId(); }; + + inline bool isAcquired() const noexcept { return m_acquired; } + inline bool isOwned(const drivers::IMusicDriver* owner) const noexcept { return m_owner == owner; } + + bool acquire(drivers::IMusicDriver* owner); + bool release(const drivers::IMusicDriver* owner); // helpers methods void setVolume(const uint8_t volume); @@ -28,7 +37,22 @@ namespace HyperSonicDrivers::devices void setVolumePan(const uint8_t volume, const uint8_t pan); inline std::shared_ptr getMixer() const noexcept { return m_mixer; }; + inline bool isOpl() const noexcept { return m_isOpl; }; + virtual hardware::IHardware* getHardware() const noexcept { return m_hardware; }; protected: + bool m_init = false; std::shared_ptr m_mixer; + hardware::IHardware* m_hardware; + private: + bool m_isOpl = false; + // TODO: remove the atomic when removing the thread in MIDDrv + std::atomic m_acquired = false; + std::atomic m_owner = nullptr; }; + + template + std::shared_ptr make_device(Args... args) + { + return std::dynamic_pointer_cast(std::make_shared(args...)); + } } diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IMidiDevice.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IMidiDevice.hpp deleted file mode 100644 index d8aa2e30..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/IMidiDevice.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - - -namespace HyperSonicDrivers -{ - namespace drivers - { - class MIDDriver; - } - - namespace devices - { - // TODO this can be merged into Device - // or added as aggregate.. better merging it i think.. - // TODO: MT-32 still missing though - class IMidiDevice - { - public: - IMidiDevice() = default; - virtual ~IMidiDevice() = default; - - // TODO: integrate MT-32 first as a device - //virtual bool init() noexcept = 0; - - virtual void sendEvent(const audio::midi::MIDIEvent& e) const noexcept = 0; - virtual void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept = 0; - virtual void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept = 0; - virtual void pause() const noexcept = 0; - virtual void resume() const noexcept = 0; - - inline bool isAcquired() const noexcept { return _acquired; } - inline bool isOwned(const /*void**/ drivers::MIDDriver* owner) const noexcept { return _owner == owner; } - - inline bool acquire(/*void**/ drivers::MIDDriver* owner) - { - if (!_acquired) { - _acquired = true; - _owner = owner; - return true; - } - else return false; - } - - bool release(const /*void**/ drivers::MIDDriver* owner) - { - if (isOwned(owner)) { - _acquired = false; - return true; - } - - // maybe here should always return false... it can be true just because is not acquired i guess... - return !isAcquired(); - } - private: - std::atomic _acquired = false; - std::atomic _owner = nullptr; - }; - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiMT32.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/MT32.cpp similarity index 79% rename from sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiMT32.cpp rename to sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/MT32.cpp index 26e66d54..c1d82c33 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiMT32.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/MT32.cpp @@ -1,9 +1,10 @@ -#include +#include #include #include -namespace HyperSonicDrivers::devices::midi +namespace HyperSonicDrivers::devices { + // test static audio::midi::MIDIEvent MT32SysEx(uint32_t addr, const uint8_t* data, uint32_t dataSize) { //typedef uint8_t byte; @@ -43,15 +44,16 @@ namespace HyperSonicDrivers::devices::midi } - MidiMT32::MidiMT32( + MT32::MT32( const std::shared_ptr& mixer, const std::filesystem::path& control_rom_file, - const std::filesystem::path& pcm_rom_file) + const std::filesystem::path& pcm_rom_file) : + IDevice(mixer, false) { m_mt32 = std::make_shared(control_rom_file, pcm_rom_file, mixer); if (!m_mt32->init()) { - utils::throwLogC(std::format("Can't init device MidiMT32")); + utils::throwLogC(std::format("Can't init device MT32")); } m_mt32->start(nullptr); @@ -59,28 +61,28 @@ namespace HyperSonicDrivers::devices::midi // test // reset MT32 - sendSysEx(MT32SysEx(0x1FC000, 0, 0)); + //m_mt32->m_service.playSysex(MT32SysEx(0x1FC000, 0, 0)); utils::delayMillis(250); - + // Setup master tune, reverb mode, reverb time, reverb level, channel mapping, partial reserve and master volume static const uint8_t initSysex1[] = "\x40\x00\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x64"; - sendSysEx(MT32SysEx(0x40000, initSysex1, sizeof(initSysex1) - 1)); + //sendSysEx(MT32SysEx(0x40000, initSysex1, sizeof(initSysex1) - 1)); utils::delayMillis(40); // Map percussion to notes 24 - 34 without reverb. It still happens in the DOTT driver, but not in the SAMNMAX one. static const uint8_t initSysex2[] = "\x40\x64\x07\x00\x4a\x64\x06\x00\x41\x64\x07\x00\x4b\x64\x08\x00\x45\x64\x06\x00\x44\x64" "\x0b\x00\x51\x64\x05\x00\x43\x64\x08\x00\x50\x64\x07\x00\x42\x64\x03\x00\x4c\x64\x07\x00"; - sendSysEx(MT32SysEx(0xC090, initSysex2, sizeof(initSysex2) - 1)); + //sendSysEx(MT32SysEx(0xC090, initSysex2, sizeof(initSysex2) - 1)); utils::delayMillis(40); const uint8_t pbRange = 0x10; for (int i = 0; i < 128; ++i) { - sendSysEx(MT32SysEx(0x014004 + (i << 3), &pbRange, 1)); + //sendSysEx(MT32SysEx(0x014004 + (i << 3), &pbRange, 1)); utils::delayMillis(5); } } - void MidiMT32::sendEvent(const audio::midi::MIDIEvent& e) const noexcept + /* void MidiMT32::sendEvent(const audio::midi::MIDIEvent& e) const noexcept { m_mt32->m_service.playMsg(e.toUint32()); } @@ -92,13 +94,13 @@ namespace HyperSonicDrivers::devices::midi void MidiMT32::sendSysEx(const audio::midi::MIDIEvent& e) const noexcept { m_mt32->m_service.playSysex(e.data.data(), e.data.size()); - } + }*/ - void MidiMT32::pause() const noexcept - { - } + //void MT32::pause() const noexcept + //{ + //} - void MidiMT32::resume() const noexcept - { - } + //void MT32::resume() const noexcept + //{ + //} } diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/MT32.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/MT32.hpp new file mode 100644 index 00000000..59705a87 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/MT32.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace HyperSonicDrivers::devices +{ + class MT32 : public IDevice + { + public: + explicit MT32( + const std::shared_ptr& mixer, + const std::filesystem::path& control_rom_file, + const std::filesystem::path& pcm_rom_file + ); + ~MT32() override = default; + + //void sendEvent(const audio::midi::MIDIEvent& e) const noexcept override; + //void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept override; + //void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept override; + //void pause() const noexcept override; + //void resume() const noexcept override; + + private: + std::shared_ptr m_mt32; + }; +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.cpp index ac411b78..18ad52be 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.cpp @@ -1,24 +1,49 @@ #include +#include +#include #include #include #include +#include namespace HyperSonicDrivers::devices { + using utils::throwLogC; + Opl::Opl( const std::shared_ptr& mixer, const hardware::opl::OplEmulator emulator, const hardware::opl::OplType type, const uint8_t volume, const uint8_t pan) : - IDevice(mixer) + IDevice(mixer, true) { using hardware::opl::OPLFactory; using utils::logC; m_opl = OPLFactory::create(emulator, type, mixer); + m_hardware = m_opl.get(); + } + + bool Opl::init() noexcept + { + if (isInit()) + return true; + if (m_opl == nullptr || !m_opl->init()) { - logC("can't initialize opl emulator"); + utils::logE("can't initialize opl emulator"); + return false; } + + m_init = true; + return true; + } + + bool Opl::shutdown() noexcept + { + if (m_opl != nullptr) + m_opl->stop(); + + return true; } } diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.hpp index 5d27eddc..911d8251 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/Opl.hpp @@ -2,9 +2,7 @@ #include #include -#include #include -#include #include #include #include @@ -25,13 +23,11 @@ namespace HyperSonicDrivers::devices ); public: - inline std::optional getChannelId() const noexcept override { return m_opl->getChannelId(); }; - - //void playAdl(); - //void playMidi(); + bool init() noexcept override; + bool shutdown() noexcept override; inline std::shared_ptr getOpl() const noexcept { return m_opl; }; - + hardware::opl::OPL* getHardware() const noexcept override { return dynamic_cast(IDevice::getHardware()); }; private: std::shared_ptr m_opl; }; diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro.cpp new file mode 100644 index 00000000..c5ca9139 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro.cpp @@ -0,0 +1,15 @@ +#include +#include + +namespace HyperSonicDrivers::devices +{ + using hardware::opl::OplType; + + SbPro::SbPro( + const std::shared_ptr& mixer, + const hardware::opl::OplEmulator emulator, + const uint8_t volume, const uint8_t pan) : + Opl(mixer, emulator, OplType::DUAL_OPL2, volume, pan) + { + } +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro.hpp new file mode 100644 index 00000000..861d0909 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace HyperSonicDrivers::devices +{ + class SbPro : public Opl + { + public: + SbPro(SbPro&) = delete; + SbPro(SbPro&&) = delete; + SbPro& operator=(SbPro&) = delete; + + explicit SbPro( + const std::shared_ptr& mixer, + const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, + const uint8_t volume = 255, + const uint8_t pan = 0 + ); + + ~SbPro() override = default; + }; +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro2.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro2.cpp new file mode 100644 index 00000000..d690e1f1 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro2.cpp @@ -0,0 +1,15 @@ +#include +#include + +namespace HyperSonicDrivers::devices +{ + using hardware::opl::OplType; + + SbPro2::SbPro2( + const std::shared_ptr& mixer, + const hardware::opl::OplEmulator emulator, + const uint8_t volume, const uint8_t pan) : + Opl(mixer, emulator, OplType::OPL3, volume, pan) + { + } +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro2.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro2.hpp new file mode 100644 index 00000000..fea3c64d --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/SbPro2.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace HyperSonicDrivers::devices +{ + class SbPro2 : public Opl + { + public: + SbPro2(SbPro2&) = delete; + SbPro2(SbPro2&&) = delete; + SbPro2& operator=(SbPro2&) = delete; + + explicit SbPro2( + const std::shared_ptr& mixer, + const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, + const uint8_t volume = 255, + const uint8_t pan = 0 + ); + + ~SbPro2() override = default; + }; +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/makers.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/makers.hpp deleted file mode 100644 index de492098..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/makers.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -namespace HyperSonicDrivers::devices -{ - template - std::shared_ptr make_midi_device(Args... args) - { - return std::dynamic_pointer_cast(std::make_shared(args...)); - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiAdlib.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiAdlib.cpp deleted file mode 100644 index 4a8d8392..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiAdlib.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -namespace HyperSonicDrivers::devices::midi -{ - MidiAdlib::MidiAdlib( - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator, - const uint8_t volume, - const uint8_t pan) - : MidiOpl(hardware::opl::OplType::OPL2, emulator, mixer, op2Bank, group, volume, pan) - { - } - - MidiAdlib::MidiAdlib( - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator, - const uint8_t volume, - const uint8_t pan) - : MidiOpl(hardware::opl::OplType::OPL2, emulator, mixer, group, volume, pan) - { - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiAdlib.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiAdlib.hpp deleted file mode 100644 index 3c7bc301..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiAdlib.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class MidiAdlib : public MidiOpl - { - public: - explicit MidiAdlib( - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, - const uint8_t volume = 255, - const uint8_t pan = 0); - - explicit MidiAdlib( - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, - const uint8_t volume = 255, - const uint8_t pan = 0); - - ~MidiAdlib() override = default; - - //void loadBankOP2(); - }; -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiMT32.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiMT32.hpp deleted file mode 100644 index a6de9678..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiMT32.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class MidiMT32 : public IMidiDevice - { - public: - explicit MidiMT32( - const std::shared_ptr& mixer, - const std::filesystem::path& control_rom_file, - const std::filesystem::path& pcm_rom_file - ); - ~MidiMT32() override = default; - - void sendEvent(const audio::midi::MIDIEvent& e) const noexcept override; - void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept override; - void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept override; - void pause() const noexcept override; - void resume() const noexcept override; - - private: - std::shared_ptr m_mt32; - }; -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiNative.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiNative.cpp deleted file mode 100644 index 2e4e8ce7..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiNative.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - MidiNative::MidiNative(const int port) : IMidiDevice() - { - // default open port 0 - m_midiOut->openPort(port); - } - - void MidiNative::sendEvent(const audio::midi::MIDIEvent& e) const noexcept - { - std::array m; - const size_t size = e.data.size() + 1; - m[0] = e.type.val; - m[1] = e.data[0]; - if (size == 3) - m[2] = e.data[1]; - - m_midiOut->sendMessage(m.data(), size); - } - - void MidiNative::sendMessage(const uint8_t msg[], const uint8_t size) const noexcept - { - assert(size >= 2 && size <= 3); - m_midiOut->sendMessage(msg, size); - } - - void MidiNative::sendSysEx(const audio::midi::MIDIEvent& e) const noexcept - { - // TODO - } - - void MidiNative::pause() const noexcept - { - // TODO - } - - void MidiNative::resume() const noexcept - { - // TODO - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiNative.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiNative.hpp deleted file mode 100644 index 328f4199..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiNative.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - - -namespace HyperSonicDrivers::devices::midi -{ - /** - * @brief This is using OS Midi devices - * It is outside the internal Mixer at the moment. - * It wasn't neither planned to use it, but it could - * be useful to have it. - */ - class MidiNative : public IMidiDevice - { - public: - explicit MidiNative(const int port = 0); - ~MidiNative() override = default; - - void sendEvent(const audio::midi::MIDIEvent& e) const noexcept override; - void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept override; - void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept override; - void pause() const noexcept override; - void resume() const noexcept override; - - private: - std::unique_ptr m_midiOut = std::make_unique(); - }; -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiOpl.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiOpl.cpp deleted file mode 100644 index c33c7455..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiOpl.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - using utils::throwLogC; - - MidiOpl::MidiOpl(const hardware::opl::OplType type, - const hardware::opl::OplEmulator emuType, - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const uint8_t volume, - const uint8_t pan) - { - m_opl = hardware::opl::OPLFactory::create(emuType, type, mixer); - if (m_opl == nullptr || m_opl->type != type) - { - throwLogC(std::format("device Opl not supporting emu_type={}, type={}", emuType, type)); - } - if (op2Bank == nullptr) - { - utils::throwLogE("OP2Bank is nullptr"); - } - - auto opl_drv = std::make_unique(m_opl); - opl_drv->setOP2Bank(op2Bank); - m_midiDriver = std::move(opl_drv); - if (!m_midiDriver->open(group, volume, pan)) - { - throwLogC("can't open OplDriver"); - } - } - - MidiOpl::MidiOpl( - const hardware::opl::OplType type, - const hardware::opl::OplEmulator emuType, - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const uint8_t volume, - const uint8_t pan) - { - using namespace hardware::opl; - - m_opl = OPLFactory::create(emuType, type, mixer); - if (m_opl == nullptr || m_opl->type != type) - { - throwLogC(std::format("device Opl not supporting emu_type={}, type={}", emuType, type)); - } - - m_midiDriver = std::make_unique(m_opl, m_opl->type != OplType::OPL2); - m_midiDriver->open(group, volume, pan); - - } - - void MidiOpl::sendEvent(const audio::midi::MIDIEvent& e) const noexcept - { - //this->send(e); - m_midiDriver->send(e); - } - - void MidiOpl::sendMessage(const uint8_t msg[], const uint8_t size) const noexcept - { - assert(size >= 2 && size <= 3); - audio::midi::MIDIEvent e; - - e.type.val = msg[0]; - e.data.push_back(msg[1]); - if (size == 3) { - e.data.push_back(msg[2]); - } - - sendEvent(e); - } - - void MidiOpl::sendSysEx(const audio::midi::MIDIEvent& e) const noexcept - { - // TODO - //_adlib->send(e); - } - - void MidiOpl::pause() const noexcept - { - m_midiDriver->pause(); - } - - void MidiOpl::resume() const noexcept - { - m_midiDriver->resume(); - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiOpl.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiOpl.hpp deleted file mode 100644 index e167dfb9..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiOpl.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class MidiOpl : public IMidiDevice - { - public: - void sendEvent(const audio::midi::MIDIEvent& e) const noexcept override; - void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept override; - void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept override; - void pause() const noexcept override; - void resume() const noexcept override; - - inline std::shared_ptr getOpl() const noexcept { return m_opl; }; - //void loadBankOP2(); - protected: - // TODO review the constructors and use a load bank instead.. - explicit MidiOpl( - const hardware::opl::OplType type, - const hardware::opl::OplEmulator emuType, - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const uint8_t volume, - const uint8_t pan); - - explicit MidiOpl( - const hardware::opl::OplType type, - const hardware::opl::OplEmulator emuType, - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const uint8_t volume, - const uint8_t pan); - - ~MidiOpl() override = default; - - private: - std::unique_ptr m_midiDriver; - std::shared_ptr m_opl; - }; -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro.cpp deleted file mode 100644 index 42ebbc52..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -namespace HyperSonicDrivers::devices::midi -{ - MidiSbPro::MidiSbPro( - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator, - const uint8_t volume, - const uint8_t pan) - : MidiOpl(hardware::opl::OplType::DUAL_OPL2, emulator, mixer, op2Bank, group, volume, pan) - { - } - - MidiSbPro::MidiSbPro( - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator, - const uint8_t volume, - const uint8_t pan) - : MidiOpl(hardware::opl::OplType::DUAL_OPL2, emulator, mixer, group, volume, pan) - { - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro.hpp deleted file mode 100644 index d78751b1..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class MidiSbPro : public MidiOpl - { - public: - explicit MidiSbPro( - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, - const uint8_t volume = 255, - const uint8_t pan = 0); - - explicit MidiSbPro( - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, - const uint8_t volume = 255, - const uint8_t pan = 0); - - ~MidiSbPro() override = default; - - //void loadBankOP2(); - }; -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro2.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro2.cpp deleted file mode 100644 index 3fc85bde..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro2.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -namespace HyperSonicDrivers::devices::midi -{ - MidiSbPro2::MidiSbPro2( - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator, - const uint8_t volume, - const uint8_t pan) - : MidiOpl(hardware::opl::OplType::OPL3, emulator, mixer, op2Bank, group, volume, pan) - { - } - - MidiSbPro2::MidiSbPro2( - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator, - const uint8_t volume, - const uint8_t pan) - : MidiOpl(hardware::opl::OplType::OPL3, emulator, mixer, group, volume, pan) - { - } -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro2.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro2.hpp deleted file mode 100644 index 50416183..00000000 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/devices/midi/MidiSbPro2.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class MidiSbPro2 : public MidiOpl - { - public: - explicit MidiSbPro2( - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, - const uint8_t volume = 255, - const uint8_t pan = 0); - - explicit MidiSbPro2( - const std::shared_ptr& mixer, - const audio::mixer::eChannelGroup group, - const hardware::opl::OplEmulator emulator = hardware::opl::OplEmulator::AUTO, - const uint8_t volume = 255, - const uint8_t pan = 0); - - ~MidiSbPro2() override = default; - - //void loadBankOP2(); - }; -} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/IMusicDriver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/IMusicDriver.hpp new file mode 100644 index 00000000..6a66dae7 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/IMusicDriver.hpp @@ -0,0 +1,32 @@ +#pragma once + +namespace HyperSonicDrivers::drivers +{ + /** + * Common Interface for music drivers: MIDI, ADL, XMI, MUS... + * + **/ + class IMusicDriver + { + public: + IMusicDriver(IMusicDriver&) = delete; + IMusicDriver(IMusicDriver&&) = delete; + IMusicDriver& operator=(IMusicDriver&) = delete; + + IMusicDriver() = default; + virtual ~IMusicDriver() = default; + + virtual void play(const uint8_t track) noexcept = 0; + virtual void stop() noexcept = 0; + + // TODO: it might not be required + //virtual void pause() = 0; + // TODO: it might not be required + //virtual void resume() = 0; + + virtual bool isPlaying() const noexcept = 0; + + // TODO: it might not be required + //virtual bool isPaused() const noexcept = 0; + }; +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.cpp index 5d4fc41e..5f09eb8f 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.cpp @@ -4,6 +4,10 @@ #include #include #include +#include +#include +#include +#include namespace HyperSonicDrivers::drivers { @@ -29,50 +33,138 @@ namespace HyperSonicDrivers::drivers return utils::getMicro(); } - MIDDriver::MIDDriver(const std::shared_ptr& device) - : m_device(device) + MIDDriver::MIDDriver( + const std::shared_ptr& device, + const audio::mixer::eChannelGroup group, + const uint8_t volume, + const uint8_t pan + ) : m_device(device), m_group(group), m_volume(volume), m_pan(pan) { + if (!m_device->acquire(this)) + { + utils::throwLogE("Device is already in used by another driver or can't be init"); + } + + // The internal Midi driver will start the device and set up the callback + if (!resetBankOP2()) + { + utils::throwLogE("can't reset Midi driver"); + } } MIDDriver::~MIDDriver() { - stop(); + MIDDriver::stop(); + m_device->release(this); } - - void MIDDriver::play(const std::shared_ptr& midi) noexcept + + void MIDDriver::setMidi(const std::shared_ptr& midi) noexcept { using audio::midi::MIDI_FORMAT; - - if (midi->format != MIDI_FORMAT::SINGLE_TRACK && midi->numTracks != 1) + + if (midi->format == MIDI_FORMAT::SIMULTANEOUS_TRACK) { - logC("MIDI format single track supported only"); + utils::throwLogE("Can't support MIDI format 1 (SIMULTANEOUS_TRACK), must be converted to format 0 (SINGLE_TRACK)"); return; } - if (midi->division & 0x8000) + m_midi = midi; + } + + bool MIDDriver::loadBankOP2(const std::shared_ptr& op2Bank) noexcept + { + if (!m_device->isOpl()) + return false; + + if (op2Bank == nullptr) { - // ticks per frame - int smpte = (midi->division & 0x7FFF) >> 8; - int ticksPerFrame = midi->division & 0xFF; - switch (smpte) - { - case -24: - case -25: - case -29: - case -30: - logW("SMPTE not implemented yet"); - break; - default: - logW(std::format("Division SMPTE not known = {}", smpte)); - } + utils::logE("OP2Bank is nullptr"); + return false; + } + + m_midiDriver.reset(); + + auto opl = std::dynamic_pointer_cast(m_device)->getOpl(); + auto opl_drv = std::make_unique(opl); + opl_drv->setOP2Bank(op2Bank); + m_midiDriver = std::move(opl_drv); + return open_(); + } - logD(std::format("Division: Ticks per frame = {}, {}", ticksPerFrame, smpte)); - logW("division ticks per frame not implemented yet"); + bool MIDDriver::resetBankOP2() noexcept + { + if (m_device->isOpl()) + { + using hardware::opl::OplType; + + auto opl = std::dynamic_pointer_cast(m_device)->getOpl(); + m_midiDriver = std::make_unique( + opl, opl->type != OplType::OPL2); } else { - // ticks per quarter note - logD(std::format("Division: Ticks per quarter note = {}", midi->division & 0x7FFF)); + // must be mt32 (TODO) + m_midiDriver = std::make_unique(); + } + + return open_(); + } + + //void MIDDriver::play(const std::shared_ptr& midi) noexcept + //{ + // using audio::midi::MIDI_FORMAT; + + // setMidi(midi); + + // if (midi->format != MIDI_FORMAT::SINGLE_TRACK && midi->numTracks != 1) + // { + // logC("MIDI format single track supported only"); + // return; + // } + + // // TODO: this is to set the callback frequency + // if (midi->division & 0x8000) + // { + // // ticks per frame + // int smpte = (midi->division & 0x7FFF) >> 8; + // int ticksPerFrame = midi->division & 0xFF; + // switch (smpte) + // { + // case -24: + // case -25: + // case -29: + // case -30: + // logW("SMPTE not implemented yet"); + // break; + // default: + // logW(std::format("Division SMPTE not known = {}", smpte)); + // } + + // logD(std::format("Division: Ticks per frame = {}, {}", ticksPerFrame, smpte)); + // logW("division ticks per frame not implemented yet"); + // } + // else + // { + // // ticks per quarter note + // logD(std::format("Division: Ticks per quarter note = {}", midi->division & 0x7FFF)); + // } + + // stop(); + // if (!m_device->acquire(this)) { + // return; + // } + + // //TODO: it would be better reusing the thread... + // m_player = std::jthread(&MIDDriver::processTrack, this, midi->getTrack(), midi->division & 0x7FFF); + // m_isPlaying = true; + //} + + void MIDDriver::play(const uint8_t track) noexcept + { + if (track >= m_midi->numTracks) + { + logW(std::format("track not available: {}", track)); + return; } stop(); @@ -80,8 +172,8 @@ namespace HyperSonicDrivers::drivers return; } - //TODO: it would be better reusing the thread... - m_player = std::jthread(&MIDDriver::processTrack, this, midi->getTrack(), midi->division & 0x7FFF); + // TODO: set up a callback instead of the thread + m_player = std::jthread(&MIDDriver::processTrack, this, m_midi->getTrack(track), m_midi->division & 0x7FFF); m_isPlaying = true; } @@ -93,7 +185,6 @@ namespace HyperSonicDrivers::drivers m_player.join(); m_force_stop = false; m_isPlaying = false; - m_device->release(this); } void MIDDriver::pause() noexcept @@ -118,6 +209,17 @@ namespace HyperSonicDrivers::drivers return m_paused; } + bool MIDDriver::open_() noexcept + { + if (!m_midiDriver->open(m_group, m_volume, m_pan)) + { + utils::logE("can't open midi driver"); + return false; + } + + return true; + } + void MIDDriver::processTrack(const audio::midi::MIDITrack& track, const uint16_t division) { using audio::midi::MIDI_EVENT_TYPES_HIGH; @@ -140,12 +242,12 @@ namespace HyperSonicDrivers::drivers { if(m_paused) { - m_device->pause(); + m_midiDriver->pause(); do { utils::delayMillis(PAUSE_MILLIS); } while (m_paused); - m_device->resume(); + m_midiDriver->resume(); start = get_start_time(); } @@ -239,12 +341,12 @@ namespace HyperSonicDrivers::drivers case MIDI_META_EVENT_TYPES_LOW::SYS_EX0: logD("SYS_EX0 META event"); // TODO: it should be sent as normal event? - m_device->sendSysEx(e); + m_midiDriver->send(e); continue; case MIDI_META_EVENT_TYPES_LOW::SYS_EX7: logD("SYS_EX7 META event"); // TODO: it should be sent as normal event? - m_device->sendSysEx(e); + m_midiDriver->send(e); continue; default: logW(std::format("MIDI_META_EVENT_TYPES_LOW not implemented/recognized: {:#02x}", e.type.low)); @@ -291,10 +393,9 @@ namespace HyperSonicDrivers::drivers start = get_start_time(); } - m_device->sendEvent(e); + m_midiDriver->send(e); } - m_device->release(this); m_isPlaying = false; } } diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.hpp index b51249ae..b638be43 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/MIDDriver.hpp @@ -5,25 +5,48 @@ #include #include #include -#include +#include #include -#include +#include +#include +#include +#include + namespace HyperSonicDrivers::drivers { // TODO/NOTE: this is more the OnTimer logic and setup of OplDriver, but generalized // for whatever midi::driver ... need to be reivewed // TODO: maybe rename it to midi_player - class MIDDriver + // TODO: deprecated class + class MIDDriver : public IMusicDriver { public: - explicit MIDDriver(const std::shared_ptr& device); - ~MIDDriver(); - void play(const std::shared_ptr& midi) noexcept; - void stop() noexcept; + explicit MIDDriver( + const std::shared_ptr& device, + const audio::mixer::eChannelGroup group, + const uint8_t volume = 255, + const uint8_t pan = 0 + ); + ~MIDDriver() override; + + void setMidi(const std::shared_ptr& midi) noexcept; + // It works only for Opl devices + bool loadBankOP2(const std::shared_ptr& op2Bank) noexcept; + // this restore the default MidiDriver (scummvm::MidiAdlib, MT32) + bool resetBankOP2() noexcept; + + //[[deprecated("use the other play method")]] + //void play(const std::shared_ptr& midi) noexcept; + + void play(const uint8_t track = 0) noexcept override; + void stop() noexcept override; + void pause() noexcept; void resume() noexcept; - bool isPlaying() const noexcept; + + bool isPlaying() const noexcept override; + bool isPaused() const noexcept; inline bool isTempoChanged() const noexcept { return m_midiTempoChanged; } inline uint32_t getTempo() noexcept { m_midiTempoChanged = false; return m_tempo; } @@ -33,10 +56,14 @@ namespace HyperSonicDrivers::drivers // would be better using SDL2 custom event // or a event queue sub-sytem instead of doing this with a simple boolean inline void setTempo(const uint32_t tempo) noexcept { m_midiTempoChanged = true; m_tempo = tempo; } - + bool open_() noexcept; private: - std::shared_ptr m_device; - + std::shared_ptr m_device; + std::unique_ptr m_midiDriver; + std::shared_ptr m_midi; + const audio::mixer::eChannelGroup m_group; + const uint8_t m_volume; + const uint8_t m_pan; // TODO: consider to create a utils/Thread class // to handle for each OS specific realtime and initialization step. std::jthread m_player; diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/IMidiDriver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/IMidiDriver.hpp index 6c87c766..1e19919c 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/IMidiDriver.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/IMidiDriver.hpp @@ -13,10 +13,6 @@ namespace HyperSonicDrivers::drivers::midi class IMidiDriver { public: - IMidiDriver(IMidiDriver&) = delete; - IMidiDriver(IMidiDriver&&) = delete; - IMidiDriver& operator=(IMidiDriver&) = delete; - IMidiDriver() = default; virtual ~IMidiDriver() = default; diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/mt32/MT32Driver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/mt32/MT32Driver.hpp new file mode 100644 index 00000000..02dac16d --- /dev/null +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/mt32/MT32Driver.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace HyperSonicDrivers::drivers::midi::mt32 +{ + class MT32Driver : public IMidiDriver + { + public: + // TODO + + bool open(const audio::mixer::eChannelGroup group, + const uint8_t volume, + const uint8_t pan) override { return true; }; + void close() override {}; + + void send(const audio::midi::MIDIEvent& e) noexcept override {}; + void send(uint32_t msg) override {}; + void send(int8_t channel, uint32_t msg) override {}; + + void pause() const noexcept override {}; + void resume() const noexcept override {}; + }; +} diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/opl/OplDriver.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/opl/OplDriver.cpp index ca4c1a20..644fc721 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/opl/OplDriver.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/opl/OplDriver.cpp @@ -12,6 +12,7 @@ namespace HyperSonicDrivers::drivers::midi::opl using audio::midi::MIDI_PERCUSSION_CHANNEL; using audio::midi::MIDI_EVENT_TYPES_HIGH; + using audio::midi::TO_HIGH; using hardware::opl::OPL2instrument_t; using hardware::opl::OplType; using utils::logW; @@ -85,7 +86,7 @@ namespace HyperSonicDrivers::drivers::midi::opl void OplDriver::send(const audio::midi::MIDIEvent& e) noexcept { - switch (static_cast(e.type.high)) + switch (TO_HIGH(e.type.high)) { case MIDI_EVENT_TYPES_HIGH::NOTE_OFF: noteOff(e.type.low, e.data[0]); diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/scummvm/MidiDriver_ADLIB.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/scummvm/MidiDriver_ADLIB.cpp index 6eaf835e..7d7db465 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/scummvm/MidiDriver_ADLIB.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/midi/scummvm/MidiDriver_ADLIB.cpp @@ -167,7 +167,17 @@ namespace HyperSonicDrivers::drivers::midi::scummvm void MidiDriver_ADLIB::send(const audio::midi::MIDIEvent& e) /*const*/ noexcept { - send(e.toUint32()); + using audio::midi::TO_HIGH; + using audio::midi::MIDI_EVENT_TYPES_HIGH; + + switch (TO_HIGH(e.type.high)) + { + case MIDI_EVENT_TYPES_HIGH::META_SYSEX: + sysEx(e.data.data(), static_cast(e.data.size())); + break; + default: + send(e.toUint32()); + } } void MidiDriver_ADLIB::send(uint32_t b) { diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.cpp index 779e1fea..277b8168 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.cpp @@ -24,21 +24,22 @@ namespace HyperSonicDrivers::drivers::westwood using utils::throwLogE; ADLDriver::ADLDriver( - const std::shared_ptr& opl, + const std::shared_ptr& opl, const audio::mixer::eChannelGroup group, const uint8_t volume, - const uint8_t pan - ) : m_rnd(random_seed), m_opl(opl) + const uint8_t pan) : + m_device(opl), m_opl(opl->getOpl()) { - if (!m_opl || !m_opl->init()) - { - throwLogE("Failed to initialize OPL or OPL is null"); - } - memset(m_channels.data(), 0, sizeof(m_channels)); - hardware::TimerCallBack cb = std::bind(&ADLDriver::callback, this); auto p = std::make_shared(cb); + + // NOTE: it acquires it due to opl->start + if (!m_device->acquire(this)) + { + throwLogE("Device is already in used by another driver or can't be init"); + } + m_opl->start( p, group, @@ -53,13 +54,9 @@ namespace HyperSonicDrivers::drivers::westwood setOplSfxVolume(255); } - ADLDriver::ADLDriver( - const devices::Opl& opl, - const audio::mixer::eChannelGroup group, - const uint8_t volume, - const uint8_t pan - ) : ADLDriver(opl.getOpl(), group, volume, pan) + ADLDriver::~ADLDriver() { + m_device->release(this); } void ADLDriver::setADLFile(const std::shared_ptr& adl_file) noexcept @@ -104,7 +101,7 @@ namespace HyperSonicDrivers::drivers::westwood ++m_programQueueEnd &= 15; } - bool ADLDriver::isChannelPlaying(const int channel) + bool ADLDriver::isChannelPlaying(const int channel) const noexcept { const std::scoped_lock lock(m_mutex); @@ -221,7 +218,7 @@ namespace HyperSonicDrivers::drivers::westwood m_oplSfxVolume = volume; - for (uint8_t i = 6; i < 9; ++i) { + for (uint8_t i = 6; i < NUM_CHANNELS; ++i) { Channel& chan = m_channels[i]; chan.volumeModifier = volume; @@ -233,10 +230,11 @@ namespace HyperSonicDrivers::drivers::westwood } } - void ADLDriver::play(const uint8_t track, const uint8_t volume) + void ADLDriver::play(const uint8_t track) noexcept { std::scoped_lock lock(m_mutex); + constexpr uint8_t volume = std::numeric_limits::max(); uint16_t soundId = 0; soundId = m_adl_file->getTrack(track); @@ -248,7 +246,12 @@ namespace HyperSonicDrivers::drivers::westwood startSound_(soundId, volume); } - bool ADLDriver::isPlaying() + void ADLDriver::stop() noexcept + { + stopAllChannels(); + } + + bool ADLDriver::isPlaying() const noexcept { return isChannelPlaying(0) || m_programQueueStart != m_programQueueEnd; } @@ -517,7 +520,7 @@ namespace HyperSonicDrivers::drivers::westwood { logD("resetAdLibState()"); - m_rnd = 0x1234; + m_rnd = random_seed; // Authorize the control of the waveforms writeOPL_(0x01, 0x20); diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.hpp index 23c53531..db1078f2 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/drivers/westwood/ADLDriver.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace HyperSonicDrivers::drivers::westwood { @@ -28,40 +29,34 @@ namespace HyperSonicDrivers::drivers::westwood /// the same file format(but need different offset adjustments); /// Kyrandia 2 and LoL format(version 4) is different again. /// - class ADLDriver + class ADLDriver : public IMusicDriver { public: - [[deprecated("use an opl device instead of opl")]] explicit ADLDriver( - const std::shared_ptr& opl, + const std::shared_ptr& opl, const audio::mixer::eChannelGroup group, const uint8_t volume = 255, const uint8_t pan = 0 ); - explicit ADLDriver( - const devices::Opl& opl, - const audio::mixer::eChannelGroup group, - const uint8_t volume = 255, - const uint8_t pan = 0 - ); + ~ADLDriver() override; - virtual ~ADLDriver() = default; void setADLFile(const std::shared_ptr& adl_file) noexcept; - bool isChannelPlaying(const int channel); + bool isChannelPlaying(const int channel) const noexcept; void stopAllChannels(); int getSoundTrigger() const; void resetSoundTrigger(); - void callback(); void setSyncJumpMask(const uint16_t mask); void setOplMusicVolume(const uint8_t volume); void setOplSfxVolume(const uint8_t volume); - void play(const uint8_t track, const uint8_t volume = 0xFF); - bool isPlaying(); + void play(const uint8_t track) noexcept override; + void stop() noexcept override; + + bool isPlaying() const noexcept override; private: void initDriver_(); void startSound_(const uint8_t track, const uint8_t volume); @@ -260,6 +255,7 @@ namespace HyperSonicDrivers::drivers::westwood uint8_t m_opExtraLevel1BD = 0; uint8_t m_opExtraLevel2BD = 0; + std::shared_ptr m_device; std::shared_ptr m_opl; struct QueueEntry diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.cpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.cpp index e43f63d9..d8145918 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.cpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.cpp @@ -25,6 +25,9 @@ namespace HyperSonicDrivers::hardware const uint8_t volume, const uint8_t pan, const int timerFrequency) { + if (m_channelId.has_value()) + stop(); + m_callback = callback; startCallbacks(group, volume, pan, timerFrequency); } diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.hpp index d6693d91..406ffd8b 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/IHardware.hpp @@ -29,10 +29,6 @@ namespace HyperSonicDrivers::hardware friend audio::streams::EmulatedStream; public: - IHardware(IHardware&) = delete; - IHardware(IHardware&&) = delete; - IHardware& operator=(IHardware&) = delete; - explicit IHardware(const std::shared_ptr& mixer); virtual ~IHardware(); diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/mt32/MT32.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/mt32/MT32.hpp index 83f6ebda..cb17e3e7 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/mt32/MT32.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/mt32/MT32.hpp @@ -9,9 +9,9 @@ #include #include -namespace HyperSonicDrivers::devices::midi +namespace HyperSonicDrivers::devices { - class MidiMT32; + class MT32; } //namespace HyperSonicDrivers::audio @@ -26,7 +26,7 @@ namespace HyperSonicDrivers::hardware::mt32 class MT32 : public IHardware { - friend devices::midi::MidiMT32; + friend devices::MT32; public: MT32(const std::filesystem::path& control_rom, const std::filesystem::path& pcm_rom, diff --git a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/opl/OPL.hpp b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/opl/OPL.hpp index c88f0c39..e4322c73 100644 --- a/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/opl/OPL.hpp +++ b/sdl2-hyper-sonic-drivers/src/HyperSonicDrivers/hardware/opl/OPL.hpp @@ -25,10 +25,6 @@ namespace HyperSonicDrivers::hardware::opl friend audio::IRenderer; public: - OPL(const OPL&) = delete; - OPL(const OPL&&) = delete; - OPL& operator=(const OPL&) = delete; - explicit OPL(const std::shared_ptr& mixer, const OplType type); ~OPL() override = default; diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/CMakeLists.txt b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/CMakeLists.txt index 4ed8a231..03fb1466 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/CMakeLists.txt +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/CMakeLists.txt @@ -132,42 +132,34 @@ macro_test( ) macro_test( - EXE TestIMidiDevice - FILES "devices/TestIMidiDevice.cpp" + EXE TestIDevice + FILES "devices/TestIDevice.cpp" LINKS_PRIVATE hyper-sonic-drivers-static FIXTURES ) macro_test( - EXE TestMidiOplDevice - FILES "devices/midi/TestMidiOpl.cpp" + EXE TestOplDevice + FILES "devices/TestOpl.cpp" LINKS_PRIVATE hyper-sonic-drivers-static - FIXTURES - "../fixtures/GENMIDI.OP2" ) macro_test( - EXE TestMidiAdlib - FILES "devices/midi/TestMidiAdlib.cpp" + EXE TestAdlib + FILES "devices/TestAdlib.cpp" LINKS_PRIVATE hyper-sonic-drivers-static - FIXTURES - "../fixtures/GENMIDI.OP2" ) macro_test( - EXE TestMidiSbPro - FILES "devices/midi/TestMidiSbPro.cpp" + EXE TestSbPro + FILES "devices/TestSbPro.cpp" LINKS_PRIVATE hyper-sonic-drivers-static - FIXTURES - "../fixtures/GENMIDI.OP2" ) macro_test( - EXE TestMidiSbPro2 - FILES "devices/midi/TestMidiSbPro2.cpp" + EXE TestSbPro2 + FILES "devices/TestSbPro2.cpp" LINKS_PRIVATE hyper-sonic-drivers-static - FIXTURES - "../fixtures/GENMIDI.OP2" ) macro_test( diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/stubs/StubMixer.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/stubs/StubMixer.hpp index c32fd630..e6d49172 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/stubs/StubMixer.hpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/audio/stubs/StubMixer.hpp @@ -44,6 +44,8 @@ namespace HyperSonicDrivers::audio::stubs void muteChannelGroup(const mixer::eChannelGroup group) noexcept override {}; void unmuteChannelGroup(const mixer::eChannelGroup group) noexcept override {}; + mixer::eChannelGroup getChannelGroup(const uint8_t id) const noexcept override { return mixer::eChannelGroup::Unknown; } + uint8_t getChannelVolume(const uint8_t id) const noexcept override { return audio::mixer::Channel_max_volume; }; void setChannelVolume(const uint8_t id, const uint8_t volume) noexcept override {}; uint8_t getChannelPan(const uint8_t id) const noexcept override { return 0; }; diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/EmulatorTestCase.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/EmulatorTestCase.hpp new file mode 100644 index 00000000..130ce8a8 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/EmulatorTestCase.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace HyperSonicDrivers::devices +{ + using audio::stubs::StubMixer; + using hardware::opl::OplEmulator; + + template + class EmulatorTestCase : public ::testing::TestWithParam> + { + public: + const OplEmulator oplEmu = std::get<0>(GetParam()); + const bool shouldFail = std::get<1>(GetParam()); + const std::shared_ptr mixer = std::make_shared(); + + void test_case() + { + T opl(this->mixer, this->oplEmu); + EXPECT_EQ(opl.init(), !this->shouldFail); + } + }; +} diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/OplDeviceMock.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/OplDeviceMock.hpp new file mode 100644 index 00000000..7ad2da8b --- /dev/null +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/OplDeviceMock.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace HyperSonicDrivers::devices +{ + class OplDeviceMock : public Opl + { + public: + explicit OplDeviceMock(const hardware::opl::OplType type, + const hardware::opl::OplEmulator emuType, + const std::shared_ptr& mixer) + : Opl(mixer, emuType, type, 255, 0) + { + } + ~OplDeviceMock() override = default; + }; +} diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/SpyDevice.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/SpyDevice.hpp new file mode 100644 index 00000000..c8b49c34 --- /dev/null +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/SpyDevice.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include + +namespace HyperSonicDrivers::devices +{ + class SpyDevice : public IDevice + { + public: + SpyDevice(const std::shared_ptr& mixer, const bool isOpl = false) : IDevice(mixer, isOpl) {}; + SpyDevice() : IDevice(audio::make_mixer(), false) {}; + + bool init() noexcept override { return true; }; + bool shutdown() noexcept override { return true; }; + std::optional getChannelId() const noexcept { return std::nullopt; }; + + + /* virtual void sendEvent(const audio::midi::MIDIEvent& e) const noexcept override + { + + }; + virtual void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept override + { + + } + virtual void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept override + { + + }*/ + /*virtual void pause() const noexcept override + { + + } + virtual void resume() const noexcept override + { + + }*/ + }; +} + diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiAdlib.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestAdlib.cpp similarity index 63% rename from sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiAdlib.cpp rename to sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestAdlib.cpp index b2e2a2d3..b75b854f 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiAdlib.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestAdlib.cpp @@ -1,24 +1,23 @@ #include #include -#include +#include #include #include #include #include #include #include -#include +#include -namespace HyperSonicDrivers::devices::midi +namespace HyperSonicDrivers::devices { - TEST(MidiAdlib, cstor_) + TEST(Adlib, cstor_AUTO) { - auto op2File = OP2File(GENMIDI_OP2); auto mixer = std::make_shared(); - EXPECT_NO_THROW(auto a = std::make_shared(mixer, op2File.getBank(), eChannelGroup::Plain)); + EXPECT_NO_THROW(auto a = std::make_shared(mixer)); } - class AdliblEmulator_ : public EmulatorTestCase {}; + class AdliblEmulator_ : public EmulatorTestCase {}; TEST_P(AdliblEmulator_, cstr_TYPE) { test_case(); @@ -35,13 +34,6 @@ namespace HyperSonicDrivers::devices::midi std::make_tuple<>(OplEmulator::NUKED, true) // TODO: this is OPL2 compatible so, it should work, at the moment forced only to be OPL3 type ) ); - - TEST(MidiAdlib, cstr_AUTO) - { - auto op2File = OP2File(GENMIDI_OP2); - auto mixer = std::make_shared(); - EXPECT_NO_THROW(MidiAdlib(mixer, op2File.getBank(), eChannelGroup::Plain)); - } } int main(int argc, char** argv) diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestIMidiDevice.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestIDevice.cpp similarity index 62% rename from sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestIMidiDevice.cpp rename to sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestIDevice.cpp index 6d499cdc..8ba74f51 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestIMidiDevice.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestIDevice.cpp @@ -1,41 +1,44 @@ #include #include -#include -#include +#include +#include #include namespace HyperSonicDrivers::devices { using drivers::MIDDriverMock; - TEST(IMidiDevice, acquire_release) + TEST(IDevice, double_acquire) { - auto device = std::make_shared(); + auto device = std::make_shared(); + + MIDDriverMock middrv(device); + EXPECT_THROW(MIDDriverMock middrv2(device), std::runtime_error); + } + + TEST(IDevice, acquire_release) + { + auto device = std::make_shared(); MIDDriverMock middrv(device); - MIDDriverMock middrv2(device); - EXPECT_FALSE(device->isAcquired()); + EXPECT_TRUE(device->isAcquired()); EXPECT_TRUE(device->release(&middrv)); - EXPECT_TRUE(device->release(&middrv2)); EXPECT_TRUE(device->release(nullptr)); EXPECT_FALSE(device->isOwned(&middrv)); - EXPECT_FALSE(device->isOwned(&middrv2)); EXPECT_TRUE(device->isOwned(nullptr)); EXPECT_TRUE(device->acquire(&middrv)); - EXPECT_FALSE(device->acquire(&middrv2)); EXPECT_FALSE(device->acquire(nullptr)); + EXPECT_TRUE(device->acquire(&middrv)); EXPECT_TRUE(device->isAcquired()); EXPECT_TRUE(device->isOwned(&middrv)); - EXPECT_FALSE(device->release(&middrv2)); EXPECT_FALSE(device->release(nullptr)); EXPECT_TRUE(device->release(&middrv)); - EXPECT_TRUE(device->release(&middrv2)); EXPECT_TRUE(device->release(nullptr)); EXPECT_FALSE(device->isAcquired()); diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiOpl.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestOpl.cpp similarity index 65% rename from sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiOpl.cpp rename to sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestOpl.cpp index c77a588f..63d21c23 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiOpl.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestOpl.cpp @@ -1,37 +1,25 @@ #include #include -#include +#include #include #include #include #include -#include -#include #include -#include -#include -#include +#include namespace HyperSonicDrivers::devices::midi { using audio::stubs::StubMixer; - using audio::opl::banks::OP2Bank; using hardware::opl::OplType; using hardware::opl::OplEmulator; - using hardware::opl::OPLFactory; using hardware::opl::OPL; - using files::dmx::OP2File; - using files::dmx::OP2File; using audio::mixer::eChannelGroup; - const std::string GENMIDI_OP2 = std::string("../fixtures/GENMIDI.OP2"); - TEST(MidiOpl, cstor_) { - auto op2File = OP2File(GENMIDI_OP2); auto mixer = std::make_shared(); - EXPECT_NO_THROW(MidiOplDeviceMock(OplType::OPL2, OplEmulator::AUTO, mixer, op2File.getBank())); - EXPECT_THROW(MidiOplDeviceMock(OplType::OPL2, OplEmulator::AUTO, mixer, nullptr), std::invalid_argument); + EXPECT_NO_THROW(OplDeviceMock(OplType::OPL2, OplEmulator::AUTO, mixer)); } class OplEmulator_ : public ::testing::TestWithParam> @@ -39,25 +27,17 @@ namespace HyperSonicDrivers::devices::midi public: const OplType oplType = std::get<0>(GetParam()); const OplEmulator oplEmu = std::get<1>(GetParam()); - const bool shouldThrow = std::get<2>(GetParam()); - const OP2File op2File = OP2File(GENMIDI_OP2); + const bool shouldFail = std::get<2>(GetParam()); const std::shared_ptr mixer = std::make_shared(); }; TEST_P(OplEmulator_, cstr_type_emu) { - if (this->shouldThrow) { - EXPECT_THROW( - MidiOplDeviceMock(this->oplType, this->oplEmu, this->mixer, this->op2File.getBank()), - std::runtime_error - ); - } - else { - EXPECT_NO_THROW(MidiOplDeviceMock(this->oplType, this->oplEmu, this->mixer, this->op2File.getBank())); - } + OplDeviceMock opl(this->oplType, this->oplEmu, this->mixer); + EXPECT_EQ(opl.init(), !this->shouldFail); } INSTANTIATE_TEST_SUITE_P( - MidiOpl, + Opl, OplEmulator_, ::testing::Values( std::make_tuple<>(OplType::OPL2, OplEmulator::AUTO, false), diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiSbPro.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestSbPro.cpp similarity index 60% rename from sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiSbPro.cpp rename to sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestSbPro.cpp index 1d1b7e65..1a182de8 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiSbPro.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestSbPro.cpp @@ -1,28 +1,27 @@ #include #include -#include +#include #include #include -#include +#include -namespace HyperSonicDrivers::devices::midi +namespace HyperSonicDrivers::devices { - TEST(MidiSbPro, cstor_) + TEST(SbPro, cstor_) { - auto op2File = OP2File(GENMIDI_OP2); auto mixer = std::make_shared(); - EXPECT_NO_THROW(auto s = MidiSbPro(mixer, op2File.getBank(), eChannelGroup::Plain)); + EXPECT_NO_THROW(auto s = SbPro(mixer, OplEmulator::DOS_BOX)); } - class SbProEmulator_ : public EmulatorTestCase {}; + class SbProEmulator_ : public EmulatorTestCase {}; TEST_P(SbProEmulator_, cstr_TYPE) { test_case(); } INSTANTIATE_TEST_SUITE_P( - MidiSbPro, + SbPro, SbProEmulator_, ::testing::Values( std::make_tuple<>(OplEmulator::AUTO, false), @@ -33,11 +32,10 @@ namespace HyperSonicDrivers::devices::midi ) ); - TEST(MidiSbPro, cstr_AUTO) + TEST(SbPro, cstr_AUTO) { - auto op2File = OP2File(GENMIDI_OP2); auto mixer = std::make_shared(); - EXPECT_NO_THROW(MidiSbPro(mixer, op2File.getBank(), eChannelGroup::Plain)); + EXPECT_NO_THROW(SbPro(mixer, OplEmulator::AUTO)); } } diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiSbPro2.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestSbPro2.cpp similarity index 61% rename from sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiSbPro2.cpp rename to sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestSbPro2.cpp index 684da033..86524dec 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/TestMidiSbPro2.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/TestSbPro2.cpp @@ -1,20 +1,19 @@ #include #include -#include -#include +#include +#include #include #include -namespace HyperSonicDrivers::devices::midi +namespace HyperSonicDrivers::devices { - TEST(MidiSbPro2, cstor_) + TEST(SbPro2, cstor_) { - auto op2File = OP2File(GENMIDI_OP2); auto mixer = std::make_shared(); - EXPECT_NO_THROW(auto s = MidiSbPro2(mixer, op2File.getBank(), eChannelGroup::Plain)); + EXPECT_NO_THROW(auto s = SbPro2(mixer, OplEmulator::NUKED)); } - class SbPro2Emulator_ : public EmulatorTestCase {}; + class SbPro2Emulator_ : public EmulatorTestCase {}; TEST_P(SbPro2Emulator_, cstr_TYPE) { @@ -33,11 +32,10 @@ namespace HyperSonicDrivers::devices::midi ) ); - TEST(MidiSbPro2, cstr_AUTO) + TEST(SbPro2, cstor_AUTO) { - auto op2File = OP2File(GENMIDI_OP2); auto mixer = std::make_shared(); - EXPECT_NO_THROW(MidiSbPro2(mixer, op2File.getBank(), eChannelGroup::Plain)); + EXPECT_NO_THROW(auto s = SbPro2(mixer)); } } diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/EmulatorTestCase.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/EmulatorTestCase.hpp deleted file mode 100644 index 9b283872..00000000 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/EmulatorTestCase.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - using audio::stubs::StubMixer; - using hardware::opl::OplType; - using hardware::opl::OplEmulator; - using hardware::opl::OPLFactory; - using files::dmx::OP2File; - using audio::mixer::eChannelGroup; - - static const std::string GENMIDI_OP2 = std::string("../fixtures/GENMIDI.OP2"); - - template - class EmulatorTestCase : public ::testing::TestWithParam> - { - public: - const hardware::opl::OplEmulator oplEmu = std::get<0>(GetParam()); - const bool shouldThrow = std::get<1>(GetParam()); - const files::dmx::OP2File op2File = OP2File(GENMIDI_OP2); - const std::shared_ptr mixer = std::make_shared(); - - void test_case() - { - using audio::mixer::eChannelGroup; - - if (this->shouldThrow) - { - EXPECT_THROW( - T(this->mixer, this->op2File.getBank(), eChannelGroup::Plain, this->oplEmu), - std::runtime_error - ); - } - else { - EXPECT_NO_THROW(T(this->mixer, this->op2File.getBank(), eChannelGroup::Plain, this->oplEmu)); - } - } - }; -} diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/MidiOplDeviceMock.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/MidiOplDeviceMock.hpp deleted file mode 100644 index b5e63dd0..00000000 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/MidiOplDeviceMock.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class MidiOplDeviceMock : public MidiOpl - { - public: - explicit MidiOplDeviceMock(const hardware::opl::OplType type, - const hardware::opl::OplEmulator emuType, - const std::shared_ptr& mixer, - const std::shared_ptr& op2Bank) - : MidiOpl(type, emuType, mixer, op2Bank, audio::mixer::eChannelGroup::Plain, 255, 0) {} - ~MidiOplDeviceMock() override = default; - }; -} diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/SpyMidiDevice.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/SpyMidiDevice.hpp deleted file mode 100644 index ace7357b..00000000 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/devices/midi/SpyMidiDevice.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -namespace HyperSonicDrivers::devices::midi -{ - class SpyMidiDevice : public IMidiDevice - { - virtual void sendEvent(const audio::midi::MIDIEvent& e) const noexcept override - { - - }; - virtual void sendMessage(const uint8_t msg[], const uint8_t size) const noexcept override - { - - } - virtual void sendSysEx(const audio::midi::MIDIEvent& e) const noexcept override - { - - } - virtual void pause() const noexcept override - { - - } - virtual void resume() const noexcept override - { - - } - }; -} - diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/MIDDriverMock.hpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/MIDDriverMock.hpp index 6cc64ff5..739260a2 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/MIDDriverMock.hpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/MIDDriverMock.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -10,8 +10,8 @@ namespace HyperSonicDrivers::drivers class MIDDriverMock : public MIDDriver { public: - explicit MIDDriverMock(const std::shared_ptr& device) : - MIDDriver(device) + explicit MIDDriverMock(const std::shared_ptr& device) : + MIDDriver(device, audio::mixer::eChannelGroup::Unknown) { } diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestMIDDriver.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestMIDDriver.cpp index cdf0dcc0..a71b549e 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestMIDDriver.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/TestMIDDriver.cpp @@ -9,8 +9,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -27,7 +26,7 @@ namespace HyperSonicDrivers::drivers TEST(MIDDriver, SEQUENCE_NAME_META_EVENT) { - auto device = std::make_shared(); + auto device = std::make_shared(); ILogger::instance->setLevel(ILogger::eLevel::Trace, ILogger::eCategory::Audio); @@ -55,101 +54,62 @@ namespace HyperSonicDrivers::drivers TEST(MIDDriver, force_stop_on_long_delta_time_delay) { - auto device = std::make_shared(); - - MIDIEvent e; - e.delta_time = 0; - e.type.high = (uint8_t)MIDI_EVENT_TYPES_HIGH::META_SYSEX; - e.type.low = (uint8_t)MIDI_META_EVENT_TYPES_LOW::META; - - // this can be a parameter - e.data.push_back((uint8_t)MIDI_META_EVENT::SEQUENCE_NAME); - - std::string s = "sequence_name"; - e.data.insert(e.data.end(), s.begin(), s.end()); - - auto midi_track = audio::midi::MIDITrack(); - midi_track.addEvent(e); - - - e.delta_time = 1000; - e.type.high = (uint8_t)MIDI_EVENT_TYPES_HIGH::PROGRAM_CHANGE; - e.type.low = 0; - e.data.clear(); - e.data.push_back((uint8_t)0); - e.data.push_back((uint8_t)0); - - midi_track.addEvent(e); - - auto midi = std::make_shared(MIDI_FORMAT::SINGLE_TRACK, 1, 192); - midi->addTrack(midi_track); - - MIDDriverMock middrv(device); - middrv.play(midi); - ASSERT_TRUE(middrv.isPlaying()); - auto start = utils::getMillis(); - utils::delayMillis(20); - middrv.stop(); - EXPECT_FALSE(middrv.isPlaying()); - auto stop = utils::getMillis(); - EXPECT_LE(stop - start, 1 * 1000); - EXPECT_FALSE(middrv.isPlaying()); + auto device = std::make_shared(); + { + + MIDIEvent e; + e.delta_time = 0; + e.type.high = (uint8_t)MIDI_EVENT_TYPES_HIGH::META_SYSEX; + e.type.low = (uint8_t)MIDI_META_EVENT_TYPES_LOW::META; + + // this can be a parameter + e.data.push_back((uint8_t)MIDI_META_EVENT::SEQUENCE_NAME); + + std::string s = "sequence_name"; + e.data.insert(e.data.end(), s.begin(), s.end()); + + auto midi_track = audio::midi::MIDITrack(); + midi_track.addEvent(e); + + + e.delta_time = 1000; + e.type.high = (uint8_t)MIDI_EVENT_TYPES_HIGH::PROGRAM_CHANGE; + e.type.low = 0; + e.data.clear(); + e.data.push_back((uint8_t)0); + e.data.push_back((uint8_t)0); + + midi_track.addEvent(e); + + auto midi = std::make_shared(MIDI_FORMAT::SINGLE_TRACK, 1, 192); + midi->addTrack(midi_track); + + MIDDriverMock middrv(device); + middrv.setMidi(midi); + middrv.play(0); + ASSERT_TRUE(middrv.isPlaying()); + auto start = utils::getMillis(); + utils::delayMillis(20); + middrv.stop(); + EXPECT_FALSE(middrv.isPlaying()); + auto stop = utils::getMillis(); + EXPECT_LE(stop - start, 1 * 1000); + EXPECT_FALSE(middrv.isPlaying()); + EXPECT_TRUE(device->isAcquired()); + } EXPECT_FALSE(device->isAcquired()); - } - - TEST(MIDDriver, acquire) - { - using audio::midi::MIDIEvent; - using audio::midi::MIDI_EVENT_TYPES_HIGH; - using audio::midi::MIDI_META_EVENT_TYPES_LOW; - using audio::midi::MIDI_META_EVENT; - using audio::midi::MIDI_FORMAT; - - auto midi_track = audio::midi::MIDITrack(); - - MIDIEvent e; - - e.delta_time = 50; - e.type.high = (uint8_t)MIDI_EVENT_TYPES_HIGH::PROGRAM_CHANGE; - e.type.low = 0; - e.data.push_back((uint8_t)0); - e.data.push_back((uint8_t)0); - midi_track.addEvent(e); - - e.delta_time = 0; - e.type.high = (uint8_t)MIDI_EVENT_TYPES_HIGH::META_SYSEX; - e.type.low = (uint8_t)MIDI_META_EVENT_TYPES_LOW::META; - e.data.clear(); - e.data.push_back((uint8_t)MIDI_META_EVENT::END_OF_TRACK); - e.data.push_back((uint8_t)0); - midi_track.addEvent(e); - auto midi = std::make_shared(MIDI_FORMAT::SINGLE_TRACK, 1, 96); - midi->addTrack(midi_track); - auto device = std::make_shared(); - - MIDDriverMock middrv1(device); - EXPECT_EQ(device.use_count(), 2); - MIDDriverMock middrv2(device); - EXPECT_EQ(device.use_count(), 3); - - ASSERT_FALSE(device->isAcquired()); - middrv1.play(midi); - ASSERT_TRUE(device->isAcquired()); - middrv2.play(midi); - ASSERT_FALSE(middrv2.isPlaying()); - middrv1.stop(); - ASSERT_FALSE(device->isAcquired()); } TEST(MIDDriver, getTempo) { auto mf = files::MIDFile("../fixtures/midifile_sample.mid"); - auto device = std::make_shared(); - MIDDriver md(device); + auto device = std::make_shared(); + MIDDriverMock md(device); EXPECT_EQ(md.getTempo(), 0); EXPECT_FALSE(md.isTempoChanged()); - md.play(mf.getMIDI()); + md.setMidi(mf.getMIDI()); + md.play(0); while (!md.isTempoChanged()) { utils::delayMillis(10); } diff --git a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/westwood/TestADLDriver.cpp b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/westwood/TestADLDriver.cpp index 41b33491..ff6c5763 100644 --- a/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/westwood/TestADLDriver.cpp +++ b/sdl2-hyper-sonic-drivers/test/HyperSonicDrivers/drivers/westwood/TestADLDriver.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace HyperSonicDrivers::drivers::westwood { @@ -16,13 +16,9 @@ namespace HyperSonicDrivers::drivers::westwood { auto mixer = std::make_shared(); auto adlFile = std::make_shared("../fixtures/DUNE19.ADL"); - auto opl = std::make_shared(OplType::OPL2, mixer); - EXPECT_EQ(opl.use_count(), 1); - EXPECT_EQ(mixer.use_count(), 2); - - ADLDriver adlDrv(opl, audio::mixer::eChannelGroup::Plain); + auto adlib = devices::make_device(mixer); + ADLDriver adlDrv(adlib, audio::mixer::eChannelGroup::Plain); adlDrv.setADLFile(adlFile); - EXPECT_EQ(opl.use_count(), 2); EXPECT_EQ(adlFile.use_count(), 2); } @@ -34,14 +30,11 @@ namespace HyperSonicDrivers::drivers::westwood auto adlFile = std::make_shared("../fixtures/DUNE19.ADL"); EXPECT_EQ(adlFile.use_count(), 1); - auto opl = std::make_shared(OplType::OPL2, mixer); - EXPECT_EQ(opl.use_count(), 1); - EXPECT_EQ(mixer.use_count(), 2); + auto adlib = devices::make_device(mixer); - auto adlDrv = std::make_shared(opl, audio::mixer::eChannelGroup::Plain); + auto adlDrv = std::make_shared(adlib, audio::mixer::eChannelGroup::Plain); adlDrv->setADLFile(adlFile); EXPECT_EQ(adlDrv.use_count(), 1); - EXPECT_EQ(opl.use_count(), 2); EXPECT_EQ(adlFile.use_count(), 2); } } diff --git a/vcpkg.json b/vcpkg.json index d0714ea5..39abd31d 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -5,7 +5,6 @@ "dependencies": [ "sdl2", "gtest", - "rtmidi", "libmt32emu", "spdlog" ]