//#ifdef __MINGW32__ //typedef struct vswprintf {} swprintf; //#endif #include #include #include #include #include #include #include #include std::map > Correlate; unsigned maxvalues[30] = { 0 }; static const char *const MidiInsName[] = { "AcouGrandPiano", "BrightAcouGrand", "ElecGrandPiano", "Honky-tonkPiano", "Rhodes Piano", "Chorused Piano", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel", "Music box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer", "Hammond Organ", "Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion", "Harmonica", "Tango Accordion", "Acoustic Guitar1", "Acoustic Guitar2", "Electric Guitar1", "Electric Guitar2", "Electric Guitar3", "Overdrive Guitar", "Distorton Guitar", "Guitar Harmonics", "Acoustic Bass", "Electric Bass 1", "Electric Bass 2", "Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", "Violin", "Viola", "Cello", "Contrabass", "Tremulo Strings", "Pizzicato String", "Orchestral Harp", "Timpany", "String Ensemble1", "String Ensemble2", "Synth Strings 1", "SynthStrings 2", "Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", "Trumpet", "Trombone", "Tuba", "Muted Trumpet", "French Horn", "Brass Section", "Synth Brass 1", "Synth Brass 2", "Soprano Sax", "Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet", "Piccolo", "Flute", "Recorder", "Pan Flute", "Bottle Blow", "Shakuhachi", "Whistle", "Ocarina", "Lead 1 squareea", "Lead 2 sawtooth", "Lead 3 calliope", "Lead 4 chiff", "Lead 5 charang", "Lead 6 voice", "Lead 7 fifths", "Lead 8 brass", "Pad 1 new age", "Pad 2 warm", "Pad 3 polysynth", "Pad 4 choir", "Pad 5 bowedpad", "Pad 6 metallic", "Pad 7 halo", "Pad 8 sweep", "FX 1 rain", "FX 2 soundtrack", "FX 3 crystal", "FX 4 atmosphere", "FX 5 brightness", "FX 6 goblins", "FX 7 echoes", "FX 8 sci-fi", "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bagpipe", "Fiddle", "Shanai", "Tinkle Bell", "Agogo Bells", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal", "Guitar FretNoise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone", "Helicopter", "Applause/Noise", "Gunshot", // 27..34: High Q; Slap; Scratch Push; Scratch Pull; Sticks; // Square Click; Metronome Click; Metronome Bell "Ac Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare", "Hand Clap", "Electric Snare", "Low Floor Tom", "Closed High Hat", "High Floor Tom", "Pedal High Hat", "Low Tom", "Open High Hat", "Low-Mid Tom", "High-Mid Tom", "Crash Cymbal 1", "High Tom", "Ride Cymbal 1", "Chinese Cymbal", "Ride Bell", "Tambourine", "Splash Cymbal", "Cow Bell", "Crash Cymbal 2", "Vibraslap", "Ride Cymbal 2", "High Bongo", "Low Bongo", "Mute High Conga", "Open High Conga", "Low Conga", "High Timbale", "Low Timbale", "High Agogo", "Low Agogo", "Cabasa", "Maracas", "Short Whistle", "Long Whistle", "Short Guiro", "Long Guiro", "Claves", "High Wood Block", "Low Wood Block", "Mute Cuica", "Open Cuica", "Mute Triangle", "Open Triangle", "Shaker","Jingle Bell","Bell Tree","Castanets","Mute Surdu","Open Surdu",""}; struct insdata { unsigned char data[11]; signed char finetune; bool operator==(const insdata& b) const { return std::memcmp(data, b.data, 11) == 0 && finetune == b.finetune; } 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; return 0; } bool operator!=(const insdata& b) const { return !operator==(b); } }; struct ins { size_t insno1, insno2; unsigned char notenum; bool pseudo4op; 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 }; struct ins tmp2 = { 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; 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]; 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; 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; 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 gmnumber = data[a*6+0]; unsigned gmnumber2 = data[a*6+1]; unsigned offset = *(unsigned*)&data[a*6+2]; if(gmnumber == 0xFF) break; int gmno = gmnumber2==0x7F ? gmnumber+0x80 : gmnumber; 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 = 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(gmnumber2 != 0 && gmnumber2 != 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 : data[offset+3]; tmp2.pseudo4op = false; 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; struct ins tmp2; tmp2.notenum = gmno < 128 ? 0 : 35; tmp2.pseudo4op = false; 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] & ~0x30; tmp[0].finetune = 0; 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] & ~0x30; tmp[1].finetune = 0; struct ins tmp2; tmp2.notenum = data[offset + 1]; tmp2.pseudo4op = false; 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]; struct ins tmp2; tmp2.notenum = data[offset + 11]; tmp2.pseudo4op = false; 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; insdata tmp[2]; for(int side=0; side<2; ++side) { tmp[side].finetune = std::fgetc(fp); 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", 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::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", (unsigned) i->first.insno1, (unsigned) i->first.insno2, (int)(i->first.notenum), flags, info.ms_sound_kon, info.ms_sound_koff); 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("const char* const banknames[%u] =\n", bankcount); printf("{\n"); for(unsigned bank=0; bank