//#ifdef __MINGW32__ //typedef struct vswprintf {} swprintf; //#endif #include #include #include #include #include #include #include #include #include "midi_inst_list.h" std::map > 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); } }; static std::map > > insdatatab; static std::map > > instab; static std::map > progs; static void SetBank(unsigned bank, unsigned patch, size_t insno) { progs[bank][patch] = insno+1; } static size_t InsertIns( const insdata& id, const insdata& id2, ins& in, const std::string& name, const std::string& name2 = "") { if(true) { std::map > >::iterator i = insdatatab.lower_bound(id); size_t insno = ~0; if(i == insdatatab.end() || i->first != id) { std::pair > > 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(!name.empty()) i->second.second.insert(name); if(!name2.empty()) i->second.second.insert(name2); insno = i->second.first; } in.insno1 = insno; } if( id != id2 ) { std::map > >::iterator i = insdatatab.lower_bound(id2); size_t insno2 = ~0; if(i == insdatatab.end() || i->first != id2) { std::pair > > 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; { std::map > >::iterator i = instab.lower_bound(in); size_t resno = ~0; if(i == instab.end() || i->first != in) { std::pair > > 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 { if(!name.empty()) i->second.second.insert(name); if(!name2.empty()) i->second.second.insert(name2); resno = i->second.first; } 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 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 maxvalues[p]) maxvalues[p] = value; #define dot(maxval) if(value<=maxval) printf("."); else printf("?[%u]%X",p,value); { //if(p==6 || p==7 || p==19||p==20) value=15-value; if(p==4 || p==10 || p==17 || p==23)// || p==25) printf(" %2X", value); 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 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> 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 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 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 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> 7); } } 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 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 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 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 "../dbopl.h" std::vector sampleBuf; static void AddMonoAudio(unsigned long count, int* samples) { sampleBuf.insert(sampleBuf.end(), samples, samples+count); } static void AddStereoAudio(unsigned long count, int* samples) { for (unsigned long i = 0; i < count; i++) sampleBuf.insert(sampleBuf.end(), samples + i * 2, samples + i * 2 + 1); } 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 > > ::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; DBOPL::Handler 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 }; opl.Init(rate); for(unsigned a=0; a<18; a+=2) opl.WriteReg(initdata[a], initdata[a+1]); const unsigned n_notes = in.insno1 == in.insno2 ? 1 : 2; unsigned x[2]; if (n_notes == 2 && !in.pseudo4op) { opl.WriteReg(0x105, 1); opl.WriteReg(0x104, 1); } for(unsigned n=0; n 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 opl.WriteReg(0xA0+n*3, x[n]&0xFF); opl.WriteReg(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 amplitudecurve_on; double highest_sofar = 0; for(unsigned period=0; period 512) {opl.Generate(AddMonoAudio, AddStereoAudio, 512); n-=512;} if(n)opl.Generate(AddMonoAudio, AddStereoAudio, n); unsigned long count = sampleBuf.size(); double mean = 0.0; for(unsigned long c=0; c 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>8) & 0xDF); // Now, for up to 60 seconds, measure mean amplitude. std::vector amplitudecurve_off; for(unsigned period=0; period 512) {opl.Generate(AddMonoAudio, AddStereoAudio, 512); n-=512;} if(n)opl.Generate(AddMonoAudio, AddStereoAudio, n); unsigned long count = sampleBuf.size(); double mean = 0.0; for(unsigned long c=0; c peak_amplitude_value) { peak_amplitude_value = amplitudecurve_on[a]; peak_amplitude_time = a; } } for(size_t a=peak_amplitude_time; a maxvalues[a/8]) continue; const std::map& data = Correlate[a]; if(data.empty()) continue; std::vector< std::pair > correlations; for(std::map::const_iterator i = data.begin(); i != data.end(); ++i) { 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 > > ::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::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; } printf(" }, // %u: %s\n", (unsigned)c, names.c_str()); } printf("};\n"); /*printf("static const struct\n" "{\n" " unsigned short adlno1, adlno2;\n" " unsigned char tone;\n" " unsigned char flags;\n" " 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"); std::vector adlins_flags; for(size_t b=instab.size(), c=0; c > > ::const_iterator i = instab.begin(); i != instab.end(); ++i) { if(i->second.first != c) continue; 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); std::string names; for(std::set::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; } printf(" }, // %u: %s\n\n", (unsigned)c, names.c_str()); fflush(stdout); adlins_flags.push_back(flags); } printf("};\n\n"); //printf("static const unsigned short banks[][256] =\n"); const unsigned bankcount = sizeof(banknames)/sizeof(*banknames); std::map > bank_data; for(unsigned bank=0; bank data(256); for(unsigned p=0; p<256; ++p) { unsigned v = progs[bank][p]; if(v == 0 || (adlins_flags[v-1]&2)) v = nosound; // Blank.in else v -= 1; data[p] = v; } bank_data[bank] = data; } std::set 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