diff options
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | include/adlmidi.hpp | 56 | ||||
-rw-r--r-- | src/adlmidi_midiplay.cpp | 175 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 4 | ||||
-rw-r--r-- | utils/adlmidi-2/midiplay.cc | 518 |
6 files changed, 268 insertions, 497 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bae41a..60c9b4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,7 +113,6 @@ endfunction() option(libADLMIDI_STATIC "Build static library of libADLMIDI" ON) option(libADLMIDI_SHARED "Build shared library of libADLMIDI" OFF) -option(WITH_CPP_EXTRAS "Build with support for C++ extras (features can be found in 'adlmidi.hpp' header)" OFF) option(WITH_MIDI_SEQUENCER "Build with embedded MIDI sequencer. Disable this if you want use library in real-time MIDI drivers or plugins." ON) option(WITH_EMBEDDED_BANKS "Use embedded banks" ON) option(WITH_HQ_RESAMPLER "Build with support for high quality resampling" OFF) @@ -209,10 +208,6 @@ function(handle_options targetLib) target_compile_definitions(${targetLib} PUBLIC ADLMIDI_DISABLE_MIDI_SEQUENCER) endif() - if(NOT WITH_CPP_EXTRAS) - target_compile_definitions(${targetLib} PUBLIC ADLMIDI_DISABLE_CPP_EXTRAS) - endif() - if(WITH_EMBEDDED_BANKS AND WITH_GENADLDATA AND NOT ADLMIDI_DOS) add_dependencies(${targetLib} gen-adldata-run) endif() @@ -365,7 +360,6 @@ install(TARGETS ${libADLMIDI_INSTALLS} install(FILES include/adlmidi.h - include/adlmidi.hpp DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") file(GLOB DOCTXT_FILES @@ -406,7 +400,6 @@ message("libADLMIDI_STATIC = ${libADLMIDI_STATIC}") message("libADLMIDI_SHARED = ${libADLMIDI_SHARED}") message("WITH_UNIT_TESTS = ${WITH_UNIT_TESTS}") -message("WITH_CPP_EXTRAS = ${WITH_CPP_EXTRAS}") message("WITH_MIDI_SEQUENCER = ${WITH_MIDI_SEQUENCER}") message("WITH_EMBEDDED_BANKS = ${WITH_EMBEDDED_BANKS}") message("WITH_HQ_RESAMPLER = ${WITH_HQ_RESAMPLER}") @@ -83,7 +83,6 @@ The library is licensed under in it's parts LGPL 2.1+, GPL v2+, GPL v3+, and MIT * **libADLMIDI_SHARED** - (ON/OFF, default OFF) Build shared library * **WITH_UNIT_TESTS** - (ON/OFF, default OFF) Enable unit testing -* **WITH_CPP_EXTRAS** - (ON/OFF, default OFF) Build libADLMIDI with some extra public features for C++ language (for example, instrument testing API is available for C++ only). * **WITH_MIDI_SEQUENCER** - (ON/OFF, default ON) Build with embedded MIDI sequencer. Disable this if you want use library in real-time MIDI drivers or plugins.) * **WITH_EMBEDDED_BANKS** - (ON/OFF, default ON) Enable or disable embedded banks (Original ADLMIDI and older versions of libADLMIDI are had embedded-only banks with no ability to load custom banks in runtime). * **WITH_HQ_RESAMPLER** - (ON/OFF, default OFF) Build with support for high quality resampling (requires zita-resampler to be installed) @@ -101,7 +100,7 @@ The library is licensed under in it's parts LGPL 2.1+, GPL v2+, GPL v3+, and MIT * **WITH_MIDIPLAY** - (ON/OFF, default OFF) Build demo MIDI player (Requires SDL2 and also pthread on Windows with MinGW) * **MIDIPLAY_WAVE_ONLY** - (ON/OFF, default OFF) Build Demo MIDI player without support of real time playing. It will output into WAV only. -* **WITH_ADLMIDI2** - (ON/OFF, default OFF) Build Classic ADLMIDI MIDI player (Requires SDL2 on Linux and macOS, requires pthread on Windows with MinGW, SDL doesn't required on Windows. Also, the **WITH_CPP_EXTRAS** flag must be enabled) +* **WITH_ADLMIDI2** - (ON/OFF, default OFF) Build Classic ADLMIDI MIDI player (Requires SDL2 on Linux and macOS, requires pthread on Windows with MinGW, SDL doesn't required on Windows). * **WITH_VLC_PLUGIN** - (ON/OFF, default OFF) Compile VLC plugin. For now, works on Linux and VLC. Support for other platforms comming soon! * **WITH_OLD_UTILS** - (ON/OFF, default OFF) Build old utilities to dump some bank formats, made by original creator of ADLMIDI * **EXAMPLE_SDL2_AUDIO** - (ON/OFF, default OFF) Build also a simple SDL2 demo MIDI player @@ -121,7 +120,6 @@ You need to make in the any IDE a library project and put into it next files ### Public header (include) * adlmidi.h - Library Public API header, use it to control library -* adlmidi.hpp - Public additional C++ API header, optional ### Internal code (src) * chips/* - Various OPL3 chip emulators and commonized interface over them @@ -187,6 +185,7 @@ To build that example you will need to have installed SDL2 library. * Fixed an accuracy of the DMX volume model, include the buggy AM intepretation * Fully rewritten an embedded banks database * Improved an accuracy of Apogee volume model, include the bug of AM instruments + * Removed C++ extras. C++-binded instruments tester is useless since a real-time MIDI API can completely replace it. ## 1.4.0 2018-10-01 * Implemented a full support for Portamento! (Thanks to [Jean Pierre Cimalando](https://github.com/jpcima) for a work!) diff --git a/include/adlmidi.hpp b/include/adlmidi.hpp deleted file mode 100644 index 0df6dd4..0000000 --- a/include/adlmidi.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation - * - * Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi> - * ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru> - * - * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: - * http://iki.fi/bisqwit/source/adlmidi.html - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef ADLMIDI_HPP -#define ADLMIDI_HPP - -#include "adlmidi.h" - -struct ADL_MIDIPlayer; - -class ADLMIDI_DECLSPEC AdlInstrumentTester -{ - struct Impl; - Impl *p; - -public: - explicit AdlInstrumentTester(ADL_MIDIPlayer *device); - virtual ~AdlInstrumentTester(); - - void start(); - - // Find list of adlib instruments that supposedly implement this GM - void FindAdlList(); - void DoNote(int note); - void DoNoteOff(); - void NextGM(int offset); - void NextAdl(int offset); - bool HandleInputChar(char ch); - -private: - AdlInstrumentTester(const AdlInstrumentTester &); - AdlInstrumentTester &operator=(const AdlInstrumentTester &); -}; - -#endif //ADLMIDI_HPP - diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index c3ef14c..70e5854 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -1865,178 +1865,3 @@ void MIDIplay::describeChannels(char *str, char *attr, size_t size) str[index] = 0; attr[index] = 0; } - -#ifndef ADLMIDI_DISABLE_CPP_EXTRAS - -struct AdlInstrumentTester::Impl -{ - uint32_t cur_gm; - uint32_t ins_idx; - int cur_note; - std::vector<uint32_t> adl_ins_list; - Synth *opl; - MIDIplay *play; -}; - -ADLMIDI_EXPORT AdlInstrumentTester::AdlInstrumentTester(ADL_MIDIPlayer *device) - : p(new Impl) -{ -#ifndef DISABLE_EMBEDDED_BANKS - MIDIplay *play = reinterpret_cast<MIDIplay *>(device->adl_midiPlayer); - p->cur_gm = 0; - p->ins_idx = 0; - p->cur_note = -1; - p->play = play; - p->opl = play ? play->m_synth.get() : NULL; -#else - ADL_UNUSED(device); -#endif -} - -ADLMIDI_EXPORT AdlInstrumentTester::~AdlInstrumentTester() -{ - delete p; -} - -ADLMIDI_EXPORT void AdlInstrumentTester::start() -{ - NextGM(0); -} - -ADLMIDI_EXPORT void AdlInstrumentTester::FindAdlList() -{ -#ifndef DISABLE_EMBEDDED_BANKS - p->play->realTime_panic(); - p->cur_note = -1; - p->opl->silenceAll(); -#endif -} - - -ADLMIDI_EXPORT void AdlInstrumentTester::DoNote(int note) -{ -#ifndef DISABLE_EMBEDDED_BANKS - DoNoteOff(); - p->play->realTime_NoteOn(0, note, 127); - p->cur_note = note; -#else - ADL_UNUSED(note); -#endif -} - -void AdlInstrumentTester::DoNoteOff() -{ -#ifndef DISABLE_EMBEDDED_BANKS - if(p->cur_note > 0) - p->play->realTime_NoteOff(0, p->cur_note); -#endif -} - -ADLMIDI_EXPORT void AdlInstrumentTester::NextGM(int offset) -{ -#ifndef DISABLE_EMBEDDED_BANKS - if(offset < 0 && (static_cast<long>(p->cur_gm) + offset) < 0) - p->cur_gm += g_embeddedBanksCount; - - p->cur_gm += offset; - - if(p->cur_gm >= g_embeddedBanksCount) - p->cur_gm = (p->cur_gm + offset) - g_embeddedBanksCount; - - p->play->m_setup.numFourOps = -1; - p->opl->setEmbeddedBank(p->cur_gm); - adlCalculateFourOpChannels(p->play, true); - p->opl->updateChannelCategories(); - -// std::printf("Bank %u [%s]\n", P->cur_gm, adl_getBankNames()[P->cur_gm]); -// std::fflush(stdout); - - FindAdlList(); -#else - ADL_UNUSED(offset); -#endif -} - -ADLMIDI_EXPORT void AdlInstrumentTester::NextAdl(int offset) -{ -#ifndef DISABLE_EMBEDDED_BANKS - -#if 0 - UI.Color(15); - std::fflush(stderr); - std::printf("SELECTED G%c%d\t%s\n", - cur_gm < 128 ? 'M' : 'P', cur_gm < 128 ? cur_gm + 1 : cur_gm - 128, - "<-> select GM, ^v select ins, qwe play note"); - std::fflush(stdout); - UI.Color(7); - std::fflush(stderr); -#endif - - if(offset < 0 && (static_cast<long>(p->ins_idx) + offset) < 0) - p->ins_idx += 127; - - p->ins_idx += offset; - - if(p->ins_idx >= 127) - p->ins_idx = (p->ins_idx + offset) - 127; - - p->play->realTime_PatchChange(0, p->ins_idx); - p->play->realTime_Controller(0, 7, 127); - p->play->realTime_Controller(0, 11, 127); - p->play->realTime_Controller(0, 10, 64); - -// std::printf("Instrument %u\n", p->ins_idx); -// std::fflush(stdout); - -#else - ADL_UNUSED(offset); -#endif -} - -ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) -{ -#ifndef DISABLE_EMBEDDED_BANKS - static const char notes[] = "zsxdcvgbhnjmq2w3er5t6y7ui9o0p"; - // c'd'ef'g'a'bC'D'EF'G'A'Bc'd'e - switch(ch) - { - case '/': - case 'H': - case 'A': - NextAdl(-1); - break; - case '*': - case 'P': - case 'B': - NextAdl(+1); - break; - case '-': - case 'K': - case 'D': - NextGM(-1); - break; - case '+': - case 'M': - case 'C': - NextGM(+1); - break; - case ' ': - DoNoteOff(); - break; - case 3: -#if !((!defined(__WIN32__) || defined(__CYGWIN__)) && !defined(__DJGPP__)) - case 27: -#endif - return false; - default: - const char *p = std::strchr(notes, ch); - if(p && *p) - DoNote((int)(p - notes) + 48); - } -#else - ADL_UNUSED(ch); -#endif - return true; -} - -#endif /* ADLMIDI_DISABLE_CPP_EXTRAS */ diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 2d47ade..a5a3b8c 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -151,10 +151,6 @@ typedef class OPL3 Synth; #define ADLMIDI_BUILD #include "adlmidi.h" //Main API -#ifndef ADLMIDI_DISABLE_CPP_EXTRAS -#include "adlmidi.hpp" //Extra C++ API -#endif - #include "adlmidi_ptr.hpp" class MIDIplay; diff --git a/utils/adlmidi-2/midiplay.cc b/utils/adlmidi-2/midiplay.cc index 7867968..f48828c 100644 --- a/utils/adlmidi-2/midiplay.cc +++ b/utils/adlmidi-2/midiplay.cc @@ -81,7 +81,7 @@ public: #include <signal.h> #include "adlmidi.h" -#include "adlmidi.hpp" + #ifndef __DJGPP__ @@ -186,7 +186,7 @@ static class UserInterface #endif public: static constexpr unsigned NColumns = 1216 / 20; - #ifdef SUPPORT_VIDEO_OUTPUT +#ifdef SUPPORT_VIDEO_OUTPUT static constexpr unsigned VidWidth = 1216, VidHeight = 2160; static constexpr unsigned FontWidth = 20, FontHeight = 45; static constexpr unsigned TxWidth = (VidWidth / FontWidth), TxHeight = (VidHeight / FontHeight); @@ -194,10 +194,10 @@ public: unsigned short CharBuffer[TxWidth * TxHeight] = {0}; bool DirtyCells[TxWidth * TxHeight] = {false}; unsigned NDirty = 0; - #endif - #ifdef _WIN32 +#endif +#ifdef _WIN32 void *handle; - #endif +#endif int x, y, color, txtline, maxy; // Text: @@ -221,22 +221,22 @@ public: va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); - #ifdef _WIN32 +#ifdef _WIN32 fflush(stderr); - #endif +#endif } #endif UserInterface(): - #ifdef SUPPORT_PUZZLE_GAME +#ifdef SUPPORT_PUZZLE_GAME player(2), computer(31), - #endif +#endif x(0), y(0), color(-1), txtline(0), maxy(0), cursor_visible(true) { GuessInitialWindowHeight(); - #ifdef _WIN32 +#ifdef _WIN32 handle = GetStdHandle(STD_OUTPUT_HANDLE); GotoXY(41, 13); CONSOLE_SCREEN_BUFFER_INFO tmp; @@ -252,19 +252,19 @@ public: //COORD size = { NColumns, 23*NumCards+5 }; //SetConsoleScreenBufferSize(handle,size); } - #endif - #if (!defined(_WIN32) || defined(__CYGWIN__)) && defined(TIOCGWINSZ) +#endif +#if (!defined(_WIN32) || defined(__CYGWIN__)) && defined(TIOCGWINSZ) std::signal(SIGWINCH, SigWinchHandler); - #endif - #ifdef __DJGPP__ +#endif +#ifdef __DJGPP__ color = 7; - #endif +#endif std::memset(slots, '.', sizeof(slots)); std::memset(background, '.', sizeof(background)); std::memset(backgroundcolor, 1, sizeof(backgroundcolor)); - #ifndef _WIN32 +#ifndef _WIN32 std::setvbuf(stderr, stderr_buffer, _IOFBF, sizeof(stderr_buffer)); - #endif +#endif RawPrn("\r"); // Ensure cursor is at the x=0 we imagine it being Print(0, 7, true, "Hit Ctrl-C to quit"); } @@ -272,7 +272,7 @@ public: { if(!cursor_visible) return; cursor_visible = false; - #ifdef _WIN32 +#ifdef _WIN32 if(handle) { const CONSOLE_CURSOR_INFO info = {100, false}; @@ -281,15 +281,15 @@ public: CheckTetris(); return; } - #endif +#endif if(!DoingInstrumentTesting) CheckTetris(); - #ifdef __DJGPP__ +#ifdef __DJGPP__ { _setcursortype(_NOCURSOR); return; } - #endif +#endif RawPrn("\33[?25l"); // hide cursor } void ShowCursor() @@ -298,28 +298,28 @@ public: cursor_visible = true; GotoXY(0, maxy); Color(7); - #ifdef _WIN32 +#ifdef _WIN32 if(handle) { const CONSOLE_CURSOR_INFO info = {100, true}; SetConsoleCursorInfo(handle, &info); return; } - #endif - #ifdef __DJGPP__ +#endif +#ifdef __DJGPP__ { _setcursortype(_NORMALCURSOR); return; } - #endif +#endif RawPrn("\33[?25h"); // show cursor std::fflush(stderr); } void VidPut(char c) { - #ifndef SUPPORT_VIDEO_OUTPUT +#ifndef SUPPORT_VIDEO_OUTPUT c = c; - #else +#else unsigned clr = (unsigned)color, tx = (unsigned)x, ty = (unsigned)y; unsigned cell_index = ty * TxWidth + tx; if(cell_index < TxWidth * TxHeight) @@ -337,7 +337,7 @@ public: } #endif } - #ifdef SUPPORT_VIDEO_OUTPUT +#ifdef SUPPORT_VIDEO_OUTPUT static unsigned VidTranslateColor(unsigned c) { static const unsigned colors[16] = @@ -389,19 +389,19 @@ public: } } } - #endif +#endif void PutC(char c) { - #ifdef _WIN32 +#ifdef _WIN32 if(handle) WriteConsole(handle, &c, 1, 0, 0); else - #endif +#endif { - #ifdef __DJGPP__ +#ifdef __DJGPP__ putch(c); - #else +#else std::fputc(c, stderr); - #endif +#endif } VidPut(c); ++x; // One letter drawn. Update cursor position. @@ -410,11 +410,11 @@ public: int Print(unsigned beginx, unsigned color, bool ln, const char *fmt, va_list ap) { char Line[1024]; - #ifndef __CYGWIN__ +#ifndef __CYGWIN__ int nchars = std::vsnprintf(Line, sizeof(Line), fmt, ap); - #else +#else int nchars = std::vsprintf(Line, fmt, ap); /* SECURITY: POSSIBLE BUFFER OVERFLOW (Cygwin) */ - #endif +#endif //if(nchars == 0) return nchars; HideCursor(); @@ -565,7 +565,7 @@ public: y += 1; x = 0; } - #ifdef _WIN32 +#ifdef _WIN32 if(handle) { CONSOLE_SCREEN_BUFFER_INFO tmp; @@ -578,14 +578,14 @@ public: } SetConsoleCursorPosition(handle, tmp2); } - #endif - #ifdef __DJGPP__ +#endif +#ifdef __DJGPP__ { gotoxy(x = newx, wherey() - (y - newy)); y = newy; return; } - #endif +#endif // Go up with \33[A if(newy < y) { @@ -613,15 +613,15 @@ public: { if(color != newcolor) { - #ifdef _WIN32 +#ifdef _WIN32 if(handle) SetConsoleTextAttribute(handle, newcolor); else - #endif - #ifdef __DJGPP__ +#endif +#ifdef __DJGPP__ textattr(newcolor); if(0) - #endif +#endif { static const char map[8 + 1] = "04261537"; RawPrn("\33[0;%s40;3%c", (newcolor & 8) ? "1;" : "", map[newcolor & 7]); @@ -1289,197 +1289,214 @@ static void SendStereoAudio(unsigned long count, short* samples) } #endif /* not DJGPP */ -/* - * THIS CLASS USES !!!ADL PRIVATE!!! - */ - -//class OPL3; -//class AdlInstrumentTester -//{ -// uint32_t cur_gm; -// uint32_t ins_idx; -// std::vector<uint32_t> adl_ins_list; -// OPL3 *opl; -// MIDIplay * play; - -//public: -// AdlInstrumentTester(ADL_MIDIPlayer *device) -// { -// cur_gm = 0; -// ins_idx = 0; -// play = reinterpret_cast<MIDIplay*>(device->adl_midiPlayer); -// if(!play) -// return; -// opl = &play->opl; -// } - -// ~AdlInstrumentTester() -// {} - -// // Find list of adlib instruments that supposedly implement this GM -// void FindAdlList() -// { -// const unsigned NumBanks = (unsigned)adl_getBanksCount(); -// std::set<unsigned> adl_ins_set; -// for(unsigned bankno = 0; bankno < NumBanks; ++bankno) -// adl_ins_set.insert(banks[bankno][cur_gm]); -// adl_ins_list.assign(adl_ins_set.begin(), adl_ins_set.end()); -// ins_idx = 0; -// NextAdl(0); -// opl->Silence(); -// } - - -// void Touch(unsigned c, unsigned volume) // Volume maxes at 127*127*127 -// { -// if(opl->LogarithmicVolumes)// !!!ADL PRIVATE!!! -// opl->Touch_Real(c, volume * 127 / (127 * 127 * 127) / 2);// !!!ADL PRIVATE!!! -// else -// { -// // The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A) -// opl->Touch_Real(c, volume > 8725 ? static_cast<unsigned int>(std::log(volume) * 11.541561 + (0.5 - 104.22845)) : 0);// !!!ADL PRIVATE!!! -// // The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A) -// //Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0); -// } -// } - -// void DoNote(int note) -// { -// if(adl_ins_list.empty()) FindAdlList(); -// const unsigned meta = adl_ins_list[ins_idx]; -// const adlinsdata &ains = opl->GetAdlMetaIns(meta);// !!!ADL PRIVATE!!! - -// int tone = (cur_gm & 128) ? (cur_gm & 127) : (note + 50); -// if(ains.tone) -// { -// /*if(ains.tone < 20) -// tone += ains.tone; -// else */ -// if(ains.tone < 128) -// tone = ains.tone; -// else -// tone -= ains.tone - 128; -// } -// double hertz = 172.00093 * std::exp(0.057762265 * (tone + 0.0)); -// int i[2] = { ains.adlno1, ains.adlno2 }; -// int32_t adlchannel[2] = { 0, 3 }; -// if(i[0] == i[1]) -// { -// adlchannel[1] = -1; -// adlchannel[0] = 6; // single-op -// std::printf("noteon at %d(%d) for %g Hz\n", -// adlchannel[0], i[0], hertz); -// } -// else -// { -// std::printf("noteon at %d(%d) and %d(%d) for %g Hz\n", -// adlchannel[0], i[0], adlchannel[1], i[1], hertz); -// } - -// opl->NoteOff(0); -// opl->NoteOff(3); -// opl->NoteOff(6); -// for(unsigned c = 0; c < 2; ++c) -// { -// if(adlchannel[c] < 0) continue; -// opl->Patch((uint16_t)adlchannel[c], (uint16_t)i[c]); -// opl->Touch_Real((uint16_t)adlchannel[c], 127 * 127 * 100); -// opl->Pan((uint16_t)adlchannel[c], 0x30); -// opl->NoteOn((uint16_t)adlchannel[c], hertz); -// } -// } - -// void NextGM(int offset) -// { -// cur_gm = (cur_gm + 256 + (uint32_t)offset) & 0xFF; -// FindAdlList(); -// } - -// void NextAdl(int offset) -// { -// if(adl_ins_list.empty()) FindAdlList(); -// const unsigned NumBanks = (unsigned)adl_getBanksCount(); -// ins_idx = (uint32_t)((int32_t)ins_idx + (int32_t)adl_ins_list.size() + offset) % adl_ins_list.size(); - -// UI.Color(15); -// std::fflush(stderr); -// std::printf("SELECTED G%c%d\t%s\n", -// cur_gm < 128 ? 'M' : 'P', cur_gm < 128 ? cur_gm + 1 : cur_gm - 128, -// "<-> select GM, ^v select ins, qwe play note"); -// std::fflush(stdout); -// UI.Color(7); -// std::fflush(stderr); -// for(unsigned a = 0; a < adl_ins_list.size(); ++a) -// { -// const unsigned i = adl_ins_list[a]; -// const adlinsdata &ains = opl->GetAdlMetaIns(i); - -// char ToneIndication[8] = " "; -// if(ains.tone) -// { -// /*if(ains.tone < 20) -// std::sprintf(ToneIndication, "+%-2d", ains.tone); -// else*/ -// if(ains.tone < 128) -// std::sprintf(ToneIndication, "=%-2d", ains.tone); -// else -// std::sprintf(ToneIndication, "-%-2d", ains.tone - 128); -// } -// std::printf("%s%s%s%u\t", -// ToneIndication, -// ains.adlno1 != ains.adlno2 ? "[2]" : " ", -// (ins_idx == a) ? "->" : "\t", -// i -// ); - -// for(unsigned bankno = 0; bankno < NumBanks; ++bankno) -// if(banks[bankno][cur_gm] == i) -// std::printf(" %u", bankno); - -// std::printf("\n"); -// } -// } - -// bool HandleInputChar(char ch) -// { -// static const char notes[] = "zsxdcvgbhnjmq2w3er5t6y7ui9o0p"; -// // c'd'ef'g'a'bC'D'EF'G'A'Bc'd'e -// switch(ch) -// { -// case '/': -// case 'H': -// case 'A': -// NextAdl(-1); -// break; -// case '*': -// case 'P': -// case 'B': -// NextAdl(+1); -// break; -// case '-': -// case 'K': -// case 'D': -// NextGM(-1); -// break; -// case '+': -// case 'M': -// case 'C': -// NextGM(+1); -// break; -// case 3: -// #if !((!defined(_WIN32) || defined(__CYGWIN__)) && !defined(__DJGPP__)) -// case 27: -// #endif -// return false; -// break; -// default: -// const char *p = strchr(notes, ch); -// if(p && *p) -// DoNote((p - notes) - 12); -// } -// return true; -// } -//}; + +class AdlInstrumentTester +{ + struct Impl; + Impl *p; + +public: + explicit AdlInstrumentTester(ADL_MIDIPlayer *device); + virtual ~AdlInstrumentTester(); + + void start(); + + // Find list of adlib instruments that supposedly implement this GM + void FindAdlList(); + void DoNote(int note); + void DoNoteOff(); + void NextGM(int offset); + void NextAdl(int offset); + bool HandleInputChar(char ch); + + void printIntst(); + +private: + AdlInstrumentTester(const AdlInstrumentTester &); + AdlInstrumentTester &operator=(const AdlInstrumentTester &); +}; + + +struct AdlInstrumentTester::Impl +{ + bool is_drums; + int play_chan; + int cur_gm; + int ins_idx; + int cur_note; + ADL_MIDIPlayer *device; +}; + +AdlInstrumentTester::AdlInstrumentTester(ADL_MIDIPlayer *device) + : p(new Impl) +{ +#ifndef DISABLE_EMBEDDED_BANKS + p->is_drums = false; + p->play_chan = 0; + p->cur_gm = 0; + p->ins_idx = 0; + p->cur_note = -1; + p->device = device; +#else + ADL_UNUSED(device); +#endif +} + +AdlInstrumentTester::~AdlInstrumentTester() +{ + delete p; +} + +void AdlInstrumentTester::start() +{ + NextGM(0); +} + +void AdlInstrumentTester::FindAdlList() +{ +#ifndef DISABLE_EMBEDDED_BANKS + adl_panic(p->device); + p->cur_note = -1; +#endif +} + + +void AdlInstrumentTester::DoNote(int note) +{ +#ifndef DISABLE_EMBEDDED_BANKS + DoNoteOff(); + adl_rt_noteOn(p->device, p->play_chan, note, 127); + p->cur_note = note; +#else + ADL_UNUSED(note); +#endif +} + +void AdlInstrumentTester::DoNoteOff() +{ +#ifndef DISABLE_EMBEDDED_BANKS + if(p->cur_note > 0) + adl_rt_noteOff(p->device, 0, p->cur_note); +#endif +} + +void AdlInstrumentTester::NextGM(int offset) +{ +#ifndef DISABLE_EMBEDDED_BANKS + int maxBanks = adl_getBanksCount(); + if(offset < 0 && (static_cast<long>(p->cur_gm) + offset) < 0) + p->cur_gm += maxBanks; + + p->cur_gm += offset; + + if(p->cur_gm >= maxBanks) + p->cur_gm = (p->cur_gm + offset) - maxBanks; + + adl_setBank(p->device, p->cur_gm); + + FindAdlList(); + + printIntst(); +#else + ADL_UNUSED(offset); +#endif +} + +void AdlInstrumentTester::NextAdl(int offset) +{ +#ifndef DISABLE_EMBEDDED_BANKS + +#if 0 + UI.Color(15); + std::fflush(stderr); + std::printf("SELECTED G%c%d\t%s\n", + cur_gm < 128 ? 'M' : 'P', cur_gm < 128 ? cur_gm + 1 : cur_gm - 128, + "<-> select GM, ^v select ins, qwe play note"); + std::fflush(stdout); + UI.Color(7); + std::fflush(stderr); +#endif + + if(offset < 0 && (static_cast<long>(p->ins_idx) + offset) < 0) + p->ins_idx += 127; + + p->ins_idx += offset; + + if(p->ins_idx >= 127) + p->ins_idx = (p->ins_idx + offset) - 127; + + adl_rt_patchChange(p->device, p->play_chan, p->ins_idx); + adl_rt_controllerChange(p->device, p->play_chan, 7, 127); + adl_rt_controllerChange(p->device, p->play_chan, 11, 127); + adl_rt_controllerChange(p->device, p->play_chan, 10, 64); + + printIntst(); +#else + ADL_UNUSED(offset); +#endif +} + +bool AdlInstrumentTester::HandleInputChar(char ch) +{ +#ifndef DISABLE_EMBEDDED_BANKS + static const char notes[] = "zsxdcvgbhnjmq2w3er5t6y7ui9o0p"; + // c'd'ef'g'a'bC'D'EF'G'A'Bc'd'e + switch(ch) + { + case '/': + case 'H': + case 'A': + NextAdl(-1); + break; + case '*': + case 'P': + case 'B': + NextAdl(+1); + break; + case '-': + case 'K': + case 'D': + NextGM(-1); + break; + case '+': + case 'M': + case 'C': + NextGM(+1); + break; + case 'T': + p->is_drums = !p->is_drums; + p->play_chan = p->is_drums ? 9 : 0; + NextAdl(0); + case ' ': + DoNoteOff(); + break; + case 3: +#if !((!defined(__WIN32__) || defined(__CYGWIN__)) && !defined(__DJGPP__)) + case 27: +#endif + return false; + default: + const char *p = std::strchr(notes, ch); + if(p && *p) + DoNote((int)(p - notes) + 48); + } +#else + ADL_UNUSED(ch); +#endif + return true; +} + +void AdlInstrumentTester::printIntst() +{ +#ifndef DISABLE_EMBEDDED_BANKS + UI.GotoXY(0, 10); + UI.Print(0, 255, false, "Bank: %3d, Instrument %3d %10s ", + p->cur_gm, p->ins_idx, p->is_drums ? "drum" : "melodic"); + UI.ShowCursor(); +#endif +} + + static void TidyupAndExit(int sig) { @@ -1724,11 +1741,11 @@ int main(int argc, char **argv) #endif ADL_MIDIPlayer *myDevice; - #ifndef __DJGPP__ +#ifndef __DJGPP__ myDevice = adl_init(PCM_RATE); - #else +#else myDevice = adl_init(48000); - #endif +#endif // Set hooks adl_setNoteHook(myDevice, adlNoteHook, (void *)&UI); @@ -1820,9 +1837,7 @@ int main(int argc, char **argv) #endif adl_setLoopEnabled(myDevice, loopEnabled); - #ifndef __DJGPP__ - - #ifndef _WIN32 +#if !defined(__DJGPP__) && !defined(_WIN32) static SDL_AudioSpec spec, obtained; spec.freq = PCM_RATE; spec.format = AUDIO_S16SYS; @@ -1842,9 +1857,7 @@ int main(int argc, char **argv) spec.samples, spec.freq, spec.channels, obtained.samples, obtained.freq, obtained.channels); } - #endif - - #endif /* not DJGPP */ +#endif /* not DJGPP and not WIN32 */ if(argc >= 3) { @@ -1948,7 +1961,7 @@ int main(int argc, char **argv) } UI.Color(7); - if(adl_openFile(myDevice, argv[1]) != 0) + if(!DoingInstrumentTesting && adl_openFile(myDevice, argv[1]) != 0) { std::fprintf(stderr, "%s\n", adl_errorInfo(myDevice)); UI.ShowCursor(); @@ -2128,7 +2141,7 @@ int main(int argc, char **argv) //Shut up all sustaining notes adl_panic(myDevice); - #ifdef __DJGPP__ +#ifdef __DJGPP__ // Fix the skewed clock and reset BIOS tick rate _farpokel(_dos_ds, 0x46C, BIOStimer_begin + (BIOStimer - BIOStimer_begin) @@ -2143,14 +2156,15 @@ int main(int argc, char **argv) UI.ShowCursor(); UI.Color(7); clrscr(); - #else - #ifdef _WIN32 +#else + +#ifdef _WIN32 WindowsAudio::Close(); - #else +#else SDL_CloseAudio(); - #endif +#endif - #endif /* djgpp */ +#endif /* djgpp */ adl_close(myDevice); |