// DumpMidi.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include int PrintMidi = 0; int PrintSampleSizes = 0; int ExportNoteOff = 0; enum eNotes { nC1 = 24, nCs1, nD1, nDs1, nE1, nF1, nFs1, nG1, nGs1, nA1, nAs1, nB1, nC2, nCs2, nD2, nDs2, nE2, nF2, nFs2, nG2, nGs2, nA2, nAs2, nB2, nC3, nCs3, nD3, nDs3, nE3, nF3, nFs3, nG3, nGs3, nA3, nAs3, nB3, nC4, nCs4, nD4, nDs4, nE4, nF4, nFs4, nG4, nGs4, nA4, nAs4, nB4, nC5, nCs5, nD5, nDs5, nE5, nF5, nFs5, nG5, nGs5, nA5, nAs5, nB5, nC6, nCs6, nD6, nDs6, nE6, nF6, nFs6, nG6, nGs6, nA6, nAs6, nB6, nC7, nCs7, nD7, nDs7, nE7, nF7, nFs7, nG7, nGs7, nA7, nAs7, nB7, nC8, nCs8, nD8, nDs8, nE8, nF8, nFs8, nG8, nGs8, nA8, nAs8, nB8, nBf1=nAs1, nBf2=nAs2, nBf3=nAs3, nBf4=nAs4, nBf5=nAs5, nBf6=nAs6, nBf7=nAs7, nBf8=nAs8, nEf1=nDs1, nEf2=nDs2, nEf3=nDs3, nEf4=nDs4, nEf5=nDs5, nEf6=nDs6, nEf7=nDs7, nEf8=nDs8, nLo = 0, nHi = 127 }; enum eDSCmds { eDS_End = 0xF0, // End of track - stop playing eDS_Delay = 0xE0, // Delay for n loops [,n] eDS_Tempo = 0xC0, // Change tempo [hi,lo] eDS_On = 0x80, // Play this note [|channel,program,pitch] eDS_Off = 0x90, // Stop this note [|channel] eDS_Pan = 0xA0, // Set channel pan [|channel,pan] eDS_Vol = 0xB0 // Set channel vol [|channel,vol] }; #define NUM_MIDI_WAVS 146 //const char *cMidiPathIn = "Z:\\Rayman2\\DS\\Cpa\\Exe\\Main\\GameDn64\\World\\Sound\\"; const char *cMDXPathIn = "Z:\\Rayman2\\DS\\Cpa\\Exe\\Main\\GameDn64\\World\\Sound\\"; const char *cMidiPathIn = "C:\\Temp\\DSMusic\\Mid\\"; const char *cMidiPathOut = "C:\\Temp\\DSMusic\\Mid\\"; const char *cWavPath = "C:\\Temp\\DSMusic\\Wav\\"; const char *cBankFile = "C:\\Temp\\DSMidi0.tbl"; const char *cMidiBankFile = "C:\\Temp\\DSMidi0.sbk"; const char *cWavNames[NUM_MIDI_WAVS] = { "M_GPiano_C2.adpcm.swav", "M_GPiano_Bb2.adpcm.swav", "M_GPiano_F3.adpcm.swav", "M_GPiano_C4.adpcm.swav", "M_GPiano_G4.adpcm.swav", "M_GPiano_C5.adpcm.swav", "M_GPiano_G5.adpcm.swav", "M_GPiano_C6.adpcm.swav", "M_MPC2.adpcm.swav", "M_MPG2.adpcm.swav", "M_MPB3.adpcm.swav", "M_ElecPiano1_C5.adpcm.swav", "M_ElecPiano1_C6.adpcm.swav", "M_CYC4.adpcm.swav", "M_CYG4.adpcm.swav", "M_HHCD5.adpcm.swav", "M_HHDD5.adpcm.swav", "M_Harpsichord_A3.adpcm.swav", "M_Harpsichord_F4.adpcm.swav", "M_Harpsichord_C5.adpcm.swav", "M_Harpsichord_Gb5.adpcm.swav", "M_Harpsichord_C6.adpcm.swav", "M_Glock_C4.adpcm.swav", "M_Glock_Bb4.adpcm.swav", "M_Glock_F5.adpcm.swav", "M_Glock_C6.adpcm.swav", "M_Music_Box_C5.adpcm.swav", "M_CGAC1.adpcm.swav", "M_CGAD1.adpcm.swav", "M_CGAC2.adpcm.swav", "M_CGAA2.adpcm.swav", "M_CGAD3.adpcm.swav", "M_CGAF3.adpcm.swav", "M_CGAF4.adpcm.swav", "M_Marimba_C4.adpcm.swav", "M_Marimba_Bb4.adpcm.swav", "M_Marimba_F5.adpcm.swav", "M_Marimba_C6.adpcm.swav", "M_SHKDD4.adpcm.swav", "M_SHKG4.adpcm.swav", "M_SHKCD5.adpcm.swav", "M_Dulcimer_C5.adpcm.swav", "M_TBD3.adpcm.swav", "M_PercOrgan_C6.adpcm.swav", "M_SND1.adpcm.swav", "M_BDC2.adpcm.swav", "M_INPE2.adpcm.swav", "M_INPF3.adpcm.swav", "M_INPG3.adpcm.swav", "M_INPA3.adpcm.swav", "M_INPAD3.adpcm.swav", "M_INPGD4.adpcm.swav", "M_BCC1.adpcm.swav", "M_BCD1.adpcm.swav", "M_Accordian_G4.adpcm.swav", "M_Accordian_A5.adpcm.swav", "M_ABA1.adpcm.swav", "M_ABD2.adpcm.swav", "M_VIG2.adpcm.swav", "M_VICD3.adpcm.swav", "M_VIG3.adpcm.swav", "M_VICD4.adpcm.swav", "M_NylonStrGtr_B4.adpcm.swav", "M_NylonStrGtr_Gb5.adpcm.swav", "M_NylonStrGtr_Db6.adpcm.swav", "M_StlStrGtr_G4.adpcm.swav", "M_StlStrGtr_E5.adpcm.swav", "M_StlStrGtr_Db6.adpcm.swav", "M_PIG3.adpcm.swav", "M_PICD4.adpcm.swav", "M_PIAD4.adpcm.swav", "M_MAC3.adpcm.swav", "M_JazzGtr_G4.adpcm.swav", "M_JazzGtr_E5.adpcm.swav", "M_JazzGtr_Db6.adpcm.swav", "M_ETC3.adpcm.swav", "M_GtrHarmonic_C5.adpcm.swav", "M_SNF1.adpcm.swav", "M_BDA2.adpcm.swav", "M_FingerBass_G3.adpcm.swav", "M_PickBass_C3.adpcm.swav", "M_SlapBass2_C3.adpcm.swav", "M_SynBass3_G3.adpcm.swav", "M_Viola_A3.adpcm.swav", "M_Viola_F4.adpcm.swav", "M_Viola_C5.adpcm.swav", "M_Cello_Bb1.adpcm.swav", "M_Cello_F2.adpcm.swav", "M_Cello_C3.adpcm.swav", "M_Cello_A3.adpcm.swav", "M_Strings_Ab3.adpcm.swav", "M_Strings_E4.adpcm.swav", "M_Strings_Gb4.adpcm.swav", "M_Strings_D5.adpcm.swav", "M_Strings_C6.adpcm.swav", "M_Pizzicato_C5.adpcm.swav", "M_Harp_E5.adpcm.swav", "M_Timpani_C3.adpcm.swav", "M_ChoirOohs_G3.adpcm.swav", "M_ChoirOohs_C4.adpcm.swav", "M_ChoirOohs_G4.adpcm.swav", "M_ChoirOohs_C5.adpcm.swav", "M_ChoirOohs_G5.adpcm.swav", "M_SynthVoice_F4.adpcm.swav", "M_OrchHit_C4.adpcm.swav", "M_Trombone_F3.adpcm.swav", "M_Trombone_C4.adpcm.swav", "M_MuteTrmpt_C5.adpcm.swav", "M_MuteTrmpt_F5.adpcm.swav", "M_MuteTrmpt_Bb5.adpcm.swav", "M_FrHorn_F4.adpcm.swav", "M_BrassSect_E4.adpcm.swav", "M_BrassSect_C5.adpcm.swav", "M_AltoSax_Bb4.adpcm.swav", "M_EngHorn_C5.adpcm.swav", "M_Bassoon_G3.adpcm.swav", "M_Clarinet_C5.adpcm.swav", "M_Flute_C6.adpcm.swav", "M_Recorder_G5.adpcm.swav", "M_PanFlute2_C5.adpcm.swav", "M_Shakuhachi_C5.adpcm.swav", "M_Ocarina_C5.adpcm.swav", "M_Charang_C5.adpcm.swav", "M_BassLead_C5.adpcm.swav", "M_NewAgePad_C5.adpcm.swav", "M_WarmPad_C5.adpcm.swav", "M_PolySynth2_C5.adpcm.swav", "M_SpaceVoice_C5.adpcm.swav", "M_HaloPad_C5.adpcm.swav", "M_IceRain_C5.adpcm.swav", "M_Soundtrack_C5.adpcm.swav", "M_Crystal_C5.adpcm.swav", "M_Harmo.adpcm.swav", "M_EchoDrops_C5.adpcm.swav", "M_Flute01.adpcm.swav", "M_Sitar2_G4.adpcm.swav", "M_Banjo_G4.adpcm.swav", "M_Ois01.adpcm.swav", "M_Kalimba_C5.adpcm.swav", "M_Bagpipes_F4.adpcm.swav", "M_Violin_C5.adpcm.swav", "M_Shanai_C5.adpcm.swav", "M_Triangle.adpcm.swav", "M_StDrum_C4.adpcm.swav", "M_StDrum_C5.adpcm.swav", "M_Breath_G5.adpcm.swav" }; #define NUM_MIDI_FILES 292 const char *cMidiFiles[NUM_MIDI_FILES] = { "reset.mdx", "Null1.mid", "wat1aa.mid", "wat1aa_1.mdx", "wat1aa_2.mdx", "mond.mid", "ray.mid", "end1.mid", "end2.mid", "rod1a.mid", "ro1a_1.mdx", "ro1a_2.mdx", "Ro1a_3.mdx", "rod1b.mid", "Ro1b_3.mdx", "ro1b_2.mdx", "ro1b_1.mdx", "astra.mid", "Astra_6.mdx", "Astra_5.mdx", "Astra_7.mdx", "hel3a.mid", "hel3b.mid", "astrb.mid", "Astra_1.mdx", "wha2ac.mid", "bast1a.mid", "bast1b.mid", "bast3b.mid", "nav4a.mid", "princa.mid", "wat1ab.mid", "wat2.mid", "wha2aa.mid", "wha2a.mid", "minea.mid", "Ba1a_3.mdx", "bast3a.mid", "Ba3a_1.mdx", "Ba3a_4.mdx", "Ba3a_2.mdx", "bast2a.mid", "Ba2a_1.mdx", "Ba1a_1.mdx", "Cask1aa.mid", "Cask1ab.mid", "ca1a_1.mdx", "ca1a_2.mdx", "cask1b.mid", "Ca1b_1.mdx", "cask2a.mid", "ca2a_1.mdx", "ca2a_2.mdx", "ca2a_3.mdx", "Ca2a_4.mdx", "Cask2b.mid", "Ca1a_3.mdx", "Ca2a_5.mdx", "ly.mid", "batan.mid", "boata.mid", "Boata_2.mdx", "Boata_6.mdx", "Boatb_1.mdx", "boatb.mid", "Boatb_2.mdx", "Boatb_3.mdx", "Boata_5.mdx", "Ly1b_1.mdx", "ly1b.mid", "tietr.mid", "CH1BA.mid", "Ch1ba_2.mdx", "ch1bb_1.mdx", "Ch1bb.mid", "ch1bb_3.mdx", "ch1bb_2.mdx", "ch2b.mid", "ch2b_1.mdx", "ch1bb_5.mdx", "ch1bb_4.mdx", "ch1a.mid", "ch1a_1.mdx", "ch1a_2.mdx", "ch1a_3.mdx", "Ch3a_4.mdx", "Ch3a.mid", "Ch3a_9.mdx", "Ch3a_5.mdx", "Ch3a_6.mdx", "Ch3a_7.mdx", "Ch3a_8.mdx", "Ch3b.mid", "Ch3a_1.mdx", "Ch3a_2.mdx", "Ch3a_3.mdx", "earth.mid", "ch2a.mid", "earth2b.mid", "Earth2_1.mdx", "earth2a.mid", "earth3b.mid", "Earth3_1.mdx", "earth3a.mid", "Earth3_2.mdx", "gld_1.mdx", "globd.mid", "gld_5.mdx", "gld_4.mdx", "globa.mid", "gla_1.mdx", "gla_2.mdx", "gla_5.mdx", "gla_6.mdx", "Gla_7.mdx", "globc.mid", "glc_1.mdx", "glc_2.mdx", "glc_3.mdx", "glb_5.mdx", "globb.mid", "glb_4.mdx", "glb_3.mdx", "morb1b.mid", "hel12a.mid", "hel12a_1.mdx", "hel12a_2.mdx", "hel12c.mid", "hel12a_3.mdx", "hel12b.mid", "hel3b_5.mdx", "wat3.mid", "hel3b_1.mdx", "hel3b_3.mdx", "hel3b_4.mdx", "hel3b_6.mdx", "esca.mid", "mask.mid", "seatb.mid", "Seatb_2.mdx", "fo1c_6.mdx", "for1c.mid", "fo1c_7.mdx", "injail.mid", "poura.mid", "jail20.mid", "for2ab.mid", "fo2ab_3.mdx", "for2aa.mid", "fo2ab_1.mdx", "fo2ab_2.mdx", "fo2ab_4.mdx", "fo2ab_5.mdx", "for2b.mid", "fo2b_1.mdx", "fo2b_2.mdx", "fo2b_3.mdx", "for1a.mid", "fo1a_1.mdx", "fo1a_2.mdx", "fo1a_3.mdx", "for1bb.mid", "fo1bb_1.mdx", "fo1bb_2.mdx", "fo1bb_3.mdx", "fo1bb_4.mdx", "fo1bb_5.mdx", "for1ba.mid", "fo1c_1.mdx", "fo1c_2.mdx", "fo1c_3.mdx", "fo1c_4.mdx", "fo1c_5.mdx", "nav3b.mid", "nav3a.mid", "Ba3a_3.mdx", "ch1c.mid", "ch1c_1.mdx", "ly1b_4.mdx", "ly1b_5.mdx", "ly1c.mid", "ly1b_2.mdx", "ly1b_3.mdx", "Ly1b_6.mdx", "ly1a.mid", "Ly1a_1.mdx", "ly2b.mid", "ly2a_2.mdx", "ly2a.mid", "ly2a_1.mdx", "Ly2a_3.mdx", "mineb.mid", "mine.mdx", "mine2.mdx", "mine3.mdx", "mine4.mdx", "Morba.mid", "morba_1.mdx", "morba_3.mdx", "morbb_4.mdx", "Morbb.mid", "morbb_3.mdx", "morbb_1.mdx", "morbb_2.mdx", "morb1c.mid", "poura_3.mdx", "na3b_1.mdx", "Na3b_5.mdx", "na3b_2.mdx", "Na3b_6.mdx", "na3b_4.mdx", "pourb.mid", "poura_1.mdx", "plum2a_2.mdx", "plum2a.mid", "plum2a_1.mdx", "plum2a_3.mdx", "vul1b_2.mdx", "vul1b.mid", "vul1b_1.mdx", "vul1ab_1.mdx", "Plum2a_4.mdx", "plum3.mid", "Plum3_3.mdx", "Plum3_2.mdx", "Plum5a_1.mdx", "plum5a.mid", "Plum5a_2.mdx", "Plum5a_3.mdx", "plum4a_3.mdx", "plum4a.mid", "Plum4a_4.mdx", "plum4a_2.mdx", "Plum4a_7.mdx", "Plum4a_6.mdx", "plum4a_1.mdx", "polo.mid", "Astrb_R.mdx", "rhopa.mid", "rhopb.mid", "rhopc.mid", "rhopd.mid", "fin.mdx", "rod2a.mid", "rod2b.mid", "seatad.mid", "seatab_3.mdx", "seatab.mid", "seatac.mid", "seatab_2.mdx", "seatab_1.mdx", "Seatb_1.mdx", "seataa.mid", "Seatad_3.mdx", "Seatad_2.mdx", "Seatad_1.mdx", "seat23b.mid", "Seat23_1.mdx", "seat23a.mid", "Seat23_2.mdx", "inski.mid", "sk_1.mdx", "Skiba.mid", "Skibb.mid", "sk_2.mdx", "skia.mid", "skic.mid", "princb.mid", "MAINA.mid", "MAINB.mid", "princc.mid", "vul2b.mid", "vul1ab.mid", "vul1a.mid", "vul1aa_2.mdx", "vul1aa.mid", "vul1aa_3.mdx", "vul1aa_1.mdx", "vul2a.mid", "vul2a_1.mdx", "vul2a_2.mdx", "vul2a_3.mdx", "vul2a_4.mdx", "wat1b.mid", "wat1b_1.mdx", "wat1b_2.mdx", "wat1b_3.mdx", "wat1b_4.mdx", "Astra_8.mdx", "wat_1.mdx", "wat.mid", "null.mid" }; long lLargestOfAll = 0; long lWavLengths[NUM_MIDI_WAVS]; unsigned char bUsedWav[NUM_MIDI_WAVS]; long lMaxWavLength[16]; long lMaxWavTotal; typedef struct _tdstMidiHeader { unsigned uTotalSampleLen; // Memory needed to load in all samples for this track unsigned uTimer; // Initial tempo unsigned char uSamplesToLoad[(NUM_MIDI_WAVS + 3) & ~3]; // Samples to load (stop when sample num == 255, never loads ALL of them) } tdstMidiHeader; // Translation table - search by program & note no., resulting index is sample to play typedef struct _midi_trans { unsigned char uProgram; unsigned char uLoNote; unsigned char uHiNote; unsigned char uKeyNote; } MIDI_TRANS; unsigned char prog_trans[][2] = { { 13, 9 }, { 48, 44 }, { 49, 44 }, { 255, 255 } }; MIDI_TRANS trans_table[] = { { 1, nLo, nF1, nDs2 }, { 1, nFs1, nCs2, nDs3 }, { 1, nD2, nA2, nG3 }, { 1, nBf2, nEf3, nC4 }, { 1, nE3, nA3, nG4 }, { 1, nBf3, nEf4, nC5 }, { 1, nE4, nA4, nG5 }, { 1, nBf4, nHi, nDs6 }, { 3, nLo, nCs2, nC3 }, { 3, nF3, nE4, nG3 }, { 3, nG4, nHi, nB4 }, { 4, nLo, nFs4, nC5 }, { 4, nG4, nHi, nC6 }, { 5, nLo, nC5, nC5 }, { 5, nD5, nG5, nG5 }, { 5, nCs6, nD6, nCs6 }, { 5, nEf6, nHi, nDs6 }, { 6, nLo, nCs3, nA3 }, { 6, nD3, nGs3, nDs4 }, { 6, nA3, nEf4, nFs4 }, { 6, nE4, nA4, nDs5 }, { 6, nBf4, nHi, nFs5 }, { 9, nLo, nF3, nD4 }, { 9, nFs3, nCs4, nA4 }, { 9, nD4, nFs4, nCs5 }, { 9, nG4, nHi, nF5 }, { 10, nLo, nHi, nCs5 }, { 11, nLo, nC2, nC2 }, { 11, nD2, nG2, nD2 }, { 11, nA2, nF3, nC3 }, { 11, nG3, nB3, nA3 }, { 11, nC4, nE4, nD4 }, { 11, nF4, nC5, nF4 }, { 11, nD5, nHi, nF5 }, { 12, nLo, nF3, nC4 }, { 12, nFs3, nCs4, nAs4 }, { 12, nD4, nGs4, nF5 }, { 12, nA4, nHi, nC6 }, { 14, nLo, nEf5, nDs5 }, { 14, nE5, nG5, nG5 }, { 14, nG6, nHi, nCs6 }, { 15, nLo, nHi, nC5 }, { 16, nLo, nHi, nD4 }, { 17, nLo, nHi, nDs6 }, { 18, nLo, nF2, nD2 }, { 18, nG2, nHi, nC3 }, { 19, nLo, nG3, nE3 }, { 19, nA3, nF4, nF4 }, { 19, nG4, nGs4, nG4 }, { 19, nA4, nA4, nA4 }, { 19, nBf4, nG5, nAs4 }, { 19, nGs5, nHi, nG5 }, { 20, nLo, nC2, nC2 }, { 20, nD2, nHi, nD2 }, { 21, nLo, nF4, nG4 }, { 21, nFs4, nHi, nGs5 }, { 22, nLo, nGs2, nA2 }, { 22, nA2, nHi, nD3 }, { 23, nLo, nBf3, nG3 }, { 23, nB3, nD4, nCs4 }, { 23, nEf4, nA4, nG4 }, { 23, nBf4, nHi, nCs5 }, { 24, nLo, nD3, nF4 }, { 24, nEf3, nA3, nAs4 }, { 24, nBf3, nHi, nDs5 }, { 25, nLo, nB2, nG3 }, { 25, nC3, nGs3, nE4 }, { 25, nA3, nHi, nCs5 }, { 26, nLo, nGs4, nG4 }, { 26, nA4, nD5, nCs5 }, { 26, nEf5, nHi, nAs5 }, { 27, nLo, nHi, nC4 }, { 28, nLo, nB2, nG3 }, { 28, nC3, nGs3, nE4 }, { 28, nA3, nHi, nCs5 }, { 29, nLo, nHi, nC4 }, { 31, nLo, nHi, nFs4 }, { 32, nLo, nB2, nC2 }, { 32, nC3, nHi, nC3 }, { 33, nLo, nHi, nG2 }, { 34, nLo, nHi, nC2 }, { 37, nLo, nHi, nC2 }, { 39, nLo, nHi, nG2 }, { 41, nLo, nCs3, nB3 }, { 41, nD3, nGs3, nG4 }, { 41, nA3, nHi, nC5 }, { 43, nLo, nCs1, nAs1 }, { 43, nD1, nA1, nF2 }, { 43, nBf1, nE2, nC3 }, { 43, nF2, nHi, nA3 }, { 44, nLo, nB2, nGs3 }, { 44, nC3, nE3, nE4 }, { 44, nF3, nB3, nFs4 }, { 44, nC4, nG4, nD5 }, { 44, nGs4, nHi, nC6 }, { 45, nLo, nHi, nE5 }, { 46, nLo, nHi, nA5 }, { 47, nLo, nHi, nFs3 }, { 53, nLo, nA2, nG3 }, { 53, nBf2, nEf3, nC4 }, { 53, nE3, nA3, nG4 }, { 53, nBf3, nEf4, nC5 }, { 53, nE4, nHi, nG5 }, { 54, nLo, nHi, nCs5 }, { 55, nLo, nHi, nDs4 }, { 57, nLo, nG2, nF3 }, { 57, nGs2, nHi, nC4 }, { 59, nLo, nD4, nC5 }, { 59, nEf4, nG4, nF5 }, { 59, nGs4, nHi, nAs5 }, { 60, nLo, nHi, nF4 }, { 61, nLo, nG3, nE4 }, { 61, nGs3, nHi, nC5 }, { 65, nLo, nHi, nAs4 }, { 69, nLo, nHi, nC5 }, { 70, nLo, nHi, nG3 }, { 71, nLo, nHi, nC5 }, { 73, nLo, nHi, nDs6 }, { 74, nLo, nHi, nB5 }, { 75, nLo, nHi, nCs5 }, { 77, nLo, nHi, nF5 }, { 79, nLo, nHi, nFs5 }, { 84, nLo, nHi, nC5 }, { 87, nLo, nHi, nC5 }, { 88, nLo, nHi, nC5 }, { 89, nLo, nHi, nC5 }, { 90, nLo, nHi, nC5 }, { 91, nLo, nHi, nC5 }, { 94, nLo, nHi, nC5 }, { 96, nLo, nHi, nC5 }, { 97, nLo, nHi, nC5 }, { 98, nLo, nHi, nC5 }, { 100, nLo, nHi, nFs4 }, { 102, nLo, nHi, nC5 }, { 103, nLo, nHi, nFs4 }, { 104, nLo, nHi, nGs4 }, { 105, nLo, nHi, nB4 }, { 106, nLo, nHi, nFs4 }, { 108, nLo, nHi, nC5 }, { 109, nLo, nHi, nA4 }, { 110, nLo, nHi, nCs5 }, { 111, nLo, nHi, nC5 }, { 112, nLo, nHi, nFs5 }, { 114, nLo, nC5, nC4 }, { 114, nG5, nHi, nC5 }, { 121, nLo, nHi, nG5 }, { 255, 255, 255, 255 } }; typedef struct { char ID[4]; unsigned int uLength; } CHUNK_HEADER; template void Swap(ITEM *ptr) { if (sizeof(ITEM)==2) { unsigned char *p = (unsigned char *)ptr, v; v = p[0]; p[0] = p[1]; p[1] = v; } if (sizeof(ITEM)==4) { unsigned char *p = (unsigned char *)ptr, v; v = p[0]; p[0] = p[3]; p[3] = v; v = p[1]; p[1] = p[2]; p[2] = v; } } void GetNext(unsigned char **pBuffer, long *plFileSize, void *pOut, int iSize) { memcpy(pOut, *pBuffer, iSize); (*pBuffer) += iSize; (*plFileSize) -= iSize; } #define GETNEXT(x) GetNext(&pB, &lLen, &x, sizeof(x)) unsigned GetVarLen(unsigned char *&pB, long &lLen, unsigned char uStartWith = 0) { unsigned uValue = uStartWith; for (;;) { unsigned char uDeltaByte; GETNEXT(uDeltaByte); uValue = (uValue << 7) | (uDeltaByte & 0x7F); if ((uDeltaByte & 0x80) == 0) break; } return uValue; } void Decode(unsigned char *pBuffer, long lFileSize, const char *pOutputName) { unsigned char *pB = pBuffer; long lLen = lFileSize; CHUNK_HEADER h; GETNEXT(h); if ((h.ID[0] != 'M') || (h.ID[1] != 'T') || (h.ID[2] != 'h') || (h.ID[3] != 'd')) { printf("No midi header\n"); return; } Swap(&h.uLength); unsigned short uFormat; GETNEXT(uFormat); Swap(&uFormat); if (uFormat != 0) { printf("Not type 0\n"); return; } unsigned short uNumTracks; GETNEXT(uNumTracks); Swap(&uNumTracks); if (uNumTracks != 1) { printf("Not just 1 track\n"); return; } unsigned uPlayerTempo = 4167; // Default to approx 120 bpm unsigned uInitialTempo = uPlayerTempo; unsigned uDivision; int iHaveCmd = 0; unsigned char uTimeLo, uTimeHi; GETNEXT(uTimeHi); GETNEXT(uTimeLo); if (uTimeHi & 0x80) { unsigned char uFramesPerSec = (uTimeHi ^ 0xFF) + 1; unsigned char uSubFrameTime = uTimeLo; printf("Code the frames / subframes bit!\n"); } else { unsigned short uPPQN = (unsigned short)uTimeHi * 256 + uTimeLo; uDivision = uPPQN; uPlayerTempo = 500000 / uDivision; } // Done with the header for (;;) { GETNEXT(h); Swap(&h.uLength); if ((h.ID[0] == 'M') && (h.ID[1] == 'T') && (h.ID[2] == 'r') && (h.ID[3] == 'k')) break; pB += h.uLength; } // Now got the track unsigned uTime = 0; unsigned uDataLen = lLen - h.uLength; unsigned char uStatus = 0; bool bEndTrack = false; // Which programs are selected for the 16 channels (so can work out pitch change for note-on) unsigned char uPrograms[16]; memset(uPrograms, 0, sizeof(uPrograms)); unsigned char uProgramAdded[NUM_MIDI_WAVS]; memset(uProgramAdded, 0, sizeof(uProgramAdded)); unsigned char uProgramLoad[NUM_MIDI_WAVS]; memset(uProgramLoad, 255, sizeof(uProgramLoad)); unsigned uProgramIndex = 0; // Tracks which channels are on/off unsigned char uChannelOnOff[16][128]; memset(uChannelOnOff, 0, sizeof(uChannelOnOff)); unsigned char *pDSData = new unsigned char[256000]; unsigned char *pDS = pDSData; unsigned uTotalWavSize = 0; while ((lLen > uDataLen) && (!bEndTrack)) { unsigned uDelta = GetVarLen(pB, lLen); uTime += uDelta; if (uDelta != 0) { *pDS++ = eDS_Delay; *pDS++ = uDelta; } unsigned char uCmd; unsigned char uData1; GETNEXT(uData1); if (uData1 & 0x80) { uCmd = uData1; if (uCmd < 0xF0) uStatus = uCmd; else if (uCmd < 0xF8) uStatus = 0; GETNEXT(uData1); } else uCmd = uStatus; if (uCmd == 0xF0) { unsigned uEventLen = GetVarLen(pB, lLen, uData1); pB += uEventLen; lLen -= uEventLen; } else if (uCmd == 0xFF) { switch (uData1) { case 0x2F: { unsigned char uSkip; GETNEXT(uSkip); bEndTrack = true; } break; case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: { // Track names, comments, other stuff unsigned char uType = uData1; unsigned char uLen; GETNEXT(uLen); pB += uLen; lLen -= uLen; } break; case 0x51: { // Tempo unsigned char uLen; GETNEXT(uLen); if (uLen == 3) { unsigned char uByte; GETNEXT(uByte); unsigned uTempo = uByte; uTempo <<= 8; GETNEXT(uByte); uTempo |= uByte; uTempo <<= 8; GETNEXT(uByte); uTempo |= uByte; uPlayerTempo = uTempo / uDivision; if (uPlayerTempo > 65535) printf("Tempo is too big!\n"); if (iHaveCmd == 0) uInitialTempo = uPlayerTempo; // HI-LO ORDER!!! *pDS++ = eDS_Tempo; *pDS++ = (unsigned char)((uPlayerTempo >> 8) & 0xFF); *pDS++ = (unsigned char)(uPlayerTempo & 0xFF); } } break; case 0x54: { // SMPTE offset unsigned char uLen; GETNEXT(uLen); pB += uLen; lLen -= uLen; } break; case 0x58: { // Time signature unsigned char uLen; GETNEXT(uLen); pB += uLen; lLen -= uLen; } break; case 0x59: { // Key signature unsigned char uLen; GETNEXT(uLen); pB += uLen; lLen -= uLen; } break; case 0x7F: { // Any proprietary event unsigned ulLen = GetVarLen(pB, lLen); pB += ulLen; lLen -= ulLen; } break; default: printf("MISSED A CODE : %u\n", uData1); bEndTrack = true; break; } } else if ((uCmd & 0x80) == 0) { printf("BAD MIDI FILE\n"); return; } else { iHaveCmd = 1; unsigned char uType = uCmd >> 4; unsigned char uData = uCmd & 0x0F; switch (uType) { case 8: // Note off { unsigned char uChannel = uData; unsigned char uNote = uData1; unsigned char uVelocity; GETNEXT(uVelocity); if (uPrograms[uChannel] == 127) break; if (uChannelOnOff[uChannel][uNote] == 0) { // printf("Channel %u.%u already off!\n", uChannel, uNote); } else uChannelOnOff[uChannel][uNote]--; if (ExportNoteOff) *pDS++ = eDS_Off | uChannel; if (PrintMidi) printf("%04X %02X\tOFF\t%02X %02X %02X\n", uTime, uDelta, uChannel, uNote, uVelocity); } break; case 9: // Note on { unsigned char uChannel = uData; unsigned char uNote = uData1; unsigned char uVelocity; GETNEXT(uVelocity); if (uVelocity == 0) { if (uPrograms[uChannel] == 127) break; if (ExportNoteOff) *pDS++ = eDS_Off | uChannel; if (uChannelOnOff[uChannel][uNote] == 0) { // printf("Channel %u.%u already off!\n", uChannel, uNote); } else uChannelOnOff[uChannel][uNote]--; // Really a note off if (PrintMidi) printf("%04X %02X\tOFF\t%02X %02X %02X\n", uTime, uDelta, uChannel, uNote, uVelocity); } else { for (int i = 0 ; ; i++) { if (trans_table[i].uProgram == 255) { // printf("Didn't find the note-on %u\n", uPrograms[uChannel]); break; // bEndTrack = true; } if ((uPrograms[uChannel] == trans_table[i].uProgram) && (uNote >= trans_table[i].uLoNote) && (uNote <= trans_table[i].uHiNote)) { *pDS++ = eDS_On | uChannel; *pDS++ = (unsigned char)(i & 0xFF); *pDS++ = (unsigned char)(uNote - trans_table[i].uKeyNote); *pDS++ = (unsigned char)uVelocity; if (uChannelOnOff[uChannel][uNote] == 127) printf("Channel %u.%u already on!\n", uChannel, uNote); else uChannelOnOff[uChannel][uNote]++; if (lWavLengths[i & 0xFF] > lMaxWavLength[uChannel]) lMaxWavLength[uChannel] = lWavLengths[i & 0xFF]; bUsedWav[i & 0xFF] = 1; if (uProgramAdded[i & 0xFF] == 0) { uProgramAdded[i & 0xFF] = 1; uProgramLoad[uProgramIndex++] = i & 0xFF; uTotalWavSize += lWavLengths[i & 0xFF]; uTotalWavSize = (uTotalWavSize + 3) & ~3; } break; } } if (PrintMidi) printf("%04X %02X\tON\t%02X %02X %02X\n", uTime, uDelta, uChannel, uNote, uVelocity); } } break; case 10: // Aftertouch (key pressure) { unsigned char uChannel = uData; unsigned char uNote = uData1; unsigned char uPressure; GETNEXT(uPressure); } break; case 11: // Control change { unsigned char uChannel = uData; unsigned char uController = uData1; unsigned char uContValue; GETNEXT(uContValue); if (uController == 7) { // Change volume for uChannel to uContValue (0-127) *pDS++ = eDS_Vol | uChannel; *pDS++ = uContValue; } else if (uController == 10) { // Change pan for uChannel to uContValue (0-left, 64-mid, 127-right) *pDS++ = eDS_Pan | uChannel; *pDS++ = uContValue; } } break; case 12: // Program (patch) change { unsigned char uChannel = uData; unsigned char uProgram = uData1; for (int i = 0 ; prog_trans[i][0] != 255 ; i++) { if (prog_trans[i][0] == uProgram) { uProgram = prog_trans[i][1]; break; } } uPrograms[uChannel] = uProgram; if (PrintMidi) printf("%04X %02X\tPATCH\tChannel %u uses %u\n", uTime, uDelta, uChannel, uProgram); } break; case 13: // Channel pressure { unsigned char uChannel = uData; unsigned char uPressure = uData1; } break; case 14: // Pitch wheel { unsigned char uChannel = uData; unsigned char uD1 = uData1, uD2; GETNEXT(uD2); unsigned short uWheel = ((unsigned short)uD1) | (((unsigned short)uD2)<<7); } break; case 15: // Status continuation stuff break; } } } *pDS++ = eDS_End; if (pOutputName != NULL) { FILE *ff = fopen(pOutputName, "wb"); if (ff != NULL) { tdstMidiHeader header; header.uTotalSampleLen = uTotalWavSize; header.uTimer = uInitialTempo; memset(header.uSamplesToLoad, 255, sizeof(header.uSamplesToLoad)); memcpy(header.uSamplesToLoad, uProgramLoad, sizeof(uProgramLoad)); fwrite(&header, sizeof(header), 1, ff); fwrite(pDSData, pDS - pDSData, 1, ff); unsigned uLen = pDS - pDSData; while (uLen & 3) { fputc(0, ff); uLen++; } fclose(ff); } } delete[] pDSData; } void DecodeFile(const char *pFilename, const char *pOutputName) { int i; FILE *fp = fopen(pFilename, "rb"); if (fp == NULL) { printf("Unable to open %s\n", pFilename); return; } fseek(fp, 0, SEEK_END); long lFileSize = ftell(fp); fseek(fp, 0, SEEK_SET); unsigned char *pBuffer = new unsigned char[lFileSize]; fread(pBuffer, 1, lFileSize, fp); fclose(fp); for (i = 0 ; i < 16 ; i++) lMaxWavLength[i] = 0; memset(bUsedWav, 0, sizeof(bUsedWav)); Decode(pBuffer, lFileSize, pOutputName); delete[] pBuffer; long lTotal = 0; for (i = 0 ; i < 16 ; i++) { // if (PrintSampleSizes) // printf("Channel %2d requires %6ld\n", i, lMaxWavLength[i]); lTotal += lMaxWavLength[i]; } if (PrintSampleSizes) printf("Total for %s is %ld\n", pFilename, lTotal); if (lTotal > lMaxWavTotal) lMaxWavTotal = lTotal; lTotal = 0; for (i = 0 ; i < NUM_MIDI_WAVS ; i++) if (bUsedWav[i]) lTotal += lWavLengths[i]; printf("Total wav space to load 'em all is %ld\n", lTotal); if (lTotal > lLargestOfAll) lLargestOfAll = lTotal; } long GetFileLength(const char *pName) { FILE *fp = fopen(pName, "rb"); if (fp == NULL) return 0; fseek(fp, 0, SEEK_END); long lLen = ftell(fp); fclose(fp); return lLen; } long GetFileLength(FILE *fp) { long lCurrent = ftell(fp); fseek(fp, 0, SEEK_END); long lLen = ftell(fp); fseek(fp, lCurrent, SEEK_SET); return lLen; } void AppendFile(FILE *fp, const char *pName) { FILE *fAdd = fopen(pName, "rb"); if (fAdd == NULL) return; fseek(fAdd, 0, SEEK_END); long lLen = ftell(fAdd); fseek(fAdd, 0, SEEK_SET); char *pTempBuffer = new char[lLen]; fread(pTempBuffer, lLen, 1, fAdd); fclose(fAdd); fwrite(pTempBuffer, lLen, 1, fp); delete[] pTempBuffer; } void BuildWavBank() { FILE *fBank = fopen(cBankFile, "wb"); if (fBank == NULL) { printf("Unable to create %s\n", cBankFile); return; } unsigned uNumWavs = NUM_MIDI_WAVS; fwrite(&uNumWavs, sizeof(uNumWavs), 1, fBank); unsigned uOffset = ftell(fBank) + uNumWavs * 2 * sizeof(unsigned); unsigned u; for (u = 0 ; u < uNumWavs ; u++) { char strWav[_MAX_PATH]; strcpy(strWav, cWavPath); strcat(strWav, cWavNames[u]); unsigned uLen = (unsigned)GetFileLength(strWav); if (uLen == 0) { printf("Unable to open %s\n", strWav); unsigned uNull = 0; fwrite(&uNull, sizeof(uNull), 1, fBank); fwrite(&uNull, sizeof(uNull), 1, fBank); } else { fwrite(&uOffset, sizeof(uOffset), 1, fBank); fwrite(&uLen, sizeof(uLen), 1, fBank); uOffset += uLen; } } for (u = 0 ; u < uNumWavs ; u++) { char strWav[_MAX_PATH]; strcpy(strWav, cWavPath); strcat(strWav, cWavNames[u]); AppendFile(fBank, strWav); } fclose(fBank); } void BuildMidiBank() { FILE *fBank = fopen(cMidiBankFile, "wb"); if (fBank == NULL) { printf("Unable to create %s\n", cMidiBankFile); return; } unsigned uNumFiles = NUM_MIDI_FILES; fwrite(&uNumFiles, sizeof(uNumFiles), 1, fBank); unsigned uOffset = ftell(fBank) + uNumFiles* 2 * sizeof(unsigned); unsigned u; for (u = 0 ; u < uNumFiles ; u++) { const char *pPtr = strrchr(cMidiFiles[u], '.'); if (pPtr == NULL) { printf("BAD FILE NAME : %s\n", cMidiFiles[u]); unsigned uNull = 0; fwrite(&uNull, sizeof(uNull), 1, fBank); fwrite(&uNull, sizeof(uNull), 1, fBank); } else { if (stricmp(pPtr, ".mdx") == 0) { char strMidi[_MAX_PATH]; strcpy(strMidi, cMDXPathIn); strcat(strMidi, cMidiFiles[u]); unsigned uLen = (unsigned)GetFileLength(strMidi); fwrite(&uOffset, sizeof(uOffset), 1, fBank); fwrite(&uLen, sizeof(uLen), 1, fBank); uOffset += uLen; } else if (stricmp(pPtr, ".mid") == 0) { char strMidi[_MAX_PATH]; strcpy(strMidi, cMidiPathOut); strcat(strMidi, cMidiFiles[u]); char *pPtr = strrchr(strMidi, '.'); strcpy(pPtr, ".dsm"); unsigned uLen = (unsigned)GetFileLength(strMidi); fwrite(&uOffset, sizeof(uOffset), 1, fBank); fwrite(&uLen, sizeof(uLen), 1, fBank); uOffset += uLen; } else { printf("BAD FILE NAME : %s\n", cMidiFiles[u]); unsigned uNull = 0; fwrite(&uNull, sizeof(uNull), 1, fBank); fwrite(&uNull, sizeof(uNull), 1, fBank); } } } for (u = 0 ; u < uNumFiles ; u++) { const char *pPtr = strrchr(cMidiFiles[u], '.'); if (pPtr == NULL) { printf("BAD FILE NAME : %s\n", cMidiFiles[u]); } else { if (stricmp(pPtr, ".mdx") == 0) { char strMidi[_MAX_PATH]; strcpy(strMidi, cMDXPathIn); strcat(strMidi, cMidiFiles[u]); AppendFile(fBank, strMidi); } else if (stricmp(pPtr, ".mid") == 0) { char strMidi[_MAX_PATH]; strcpy(strMidi, cMidiPathOut); strcat(strMidi, cMidiFiles[u]); char *pPtr = strrchr(strMidi, '.'); strcpy(pPtr, ".dsm"); AppendFile(fBank, strMidi); } else { printf("BAD FILE NAME : %s\n", cMidiFiles[u]); } } } fclose(fBank); } int _tmain(int argc, _TCHAR* argv[]) { int i; for (i = 0 ; i < NUM_MIDI_WAVS ; i++) { TCHAR wav_file[_MAX_PATH]; strcpy(wav_file, cWavPath); strcat(wav_file, cWavNames[i]); FILE *fm = fopen(wav_file, "rb"); if (fm != NULL) { fseek(fm, 0, SEEK_END); lWavLengths[i] = ftell(fm); fclose(fm); } else lWavLengths[i] = 0; } lMaxWavTotal = 0; if (argc == 2) { DecodeFile(argv[1], "C:\\TEMP\\DSMIDIFILE.BIN"); } else if (argc == 1) { for (i = 0 ; i < NUM_MIDI_FILES ; i++) { char *pPtr = strrchr(cMidiFiles[i], '.'); if ((pPtr != NULL) && (stricmp(pPtr, ".mid") == 0)) { char cFile[_MAX_PATH]; strcpy(cFile, cMidiPathIn); strcat(cFile, cMidiFiles[i]); char cDSFile[_MAX_PATH]; strcpy(cDSFile, cMidiPathOut); strcat(cDSFile, cMidiFiles[i]); pPtr = strrchr(cDSFile, '.'); strcpy(pPtr, ".dsm"); DecodeFile(cFile, cDSFile); } } } else { return 0; } printf("Max required = %ld\n", lMaxWavTotal); printf("Total required = %ld\n", lLargestOfAll); BuildWavBank(); BuildMidiBank(); return 0; }