aboutsummaryrefslogtreecommitdiff
path: root/src/gen_adldata/gen_adldata.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gen_adldata/gen_adldata.cc')
-rw-r--r--src/gen_adldata/gen_adldata.cc1704
1 files changed, 380 insertions, 1324 deletions
diff --git a/src/gen_adldata/gen_adldata.cc b/src/gen_adldata/gen_adldata.cc
index 52ac5e7..80c4910 100644
--- a/src/gen_adldata/gen_adldata.cc
+++ b/src/gen_adldata/gen_adldata.cc
@@ -2,1321 +2,312 @@
//typedef struct vswprintf {} swprintf;
//#endif
#include <cstdio>
-#include <vector>
#include <string>
-#include <algorithm>
#include <cstring>
-#include <cmath>
-#include <map>
-#include <set>
-#include "midi_inst_list.h"
-
-std::map<unsigned,
- std::map<unsigned, unsigned>
- > Correlate;
-unsigned maxvalues[30] = { 0 };
-
-struct insdata
-{
- unsigned char data[11];
- signed char finetune;
- bool diff;
- bool operator==(const insdata& b) const
- {
- return std::memcmp(data, b.data, 11) == 0 && finetune == b.finetune && diff == b.diff;
- }
- bool operator< (const insdata& b) const
- {
- int c = std::memcmp(data, b.data, 11);
- if(c != 0) return c < 0;
- if(finetune != b.finetune) return finetune < b.finetune;
- if(diff != b.diff) return (!diff)==(b.diff);
- return 0;
- }
- bool operator!=(const insdata& b) const { return !operator==(b); }
-};
-struct ins
-{
- size_t insno1, insno2;
- unsigned char notenum;
- bool pseudo4op;
- double fine_tune;
-
- bool operator==(const ins& b) const
- {
- return notenum == b.notenum
- && insno1 == b.insno1
- && insno2 == b.insno2
- && pseudo4op == b.pseudo4op;
- }
- bool operator< (const ins& b) const
- {
- if(insno1 != b.insno1) return insno1 < b.insno1;
- if(insno2 != b.insno2) return insno2 < b.insno2;
- if(notenum != b.notenum) return notenum < b.notenum;
- if(pseudo4op != b.pseudo4op) return pseudo4op < b.pseudo4op;
- return 0;
- }
- bool operator!=(const ins& b) const { return !operator==(b); }
-};
+#include "ini/ini_processing.h"
-static std::map<insdata, std::pair<size_t, std::set<std::string> > > insdatatab;
+#include "progs_cache.h"
+#include "measurer.h"
-static std::map<ins, std::pair<size_t, std::set<std::string> > > instab;
-static std::map<unsigned, std::map<unsigned, size_t> > progs;
+#include "midi_inst_list.h"
-static void SetBank(unsigned bank, unsigned patch, size_t insno)
-{
- progs[bank][patch] = insno+1;
-}
+#include "file_formats/load_ail.h"
+#include "file_formats/load_bisqwit.h"
+#include "file_formats/load_bnk2.h"
+#include "file_formats/load_bnk.h"
+#include "file_formats/load_ibk.h"
+#include "file_formats/load_jv.h"
+#include "file_formats/load_op2.h"
+#include "file_formats/load_tmb.h"
-static size_t InsertIns(
- const insdata& id,
- const insdata& id2,
- ins& in,
- const std::string& name,
- const std::string& name2 = "")
+int main(int argc, char**argv)
{
- if(true)
- {
- std::map<insdata, std::pair<size_t,std::set<std::string> > >::iterator
- i = insdatatab.lower_bound(id);
-
- size_t insno = ~0;
- if(i == insdatatab.end() || i->first != id)
- {
- std::pair<insdata, std::pair<size_t,std::set<std::string> > > res;
- res.first = id;
- res.second.first = insdatatab.size();
- if(!name.empty()) res.second.second.insert(name);
- if(!name2.empty()) res.second.second.insert(name2);
- insdatatab.insert(i, res);
- insno = res.second.first;
- }
- else
+ if(argc == 1)
{
- if(!name.empty()) i->second.second.insert(name);
- if(!name2.empty()) i->second.second.insert(name2);
- insno = i->second.first;
+ printf("Usage:\n"
+ "\n"
+ "bin/gen_adldata src/adldata.cpp\n"
+ "\n");
+ return 1;
}
- in.insno1 = insno;
- }
- if( id != id2 )
- {
- std::map<insdata, std::pair<size_t,std::set<std::string> > >::iterator
- i = insdatatab.lower_bound(id2);
- size_t insno2 = ~0;
- if(i == insdatatab.end() || i->first != id2)
- {
- std::pair<insdata, std::pair<size_t,std::set<std::string> > > res;
- res.first = id2;
- res.second.first = insdatatab.size();
- if(!name.empty()) res.second.second.insert(name);
- if(!name2.empty()) res.second.second.insert(name2);
- insdatatab.insert(i, res);
- insno2 = res.second.first;
- }
- else
- {
- if(!name.empty()) i->second.second.insert(name);
- if(!name2.empty()) i->second.second.insert(name2);
- insno2 = i->second.first;
- }
- in.insno2 = insno2;
- }
- else
- in.insno2 = in.insno1;
-
+ const char *outFile_s = argv[1];
- {
- std::map<ins, std::pair<size_t,std::set<std::string> > >::iterator
- i = instab.lower_bound(in);
-
- size_t resno = ~0;
- if(i == instab.end() || i->first != in)
- {
- std::pair<ins, std::pair<size_t,std::set<std::string> > > res;
- res.first = in;
- res.second.first = instab.size();
- if(!name.empty()) res.second.second.insert(name);
- if(!name2.empty()) res.second.second.insert(name2);
- instab.insert(i, res);
- resno = res.second.first;
- }
- else
+ FILE *outFile = fopen(outFile_s, "w");
+ if(!outFile)
{
- if(!name.empty()) i->second.second.insert(name);
- if(!name2.empty()) i->second.second.insert(name2);
- resno = i->second.first;
+ fprintf(stderr, "Can't open %s file for write!\n", outFile_s);
+ return 1;
}
- return resno;
- }
-}
-// Create silent 'nosound' instrument
-size_t InsertNoSoundIns()
-{
- // { 0x0F70700,0x0F70710, 0xFF,0xFF, 0x0,+0 },
- insdata tmp1 = { {0x00, 0x10, 0x07, 0x07, 0xF7, 0xF7, 0x00, 0x00, 0xFF, 0xFF, 0x00}, 0, 0 };
- struct ins tmp2 = { 0, 0, 0, 0.0, 0 };
- return InsertIns(tmp1, tmp1, tmp2, "nosound");
-}
-
-static void LoadBNK(const char* fn, unsigned bank, const char* prefix, bool is_fat, bool percussive)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp),
- std::fclose(fp);
-
- /*printf("%s:\n", fn);*/
- unsigned short version = *(short*)&data[0]; // major,minor (2 bytes)
- // "ADLIB-" (6 bytes)
- unsigned short entries_used = *(short*)&data[8]; // entries used
- unsigned short total_entries = *(short*)&data[10]; // total entries
- unsigned name_offset = *(unsigned*)&data[12];// name_offset
- unsigned data_offset = *(unsigned*)&data[16];// data_offset
- // 16..23: 8 byte sof filler
- /*printf("version=%u %u %u %u %u\n",
- version, entries_used,total_entries,name_offset,data_offset);*/
-
- for(unsigned n=0; n<entries_used; ++n)
+ fprintf(outFile, "\
+#include \"adldata.hh\"\n\
+\n\
+/* THIS OPL-3 FM INSTRUMENT DATA IS AUTOMATICALLY GENERATED\n\
+ * FROM A NUMBER OF SOURCES, MOSTLY PC GAMES.\n\
+ * PREPROCESSED, CONVERTED, AND POSTPROCESSED OFF-SCREEN.\n\
+ */\n\
+");
{
- const size_t offset1 = name_offset + n*12;
-
- unsigned short data_index = data[offset1+0] + data[offset1+1]*256;
- unsigned char usage_flag = data[offset1+2];
- std::string name;
- for(unsigned p=0; p<9; ++p)
- {
- if(data[offset1+3+p] == '\0') break;
- name += char(data[offset1+3+p]);
- }
-
- const size_t offset2 = data_offset + data_index * 30;
- const unsigned char mode = data[offset2+0];
- const unsigned char voice_num = data[offset2+1];
- const unsigned char* op1 = &data[offset2+2]; // 13 bytes
- const unsigned char* op2 = &data[offset2+15];
- const unsigned char waveform_mod = data[offset2+28];
- const unsigned char waveform_car = data[offset2+29];
-
- /*printf("%5d %3d %8s mode=%02X voice=%02X: ", data_index,usage_flag, name.c_str(),
- mode,voice_num);*/
-
- int gmno = is_fat
- ? ((n & 127) + percussive*128)
- : (n + percussive*128);
-
- if(is_fat && percussive)
+ IniProcessing ini;
+ if(!ini.open("banks.ini"))
{
- if(name[2] == 'O'
- || name[2] == 'S')
- {
- gmno = 128 + std::stoi(name.substr(3));
- }
+ fprintf(stderr, "Can't open banks.ini!\n");
+ return 1;
}
- char name2[512];
- if(is_fat)
- sprintf(name2, "%s%c%u", prefix, percussive?'P':'M', gmno&127);
- else
- sprintf(name2, "%s%u", prefix, n);
-
- insdata tmp;
- tmp.data[0] = (op1[ 9] << 7) // TREMOLO FLAG
- + (op1[10] << 6) // VIBRATO FLAG
- + (op1[ 5] << 5) // SUSTAIN FLAG
- + (op1[11] << 4) // SCALING FLAG
- + op1[ 1]; // FREQMUL
-
- tmp.data[1] = (op2[ 9] << 7)
- + (op2[10] << 6)
- + (op2[ 5] << 5)
- + (op2[11] << 4)
- + op2[ 1];
- tmp.data[2] = op1[3]*0x10 + op1[6]; // ATTACK, DECAY
- tmp.data[3] = op2[3]*0x10 + op2[6];
- tmp.data[4] = op1[4]*0x10 + op1[7]; // SUSTAIN, RELEASE
- tmp.data[5] = op2[4]*0x10 + op2[7];
- tmp.data[6] = waveform_mod;
- tmp.data[7] = waveform_car;
- tmp.data[8] = op1[0]*0x40 + op1[8]; // KSL , LEVEL
- tmp.data[9] = op2[0]*0x40 + op2[8]; // KSL , LEVEL
- tmp.data[10] = op1[2]*2 + op1[12]; // FEEDBACK, ADDITIVEFLAG
- tmp.finetune = 0;
- tmp.diff=false;
- // Note: op2[2] and op2[12] are unused and contain garbage.
- ins tmp2;
- tmp2.notenum = is_fat ? voice_num : (percussive ? usage_flag : 0);
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
-
- if(is_fat) tmp.data[10] ^= 1;
-
- size_t resno = InsertIns(tmp,tmp, tmp2, std::string(1,'\377')+name, name2);
+ uint32_t banks_count;
+ ini.beginGroup("General");
+ ini.read("banks", banks_count, 0);
+ ini.endGroup();
- if(!is_fat)
+ if(!banks_count)
{
- SetBank(bank, gmno, resno);
- }
- else
- {
- if(name[2] == 'O' || name[1] == 'M') SetBank(bank+0, gmno, resno);
- if(name[2] == 'S' || name[1] == 'M') SetBank(bank+1, gmno, resno);
+ fprintf(stderr, "Zero count of banks found in banks.ini!\n");
+ return 1;
}
- /*
- for(unsigned p=0; p<30; ++p)
+ for(uint32_t bank = 0; bank < banks_count; bank++)
{
- unsigned char value = data[offset2+p];
- if(value > maxvalues[p]) maxvalues[p] = value;
+ if(!ini.beginGroup(std::string("bank-") + std::to_string(bank)))
+ {
+ fprintf(stderr, "Failed to find bank %u!\n", bank);
+ return 1;
+ }
+ std::string bank_name;
+ std::string filepath;
+ std::string filepath_d;
+ std::string prefix;
+ std::string prefix_d;
+ std::string filter_m;
+ std::string filter_p;
+ std::string format;
+
+ ini.read("name", bank_name, "Untitled");
+ ini.read("format", format, "Unknown");
+ ini.read("file", filepath, "");
+ ini.read("file-p", filepath_d, "");
+ ini.read("prefix", prefix, "");
+ ini.read("prefix-p", prefix_d, "");
+ ini.read("filter-m", filter_m, "");
+ ini.read("filter-p", filter_p, "");
+
+ if(filepath.empty())
+ {
+ fprintf(stderr, "Failed to load bank %u, file is empty!\n", bank);
+ return 1;
+ }
- #define dot(maxval) if(value<=maxval) printf("."); else printf("?[%u]%X",p,value);
+ banknames.push_back(bank_name);
- {
- //if(p==6 || p==7 || p==19||p==20) value=15-value;
+ //printf("Loading %s...\n", filepath.c_str());
- if(p==4 || p==10 || p==17 || p==23)// || p==25)
- printf(" %2X", value);
+ if(format == "AIL")
+ {
+ if(!LoadMiles(filepath.c_str(), bank, prefix.c_str()))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
else
- printf(" %X", value);
- }
- nl:;
- //if(p == 12) printf("\n%*s", 22, "");
- //if(p == 25) printf("\n%*s", 22, "");
- }
- printf("\n");
- */
- }
-}
-
-static void LoadBNK2(const char* fn, unsigned bank, const char* prefix,
- const std::string& melo_filter,
- const std::string& perc_filter)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp),
- std::fclose(fp);
-
- unsigned short ins_entries = *(unsigned short*)&data[28+2+10];
- unsigned char* records = &data[48];
-
- for(unsigned n=0; n<ins_entries; ++n)
- {
- const size_t offset1 = n*28;
- int used = records[offset1 + 15];
- int attrib = *(int*)&records[offset1 + 16];
- int offset2 = *(int*)&records[offset1 + 20];
- if(used == 0) continue;
-
- std::string name;
- for(unsigned p=0; p<12; ++p)
- {
- if(records[offset1+3+p] == '\0') break;
- name += char(records[offset1+3+p]);
- }
-
- int gmno = 0;
- if(name.substr(0, melo_filter.size()) == melo_filter)
- gmno = std::stoi(name.substr(melo_filter.size()));
- else if(name.substr(0, perc_filter.size()) == perc_filter)
- gmno = std::stoi(name.substr(perc_filter.size())) + 128;
- else
- continue;
-
- const unsigned char* insdata = &data[offset2];
- const unsigned char* ops[4] = { insdata+0, insdata+6, insdata+12, insdata+18 };
- unsigned char C4xxxFFFC = insdata[24];
- unsigned char xxP24NNN = insdata[25];
- unsigned char TTTTTTTT = insdata[26];
- unsigned char xxxxxxxx = insdata[27];
-
- char name2[512];
- sprintf(name2, "%s%c%u", prefix, (gmno&128)?'P':'M', gmno&127);
-
- struct insdata tmp[2];
- for(unsigned a=0; a<2; ++a)
- {
- tmp[a].data[0] = ops[a*2+0][0];
- tmp[a].data[1] = ops[a*2+1][0];
- tmp[a].data[2] = ops[a*2+0][2];
- tmp[a].data[3] = ops[a*2+1][2];
- tmp[a].data[4] = ops[a*2+0][3];
- tmp[a].data[5] = ops[a*2+1][3];
- tmp[a].data[6] = ops[a*2+0][4] & 0x07;
- tmp[a].data[7] = ops[a*2+1][4] & 0x07;
- tmp[a].data[8] = ops[a*2+0][1];
- tmp[a].data[9] = ops[a*2+1][1];
- tmp[a].finetune = TTTTTTTT;
- tmp[a].diff=false;
- }
- tmp[0].data[10] = C4xxxFFFC & 0x0F;
- tmp[1].data[10] = (tmp[0].data[10] & 0x0E) | (C4xxxFFFC >> 7);
-
- ins tmp2;
- tmp2.notenum = (gmno & 128) ? 35 : 0;
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
-
- if(xxP24NNN & 8)
- {
- // dual-op
- size_t resno = InsertIns(tmp[0],tmp[1], tmp2, std::string(1,'\377')+name, name2);
- SetBank(bank, gmno, resno);
- }
- else
- {
- // single-op
- size_t resno = InsertIns(tmp[0],tmp[0], tmp2, std::string(1,'\377')+name, name2);
- SetBank(bank, gmno, resno);
- }
- }
-}
-
-struct Doom_OPL2instrument {
- unsigned char trem_vibr_1; /* OP 1: tremolo/vibrato/sustain/KSR/multi */
- unsigned char att_dec_1; /* OP 1: attack rate/decay rate */
- unsigned char sust_rel_1; /* OP 1: sustain level/release rate */
- unsigned char wave_1; /* OP 1: waveform select */
- unsigned char scale_1; /* OP 1: key scale level */
- unsigned char level_1; /* OP 1: output level */
- unsigned char feedback; /* feedback/AM-FM (both operators) */
- unsigned char trem_vibr_2; /* OP 2: tremolo/vibrato/sustain/KSR/multi */
- unsigned char att_dec_2; /* OP 2: attack rate/decay rate */
- unsigned char sust_rel_2; /* OP 2: sustain level/release rate */
- unsigned char wave_2; /* OP 2: waveform select */
- unsigned char scale_2; /* OP 2: key scale level */
- unsigned char level_2; /* OP 2: output level */
- unsigned char unused;
- short basenote; /* base note offset */
-} __attribute__ ((packed));
-
-struct Doom_opl_instr {
- unsigned short flags;
-#define FL_FIXED_PITCH 0x0001 // note has fixed pitch (drum note)
-#define FL_UNKNOWN 0x0002 // ??? (used in instrument #65 only)
-#define FL_DOUBLE_VOICE 0x0004 // use two voices instead of one
-
- unsigned char finetune;
- unsigned char note;
- struct Doom_OPL2instrument patchdata[2];
-} __attribute__ ((packed));
-
-
-static void LoadDoom(const char* fn, unsigned bank, const char* prefix)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp),
- std::fclose(fp);
-
- for(unsigned a=0; a<175; ++a)
- {
- const size_t offset1 = 0x18A4 + a*32;
- const size_t offset2 = 8 + a*36;
-
- std::string name;
- for(unsigned p=0; p<32; ++p)
- if(data[offset1]!='\0')
- name += char(data[offset1+p]);
-
- //printf("%3d %3d %3d %8s: ", a,b,c, name.c_str());
- int gmno = a<128 ? a : ((a|128)+35);
-
- char name2[512]; sprintf(name2, "%s%c%u", prefix, (gmno<128?'M':'P'), gmno&127);
-
- Doom_opl_instr& ins = *(Doom_opl_instr*) &data[offset2];
-
- insdata tmp[2];
- tmp[0].diff=false;
- tmp[1].diff=true;
- for(unsigned index=0; index<2; ++index)
- {
- const Doom_OPL2instrument& src = ins.patchdata[index];
- tmp[index].data[0] = src.trem_vibr_1;
- tmp[index].data[1] = src.trem_vibr_2;
- tmp[index].data[2] = src.att_dec_1;
- tmp[index].data[3] = src.att_dec_2;
- tmp[index].data[4] = src.sust_rel_1;
- tmp[index].data[5] = src.sust_rel_2;
- tmp[index].data[6] = src.wave_1;
- tmp[index].data[7] = src.wave_2;
- tmp[index].data[8] = src.scale_1 | src.level_1;
- tmp[index].data[9] = src.scale_2 | src.level_2;
- tmp[index].data[10] = src.feedback;
- tmp[index].finetune = src.basenote+12;
- }
- struct ins tmp2;
- tmp2.notenum = ins.note;
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
- while(tmp2.notenum && tmp2.notenum < 20)
- {
- tmp2.notenum += 12;
- tmp[0].finetune -= 12;
- tmp[1].finetune -= 12;
- }
-
- if(!(ins.flags&4))
- {
- size_t resno = InsertIns(tmp[0],tmp[0],tmp2, std::string(1,'\377')+name, name2);
- SetBank(bank, gmno, resno);
- }
- else // Double instrument
- {
- tmp2.pseudo4op = true;
- tmp2.fine_tune = ( ((double)ins.finetune-128.0)*15.625)/1000.0;
- if(ins.finetune==129)
- tmp2.fine_tune=0.000025;
- else if(ins.finetune==127)
- tmp2.fine_tune=-0.000025;
- //printf("/*DOOM FINE TUNE (flags %000X instrument is %d) IS %d -> %lf*/\n", ins.flags, a, ins.finetune, tmp2.fine_tune);
- size_t resno = InsertIns(tmp[0], tmp[1], tmp2, std::string(1,'\377')+name, name2);
- SetBank(bank, gmno, resno);
- }
-
- /*const Doom_OPL2instrument& A = ins.patchdata[0];
- const Doom_OPL2instrument& B = ins.patchdata[1];
- printf(
- "flags:%04X fine:%02X note:%02X\n"
- "{t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X f:%02X\n"
- " t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X ?:%02X base:%d}\n"
- "{t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X f:%02X\n"
- " t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X ?:%02X base:%d} ",
- ins.flags, ins.finetune, ins.note,
- A.trem_vibr_1, A.att_dec_1, A.sust_rel_1,
- A.wave_1, A.scale_1, A.level_1, A.feedback,
- A.trem_vibr_2, A.att_dec_2, A.sust_rel_2,
- A.wave_2, A.scale_2, A.level_2, A.unused, A.basenote,
- B.trem_vibr_1, B.att_dec_1, B.sust_rel_1,
- B.wave_1, B.scale_1, B.level_1, B.feedback,
- B.trem_vibr_2, B.att_dec_2, B.sust_rel_2,
- B.wave_2, B.scale_2, B.level_2, B.unused, B.basenote);
- printf(" %s VS %s\n", name.c_str(), MidiInsName[a]);
- printf("------------------------------------------------------------\n");*/
- }
-}
-static void LoadMiles(const char* fn, unsigned bank, const char* prefix)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp),
- std::fclose(fp);
-
- for(unsigned a=0; a<2000; ++a)
- {
- unsigned gm_patch = data[a*6+0];
- unsigned gm_bank = data[a*6+1];
- unsigned offset = *(unsigned*)&data[a*6+2];
-
- if(gm_patch == 0xFF)
- break;
-
- int gmno = gm_bank==0x7F ? gm_patch + 0x80 : gm_patch;
- int midi_index = gmno < 128 ? gmno
- : gmno < 128+35 ? -1
- : gmno < 128+88 ? gmno-35
- : -1;
- unsigned length = data[offset] + data[offset+1]*256;
- signed char notenum = ((signed char)data[offset+2]);
-
- /*printf("%02X %02X %08X ", gmnumber,gmnumber2, offset);
- for(unsigned b=0; b<length; ++b)
- {
- if(b > 3 && (b-3)%11 == 0) printf("\n ");
- printf("%02X ", data[offset+b]);
- }
- printf("\n");*/
-
- if(gm_bank != 0 && gm_bank != 0x7F)
- continue;
-
- char name2[512]; sprintf(name2, "%s%c%u", prefix,
- (gmno < 128 ? 'M':'P'), gmno & 127);
-
- insdata tmp[200];
-
- const unsigned inscount = (length-3)/11;
- for(unsigned i=0; i<inscount; ++i)
- {
- unsigned o = offset + 3 + i*11;
- tmp[i].finetune = (gmno < 128 && i == 0) ? notenum : 0;
- tmp[i].diff = false;
- tmp[i].data[0] = data[o+0]; // 20
- tmp[i].data[8] = data[o+1]; // 40 (vol)
- tmp[i].data[2] = data[o+2]; // 60
- tmp[i].data[4] = data[o+3]; // 80
- tmp[i].data[6] = data[o+4]; // E0
- tmp[i].data[1] = data[o+6]; // 23
- tmp[i].data[9] = data[o+7]; // 43 (vol)
- tmp[i].data[3] = data[o+8]; // 63
- tmp[i].data[5] = data[o+9]; // 83
- tmp[i].data[7] = data[o+10]; // E3
-
- unsigned fb_c = data[offset+3+5];
- tmp[i].data[10] = fb_c;
- if(i == 1)
+ if(format == "Bisqwit")
{
- tmp[0].data[10] = fb_c & 0x0F;
- tmp[1].data[10] = (fb_c & 0x0E) | (fb_c >> 7);
+ if(!LoadBisqwit(filepath.c_str(), bank, prefix.c_str()))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ else
+ if(format == "OP2")
+ {
+ if(!LoadDoom(filepath.c_str(), bank, prefix.c_str()))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ else
+ if(format == "TMB")
+ {
+ if(!LoadTMB(filepath.c_str(), bank, prefix.c_str()))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ else
+ if(format == "Junglevision")
+ {
+ if(!LoadJunglevision(filepath.c_str(), bank, prefix.c_str()))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ else
+ if(format == "AdLibGold")
+ {
+ if(!LoadBNK2(filepath.c_str(), bank, prefix.c_str(), filter_m, filter_p))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ else
+ if(format == "HMI")
+ {
+ if(!LoadBNK(filepath.c_str(), bank, prefix.c_str(), false, false))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ if(!filepath_d.empty())
+ {
+ if(!LoadBNK(filepath_d.c_str(),bank, prefix_d.c_str(), false, true))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ }
+ else
+ if(format == "IBK")
+ {
+ if(!LoadIBK(filepath.c_str(), bank, prefix.c_str(), false))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ if(!filepath_d.empty())
+ {
+ //printf("Loading %s... \n", filepath_d.c_str());
+ if(!LoadIBK(filepath_d.c_str(),bank, prefix_d.c_str(), true))
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str());
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Failed to load bank %u, file %s!\nUnknown format type %s\n",
+ bank,
+ filepath.c_str(),
+ format.c_str());
+ return 1;
}
- }
- if(inscount == 1)
- tmp[1] = tmp[0];
-
- if(inscount <= 2)
- {
- struct ins tmp2;
- tmp2.notenum = gmno < 128 ? 0 : notenum;
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
- std::string name;
- if(midi_index >= 0) name = std::string(1,'\377')+MidiInsName[midi_index];
- size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2);
- SetBank(bank, gmno, resno);
- }
- }
-}
-
-static void LoadIBK(const char* fn, unsigned bank, const char* prefix, bool percussive)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp),
- std::fclose(fp);
-
- unsigned offs1_base = 0x804, offs1_len = 9;
- unsigned offs2_base = 0x004, offs2_len = 16;
-
- for(unsigned a=0; a<128; ++a)
- {
- unsigned offset1 = offs1_base + a*offs1_len;
- unsigned offset2 = offs2_base + a*offs2_len;
-
- std::string name;
- for(unsigned p=0; p<9; ++p)
- if(data[offset1]!='\0')
- name += char(data[offset1+p]);
-
- int gmno = a + 128*percussive;
- int midi_index = gmno < 128 ? gmno
- : gmno < 128+35 ? -1
- : gmno < 128+88 ? gmno-35
- : -1;
- char name2[512]; sprintf(name2, "%s%c%u", prefix,
- (gmno<128?'M':'P'), gmno&127);
-
- insdata tmp;
- tmp.data[0] = data[offset2+0];
- tmp.data[1] = data[offset2+1];
- tmp.data[8] = data[offset2+2];
- tmp.data[9] = data[offset2+3];
- tmp.data[2] = data[offset2+4];
- tmp.data[3] = data[offset2+5];
- tmp.data[4] = data[offset2+6];
- tmp.data[5] = data[offset2+7];
- tmp.data[6] = data[offset2+8];
- tmp.data[7] = data[offset2+9];
- tmp.data[10] = data[offset2+10];
- // [+11] seems to be used also, what is it for?
- tmp.finetune = 0;
- tmp.diff=false;
- struct ins tmp2;
- tmp2.notenum = gmno < 128 ? 0 : 35;
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
-
- size_t resno = InsertIns(tmp,tmp, tmp2, std::string(1,'\377')+name, name2);
- SetBank(bank, gmno, resno);
- }
-}
-
-static void LoadJunglevision(const char* fn, unsigned bank, const char* prefix)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp);
- std::fclose(fp);
-
- unsigned ins_count = data[0x20] + (data[0x21] << 8);
- unsigned drum_count = data[0x22] + (data[0x23] << 8);
- unsigned first_ins = data[0x24] + (data[0x25] << 8);
- unsigned first_drum = data[0x26] + (data[0x27] << 8);
-
- unsigned total_ins = ins_count + drum_count;
-
- for ( unsigned a = 0; a < total_ins; ++a )
- {
- unsigned offset = 0x28 + a * 0x18;
- unsigned gmno = (a < ins_count) ? (a + first_ins) : (a + first_drum);
- int midi_index = gmno < 128 ? gmno
- : gmno < 128+35 ? -1
- : gmno < 128+88 ? gmno-35
- : -1;
-
- insdata tmp[2];
-
- tmp[0].data[0] = data[offset + 2];
- tmp[0].data[1] = data[offset + 8];
- tmp[0].data[2] = data[offset + 4];
- tmp[0].data[3] = data[offset + 10];
- tmp[0].data[4] = data[offset + 5];
- tmp[0].data[5] = data[offset + 11];
- tmp[0].data[6] = data[offset + 6];
- tmp[0].data[7] = data[offset + 12];
- tmp[0].data[8] = data[offset + 3];
- tmp[0].data[9] = data[offset + 9];
- tmp[0].data[10] = data[offset + 7] & 0x0F;//~0x30;
- tmp[0].finetune = 0;
- tmp[0].diff=false;
-
- tmp[1].data[0] = data[offset + 2 + 11];
- tmp[1].data[1] = data[offset + 8 + 11];
- tmp[1].data[2] = data[offset + 4 + 11];
- tmp[1].data[3] = data[offset + 10 + 11];
- tmp[1].data[4] = data[offset + 5 + 11];
- tmp[1].data[5] = data[offset + 11 + 11];
- tmp[1].data[6] = data[offset + 6 + 11];
- tmp[1].data[7] = data[offset + 12 + 11];
- tmp[1].data[8] = data[offset + 3 + 11];
- tmp[1].data[9] = data[offset + 9 + 11];
- tmp[1].data[10] = data[offset + 7 + 11] & 0x0F;//~0x30;
- tmp[1].finetune = 0;
- tmp[1].diff=false;
-
- struct ins tmp2;
- tmp2.notenum = data[offset + 1];
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
-
- while(tmp2.notenum && tmp2.notenum < 20)
- {
- tmp2.notenum += 12;
- tmp[0].finetune -= 12;
- tmp[1].finetune -= 12;
- }
-
- std::string name;
- if(midi_index >= 0) name = std::string(1,'\377')+MidiInsName[midi_index];
-
- char name2[512]; sprintf(name2, "%s%c%u", prefix,
- (gmno<128?'M':'P'), gmno&127);
-
- if(!data[offset])
- {
- size_t resno = InsertIns(tmp[0],tmp[0],tmp2, name, name2);
- SetBank(bank, gmno, resno);
- }
- else // Double instrument
- {
- size_t resno = InsertIns(tmp[0],tmp[1],tmp2, name, name2);
- SetBank(bank, gmno, resno);
- }
- }
-}
-
-static void LoadTMB(const char* fn, unsigned bank, const char* prefix)
-{
- FILE* fp = std::fopen(fn, "rb");
- std::fseek(fp, 0, SEEK_END);
- std::vector<unsigned char> data(std::ftell(fp));
- std::rewind(fp);
- std::fread(&data[0], 1, data.size(), fp);
- std::fclose(fp);
-
- for ( unsigned a = 0; a < 256; ++a )
- {
- unsigned offset = a * 0x0D;
- unsigned gmno = a;
- int midi_index = gmno < 128 ? gmno
- : gmno < 128+35 ? -1
- : gmno < 128+88 ? gmno-35
- : -1;
-
- insdata tmp;
-
- tmp.data[0] = data[offset + 0];
- tmp.data[1] = data[offset + 1];
- tmp.data[2] = data[offset + 4];
- tmp.data[3] = data[offset + 5];
- tmp.data[4] = data[offset + 6];
- tmp.data[5] = data[offset + 7];
- tmp.data[6] = data[offset + 8];
- tmp.data[7] = data[offset + 9];
- tmp.data[8] = data[offset + 2];
- tmp.data[9] = data[offset + 3];
- tmp.data[10] = data[offset + 10];
- tmp.finetune = 0; //data[offset + 12];
- tmp.diff=false;
-
- struct ins tmp2;
- tmp2.notenum = data[offset + 11];
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
-
- std::string name;
- if(midi_index >= 0) name = std::string(1,'\377')+MidiInsName[midi_index];
-
- char name2[512]; sprintf(name2, "%s%c%u", prefix,
- (gmno<128?'M':'P'), gmno&127);
-
- size_t resno = InsertIns(tmp,tmp,tmp2, name, name2);
- SetBank(bank, gmno, resno);
- }
-}
-
-static void LoadBisqwit(const char* fn, unsigned bank, const char* prefix)
-{
- FILE* fp = std::fopen(fn, "rb");
- for ( unsigned a = 0; a < 256; ++a )
- {
- unsigned offset = a * 25;
- unsigned gmno = a;
- int midi_index = gmno < 128 ? gmno
- : gmno < 128+35 ? -1
- : gmno < 128+88 ? gmno-35
- : -1;
-
- struct ins tmp2;
- tmp2.notenum = std::fgetc(fp);
- tmp2.pseudo4op = false;
- tmp2.fine_tune = 0.0;
-
- insdata tmp[2];
- for(int side=0; side<2; ++side)
- {
- tmp[side].finetune = std::fgetc(fp);
- tmp[side].diff=false;
- std::fread(tmp[side].data, 1, 11, fp);
- }
-
- std::string name;
- if(midi_index >= 0) name = std::string(1,'\377')+MidiInsName[midi_index];
-
- char name2[512]; sprintf(name2, "%s%c%u", prefix,
- (gmno<128?'M':'P'), gmno&127);
-
- size_t resno = InsertIns(tmp[0],tmp[1],tmp2, name, name2);
- SetBank(bank, gmno, resno);
- }
- std::fclose(fp);
-}
-
-#include "../nukedopl3.h"
-
-std::vector<int16_t> stereoSampleBuf;
-
-struct DurationInfo
-{
- long ms_sound_kon;
- long ms_sound_koff;
- bool nosound;
-};
-static DurationInfo MeasureDurations(const ins& in)
-{
- insdata id[2];
- bool found[2] = {false,false};
- for(std::map<insdata, std::pair<size_t, std::set<std::string> > >
- ::const_iterator
- j = insdatatab.begin();
- j != insdatatab.end();
- ++j)
- {
- 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; }
- }
- const unsigned rate = 22050;
- 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;
-
- _opl3_chip opl;
- 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
- };
- OPL3_Reset(&opl, rate);
- for(unsigned a=0; a<18; a+=2) OPL3_WriteReg(&opl, initdata[a], initdata[a+1]);
-
- const unsigned n_notes = in.insno1 == in.insno2 ? 1 : 2;
- unsigned x[2];
-
- if (n_notes == 2 && !in.pseudo4op)
- {
- OPL3_WriteReg(&opl, 0x105, 1);
- OPL3_WriteReg(&opl, 0x104, 1);
- }
-
- 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) OPL3_WriteReg(&opl, patchdata[a]+n*8, id[n].data[a]);
- OPL3_WriteReg(&opl, patchdata[10]+n*8, id[n].data[10] | 0x30);
- }
- for(unsigned n=0; n<n_notes; ++n)
- {
- double hertz = 172.00093 * std::exp(0.057762265 * (notenum + id[n].finetune));
- if(hertz > 131071)
- {
- fprintf(stderr, "Why does note %d + finetune %d produce hertz %g?\n",
- notenum, id[n].finetune, hertz);
- hertz = 131071;
- }
- x[n] = 0x2000;
- while(hertz >= 1023.5) { hertz /= 2.0; x[n] += 0x400; } // Calculate octave
- x[n] += (int)(hertz + 0.5);
-
- // Keyon the note
- OPL3_WriteReg(&opl, 0xA0+n*3, x[n]&0xFF);
- OPL3_WriteReg(&opl, 0xB0+n*3, x[n]>>8);
- }
-
- const unsigned max_on = 40;
- const unsigned max_off = 60;
-
- // For up to 40 seconds, measure mean amplitude.
- std::vector<double> amplitudecurve_on;
- double highest_sofar = 0;
- for(unsigned period=0; period<max_on*interval; ++period)
- {
- stereoSampleBuf.clear();
- stereoSampleBuf.resize(samples_per_interval * 2);
- OPL3_GenerateStream(&opl, stereoSampleBuf.data(), samples_per_interval);
-
- double mean = 0.0;
- for(unsigned long c=0; c<samples_per_interval; ++c)
- mean += stereoSampleBuf[c*2];
- mean /= samples_per_interval;
- double std_deviation = 0;
- for(unsigned long c=0; c<samples_per_interval; ++c)
- {
- double diff = (stereoSampleBuf[c*2]-mean);
- std_deviation += diff*diff;
- }
- std_deviation = std::sqrt(std_deviation / samples_per_interval);
- amplitudecurve_on.push_back(std_deviation);
- if(std_deviation > highest_sofar)
- highest_sofar = std_deviation;
-
- if(period > 6*interval && std_deviation < highest_sofar*0.2)
- break;
- }
-
- // Keyoff the note
- for(unsigned n=0; n<n_notes; ++n)
- OPL3_WriteReg(&opl, 0xB0+n, (x[n]>>8) & 0xDF);
- // Now, for up to 60 seconds, measure mean amplitude.
- std::vector<double> amplitudecurve_off;
- for(unsigned period=0; period<max_off*interval; ++period)
- {
- stereoSampleBuf.clear();
- stereoSampleBuf.resize(samples_per_interval * 2);
- OPL3_GenerateStream(&opl, stereoSampleBuf.data(), samples_per_interval);
- double mean = 0.0;
- for(unsigned long c=0; c<samples_per_interval; ++c)
- mean += stereoSampleBuf[c*2];
- mean /= samples_per_interval;
- double std_deviation = 0;
- for(unsigned long c=0; c<samples_per_interval; ++c)
- {
- double diff = (stereoSampleBuf[c*2]-mean);
- std_deviation += diff*diff;
+ ini.endGroup();
}
- std_deviation = std::sqrt(std_deviation / samples_per_interval);
- amplitudecurve_off.push_back(std_deviation);
- if(std_deviation < highest_sofar*0.2) break;
+ printf("Loaded %u banks!\n", banks_count);
+ fflush(stdout);
}
- /* 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)
+ #if 0
+ for(unsigned a = 0; a < 36 * 8; ++a)
{
- if(amplitudecurve_on[a] > peak_amplitude_value)
- {
- peak_amplitude_value = amplitudecurve_on[a];
- peak_amplitude_time = a;
- }
- }
- for(size_t a=peak_amplitude_time; a<amplitudecurve_on.size(); ++a)
- {
- if(amplitudecurve_on[a] <= peak_amplitude_value * 0.2)
- {
- quarter_amplitude_time = a;
- break;
- }
- }
- for(size_t a=0; a<amplitudecurve_off.size(); ++a)
- {
- if(amplitudecurve_off[a] <= peak_amplitude_value * 0.2)
- {
- keyoff_out_time = a;
- break;
- }
- }
-
- if(keyoff_out_time == 0 && amplitudecurve_on.back() < peak_amplitude_value*0.2)
- keyoff_out_time = quarter_amplitude_time;
+ if((1 << (a % 8)) > maxvalues[a / 8]) continue;
- if(peak_amplitude_time == 0)
- {
- printf(
- " // Amplitude begins at %6.1f,\n"
- " // fades to 20%% at %.1fs, keyoff fades to 20%% in %.1fs.\n",
- begin_amplitude,
- quarter_amplitude_time / double(interval),
- keyoff_out_time / double(interval));
- }
- else
- {
- printf(
- " // Amplitude begins at %6.1f, peaks %6.1f at %.1fs,\n"
- " // fades to 20%% at %.1fs, keyoff fades to 20%% in %.1fs.\n",
- begin_amplitude,
- peak_amplitude_value,
- peak_amplitude_time / double(interval),
- quarter_amplitude_time / double(interval),
- keyoff_out_time / double(interval));
- }
-
- DurationInfo result;
- result.ms_sound_kon = quarter_amplitude_time * 1000.0 / interval;
- result.ms_sound_koff = keyoff_out_time * 1000.0 / interval;
- result.nosound = (peak_amplitude_value < 0.5);
- return result;
-}
-
-int main()
-{
- printf("\
-#include \"adldata.hh\"\n\
-\n\
-/* THIS ADLIB FM INSTRUMENT DATA IS AUTOMATICALLY GENERATED\n\
- * FROM A NUMBER OF SOURCES, MOSTLY PC GAMES.\n\
- * PREPROCESSED, CONVERTED, AND POSTPROCESSED OFF-SCREEN.\n\
- */\n\
-");
- size_t nosound = InsertNoSoundIns();
-
- LoadMiles("fm_banks/opl_files/sc3.opl", 0, "G"); // Our "standard" bank! Same as file22.opl
-
- LoadBisqwit("fm_banks/op3_files/bisqwit.adlraw", 1, "Bisq");
-
- LoadBNK("fm_banks/bnk_files/melodic.bnk", 2, "HMIGM", false, false); // same as file156.bnk
- LoadBNK("fm_banks/bnk_files/drum.bnk", 2, "HMIGP", false, true);
- LoadBNK("fm_banks/bnk_files/intmelo.bnk", 3, "intM", false, false);
- LoadBNK("fm_banks/bnk_files/intdrum.bnk", 3, "intP", false, true);
- LoadBNK("fm_banks/bnk_files/hammelo.bnk", 4, "hamM", false, false);
- LoadBNK("fm_banks/bnk_files/hamdrum.bnk", 4, "hamP", false, true);
- LoadBNK("fm_banks/bnk_files/rickmelo.bnk",5, "rickM", false, false);
- LoadBNK("fm_banks/bnk_files/rickdrum.bnk",5, "rickP", false, true);
-
- LoadBNK("fm_banks/bnk_files/d2melo.bnk", 6, "b6M", false, false);
- LoadBNK("fm_banks/bnk_files/d2drum.bnk", 6, "b6P", false, true);
- LoadBNK("fm_banks/bnk_files/normmelo.bnk", 7, "b7M", false, false);
- LoadBNK("fm_banks/bnk_files/normdrum.bnk", 7, "b7P", false, true); // same as file122.bnk
- LoadBNK("fm_banks/bnk_files/ssmelo.bnk", 8, "b8M", false, false);
- LoadBNK("fm_banks/bnk_files/ssdrum.bnk", 8, "b8P", false, true);
-
- LoadTMB("fm_banks/bnk_files/themepark.tmb", 9, "b9MP");
- //LoadBNK("fm_banks/bnk_files/file131.bnk", 9, "b9M", false, false);
- //LoadBNK("fm_banks/bnk_files/file132.bnk", 9, "b9P", false, true);
- LoadBNK("fm_banks/bnk_files/file133.bnk", 10,"b10P", false, true);
- LoadBNK("fm_banks/bnk_files/file134.bnk", 10,"b10M", false, false);
- LoadBNK("fm_banks/bnk_files/file142.bnk", 11, "b11P", false, true);
- LoadBNK("fm_banks/bnk_files/file143.bnk", 11, "b11M", false, false);
- LoadBNK("fm_banks/bnk_files/file145.bnk", 12, "b12M", false, false);//file145 is MELODIC
- LoadBNK("fm_banks/bnk_files/file144.bnk", 12, "b12P", false, true);//file144 is DRUMS
- LoadBNK("fm_banks/bnk_files/file167.bnk", 13, "b13P", false, true);
- LoadBNK("fm_banks/bnk_files/file168.bnk", 13, "b13M", false, false);
-
- LoadDoom("fm_banks/doom2/genmidi.op2", 14, "dM");
- LoadDoom("fm_banks/doom2/genmidi.htc", 15, "hxM"); // same as genmidi.hxn
- LoadDoom("fm_banks/doom2/default.op2", 16, "mus");
-
- LoadMiles("fm_banks/opl_files/file17.opl", 17, "f17G");
- LoadMiles("fm_banks/opl_files/warcraft.ad", 18, "sG"); // same as file44, warcraft.opl
- LoadMiles("fm_banks/opl_files/file19.opl", 19, "f19G");
- LoadMiles("fm_banks/opl_files/file20.opl", 20, "f20G");
- LoadMiles("fm_banks/opl_files/file21.opl", 21, "f21G");
- LoadMiles("fm_banks/opl_files/nemesis.opl", 22, "nem");
- LoadMiles("fm_banks/opl_files/file23.opl", 23, "f23G");
- LoadMiles("fm_banks/opl_files/file24.opl", 24, "f24G");
- LoadMiles("fm_banks/opl_files/file25.opl", 25, "f25G");
- LoadMiles("fm_banks/opl_files/file26.opl", 26, "f26G");
- LoadMiles("fm_banks/opl_files/file27.opl", 27, "f27G");
- LoadMiles("fm_banks/opl_files/nhlpa.opl", 28, "nhl");
- LoadMiles("fm_banks/opl_files/file29.opl", 29, "f29G");
- LoadMiles("fm_banks/opl_files/file30.opl", 30, "f30G");
- LoadMiles("fm_banks/opl_files/file31.opl", 31, "f31G");
- LoadMiles("fm_banks/opl_files/file32.opl", 32, "f32G");
- LoadMiles("fm_banks/opl_files/file13.opl", 33, "f13G");
- LoadMiles("fm_banks/opl_files/file34.opl", 34, "f34G");
- LoadMiles("fm_banks/opl_files/file35.opl", 35, "f35G");
- LoadMiles("fm_banks/opl_files/file36.opl", 36, "f36G");
- LoadMiles("fm_banks/opl_files/file37.opl", 37, "f37G");
- LoadMiles("fm_banks/opl_files/simfarm.opl", 38, "qG");
- LoadMiles("fm_banks/opl_files/simfarm.ad", 39, "mG"); // same as file18.opl
- LoadMiles("fm_banks/opl_files/file12.opl", 40, "f12G");
- LoadMiles("fm_banks/opl_files/file41.opl", 41, "f41G");
- LoadMiles("fm_banks/opl_files/file42.opl", 42, "f42G");
- LoadMiles("fm_banks/opl_files/file47.opl", 43, "f47G");
- LoadMiles("fm_banks/opl_files/file48.opl", 44, "f48G");
- LoadMiles("fm_banks/opl_files/file49.opl", 45, "f49G");
- LoadMiles("fm_banks/opl_files/file50.opl", 46, "f50G");
- LoadMiles("fm_banks/opl_files/file53.opl", 47, "f53G");
- LoadBNK("fm_banks/bnk_files/file144.bnk", 47, "f53GD", false, true);//Attempt to append missing drums
- LoadMiles("fm_banks/opl_files/file54.opl", 48, "f54G");
-
- LoadMiles("fm_banks/opl_files/sample.ad", 49, "MG"); // same as file51.opl
- LoadMiles("fm_banks/opl_files/sample.opl", 50, "oG"); // same as file40.opl
- LoadMiles("fm_banks/opl_files/file15.opl", 51, "f15G");
- LoadMiles("fm_banks/opl_files/file16.opl", 52, "f16G");
-
- LoadBNK2("fm_banks/bnk_files/file159.bnk", 53, "b50", "gm","gps"); // fat-opl3
- LoadBNK2("fm_banks/bnk_files/file159.bnk", 54, "b51", "gm","gpo");
-
- LoadIBK("fm_banks/ibk_files/soccer-genmidi.ibk", 55, "b55M", false);
- LoadIBK("fm_banks/ibk_files/soccer-percs.ibk", 55, "b55P", true);
- LoadIBK("fm_banks/ibk_files/game.ibk", 56, "b56", false);
- LoadIBK("fm_banks/ibk_files/mt_fm.ibk", 57, "b57", false);
-
- LoadJunglevision("fm_banks/op3_files/fat2.op3", 58, "fat2");
- LoadJunglevision("fm_banks/op3_files/fat4.op3", 59, "fat4");
- LoadJunglevision("fm_banks/op3_files/jv_2op.op3", 60, "b60");
- LoadJunglevision("fm_banks/op3_files/wallace.op3", 61, "b61");
-
- LoadTMB("fm_banks/tmb_files/d3dtimbr.tmb", 62, "duke");
- LoadTMB("fm_banks/tmb_files/swtimbr.tmb", 63, "sw");
-
- LoadDoom("fm_banks/raptor/genmidi.op2", 64, "rapt");
-
- //LoadJunglevision("fm_banks/op3_files/fat2_modded.op3", 65, "b65M");
- LoadTMB("fm_banks/op3_files/gmopl_wohl_mod.tmb", 65, "b65");
-
- //LoadIBK("fm_banks/ibk_files/JOconnel.IBK", 66, "b66M", false);
- //LoadIBK("fm_banks/ibk_files/my-gmopldrums.IBK", 66, "b66P", true);
- LoadTMB("fm_banks/op3_files/gmoconel.tmb", 66, "b66");
-
- LoadTMB("fm_banks/tmb_files/default.tmb", 67, "3drm67");
- //LoadDoom("fm_banks/doom2/wolfinstein.op2", 67, "wolf"); //Small experiment!
-
- //LoadJunglevision("fm_banks/op3_files/2x2.op3", 68, "2x2byJAN");
- LoadMiles("fm_banks/op3_files/2x2.opl", 68, "2x2byJAN");
-
- LoadTMB("fm_banks/tmb_files/bloodtmb.tmb", 69, "apgblood");
- LoadTMB("fm_banks/tmb_files/lee.tmb", 70, "apglee");
- LoadTMB("fm_banks/tmb_files/nam.tmb", 71, "apgnam");
-
- LoadDoom("fm_banks/doom2/DMXOPL-by-sneakernets.op2", 72, "skeakernets");
-
- //LoadBNK("bnk_files/grassman1.bnk", 63, "b63", false);
- //LoadBNK("bnk_files/grassman2.bnk", 64, "b64", false);
-
- //LoadIBK("ibk_files/nitemare_3d.ibk", 65, "b65G", false); // Seems to be identical to wallace.op3 despite different format!
-
- static const char* const banknames[] =
- {// 0
- "AIL (Star Control 3, Albion, Empire 2, Sensible Soccer, Settlers 2, many others)",
- "Bisqwit (selection of 4op and 2op)",
- "HMI (Descent, Asterix)", //melodic,drum
- "HMI (Descent:: Int)", //intmelo,intdrum
- "HMI (Descent:: Ham)", //hammelo,hamdrum
- "HMI (Descent:: Rick)", //rickmelo,rickdrum
- "HMI (Descent 2)", //d2melo,d2drum
- "HMI (Normality)", //normmelo,normdrum
- "HMI (Shattered Steel)", //ssmelo,ssdrum
- "HMI (Theme Park)", // file131, file132
- // 10
- "HMI (3d Table Sports, Battle Arena Toshinden)", //file133, file134
- "HMI (Aces of the Deep)", //file142, file143
- "HMI (Earthsiege)", //file144, file145
- "HMI (Anvil of Dawn)", //file167,file168
- "DMX (Doom :: partially pseudo 4op)",
- "DMX (Hexen, Heretic :: partially pseudo 4op)",
- "DMX (MUS Play :: partially pseudo 4op)",
- "AIL (Discworld, Grandest Fleet, Pocahontas, Slob Zone 3d, Ultima 4, Zorro)", // file17
- "AIL (Warcraft 2)",
- "AIL (Syndicate)", // file19
- // 20
- "AIL (Guilty, Orion Conspiracy, Terra Nova Strike Force Centauri :: 4op)", // file20
- "AIL (Magic Carpet 2)", // file21
- "AIL (Nemesis)",
- "AIL (Jagged Alliance)", //file23
- "AIL (When Two Worlds War :: 4op, MISSING INSTRUMENTS)", //file24
- "AIL (Bards Tale Construction :: MISSING INSTRUMENTS)", //file25
- "AIL (Return to Zork)", //file26
- "AIL (Theme Hospital)", //file27
- "AIL (National Hockey League PA)",
- "AIL (Inherit The Earth)", //file29
- // 30
- "AIL (Inherit The Earth, file two)", //file30
- "AIL (Little Big Adventure :: 4op)", //file31
- "AIL (Wreckin Crew)", //file32
- "AIL (Death Gate)", // file13
- "AIL (FIFA International Soccer)", //file34
- "AIL (Starship Invasion)", //file35
- "AIL (Super Street Fighter 2 :: 4op)", //file36
- "AIL (Lords of the Realm :: MISSING INSTRUMENTS)", //file37
- "AIL (SimFarm, SimHealth :: 4op)",
- "AIL (SimFarm, Settlers, Serf City)",
- // 40
- "AIL (Caesar 2 :: partially 4op, MISSING INSTRUMENTS)", // file12
- "AIL (Syndicate Wars)", //file41
- "AIL (Bubble Bobble Feat. Rainbow Islands, Z)", //file42
- "AIL (Warcraft)", //file47
- "AIL (Terra Nova Strike Force Centuri :: partially 4op)", //file48
- "AIL (System Shock :: partially 4op)", //file49
- "AIL (Advanced Civilization)", //file50
- "AIL (Battle Chess 4000 :: partially 4op, melodic only)", //file53
- "AIL (Ultimate Soccer Manager :: partially 4op)", //file54
- "AIL (Air Bucks, Blue And The Gray, America Invades, Terminator 2029)", // sample.ad
- // 50
- "AIL (Ultima Underworld 2)", // sample.opl
- "AIL (Kasparov's Gambit)", // file15
- "AIL (High Seas Trader :: MISSING INSTRUMENTS)", // file16
- "AIL (Master of Magic, Master of Orion 2 :: 4op, std percussion)", //file159
- "AIL (Master of Magic, Master of Orion 2 :: 4op, orchestral percussion)", //file159
- "SB (Action Soccer)",
- "SB (3d Cyberpuck :: melodic only)",
- "SB (Simon the Sorcerer :: melodic only)",
- "OP3 (The Fat Man 2op set)",
- "OP3 (The Fat Man 4op set)",
- // 60
- "OP3 (JungleVision 2op set :: melodic only)",
- "OP3 (Wallace 2op set, Nitemare 3D :: melodic only)",
- "TMB (Duke Nukem 3D)",
- "TMB (Shadow Warrior)",
- "DMX (Raptor)",
- "OP3 (Modded GMOPL by Wohlstand)",
- "SB (Jammey O'Connel's bank)",
- "TMB (Default bank of Build Engine)",
- "OP3 (4op bank by James Alan Nguyen)",
- "TMB (Blood)",
- // 70
- "TMB (Lee)",
- "TMB (Nam)",
- "DMX (Bank by Sneakernets)"
- };
-
-#if 0
- for(unsigned a=0; a<36*8; ++a)
- {
- if( (1 << (a%8)) > maxvalues[a/8]) continue;
-
- const std::map<unsigned,unsigned>& data = Correlate[a];
+ const std::map<unsigned, unsigned> &data = Correlate[a];
if(data.empty()) continue;
- std::vector< std::pair<unsigned,unsigned> > correlations;
- for(std::map<unsigned,unsigned>::const_iterator
+ std::vector< std::pair<unsigned, unsigned> > correlations;
+ for(std::map<unsigned, unsigned>::const_iterator
i = data.begin();
i != data.end();
++i)
{
- correlations.push_back( std::make_pair( i->second,i->first ) );
+ correlations.push_back(std::make_pair(i->second, i->first));
}
std::sort(correlations.begin(), correlations.end());
- printf("Byte %2u bit %u=mask %02X:\n", a/8, a%8, 1<<(a%8));
- for(size_t c=0; c<correlations.size() && c < 10; ++c)
- {
- unsigned count = correlations[correlations.size()-1-c ].first;
- unsigned index = correlations[correlations.size()-1-c ].second;
- printf("\tAdldata index %u, bit %u=mask %02X (%u matches)\n",
- index/8, index%8, 1 << (index%8), count);
- }
- }
-#endif
-
- printf(
- /*
- "static const struct\n"
- "{\n"
- " unsigned modulator_E862, carrier_E862; // See below\n"
- " unsigned char modulator_40, carrier_40; // KSL/attenuation settings\n"
- " unsigned char feedconn; // Feedback/connection bits for the channel\n"
- " signed char finetune; // Finetune\n"
- "} adl[] =\n"*/
- "const adldata adl[%u] =\n"
- "{ // ,---------+-------- Wave select settings\n"
- " // | ,-------ч-+------ Sustain/release rates\n"
- " // | | ,-----ч-ч-+---- Attack/decay rates\n"
- " // | | | ,---ч-ч-ч-+-- AM/VIB/EG/KSR/Multiple bits\n"
- " // | | | | | | | |\n"
- " // | | | | | | | | ,----+-- KSL/attenuation settings\n"
- " // | | | | | | | | | | ,----- Feedback/connection bits\n"
- " // | | | | | | | | | | |\n", (unsigned)insdatatab.size());
- for(size_t b=insdatatab.size(), c=0; c<b; ++c)
- for(std::map<insdata,std::pair<size_t,std::set<std::string> > >
- ::const_iterator
- i = insdatatab.begin();
- i != insdatatab.end();
- ++i)
- {
- if(i->second.first != c) continue;
- printf(" { ");
-
- unsigned carrier_E862 =
- (i->first.data[6] << 24)
- + (i->first.data[4] << 16)
- + (i->first.data[2] << 8)
- + (i->first.data[0] << 0);
- unsigned modulator_E862 =
- (i->first.data[7] << 24)
- + (i->first.data[5] << 16)
- + (i->first.data[3] << 8)
- + (i->first.data[1] << 0);
- printf("0x%07X,0x%07X, 0x%02X,0x%02X, 0x%X, %+d, %s",
- carrier_E862,
- modulator_E862,
- i->first.data[8],
- i->first.data[9],
- i->first.data[10],
- i->first.finetune,
- i->first.diff?"true":"false");
-
- std::string names;
- for(std::set<std::string>::const_iterator
- j = i->second.second.begin();
- j != i->second.second.end();
- ++j)
+ fprintf(outFile, "Byte %2u bit %u=mask %02X:\n", a / 8, a % 8, 1 << (a % 8));
+ for(size_t c = 0; c < correlations.size() && c < 10; ++c)
+ {
+ unsigned count = correlations[correlations.size() - 1 - c ].first;
+ unsigned index = correlations[correlations.size() - 1 - c ].second;
+ fprintf(outFile, "\tAdldata index %u, bit %u=mask %02X (%u matches)\n",
+ index / 8, index % 8, 1 << (index % 8), count);
+ }
+ }
+ #endif
+
+ printf("Writing raw instrument data...\n");
+ fflush(stdout);
+ {
+ fprintf(outFile,
+ /*
+ "static const struct\n"
+ "{\n"
+ " unsigned modulator_E862, carrier_E862; // See below\n"
+ " unsigned char modulator_40, carrier_40; // KSL/attenuation settings\n"
+ " unsigned char feedconn; // Feedback/connection bits for the channel\n"
+ " signed char finetune; // Finetune\n"
+ "} adl[] =\n"*/
+ "const adldata adl[%u] =\n"
+ "{ // ,---------+-------- Wave select settings\n"
+ " // | ,-------ч-+------ Sustain/release rates\n"
+ " // | | ,-----ч-ч-+---- Attack/decay rates\n"
+ " // | | | ,---ч-ч-ч-+-- AM/VIB/EG/KSR/Multiple bits\n"
+ " // | | | | | | | |\n"
+ " // | | | | | | | | ,----+-- KSL/attenuation settings\n"
+ " // | | | | | | | | | | ,----- Feedback/connection bits\n"
+ " // | | | | | | | | | | | ,----- Fine tune\n\n"
+ " // | | | | | | | | | | | |\n"
+ " // | | | | | | | | | | | |\n", (unsigned)insdatatab.size());
+
+ for(size_t b = insdatatab.size(), c = 0; c < b; ++c)
+ {
+ for(std::map<insdata, std::pair<size_t, std::set<std::string> > >
+ ::const_iterator
+ i = insdatatab.begin();
+ i != insdatatab.end();
+ ++i)
{
- if(!names.empty()) names += "; ";
- if((*j)[0] == '\377')
- names += j->substr(1);
- else
- names += *j;
+ if(i->second.first != c) continue;
+ fprintf(outFile, " { ");
+
+ uint32_t carrier_E862 =
+ uint32_t(i->first.data[6] << 24)
+ + uint32_t(i->first.data[4] << 16)
+ + uint32_t(i->first.data[2] << 8)
+ + uint32_t(i->first.data[0] << 0);
+ uint32_t modulator_E862 =
+ uint32_t(i->first.data[7] << 24)
+ + uint32_t(i->first.data[5] << 16)
+ + uint32_t(i->first.data[3] << 8)
+ + uint32_t(i->first.data[1] << 0);
+
+ fprintf(outFile, "0x%07X,0x%07X, 0x%02X,0x%02X, 0x%X, %+d",
+ carrier_E862,
+ modulator_E862,
+ i->first.data[8],
+ i->first.data[9],
+ i->first.data[10],
+ i->first.finetune);
+
+ std::string names;
+ for(std::set<std::string>::const_iterator
+ j = i->second.second.begin();
+ j != i->second.second.end();
+ ++j)
+ {
+ if(!names.empty()) names += "; ";
+ if((*j)[0] == '\377')
+ names += j->substr(1);
+ else
+ names += *j;
+ }
+ fprintf(outFile, " }, // %u: %s\n", (unsigned)c, names.c_str());
}
- printf(" }, // %u: %s\n", (unsigned)c, names.c_str());
}
- printf("};\n");
- /*printf("static const struct\n"
+ fprintf(outFile, "};\n");
+ }
+
+ /*fprintf(outFile, "static const struct\n"
"{\n"
" unsigned short adlno1, adlno2;\n"
" unsigned char tone;\n"
@@ -1324,30 +315,79 @@ int main()
" long ms_sound_kon; // Number of milliseconds it produces sound;\n"
" long ms_sound_koff;\n"
"} adlins[] =\n");*/
- printf("const struct adlinsdata adlins[%u] =\n", (unsigned)instab.size());
- printf("{\n");
+
+ fprintf(outFile, "const struct adlinsdata adlins[%u] =\n", (unsigned)instab.size());
+ fprintf(outFile, "{\n");
+
+ MeasureThreaded measureCounter;
+ {
+ printf("Beginning to generate measures data...\n");
+ fflush(stdout);
+ measureCounter.LoadCache("fm_banks/adldata-cache.dat");
+ measureCounter.m_total = instab.size();
+ for(size_t b = instab.size(), c = 0; c < b; ++c)
+ {
+ for(std::map<ins, std::pair<size_t, std::set<std::string> > >::const_iterator i = instab.begin(); i != instab.end(); ++i)
+ {
+ if(i->second.first != c) continue;
+ measureCounter.run(i);
+ }
+ }
+ fflush(stdout);
+ measureCounter.waitAll();
+ measureCounter.SaveCache("fm_banks/adldata-cache.dat");
+ }
+
+ printf("Writing generated measure data...\n");
+ fflush(stdout);
+
std::vector<unsigned> adlins_flags;
- for(size_t b=instab.size(), c=0; c<b; ++c)
- for(std::map<ins,std::pair<size_t,std::set<std::string> > >
+
+ for(size_t b = instab.size(), c = 0; c < b; ++c)
+ for(std::map<ins, std::pair<size_t, std::set<std::string> > >
::const_iterator
i = instab.begin();
i != instab.end();
++i)
{
if(i->second.first != c) continue;
+ //DurationInfo info = MeasureDurations(i->first);
+ MeasureThreaded::DurationInfoCache::iterator indo_i = measureCounter.m_durationInfo.find(i->first);
+ DurationInfo info = indo_i->second;
+ {
+ if(info.peak_amplitude_time == 0)
+ {
+ fprintf(outFile,
+ " // Amplitude begins at %6.1f,\n"
+ " // fades to 20%% at %.1fs, keyoff fades to 20%% in %.1fs.\n",
+ info.begin_amplitude,
+ info.quarter_amplitude_time / double(info.interval),
+ info.keyoff_out_time / double(info.interval));
+ }
+ else
+ {
+ fprintf(outFile,
+ " // Amplitude begins at %6.1f, peaks %6.1f at %.1fs,\n"
+ " // fades to 20%% at %.1fs, keyoff fades to 20%% in %.1fs.\n",
+ info.begin_amplitude,
+ info.peak_amplitude_value,
+ info.peak_amplitude_time / double(info.interval),
+ info.quarter_amplitude_time / double(info.interval),
+ info.keyoff_out_time / double(info.interval));
+ }
+ }
- DurationInfo info = MeasureDurations(i->first);
unsigned flags = (i->first.pseudo4op ? 1 : 0) | (info.nosound ? 2 : 0);
- printf(" {");
- printf("%4d,%4d,%3d, %d, %6ld,%6ld,%lf",
- (unsigned) i->first.insno1,
- (unsigned) i->first.insno2,
- (int)(i->first.notenum),
- flags,
- info.ms_sound_kon,
- info.ms_sound_koff,
- i->first.fine_tune);
+ fprintf(outFile, " {");
+ fprintf(outFile, "%4d,%4d,%3d, %d, %6ld,%6ld,%lf",
+ (unsigned) i->first.insno1,
+ (unsigned) i->first.insno2,
+ (int)(i->first.notenum),
+ flags,
+ info.ms_sound_kon,
+ info.ms_sound_koff,
+ i->first.fine_tune);
std::string names;
for(std::set<std::string>::const_iterator
j = i->second.second.begin();
@@ -1360,23 +400,34 @@ int main()
else
names += *j;
}
- printf(" }, // %u: %s\n\n", (unsigned)c, names.c_str());
- fflush(stdout);
+ fprintf(outFile, " }, // %u: %s\n\n", (unsigned)c, names.c_str());
+ fflush(outFile);
adlins_flags.push_back(flags);
}
- printf("};\n\n");
+ fprintf(outFile, "};\n\n");
+
+
+ printf("Writing banks data...\n");
+ fflush(stdout);
+
+ //fprintf(outFile, "static const unsigned short banks[][256] =\n");
+ #ifdef HARD_BANKS
+ const unsigned bankcount = sizeof(banknames) / sizeof(*banknames);
+ #else
+ const size_t bankcount = banknames.size();
+ #endif
+
+ size_t nosound = InsertNoSoundIns();
- //printf("static const unsigned short banks[][256] =\n");
- const unsigned bankcount = sizeof(banknames)/sizeof(*banknames);
- std::map<unsigned, std::vector<unsigned> > bank_data;
- for(unsigned bank=0; bank<bankcount; ++bank)
+ std::map<size_t, std::vector<size_t> > bank_data;
+ for(size_t bank = 0; bank < bankcount; ++bank)
{
//bool redundant = true;
- std::vector<unsigned> data(256);
- for(unsigned p=0; p<256; ++p)
+ std::vector<size_t> data(256);
+ for(size_t p = 0; p < 256; ++p)
{
- unsigned v = progs[bank][p];
- if(v == 0 || (adlins_flags[v-1]&2))
+ size_t v = progs[bank][p];
+ if(v == 0 || (adlins_flags[v - 1] & 2))
v = nosound; // Blank.in
else
v -= 1;
@@ -1384,57 +435,62 @@ int main()
}
bank_data[bank] = data;
}
- std::set<unsigned> listed;
-
- printf(
- "\n\n//Returns total number of generated banks\n"
- "int maxAdlBanks()\n"
- "{"
- " return %u;\n"
- "}\n\n"
- "const char* const banknames[%u] =\n", bankcount, bankcount);
- printf("{\n");
- for(unsigned bank=0; bank<bankcount; ++bank)
- printf(" \"%s\",\n", banknames[bank]);
- printf("};\n");
-
- printf("const unsigned short banks[%u][256] =\n", bankcount);
- printf("{\n");
- for(unsigned bank=0; bank<bankcount; ++bank)
- {
- printf(" { // bank %u, %s\n", bank, banknames[bank]);
+ std::set<size_t> listed;
+
+ fprintf(outFile,
+ "\n\n//Returns total number of generated banks\n"
+ "int maxAdlBanks()\n"
+ "{"
+ " return %u;\n"
+ "}\n\n"
+ "const char* const banknames[%u] =\n", (unsigned int)bankcount, (unsigned int)bankcount);
+ fprintf(outFile, "{\n");
+ for(unsigned bank = 0; bank < bankcount; ++bank)
+ fprintf(outFile, " \"%s\",\n", banknames[bank].c_str());
+ fprintf(outFile, "};\n");
+
+ fprintf(outFile, "const unsigned short banks[%u][256] =\n", (unsigned int)bankcount);
+ fprintf(outFile, "{\n");
+ for(unsigned bank = 0; bank < bankcount; ++bank)
+ {
+ fprintf(outFile, " { // bank %u, %s\n", bank, banknames[bank].c_str());
bool redundant = true;
- for(unsigned p=0; p<256; ++p)
+ for(unsigned p = 0; p < 256; ++p)
{
- unsigned v = bank_data[bank][p];
+ size_t v = bank_data[bank][p];
if(listed.find(v) == listed.end())
{
listed.insert(v);
redundant = false;
}
- printf("%4d,", v);
- if(p%16 == 15) printf("\n");
+ fprintf(outFile, "%4d,", (unsigned int)v);
+ if(p % 16 == 15) fprintf(outFile, "\n");
}
- printf(" },\n");
+ fprintf(outFile, " },\n");
if(redundant)
{
- printf(" // Bank %u defines nothing new.\n", bank);
- for(unsigned refbank=0; refbank<bank; ++refbank)
+ fprintf(outFile, " // Bank %u defines nothing new.\n", bank);
+ for(unsigned refbank = 0; refbank < bank; ++refbank)
{
bool match = true;
- for(unsigned p=0; p<256; ++p)
+ for(unsigned p = 0; p < 256; ++p)
if(bank_data[bank][p] != nosound
- && bank_data[bank][p] != bank_data[refbank][p])
+ && bank_data[bank][p] != bank_data[refbank][p])
{
- match=false;
+ match = false;
break;
}
if(match)
- printf(" // Bank %u is just a subset of bank %u!\n",
- bank, refbank);
+ fprintf(outFile, " // Bank %u is just a subset of bank %u!\n",
+ bank, refbank);
}
}
}
- printf("};\n");
+ fprintf(outFile, "};\n");
+ fflush(outFile);
+ fclose(outFile);
+
+ printf("Generation of ADLMIDI data has been completed!\n");
+ fflush(stdout);
}