diff options
Diffstat (limited to 'utils')
26 files changed, 553 insertions, 381 deletions
diff --git a/utils/adlmidi-2/9x15.hpp b/utils/adlmidi-2/9x15.hpp index e535d49..76e0660 100644 --- a/utils/adlmidi-2/9x15.hpp +++ b/utils/adlmidi-2/9x15.hpp @@ -160,8 +160,8 @@ struct font9x15: public UIfontBase virtual unsigned GetIndex(char32_t c) const { return ns_font9x15::unicode_to_bitmap_index[c]; } }; -static UIfontBase* Getfont9x15() -{ - static font9x15 f; - return &f; -} +//static UIfontBase* Getfont9x15() +//{ +// static font9x15 f; +// return &f; +//} diff --git a/utils/adlmidi-2/midiplay.cc b/utils/adlmidi-2/midiplay.cc index b670083..74806eb 100644 --- a/utils/adlmidi-2/midiplay.cc +++ b/utils/adlmidi-2/midiplay.cc @@ -1593,6 +1593,7 @@ int main(int argc, char **argv) UI.Color(7); std::fflush(stderr); std::printf( + "\n\n" "Usage: adlmidi <midifilename> [ <options> ] [ <banknumber> [ <numcards> [ <numfourops>] ] ]\n" " adlmidi <midifilename> -1 To enter instrument tester\n" " -p Enables adlib percussion instrument mode (use with CMF files)\n" @@ -1758,7 +1759,7 @@ int main(int argc, char **argv) if(argc >= 3) { - if(is_number(argv[2])) + if(is_number(argv[2]) || !strcmp(argv[2], "-1")) { int bankno = std::atoi(argv[2]); if(bankno == -1) diff --git a/utils/adlmidi-2/puzzlegame.cc b/utils/adlmidi-2/puzzlegame.cc index e9d2b9b..f8fa57c 100644 --- a/utils/adlmidi-2/puzzlegame.cc +++ b/utils/adlmidi-2/puzzlegame.cc @@ -4,6 +4,8 @@ #include "input.hpp" #include "puzzlegame.hpp" +char ADLMIDI_PuzzleGame::peeked_input = 0; + unsigned long ADLMIDI_PuzzleGame::TimerRead() { static std::chrono::time_point<std::chrono::system_clock> begin = std::chrono::system_clock::now(); diff --git a/utils/adlmidi-2/puzzlegame.hpp b/utils/adlmidi-2/puzzlegame.hpp index 03ad921..a35f1cb 100755 --- a/utils/adlmidi-2/puzzlegame.hpp +++ b/utils/adlmidi-2/puzzlegame.hpp @@ -36,7 +36,7 @@ namespace ADLMIDI_PuzzleGame void Sound(unsigned/*freq*/, unsigned/*duration*/); void PutCell(int x, int y, unsigned cell); void ScreenPutString(const char* str, unsigned attr, unsigned column, unsigned row); - static char peeked_input = 0; + extern char peeked_input; bool kbhit(); char getch(); diff --git a/utils/dumpbank/dumpbank.cpp b/utils/dumpbank/dumpbank.cpp index 84283e7..d2df74a 100644 --- a/utils/dumpbank/dumpbank.cpp +++ b/utils/dumpbank/dumpbank.cpp @@ -190,5 +190,12 @@ static void LoadBNK(const char* fn) int main(int argc, const char* const* argv) { + if(argc < 2) + { + std::printf("Usage: \n" + " %s filename.bnk\n" + "\n", argv[0]); + return 1; + } LoadBNK(argv[1]); } diff --git a/utils/dumpmiles/dumpmiles.cpp b/utils/dumpmiles/dumpmiles.cpp index 0c2d51b..a1a3816 100644 --- a/utils/dumpmiles/dumpmiles.cpp +++ b/utils/dumpmiles/dumpmiles.cpp @@ -49,5 +49,14 @@ static void LoadMiles(const char* fn) int main(int argc, const char* const* argv) { + if(argc < 2) + { + std::printf("Usage: \n" + " %s filename.opl\n" + "or:\n" + " %s filename.opl\n" + "\n", argv[0], argv[0]); + return 1; + } LoadMiles(argv[1]); } diff --git a/utils/gen_adldata/file_formats/load_ail.h b/utils/gen_adldata/file_formats/load_ail.h index a10ff92..e63b1d7 100644 --- a/utils/gen_adldata/file_formats/load_ail.h +++ b/utils/gen_adldata/file_formats/load_ail.h @@ -89,6 +89,7 @@ static bool LoadMiles(const char *fn, unsigned bank, const char *prefix) struct ins tmp2; tmp2.notenum = gmno < 128 ? 0 : (unsigned char)notenum; tmp2.pseudo4op = false; + tmp2.real4op = (inscount > 1); tmp2.voice2_fine_tune = 0.0; std::string name; if(midi_index >= 0) name = std::string(1, '\377') + MidiInsName[midi_index]; diff --git a/utils/gen_adldata/file_formats/load_bisqwit.h b/utils/gen_adldata/file_formats/load_bisqwit.h index 015b0eb..f5f73dc 100644 --- a/utils/gen_adldata/file_formats/load_bisqwit.h +++ b/utils/gen_adldata/file_formats/load_bisqwit.h @@ -44,6 +44,7 @@ static bool LoadBisqwit(const char *fn, unsigned bank, const char *prefix) (gmno < 128 ? 'M' : 'P'), gmno & 127); tmp[1].diff = (tmp[0] != tmp[1]); + tmp2.real4op = tmp[1].diff; size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2, (tmp[0] == tmp[1])); SetBank(bank, gmno, resno); } diff --git a/utils/gen_adldata/file_formats/load_bnk.h b/utils/gen_adldata/file_formats/load_bnk.h index a41185a..aa7701f 100644 --- a/utils/gen_adldata/file_formats/load_bnk.h +++ b/utils/gen_adldata/file_formats/load_bnk.h @@ -69,7 +69,8 @@ static bool LoadBNK(const char *fn, unsigned bank, const char *prefix, bool is_f if(name[2] == 'O' || name[2] == 'S') { - gmno = 128 + std::stoi(name.substr(3)); + std::string n = name.substr(3); + gmno = 128 + std::atoi(n.c_str()); } } @@ -107,6 +108,7 @@ static bool LoadBNK(const char *fn, unsigned bank, const char *prefix, bool is_f ins tmp2; tmp2.notenum = is_fat ? voice_num : (percussive ? usage_flag : 0); tmp2.pseudo4op = false; + tmp2.real4op = false; tmp2.voice2_fine_tune = 0.0; if(is_fat) tmp.data[10] ^= 1; diff --git a/utils/gen_adldata/file_formats/load_bnk2.h b/utils/gen_adldata/file_formats/load_bnk2.h index 1f3d4a1..4772da5 100644 --- a/utils/gen_adldata/file_formats/load_bnk2.h +++ b/utils/gen_adldata/file_formats/load_bnk2.h @@ -3,6 +3,11 @@ #include "../progs_cache.h" +inline int stdstoi(const std::string& str) +{ + return std::atoi(str.c_str()); +} + static bool LoadBNK2(const char *fn, unsigned bank, const char *prefix, const std::string &melo_filter, const std::string &perc_filter) @@ -43,9 +48,9 @@ static bool LoadBNK2(const char *fn, unsigned bank, const char *prefix, int gmno = 0; if(name.substr(0, melo_filter.size()) == melo_filter) - gmno = std::stoi(name.substr(melo_filter.size())); + gmno = stdstoi(name.substr(melo_filter.size())); else if(name.substr(0, perc_filter.size()) == perc_filter) - gmno = std::stoi(name.substr(perc_filter.size())) + 128; + gmno = stdstoi(name.substr(perc_filter.size())) + 128; else continue; @@ -81,6 +86,7 @@ static bool LoadBNK2(const char *fn, unsigned bank, const char *prefix, ins tmp2; tmp2.notenum = (gmno & 128) ? 35 : 0; tmp2.pseudo4op = false; + tmp2.real4op = false; tmp2.voice2_fine_tune = 0.0; if(xxP24NNN & 8) diff --git a/utils/gen_adldata/file_formats/load_ea.h b/utils/gen_adldata/file_formats/load_ea.h index 5e0baa4..79367d9 100644 --- a/utils/gen_adldata/file_formats/load_ea.h +++ b/utils/gen_adldata/file_formats/load_ea.h @@ -85,16 +85,17 @@ static bool LoadEA(const char *fn, unsigned bank, const char *prefix) ins tmp2{}; tmp2.notenum = 0; tmp2.pseudo4op = false; + tmp2.real4op = false; std::string name; char name2[512]; if(gmno < 20) { - std::snprintf(name2, 512, "%sM%u", prefix, gmno); + snprintf(name2, 512, "%sM%u", prefix, gmno); } else { - std::snprintf(name2, 512, "%sunk%04X", prefix, offset); + snprintf(name2, 512, "%sunk%04X", prefix, offset); } size_t resno = InsertIns(tmp, tmp2, std::string(1, '\377') + name, name2); SetBank(bank, gmno, resno); diff --git a/utils/gen_adldata/file_formats/load_ibk.h b/utils/gen_adldata/file_formats/load_ibk.h index bc03962..12fa520 100644 --- a/utils/gen_adldata/file_formats/load_ibk.h +++ b/utils/gen_adldata/file_formats/load_ibk.h @@ -61,6 +61,7 @@ static bool LoadIBK(const char *fn, unsigned bank, const char *prefix, bool perc struct ins tmp2; tmp2.notenum = gmno < 128 ? 0 : 35; tmp2.pseudo4op = false; + tmp2.real4op = false; tmp2.voice2_fine_tune = 0.0; size_t resno = InsertIns(tmp, tmp2, std::string(1, '\377') + name, name2); diff --git a/utils/gen_adldata/file_formats/load_jv.h b/utils/gen_adldata/file_formats/load_jv.h index b79832f..35caead 100644 --- a/utils/gen_adldata/file_formats/load_jv.h +++ b/utils/gen_adldata/file_formats/load_jv.h @@ -71,6 +71,7 @@ static bool LoadJunglevision(const char *fn, unsigned bank, const char *prefix) struct ins tmp2; tmp2.notenum = data[offset + 1]; tmp2.pseudo4op = false; + tmp2.real4op = (data[offset] != 0); tmp2.voice2_fine_tune = 0.0; while(tmp2.notenum && tmp2.notenum < 20) diff --git a/utils/gen_adldata/file_formats/load_op2.h b/utils/gen_adldata/file_formats/load_op2.h index 8b7fec6..48b7eae 100644 --- a/utils/gen_adldata/file_formats/load_op2.h +++ b/utils/gen_adldata/file_formats/load_op2.h @@ -82,7 +82,7 @@ static bool LoadDoom(const char *fn, unsigned bank, const char *prefix) int gmno = int(a < 128 ? a : ((a | 128) + 35)); char name2[512]; - std::snprintf(name2, 512, "%s%c%u", prefix, (gmno < 128 ? 'M' : 'P'), gmno & 127); + snprintf(name2, 512, "%s%c%u", prefix, (gmno < 128 ? 'M' : 'P'), gmno & 127); Doom_opl_instr &ins = *(Doom_opl_instr *) &data[offset2]; @@ -108,6 +108,7 @@ static bool LoadDoom(const char *fn, unsigned bank, const char *prefix) struct ins tmp2; tmp2.notenum = ins.note; tmp2.pseudo4op = false; + tmp2.real4op = false; tmp2.voice2_fine_tune = 0.0; while(tmp2.notenum && tmp2.notenum < 20) { diff --git a/utils/gen_adldata/file_formats/load_tmb.h b/utils/gen_adldata/file_formats/load_tmb.h index ab1ff37..5b38433 100644 --- a/utils/gen_adldata/file_formats/load_tmb.h +++ b/utils/gen_adldata/file_formats/load_tmb.h @@ -50,6 +50,7 @@ static bool LoadTMB(const char *fn, unsigned bank, const char *prefix) struct ins tmp2; tmp2.notenum = data[offset + 11]; tmp2.pseudo4op = false; + tmp2.real4op = false; tmp2.voice2_fine_tune = 0.0; std::string name; diff --git a/utils/gen_adldata/file_formats/load_wopl.h b/utils/gen_adldata/file_formats/load_wopl.h index 26a2611..fe4865d 100644 --- a/utils/gen_adldata/file_formats/load_wopl.h +++ b/utils/gen_adldata/file_formats/load_wopl.h @@ -57,8 +57,8 @@ static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) uint16_t pbanks_count = toUint16BE((const uint8_t *)data.data() + 0x0f); AdlBankSetup setup; - setup.deepTremolo = (data[0x11] >> 0) & 0x01; - setup.deepVibrato = (data[0x11] >> 1) & 0x01; + setup.deepTremolo = (data[0x11] & 0x01) != 0; + setup.deepVibrato = (data[0x11] & 0x02) != 0; setup.volumeModel = (int)data[0x12]; setup.adLibPercussions = false; setup.scaleModulators = false; @@ -169,6 +169,7 @@ static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) tmp2.notenum = is_percussion ? data[offset + 38] : 0; bool real4op = (flags & (uint8_t)WOPL_Flags::Mode_4op) != 0; tmp2.pseudo4op = (flags & (uint8_t)WOPL_Flags::Mode_DoubleVoice) != 0; + tmp2.real4op = real4op && !tmp2.pseudo4op; tmp2.voice2_fine_tune = 0; tmp[0].diff = false; tmp[1].diff = real4op && !tmp2.pseudo4op; @@ -207,9 +208,9 @@ static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) char name2[512]; std::memset(name2, 0, 512); if(is_percussion) - std::snprintf(name2, 512, "%sP%u", prefix, gmno & 127); + snprintf(name2, 512, "%sP%u", prefix, gmno & 127); else - std::snprintf(name2, 512, "%sM%u", prefix, i); + snprintf(name2, 512, "%sM%u", prefix, i); if(!real4op && !tmp2.pseudo4op) { diff --git a/utils/gen_adldata/gen_adldata.cc b/utils/gen_adldata/gen_adldata.cc index 7c8af8b..bc5c231 100644 --- a/utils/gen_adldata/gen_adldata.cc +++ b/utils/gen_adldata/gen_adldata.cc @@ -312,7 +312,7 @@ int main(int argc, char**argv) i->first.data[10], i->first.finetune); - #ifdef ADLDATA_WITH_COMMENTS +#ifdef ADLDATA_WITH_COMMENTS std::string names; for(std::set<std::string>::const_iterator j = i->second.second.begin(); @@ -326,9 +326,9 @@ int main(int argc, char**argv) names += *j; } std::fprintf(outFile, " }, // %u: %s\n", (unsigned)c, names.c_str()); - #else +#else std::fprintf(outFile, " },\n"); - #endif +#endif } } std::fprintf(outFile, "};\n"); @@ -341,6 +341,7 @@ int main(int argc, char**argv) " unsigned char flags;\n" " long ms_sound_kon; // Number of milliseconds it produces sound;\n" " long ms_sound_koff;\n" + " double voice2_fine_tune;\n" "} adlins[] =\n");*/ std::fprintf(outFile, "const struct adlinsdata adlins[%u] =\n", (unsigned)instab.size()); @@ -348,7 +349,7 @@ int main(int argc, char**argv) MeasureThreaded measureCounter; { - std::printf("Beginning to generate measures data... (Hardware concurrency: %d)\n", std::thread::hardware_concurrency()); + std::printf("Beginning to generate measures data... (hardware concurrency of %d)\n", std::thread::hardware_concurrency()); std::fflush(stdout); measureCounter.LoadCache("fm_banks/adldata-cache.dat"); measureCounter.m_total = instab.size(); @@ -381,7 +382,7 @@ int main(int argc, char**argv) //DurationInfo info = MeasureDurations(i->first); MeasureThreaded::DurationInfoCache::iterator indo_i = measureCounter.m_durationInfo.find(i->first); DurationInfo info = indo_i->second; - #ifdef ADLDATA_WITH_COMMENTS +#ifdef ADLDATA_WITH_COMMENTS { if(info.peak_amplitude_time == 0) { @@ -404,12 +405,14 @@ int main(int argc, char**argv) info.keyoff_out_time / double(info.interval)); } } - #endif +#endif - unsigned flags = (i->first.pseudo4op ? 1 : 0) | (info.nosound ? 2 : 0); + unsigned flags = (i->first.pseudo4op ? ins::Flag_Pseudo4op : 0)| + (i->first.real4op ? ins::Flag_Real4op : 0) | + (info.nosound ? ins::Flag_NoSound : 0); std::fprintf(outFile, " {"); - std::fprintf(outFile, "%4d,%4d,%3d, %d, %6" PRId64 ",%6" PRId64 ",%lf", + std::fprintf(outFile, "%4d,%4d,%3d, %d, %6" PRId64 ",%6" PRId64 ",%g", (unsigned) i->first.insno1, (unsigned) i->first.insno2, (int)(i->first.notenum), @@ -429,11 +432,11 @@ int main(int argc, char**argv) else names += *j; } - #ifdef ADLDATA_WITH_COMMENTS +#ifdef ADLDATA_WITH_COMMENTS std::fprintf(outFile, " }, // %u: %s\n\n", (unsigned)c, names.c_str()); - #else +#else std::fprintf(outFile, " },\n"); - #endif +#endif std::fflush(outFile); adlins_flags.push_back(flags); } @@ -444,11 +447,11 @@ int main(int argc, char**argv) std::fflush(stdout); //fprintf(outFile, "static const unsigned short banks[][256] =\n"); - #ifdef HARD_BANKS +#ifdef HARD_BANKS const unsigned bankcount = sizeof(banknames) / sizeof(*banknames); - #else +#else const size_t bankcount = banknames.size(); - #endif +#endif size_t nosound = InsertNoSoundIns(); @@ -486,25 +489,29 @@ int main(int argc, char**argv) std::fprintf(outFile, "{\n"); for(unsigned bank = 0; bank < bankcount; ++bank) { - #ifdef ADLDATA_WITH_COMMENTS +#ifdef ADLDATA_WITH_COMMENTS std::fprintf(outFile, " { // bank %u, %s\n", bank, banknames[bank].c_str()); - #else +#else std::fprintf(outFile, " {\n"); #endif +#ifdef ADLDATA_WITH_COMMENTS bool redundant = true; +#endif for(unsigned p = 0; p < 256; ++p) { size_t v = bank_data[bank][p]; if(listed.find(v) == listed.end()) { listed.insert(v); +#ifdef ADLDATA_WITH_COMMENTS redundant = false; +#endif } std::fprintf(outFile, "%4d,", (unsigned int)v); if(p % 16 == 15) fprintf(outFile, "\n"); } std::fprintf(outFile, " },\n"); - #ifdef ADLDATA_WITH_COMMENTS +#ifdef ADLDATA_WITH_COMMENTS if(redundant) { std::fprintf(outFile, " // Bank %u defines nothing new.\n", bank); @@ -523,7 +530,7 @@ int main(int argc, char**argv) bank, refbank); } } - #endif +#endif } std::fprintf(outFile, "};\n\n"); diff --git a/utils/gen_adldata/ini/ini_processing.cpp b/utils/gen_adldata/ini/ini_processing.cpp index 26da540..8a2807b 100644 --- a/utils/gen_adldata/ini/ini_processing.cpp +++ b/utils/gen_adldata/ini/ini_processing.cpp @@ -1,27 +1,26 @@ /* -INI Processor - a small library which allows you parsing INI-files - -Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -*/ + * INI Processor - a small library which allows you parsing INI-files + * + * Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ //#define USE_FILE_MAPPER diff --git a/utils/gen_adldata/ini/ini_processing.h b/utils/gen_adldata/ini/ini_processing.h index 8da4b7e..64777a5 100644 --- a/utils/gen_adldata/ini/ini_processing.h +++ b/utils/gen_adldata/ini/ini_processing.h @@ -1,26 +1,26 @@ /* -INI Processor - a small library which allows you parsing INI-files - -Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ + * INI Processor - a small library which allows you parsing INI-files + * + * Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ #ifndef INIPROCESSING_H #define INIPROCESSING_H diff --git a/utils/gen_adldata/ini/ini_processing_variant.h b/utils/gen_adldata/ini/ini_processing_variant.h index 41a96dd..d659aa9 100644 --- a/utils/gen_adldata/ini/ini_processing_variant.h +++ b/utils/gen_adldata/ini/ini_processing_variant.h @@ -1,31 +1,31 @@ /* -INI Processor - a small library which allows you parsing INI-files - -Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru> - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ + * INI Processor - a small library which allows you parsing INI-files + * + * Copyright (c) 2015-2018 Vitaly Novichkov <admin@wohlnet.ru> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ /* -A QVariant-like thing created just like a proxy between -INI Processor and target value (to be compatible with QSettings) -*/ + * A QVariant-like thing created just like a proxy between + * INI Processor and target value (to be compatible with QSettings) + */ #ifndef INI_PROCESSING_VARIANT_H #define INI_PROCESSING_VARIANT_H diff --git a/utils/gen_adldata/measurer.cpp b/utils/gen_adldata/measurer.cpp index 7a81379..7caf883 100644 --- a/utils/gen_adldata/measurer.cpp +++ b/utils/gen_adldata/measurer.cpp @@ -1,7 +1,9 @@ #include "measurer.h" #include <cmath> -#include "../../src/chips/opl_chip_base.h" +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif // Nuked OPL3 emulator, Most accurate, but requires the powerful CPU #ifndef ADLMIDI_DISABLE_NUKED_EMULATOR @@ -14,208 +16,367 @@ # include "../../src/chips/dosbox_opl3.h" #endif -DurationInfo MeasureDurations(const ins &in) +template <class T> +class AudioHistory { - std::vector<int16_t> stereoSampleBuf; -#ifdef ADLMIDI_USE_DOSBOX_OPL - std::vector<int32_t> stereoSampleBuf_32; -#endif - insdata id[2]; - bool found[2] = {false, false}; - for(InstrumentDataTab::const_iterator j = insdatatab.begin(); - j != insdatatab.end(); - ++j) + std::unique_ptr<T[]> m_data; + size_t m_index = 0; // points to the next write slot + size_t m_length = 0; + size_t m_capacity = 0; + +public: + size_t size() const { return m_length; } + size_t capacity() const { return m_capacity; } + const T *data() const { return &m_data[m_index + m_capacity - m_length]; } + + void reset(size_t capacity) { - if(j->second.first == in.insno1) - { - id[0] = j->first; - found[0] = true; - if(found[1]) break; - } - if(j->second.first == in.insno2) - { - id[1] = j->first; - found[1] = true; - if(found[0]) break; - } + m_data.reset(new T[2 * capacity]()); + m_index = 0; + m_length = 0; + m_capacity = capacity; } - const unsigned rate = 22010; - const unsigned interval = 150; - const unsigned samples_per_interval = rate / interval; - const int notenum = - in.notenum < 20 ? (44 + in.notenum) - : in.notenum >= 128 ? (44 + 128 - in.notenum) - : in.notenum; - OPLChipBase *opl; + void clear() + { + m_length = 0; + } - //DosBoxOPL3 db; opl = &db; - //NukedOPL3 nuke; opl = &nuke; - NukedOPL3v174 nuke74; opl = &nuke74; + void add(const T &item) + { + T *data = m_data.get(); + const size_t capacity = m_capacity; + size_t index = m_index; + data[index] = item; + data[index + capacity] = item; + m_index = (index + 1 != capacity) ? (index + 1) : 0; + size_t length = m_length + 1; + m_length = (length < capacity) ? length : capacity; + } +}; -#define WRITE_REG(key, value) opl->writeReg((uint16_t)(key), (uint8_t)(value)) +static void HannWindow(double *w, unsigned n) +{ + for (unsigned i = 0; i < n; ++i) + w[i] = 0.5 * (1.0 - std::cos(2 * M_PI * i / (n - 1))); +} - static const short initdata[(2 + 3 + 2 + 2) * 2] = +static double MeasureRMS(const double *signal, const double *window, unsigned length) +{ + double mean = 0; +#pragma omp simd reduction(+: mean) + for(unsigned i = 0; i < length; ++i) + mean += window[i] * signal[i]; + mean /= length; + + double rms = 0; +#pragma omp simd reduction(+: rms) + for(unsigned i = 0; i < length; ++i) { - 0x004, 96, 0x004, 128, // Pulse timer - 0x105, 0, 0x105, 1, 0x105, 0, // Pulse OPL3 enable, leave disabled - 0x001, 32, 0x0BD, 0 // Enable wave & melodic - }; - opl->setRate(rate); + double diff = window[i] * signal[i] - mean; + rms += diff * diff; + } + rms = std::sqrt(rms / (length - 1)); - for(unsigned a = 0; a < 18; a += 2) WRITE_REG(initdata[a], initdata[a + 1]); + return rms; +} - const unsigned n_notes = in.insno1 == in.insno2 ? 1 : 2; - unsigned x[2]; +static const unsigned g_outputRate = 49716; - if(n_notes == 2 && !in.pseudo4op) +struct TinySynth +{ + OPLChipBase *m_chip; + unsigned m_notesNum; + int m_notenum; + int8_t m_fineTune; + int16_t m_noteOffsets[2]; + unsigned m_x[2]; + + void resetChip() { - WRITE_REG(0x105, 1); - WRITE_REG(0x104, 1); - } + static const short initdata[(2 + 3 + 2 + 2) * 2] = + { + 0x004, 96, 0x004, 128, // Pulse timer + 0x105, 0, 0x105, 1, 0x105, 0, // Pulse OPL3 enable, leave disabled + 0x001, 32, 0x0BD, 0 // Enable wave & melodic + }; - for(unsigned n = 0; n < n_notes; ++n) - { - static const unsigned char patchdata[11] = - {0x20, 0x23, 0x60, 0x63, 0x80, 0x83, 0xE0, 0xE3, 0x40, 0x43, 0xC0}; - for(unsigned a = 0; a < 10; ++a) WRITE_REG(patchdata[a] + n * 8, id[n].data[a]); - WRITE_REG(patchdata[10] + n * 8, id[n].data[10] | 0x30); + m_chip->setRate(g_outputRate); + + for(unsigned a = 0; a < 18; a += 2) + m_chip->writeReg((uint16_t)initdata[a], (uint8_t)initdata[a + 1]); } - for(unsigned n = 0; n < n_notes; ++n) + void setInstrument(const ins &in) { - double hertz = 172.00093 * std::exp(0.057762265 * (notenum + id[n].finetune)); - if(hertz > 131071) + insdata rawData[2]; + bool found[2] = {false, false}; + for(InstrumentDataTab::const_iterator j = insdatatab.begin(); + j != insdatatab.end(); + ++j) + { + if(j->second.first == in.insno1) + { + rawData[0] = j->first; + found[0] = true; + if(found[1]) break; + } + if(j->second.first == in.insno2) + { + rawData[1] = j->first; + found[1] = true; + if(found[0]) break; + } + } + + std::memset(m_x, 0, sizeof(m_x)); + m_notenum = in.notenum >= 128 ? (in.notenum - 128) : in.notenum; + if(m_notenum == 0) + m_notenum = 25; + m_notesNum = in.insno1 == in.insno2 ? 1 : 2; + m_fineTune = 0; + m_noteOffsets[0] = rawData[0].finetune; + m_noteOffsets[1] = rawData[1].finetune; + if(in.pseudo4op) + m_fineTune = in.voice2_fine_tune; + if(in.real4op) { - std::fprintf(stderr, "MEASURER WARNING: Why does note %d + finetune %d produce hertz %g? \n", - notenum, id[n].finetune, hertz); - hertz = 131071; + m_chip->writeReg(0x105, 1); + m_chip->writeReg(0x104, 0xFF); } - x[n] = 0x2000; - while(hertz >= 1023.5) + + //For clearer measurement, disable tremolo and vibrato + rawData[0].data[0] &= 0x3F; + rawData[0].data[1] &= 0x3F; + rawData[1].data[0] &= 0x3F; + rawData[1].data[1] &= 0x3F; + + for(unsigned n = 0; n < m_notesNum; ++n) { - hertz /= 2.0; // Calculate octave - x[n] += 0x400; + static const unsigned char patchdata[11] = + {0x20, 0x23, 0x60, 0x63, 0x80, 0x83, 0xE0, 0xE3, 0x40, 0x43, 0xC0}; + for(unsigned a = 0; a < 10; ++a) + m_chip->writeReg(patchdata[a] + n * 8, rawData[n].data[a]); + m_chip->writeReg(patchdata[10] + n * 8, rawData[n].data[10] | 0x30); } - x[n] += (unsigned int)(hertz + 0.5); + } + + void noteOn() + { + std::memset(m_x, 0, sizeof(m_x)); + for(unsigned n = 0; n < m_notesNum; ++n) + { + double hertz = 172.00093 * std::exp(0.057762265 * (m_notenum + m_noteOffsets[n])); + if(hertz > 131071) + { + std::fprintf(stdout, "%s:%d:0: warning: Why does note %d + note-offset %d produce hertz %g?\n", __FILE__, __LINE__, + m_notenum, m_noteOffsets[n], hertz); + std::fflush(stdout); + hertz = 131071; + } + m_x[n] = 0x2000; + while(hertz >= 1023.5) + { + hertz /= 2.0; // Calculate octave + m_x[n] += 0x400; + } + m_x[n] += (unsigned int)(hertz + 0.5); - // Keyon the note - WRITE_REG(0xA0 + n * 3, x[n] & 0xFF); - WRITE_REG(0xB0 + n * 3, x[n] >> 8); + // Keyon the note + m_chip->writeReg(0xA0 + n * 3, m_x[n] & 0xFF); + m_chip->writeReg(0xB0 + n * 3, m_x[n] >> 8); + } + } + + void noteOff() + { + // Keyoff the note + for(unsigned n = 0; n < m_notesNum; ++n) + m_chip->writeReg(0xB0 + n * 3, (m_x[n] >> 8) & 0xDF); } + void generate(int16_t *output, size_t frames) + { + m_chip->generate(output, frames); + } +}; + + +DurationInfo MeasureDurations(const ins &in, OPLChipBase *chip) +{ + AudioHistory<double> audioHistory; + + const unsigned interval = 150; + const unsigned samples_per_interval = g_outputRate / interval; + + const double historyLength = 0.1; // maximum duration to memorize (seconds) + audioHistory.reset(std::ceil(historyLength * g_outputRate)); + + std::unique_ptr<double[]> window; + window.reset(new double[audioHistory.capacity()]); + unsigned winsize = 0; + + TinySynth synth; + synth.m_chip = chip; + synth.resetChip(); + synth.setInstrument(in); + synth.noteOn(); + + /* For capturing */ const unsigned max_silent = 6; const unsigned max_on = 40; const unsigned max_off = 60; + unsigned max_period_on = max_on * interval; + unsigned max_period_off = max_off * interval; + + const double min_coefficient_on = 0.008; + const double min_coefficient_off = 0.2; + + unsigned windows_passed_on = 0; + unsigned windows_passed_off = 0; + + /* For Analyze the results */ + double begin_amplitude = 0; + double peak_amplitude_value = 0; + size_t peak_amplitude_time = 0; + size_t quarter_amplitude_time = max_period_on; + bool quarter_amplitude_time_found = false; + size_t keyoff_out_time = 0; + bool keyoff_out_time_found = false; + + const size_t audioBufferLength = 256; + const size_t audioBufferSize = 2 * audioBufferLength; + int16_t audioBuffer[audioBufferSize]; + // For up to 40 seconds, measure mean amplitude. - std::vector<double> amplitudecurve_on; double highest_sofar = 0; short sound_min = 0, sound_max = 0; - for(unsigned period = 0; period < max_on * interval; ++period) + + for(unsigned period = 0; period < max_period_on; ++period, ++windows_passed_on) { - stereoSampleBuf.clear(); - stereoSampleBuf.resize(samples_per_interval * 2); - opl->generate(stereoSampleBuf.data(), samples_per_interval); + for(unsigned i = 0; i < samples_per_interval;) + { + size_t blocksize = samples_per_interval - i; + blocksize = (blocksize < audioBufferLength) ? blocksize : audioBufferLength; + synth.generate(audioBuffer, blocksize); + for (unsigned j = 0; j < blocksize; ++j) + { + int16_t s = audioBuffer[2 * j]; + audioHistory.add(s); + if(sound_min > s) sound_min = s; + if(sound_max < s) sound_max = s; + } + i += blocksize; + } - double mean = 0.0; - for(unsigned long c = 0; c < samples_per_interval; ++c) + if(winsize != audioHistory.size()) { - short s = stereoSampleBuf[c * 2]; - mean += s; - if(sound_min > s) sound_min = s; - if(sound_max < s) sound_max = s; + winsize = audioHistory.size(); + HannWindow(window.get(), winsize); } - mean /= samples_per_interval; - double std_deviation = 0; - for(unsigned long c = 0; c < samples_per_interval; ++c) + + double rms = MeasureRMS(audioHistory.data(), window.get(), winsize); + /* ======== Peak time detection ======== */ + if(period == 0) + { + begin_amplitude = rms; + peak_amplitude_value = rms; + peak_amplitude_time = 0; + } + else if(rms > peak_amplitude_value) { - double diff = (stereoSampleBuf[c * 2] - mean); - std_deviation += diff * diff; + peak_amplitude_value = rms; + peak_amplitude_time = period; + // In next step, update the quater amplitude time + quarter_amplitude_time_found = false; } - std_deviation = std::sqrt(std_deviation / samples_per_interval); - amplitudecurve_on.push_back(std_deviation); - if(std_deviation > highest_sofar) - highest_sofar = std_deviation; + else if(!quarter_amplitude_time_found && (rms <= peak_amplitude_value * min_coefficient_on)) + { + quarter_amplitude_time = period; + quarter_amplitude_time_found = true; + } + /* ======== Peak time detection =END==== */ + if(rms > highest_sofar) + highest_sofar = rms; if((period > max_silent * interval) && - ((std_deviation < highest_sofar * 0.2)|| - (sound_min >= -1 && sound_max <= 1)) + ( (rms < highest_sofar * min_coefficient_on) || (sound_min >= -1 && sound_max <= 1) ) ) break; } - // Keyoff the note - for(unsigned n = 0; n < n_notes; ++n) - WRITE_REG(0xB0 + n * 3, (x[n] >> 8) & 0xDF); + if(!quarter_amplitude_time_found) + quarter_amplitude_time = windows_passed_on; - // Now, for up to 60 seconds, measure mean amplitude. - std::vector<double> amplitudecurve_off; - for(unsigned period = 0; period < max_off * interval; ++period) + if(windows_passed_on >= max_period_on) { - stereoSampleBuf.clear(); - stereoSampleBuf.resize(samples_per_interval * 2); - opl->generate(stereoSampleBuf.data(), samples_per_interval); - - double mean = 0.0; - for(unsigned long c = 0; c < samples_per_interval; ++c) - { - short s = stereoSampleBuf[c * 2]; - mean += s; - if(sound_min > s) sound_min = s; - if(sound_max < s) sound_max = s; - } - mean /= samples_per_interval; - double std_deviation = 0; - for(unsigned long c = 0; c < samples_per_interval; ++c) + // Just Keyoff the note + synth.noteOff(); + } + else + { + // Reset the emulator and re-run the "ON" simulation until reaching the peak time + synth.resetChip(); + synth.setInstrument(in); + synth.noteOn(); + + audioHistory.reset(std::ceil(historyLength * g_outputRate)); + for(unsigned period = 0; + (period < peak_amplitude_time) && (period < max_period_on); + ++period) { - double diff = (stereoSampleBuf[c * 2] - mean); - std_deviation += diff * diff; + for(unsigned i = 0; i < samples_per_interval;) + { + size_t blocksize = samples_per_interval - i; + blocksize = (blocksize < audioBufferLength) ? blocksize : audioBufferLength; + synth.generate(audioBuffer, blocksize); + for (unsigned j = 0; j < blocksize; ++j) + audioHistory.add(audioBuffer[2 * j]); + i += blocksize; + } } - std_deviation = std::sqrt(std_deviation / samples_per_interval); - amplitudecurve_off.push_back(std_deviation); - - if(std_deviation < highest_sofar * 0.2) - break; - - if((period > max_silent * interval) && (sound_min >= -1 && sound_max <= 1)) - break; + synth.noteOff(); } - /* Analyze the results */ - double begin_amplitude = amplitudecurve_on[0]; - double peak_amplitude_value = begin_amplitude; - size_t peak_amplitude_time = 0; - size_t quarter_amplitude_time = amplitudecurve_on.size(); - size_t keyoff_out_time = 0; - - for(size_t a = 1; a < amplitudecurve_on.size(); ++a) + // Now, for up to 60 seconds, measure mean amplitude. + for(unsigned period = 0; period < max_period_off; ++period, ++windows_passed_off) { - if(amplitudecurve_on[a] > peak_amplitude_value) + for(unsigned i = 0; i < samples_per_interval;) { - peak_amplitude_value = amplitudecurve_on[a]; - peak_amplitude_time = a; + size_t blocksize = samples_per_interval - i; + blocksize = (blocksize < 256) ? blocksize : 256; + synth.generate(audioBuffer, blocksize); + for (unsigned j = 0; j < blocksize; ++j) + { + int16_t s = audioBuffer[2 * j]; + audioHistory.add(s); + if(sound_min > s) sound_min = s; + if(sound_max < s) sound_max = s; + } + i += blocksize; } - } - for(size_t a = peak_amplitude_time; a < amplitudecurve_on.size(); ++a) - { - if(amplitudecurve_on[a] <= peak_amplitude_value * 0.2) + + if(winsize != audioHistory.size()) { - quarter_amplitude_time = a; - break; + winsize = audioHistory.size(); + HannWindow(window.get(), winsize); } - } - for(size_t a = 0; a < amplitudecurve_off.size(); ++a) - { - if(amplitudecurve_off[a] <= peak_amplitude_value * 0.2) + + double rms = MeasureRMS(audioHistory.data(), window.get(), winsize); + /* ======== Find Key Off time ======== */ + if(!keyoff_out_time_found && (rms <= peak_amplitude_value * min_coefficient_off)) { - keyoff_out_time = a; - break; + keyoff_out_time = period; + keyoff_out_time_found = true; } - } + /* ======== Find Key Off time ==END=== */ + if(rms < highest_sofar * min_coefficient_off) + break; - if(keyoff_out_time == 0 && amplitudecurve_on.back() < peak_amplitude_value * 0.2) - keyoff_out_time = quarter_amplitude_time; + if((period > max_silent * interval) && (sound_min >= -1 && sound_max <= 1)) + break; + } DurationInfo result; result.peak_amplitude_time = peak_amplitude_time; @@ -227,11 +388,10 @@ DurationInfo MeasureDurations(const ins &in) result.ms_sound_kon = (int64_t)(quarter_amplitude_time * 1000.0 / interval); result.ms_sound_koff = (int64_t)(keyoff_out_time * 1000.0 / interval); result.nosound = (peak_amplitude_value < 0.5) || ((sound_min >= -1) && (sound_max <= 1)); + return result; } -static const char* spinner = "-\\|/"; - void MeasureThreaded::LoadCache(const char *fileName) { FILE *in = std::fopen(fileName, "rb"); @@ -290,6 +450,8 @@ void MeasureThreaded::LoadCache(const char *fileName) inst.insno2 = inval; if(std::fread(&inst.notenum, 1, 1, in) != 1) break; + if(std::fread(&inst.real4op, 1, 1, in) != 1) + break; if(std::fread(&inst.pseudo4op, 1, 1, in) != 1) break; if(std::fread(&inst.voice2_fine_tune, sizeof(double), 1, in) != 1) @@ -418,6 +580,7 @@ void MeasureThreaded::SaveCache(const char *fileName) outval = in.insno2; fwrite(&outval, 1, sizeof(uint64_t), out); fwrite(&in.notenum, 1, 1, out); + fwrite(&in.real4op, 1, 1, out); fwrite(&in.pseudo4op, 1, 1, out); fwrite(&in.voice2_fine_tune, sizeof(double), 1, out); @@ -458,9 +621,13 @@ void MeasureThreaded::SaveCache(const char *fileName) std::fclose(out); } +#ifdef ADL_GENDATA_PRINT_PROGRESS + +static const char* spinner = "-\\|/"; + void MeasureThreaded::printProgress() { - std::printf("Calculating measures... [%c %3u%% (%4u/%4u) Threads %3u, Matches %u] \r", + std::printf("Calculating measures... [%c %3u%% {%4u/%4u} Threads %3u, Matches %u] \r", spinner[m_done.load() % 4], (unsigned int)(((double)m_done.load() / (double)(m_total)) * 100), (unsigned int)m_done.load(), @@ -470,6 +637,12 @@ void MeasureThreaded::printProgress() ); std::fflush(stdout); } +#else +void MeasureThreaded::printProgress() +{ + //Do nothing +} +#endif void MeasureThreaded::printFinal() { @@ -501,14 +674,18 @@ void MeasureThreaded::run(InstrumentsData::const_iterator i) dd->myself = this; dd->start(); m_threads.push_back(dd); +#ifdef ADL_GENDATA_PRINT_PROGRESS printProgress(); +#endif } void MeasureThreaded::waitAll() { for(auto &th : m_threads) { +#ifdef ADL_GENDATA_PRINT_PROGRESS printProgress(); +#endif delete th; } m_threads.clear(); @@ -524,6 +701,7 @@ void MeasureThreaded::destData::callback(void *myself) { destData *s = reinterpret_cast<destData *>(myself); DurationInfo info; + DosBoxOPL3 dosbox; DurationInfoCache::iterator cachedEntry = s->myself->m_durationInfo.find(s->i->first); if(cachedEntry != s->myself->m_durationInfo.end()) @@ -532,7 +710,7 @@ void MeasureThreaded::destData::callback(void *myself) goto endWork; } - info = MeasureDurations(s->i->first); + info = MeasureDurations(s->i->first, &dosbox); s->myself->m_durationInfo_mx.lock(); s->myself->m_durationInfo.insert({s->i->first, info}); s->myself->m_durationInfo_mx.unlock(); diff --git a/utils/gen_adldata/measurer.h b/utils/gen_adldata/measurer.h index b9ae3c6..63475ca 100644 --- a/utils/gen_adldata/measurer.h +++ b/utils/gen_adldata/measurer.h @@ -100,6 +100,7 @@ struct MeasureThreaded void waitAll(); }; -extern DurationInfo MeasureDurations(const ins &in); +class OPLChipBase; +extern DurationInfo MeasureDurations(const ins &in, OPLChipBase *chip); #endif // MEASURER_H diff --git a/utils/gen_adldata/progs_cache.cpp b/utils/gen_adldata/progs_cache.cpp index a59e7b7..81bba4c 100644 --- a/utils/gen_adldata/progs_cache.cpp +++ b/utils/gen_adldata/progs_cache.cpp @@ -112,7 +112,7 @@ size_t InsertNoSoundIns() { // { 0x0F70700,0x0F70710, 0xFF,0xFF, 0x0,+0 }, insdata tmp1 = MakeNoSoundIns(); - struct ins tmp2 = { 0, 0, 0, false, 0.0 }; + struct ins tmp2 = { 0, 0, 0, false, false, 0.0 }; return InsertIns(tmp1, tmp1, tmp2, "nosound", ""); } diff --git a/utils/gen_adldata/progs_cache.h b/utils/gen_adldata/progs_cache.h index 7b4cd39..5a916f5 100644 --- a/utils/gen_adldata/progs_cache.h +++ b/utils/gen_adldata/progs_cache.h @@ -49,9 +49,11 @@ inline bool equal_approx(double const a, double const b) struct ins { + enum { Flag_Pseudo4op = 0x01, Flag_NoSound = 0x02, Flag_Real4op = 0x04 }; size_t insno1, insno2; unsigned char notenum; bool pseudo4op; + bool real4op; double voice2_fine_tune; bool operator==(const ins &b) const @@ -60,6 +62,7 @@ struct ins && insno1 == b.insno1 && insno2 == b.insno2 && pseudo4op == b.pseudo4op + && real4op == b.real4op && equal_approx(voice2_fine_tune, b.voice2_fine_tune); } bool operator< (const ins &b) const @@ -68,6 +71,7 @@ struct ins if(insno2 != b.insno2) return insno2 < b.insno2; if(notenum != b.notenum) return notenum < b.notenum; if(pseudo4op != b.pseudo4op) return pseudo4op < b.pseudo4op; + if(real4op != b.real4op) return real4op < b.real4op; if(!equal_approx(voice2_fine_tune, b.voice2_fine_tune)) return voice2_fine_tune < b.voice2_fine_tune; return 0; } diff --git a/utils/midiplay/adlmidiplay.cpp b/utils/midiplay/adlmidiplay.cpp index a591626..8bffc50 100644 --- a/utils/midiplay/adlmidiplay.cpp +++ b/utils/midiplay/adlmidiplay.cpp @@ -320,6 +320,8 @@ int main(int argc, char **argv) #endif #ifndef HARDWARE_OPL3 int emulator = ADLMIDI_EMU_NUKED; + #endif + #if !defined(HARDWARE_OPL3) && !defined(OUTPUT_WAVE_ONLY) g_audioFormat.type = ADLMIDI_SampleType_S16; g_audioFormat.containerSize = sizeof(Sint16); g_audioFormat.sampleOffset = sizeof(Sint16) * 2; @@ -334,7 +336,7 @@ int main(int argc, char **argv) else if(!std::strcmp("-v", argv[2])) adl_setHVibrato(myDevice, 1);//Force turn on deep vibrato - #ifndef OUTPUT_WAVE_ONLY + #if !defined(OUTPUT_WAVE_ONLY) && !defined(HARDWARE_OPL3) else if(!std::strcmp("-w", argv[2])) { //Current Wave output implementation allows only SINT16 output @@ -402,6 +404,7 @@ int main(int argc, char **argv) adl_switchEmulator(myDevice, emulator); #endif + std::fprintf(stdout, " - Library version %s\n", adl_linkedLibraryVersion()); #ifdef HARDWARE_OPL3 std::fprintf(stdout, " - Hardware OPL3 chip in use\n"); #else diff --git a/utils/vlc_codec/libadlmidi.c b/utils/vlc_codec/libadlmidi.c index 5f85a4d..aedd718 100644 --- a/utils/vlc_codec/libadlmidi.c +++ b/utils/vlc_codec/libadlmidi.c @@ -18,14 +18,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. *****************************************************************************/ -//#ifdef HAVE_CONFIG_H -//# include "config.h" -//#endif - #include <vlc_common.h> #include <vlc_plugin.h> #include <vlc_codec.h> #include <vlc_dialog.h> +#include <libvlc_version.h> #include <unistd.h> @@ -43,18 +40,20 @@ #define SOUNDFONT_LONGTEXT N_( \ "Custom bank file to use for software synthesis." ) -//#define CHORUS_TEXT N_("Chorus") +#if 0 /* Old code */ +#define CHORUS_TEXT N_("Chorus") -//#define GAIN_TEXT N_("Synthesis gain") -//#define GAIN_LONGTEXT N_("This gain is applied to synthesis output. " \ -// "High values may cause saturation when many notes are played at a time." ) +#define GAIN_TEXT N_("Synthesis gain") +#define GAIN_LONGTEXT N_("This gain is applied to synthesis output. " \ + "High values may cause saturation when many notes are played at a time." ) -//#define POLYPHONY_TEXT N_("Polyphony") -//#define POLYPHONY_LONGTEXT N_( \ -// "The polyphony defines how many voices can be played at a time. " \ -// "Larger values require more processing power.") +#define POLYPHONY_TEXT N_("Polyphony") +#define POLYPHONY_LONGTEXT N_( \ + "The polyphony defines how many voices can be played at a time. " \ + "Larger values require more processing power.") -//#define REVERB_TEXT N_("Reverb") +#define REVERB_TEXT N_("Reverb") +#endif #define SAMPLE_RATE_TEXT N_("Sample rate") @@ -67,7 +66,11 @@ static void Close (vlc_object_t *); vlc_module_begin () set_description (N_("ADLMIDI OPL3 Synth MIDI synthesizer")) +#if (LIBVLC_VERSION_MAJOR >= 3) + set_capability ("audio decoder", 150) +#else set_capability ("decoder", 150) +#endif set_shortname (N_("ADLMIDI")) set_category (CAT_INPUT) set_subcategory (SUBCAT_INPUT_ACODEC) @@ -105,7 +108,11 @@ static const struct ADLMIDI_AudioFormat g_output_format = }; //static int DecodeBlock (decoder_t *p_dec, block_t *p_block); //For different version +#if (LIBVLC_VERSION_MAJOR >= 3) +static int DecodeBlock (decoder_t *p_dec, block_t *p_block); +#else static block_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block); +#endif static void Flush (decoder_t *); static int Open (vlc_object_t *p_this) @@ -149,10 +156,12 @@ static int Open (vlc_object_t *p_this) date_Set (&p_sys->end_date, 0); p_dec->p_sys = p_sys; - //==For different version== - //p_dec->pf_decode = DecodeBlock; - //p_dec->pf_flush = Flush; +#if (LIBVLC_VERSION_MAJOR >= 3) + p_dec->pf_decode = DecodeBlock; + p_dec->pf_flush = Flush; +#else p_dec->pf_decode_audio = DecodeBlock; +#endif return VLC_SUCCESS;//VLCDEC_SUCCESS } @@ -168,134 +177,61 @@ static void Close (vlc_object_t *p_this) static void Flush (decoder_t *p_dec) { decoder_sys_t *p_sys = p_dec->p_sys; - +#if (LIBVLC_VERSION_MAJOR >= 3) date_Set (&p_sys->end_date, VLC_TS_INVALID); +#else + date_Set (&p_sys->end_date, 0); +#endif adl_panic(p_sys->synth); } +#if (LIBVLC_VERSION_MAJOR >= 3) +static int DecodeBlock (decoder_t *p_dec, block_t *p_block) +{ + decoder_sys_t *p_sys = p_dec->p_sys; + block_t *p_out = NULL; +#else static block_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block) { block_t *p_block; decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_out = NULL; - if (pp_block == NULL) return NULL; p_block = *pp_block; - if (p_block == NULL) - return NULL; - *pp_block = NULL; - - if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) - { - date_Set (&p_sys->end_date, 0); - adl_panic(p_sys->synth); - } - - if (p_block->i_pts > VLC_TS_INVALID && !date_Get (&p_sys->end_date)) - date_Set (&p_sys->end_date, p_block->i_pts); - else - if (p_block->i_pts < date_Get (&p_sys->end_date)) - { - msg_Warn (p_dec, "MIDI message in the past?"); - goto drop; - } - - if (p_block->i_buffer < 1) - goto drop; - - uint8_t event = p_block->p_buffer[0]; - uint8_t channel = p_block->p_buffer[0] & 0xf; - event &= 0xF0; - - if (event == 0xF0) - switch (channel) - { - case 0: - if (p_block->p_buffer[p_block->i_buffer - 1] != 0xF7) - { - case 7: - msg_Warn (p_dec, "fragmented SysEx not implemented"); - goto drop; - } - //fluid_synth_sysex (p_sys->synth, (char *)p_block->p_buffer + 1, - // p_block->i_buffer - 2, NULL, NULL, NULL, 0); - break; - case 0xF: - adl_rt_resetState(p_sys->synth); - break; - } - - uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0; - uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0; +#endif - switch (event & 0xF0) + if (p_block == NULL) { - case 0x80: - adl_rt_noteOff(p_sys->synth, channel, p1); - break; - case 0x90: - adl_rt_noteOn(p_sys->synth, channel, p1, p2); - break; - /*case 0xA0: note aftertouch not implemented */ - case 0xB0: - adl_rt_controllerChange(p_sys->synth, channel, p1, p2); - break; - case 0xC0: - adl_rt_patchChange(p_sys->synth, channel, p1); - break; - case 0xD0: - adl_rt_channelAfterTouch(p_sys->synth, channel, p1); - break; - case 0xE0: - adl_rt_pitchBendML(p_sys->synth, channel, p2, p1); - break; +#if (LIBVLC_VERSION_MAJOR >= 3) + return VLCDEC_SUCCESS; +#else + return p_out; +#endif } - unsigned samples = - (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000; - if (samples == 0) - goto drop; - - p_out = decoder_NewAudioBuffer (p_dec, samples); - if (p_out == NULL) - goto drop; - - p_out->i_pts = date_Get (&p_sys->end_date ); - samples = adl_generateFormat(p_sys->synth, (int)samples * 2, - (ADL_UInt8*)p_out->p_buffer, - (ADL_UInt8*)(p_out->p_buffer + g_output_format.containerSize), - &g_output_format); - samples /= 2; - p_out->i_length = date_Increment (&p_sys->end_date, samples) - p_out->i_pts; - -drop: - block_Release (p_block); - return p_out; -} - -#if 0 -static int DecodeBlock (decoder_t *p_dec, block_t *p_block) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - block_t *p_out = NULL; - - if (p_block == NULL) /* No Drain */ - return VLC_SUCCESS;//VLCDEC_SUCCESS +#if (LIBVLC_VERSION_MAJOR < 3) + *pp_block = NULL; +#endif if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) { +#if (LIBVLC_VERSION_MAJOR >= 3) Flush (p_dec); if (p_block->i_flags & BLOCK_FLAG_CORRUPTED) { block_Release(p_block); - return VLC_SUCCESS;//VLCDEC_SUCCESS + return VLCDEC_SUCCESS; } +#else + Flush (p_dec); +#endif } - if (p_block->i_pts > VLC_TS_INVALID && !date_Get (&p_sys->end_date)) + if (p_block->i_pts > VLC_TS_INVALID + && !date_Get (&p_sys->end_date)) date_Set (&p_sys->end_date, p_block->i_pts); else if (p_block->i_pts < date_Get (&p_sys->end_date)) @@ -360,21 +296,30 @@ static int DecodeBlock (decoder_t *p_dec, block_t *p_block) if (samples == 0) goto drop; +#if (LIBVLC_VERSION_MAJOR >= 3) if (decoder_UpdateAudioFormat (p_dec)) goto drop; +#endif + p_out = decoder_NewAudioBuffer (p_dec, samples); if (p_out == NULL) goto drop; p_out->i_pts = date_Get (&p_sys->end_date ); - p_out->i_length = date_Increment (&p_sys->end_date, samples) - - p_out->i_pts; - adl_generate(p_sys->synth, samples * 2, p_out->p_buffer); + samples = adl_generateFormat(p_sys->synth, (int)samples * 2, + (ADL_UInt8*)p_out->p_buffer, + (ADL_UInt8*)(p_out->p_buffer + g_output_format.containerSize), + &g_output_format); + samples /= 2; + p_out->i_length = date_Increment (&p_sys->end_date, samples) - p_out->i_pts; + drop: block_Release (p_block); +#if (LIBVLC_VERSION_MAJOR >= 3) if (p_out != NULL) decoder_QueueAudio (p_dec, p_out); - return VLC_SUCCESS;//VLCDEC_SUCCESS -} - + return VLCDEC_SUCCESS; +#else + return p_out; #endif +} |