cleaner.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. #include "main.h"
  2. #pragma warning(disable:4200)
  3. extern BYTE ff7loopstart[12];
  4. extern BYTE ff7loopend[10];
  5. extern cfg_int cfg_hack_xg_drums, cfg_hack_dls_instruments, cfg_hack_dls_drums, cfg_ff7loopz;
  6. typedef union
  7. {
  8. BYTE b[4];
  9. DWORD dw;
  10. } b_dw;
  11. typedef struct
  12. {
  13. DWORD pos, tm, sz;
  14. BYTE le;
  15. BYTE data[];
  16. }
  17. TRACK;
  18. DWORD _fastcall rev32(DWORD);
  19. //WORD _fastcall rev16(WORD);
  20. int test_drum_kit(DWORD no, IDirectMusicCollection* dls);
  21. void do_dls_check(DWORD * i, IDirectMusicCollection * dls);
  22. class CCleaner
  23. {
  24. public:
  25. INSTRUMENT_DESC* instr, **instr_ptr;
  26. BYTE ctab[16][128];
  27. // UINT dm_vol;
  28. grow_buf outbuf;
  29. UINT ntrax, ntrax1;
  30. UINT maxvol;
  31. TRACK** in_trax;
  32. TRACK* out_trax[16];
  33. DWORD ct;
  34. UINT tf;
  35. MIDI_file* mf;
  36. DWORD vol_set;
  37. bool drumfix, insfix;
  38. b_dw ins[16], ins_set[16];
  39. bool f2, tr1, dm, only_ins, ins_no_lsb;
  40. bool hasnotes[16];
  41. void check_ins(UINT msb, UINT lsb, UINT patch, UINT note, BOOL drum, UINT ch) //called on note
  42. {
  43. if (ins_no_lsb) lsb = 0;
  44. INSTRUMENT_DESC * d = instr;
  45. while (d)
  46. {
  47. if (d->bank_hi == msb && d->bank_lo == lsb && d->patch == patch && d->drum == drum) break;
  48. d = d->next;
  49. }
  50. if (d)
  51. {
  52. d->count++;
  53. if (d->note_max < note) d->note_max = note;
  54. if (d->note_min > note) d->note_min = note;
  55. d->channels |= 1 << ch;
  56. }
  57. else
  58. {
  59. d = new INSTRUMENT_DESC;
  60. *instr_ptr = d;
  61. instr_ptr = &d->next;
  62. d->next = 0;
  63. d->note_min = d->note_max = note;
  64. d->bank_hi = msb;
  65. d->bank_lo = lsb;
  66. d->patch = patch;
  67. d->count = 1;
  68. d->drum = drum;
  69. d->user = 0;
  70. d->channels = 1 << ch;
  71. }
  72. }
  73. void AdvanceTime(TRACK* t);
  74. void AddEvent(BYTE ev, BYTE* data);
  75. void WriteTrack(TRACK* t);
  76. int Run(MIDI_file* mf, DWORD, void ** out_data, int * out_size);
  77. void do_shit(UINT n);
  78. UINT get_next_time()
  79. {
  80. UINT t = -1;
  81. UINT n;
  82. for (n = 0;n < ntrax;n++)
  83. {
  84. UINT t1 = in_trax[n]->tm;
  85. if (t1 < t) t = t1;
  86. }
  87. return t;
  88. }
  89. BOOL event_ok(BYTE e, BYTE* p)
  90. {
  91. BYTE _c = e & 0xF0;
  92. BYTE ch = e & 0xF;
  93. if (_c == 0xB0)
  94. {
  95. if (cfg_hack_xg_drums && ch == 9 && p[1] == 0 && (p[0] == 0 || p[0] == 0x20))
  96. return 0;
  97. if (p[0] > 127)
  98. return 0;
  99. ctab[ch][p[0]] = p[1];
  100. if (p[0] == 0)
  101. {
  102. ins[ch].b[2] = p[1];
  103. if (insfix) return 0;
  104. }
  105. if (p[0] == 0x20)
  106. {
  107. ins[ch].b[1] = p[1];
  108. if (insfix) return 0;
  109. }
  110. if (dm) //keep dm drivers happy...
  111. {
  112. if (p[0] >= 0x20 && p[0] < 0x40) //lsb values
  113. {
  114. return 0;
  115. }
  116. else if (p[0] < 0x20)
  117. {
  118. BYTE data[2] = {(BYTE)(p[0] + 0x20),ctab[ch][p[0] + 0x20]};
  119. AddEvent(e, data);
  120. }
  121. }
  122. return 1;
  123. }
  124. else if (_c == 0xC0)
  125. {
  126. if (ch == 9)
  127. {
  128. if (drumfix && !test_drum_kit(p[0], mf->pDLS)) return 0;
  129. ins[ch].b[0] = p[0];
  130. }
  131. else
  132. {
  133. ins[ch].b[0] = p[0];
  134. if (insfix) return 0;
  135. }
  136. }
  137. else if (_c == 0x90 && p[1])
  138. {
  139. if (only_ins)
  140. check_ins(ins[ch].b[2], ins[ch].b[1], ins[ch].b[0], p[0], ch == 9, ch);
  141. if (ch != 9 && insfix)
  142. {
  143. if (ins_set[ch].dw != ins[ch].dw)
  144. {
  145. do_dls_check(&ins[ch].dw, mf->pDLS);
  146. if (ins_set[ch].b[1] != ins[ch].b[1])
  147. {
  148. BYTE t[2] = {0x20, ins[ch].b[1]};
  149. AddEvent(0xB0 | ch, t);
  150. }
  151. if (ins_set[ch].b[2] != ins[ch].b[2])
  152. {
  153. BYTE t[2] = {0, ins[ch].b[2]};
  154. AddEvent(0xB0 | ch, t);
  155. }
  156. AddEvent(0xC0 | ch, ins[ch].b);
  157. ins_set[ch].dw = ins[ch].dw;
  158. }
  159. }
  160. }
  161. return 1;
  162. }
  163. CCleaner()
  164. {
  165. memset(ins, 0, sizeof(ins));
  166. memset(ins_set, -1, sizeof(ins_set));
  167. memset(hasnotes, 0, sizeof(hasnotes));
  168. memset(out_trax, 0, sizeof(out_trax));
  169. in_trax = 0;
  170. }
  171. ~CCleaner()
  172. {
  173. UINT n;
  174. if (in_trax)
  175. {
  176. for (n = 0;n < ntrax;n++)
  177. if (in_trax[n]) {free(in_trax[n]);in_trax[n] = 0;}
  178. free(in_trax);
  179. }
  180. for (n = 0;n < 16;n++)
  181. {
  182. if (out_trax[n])
  183. {
  184. free(out_trax[n]);
  185. out_trax[n] = 0;
  186. }
  187. }
  188. }
  189. };
  190. void CCleaner::do_shit(UINT n)
  191. {
  192. BYTE ce = 0;
  193. TRACK* t = in_trax[n];
  194. if (!t) return ;
  195. while (t->tm == ct)
  196. {
  197. if (t->pos >= t->sz)
  198. {
  199. t->pos = -1;
  200. t->tm = -1;
  201. tf++;
  202. break;
  203. }
  204. BYTE c0 = t->data[t->pos];
  205. if (c0 == 0xFF) //Meta-events
  206. {
  207. if (cfg_ff7loopz
  208. && (t->sz - t->pos) >= sizeof(ff7loopend) // bounds check
  209. && !memcmp(t->data + t->pos, ff7loopend, sizeof(ff7loopend)))
  210. {
  211. // MessageBox(GetActiveWindow(),"blah",0,0);
  212. // AdvanceTime(t);
  213. tf = ntrax;
  214. // return;
  215. }
  216. BYTE c1 = t->data[t->pos + 1];
  217. if (c1 == 0x2F)
  218. {
  219. t->pos += 3;
  220. t->tm = -1;
  221. tf++;
  222. }
  223. {
  224. t->pos += 2;
  225. if (t->pos < t->sz)
  226. {
  227. unsigned int _d;
  228. t->pos += DecodeDelta(t->data + t->pos, &_d, t->sz - t->pos);
  229. t->pos += _d;
  230. }
  231. }
  232. } else if (c0 == 0xF0)
  233. {
  234. t->pos += ReadSysex(&t->data[t->pos], t->sz - t->pos);
  235. }
  236. else if (c0 == 0xF7) t->pos++;
  237. else if ((c0&0xF0) == 0xF0) //WTF?
  238. {
  239. t->pos = -1;
  240. t->tm = -1;
  241. tf++;
  242. break;
  243. }
  244. else
  245. {
  246. if (c0&0x80)
  247. {
  248. ce = c0;
  249. t->pos++;
  250. }
  251. else ce = t->le;
  252. if (event_ok(ce, &t->data[t->pos])) AddEvent(ce, &t->data[t->pos]);
  253. if ((ce&0xF0) == 0xC0 || (ce&0xF0) == 0xD0) t->pos++;
  254. else t->pos += 2;
  255. t->le = ce;
  256. }
  257. if (t->tm != -1 && t->pos >= t->sz)
  258. {
  259. t->pos = -1;
  260. t->tm = -1;
  261. tf++;
  262. break;
  263. }
  264. AdvanceTime(t);
  265. }
  266. }
  267. #define WriteBuf(A,B) outbuf.write(A,B)
  268. #pragma pack(push)
  269. #pragma pack(1)
  270. typedef struct
  271. {
  272. WORD t, n, d;
  273. }
  274. MHD;
  275. typedef struct
  276. {
  277. DWORD c, s;
  278. }
  279. CHD;
  280. #pragma pack(pop)
  281. void CCleaner::AdvanceTime(TRACK* t)
  282. {
  283. if (t->tm != -1)
  284. {
  285. unsigned int d;
  286. UINT _n = DecodeDelta(t->data + t->pos, &d, t->sz - t->pos);
  287. if (_n < 4) t->tm += d;
  288. t->pos += _n;
  289. }
  290. }
  291. void CCleaner::AddEvent(BYTE ev, BYTE* data)
  292. {
  293. if (only_ins) return ;
  294. BYTE nt = ev & 0xF;
  295. BYTE ec = ev & 0xF0;
  296. if (tr1) nt = 0;
  297. TRACK *t = out_trax[nt];
  298. ZeroMemory(ctab, sizeof(ctab));
  299. if (!t)
  300. {
  301. t = out_trax[nt] = (TRACK*)malloc(sizeof(TRACK) + 0x1000);
  302. if (!t) return ;
  303. ZeroMemory(t, 16);
  304. t->sz = 0x1000;
  305. t->tm = 0;
  306. }
  307. else if (t->pos > t->sz - 0x10)
  308. {
  309. t->sz *= 2;
  310. out_trax[nt] = (TRACK*)realloc(t, sizeof(TRACK) + t->sz);
  311. if (!out_trax[nt])
  312. {
  313. free(t);
  314. return ;
  315. }
  316. t = out_trax[nt];
  317. }
  318. if (t->tm < ct)
  319. {
  320. t->pos += EncodeDelta(&t->data[t->pos], ct - t->tm);
  321. t->tm = ct;
  322. }
  323. else
  324. {
  325. t->data[t->pos++] = 0;
  326. }
  327. if (ec == 0x90)
  328. {
  329. hasnotes[nt] = 1;
  330. data[0] &= 0x7F; /* don't allow 8bit note numbers */
  331. }
  332. else if (ec == 0x80)
  333. {
  334. data[0] &= 0x7F; /* don't allow 8bit note numbers */
  335. }
  336. /*if (ev!=t->le) */{t->data[t->pos++] = ev;t->le = ev;}
  337. t->data[t->pos++] = data[0];
  338. if (ec != 0xC0 && ec != 0xD0) t->data[t->pos++] = data[1];
  339. }
  340. void CCleaner::WriteTrack(TRACK* t)
  341. {
  342. CHD chd;
  343. chd.c = 'krTM';
  344. chd.s = rev32(t->pos);
  345. WriteBuf(&chd, 8);
  346. WriteBuf(&t->data, t->pos);
  347. ntrax1++;
  348. }
  349. int DoCleanUp(MIDI_file* mf, DWORD mode, void** out_data, int * out_size)
  350. {
  351. CCleaner c;
  352. c.only_ins = 0;
  353. return c.Run(mf, mode, out_data, out_size);
  354. }
  355. int CCleaner::Run(MIDI_file* _mf, DWORD _md, void ** out_data, int * out_size)
  356. {
  357. f2 = *(WORD*)(_mf->data + 8) == 0x0200;
  358. maxvol = 90;
  359. vol_set = 0;
  360. dm = (_md & CLEAN_DM) ? 1 : 0;
  361. tr1 = (_md & CLEAN_1TRACK) ? 1 : 0;
  362. if (_md&CLEAN_DLS)
  363. {
  364. drumfix = dm && cfg_hack_dls_drums;
  365. insfix = dm && cfg_hack_dls_instruments;
  366. }
  367. else
  368. {
  369. drumfix = insfix = 0;
  370. }
  371. mf = _mf;
  372. instr_ptr = &instr;
  373. instr = 0;
  374. UINT n;
  375. ct = 0;
  376. tf = 0;
  377. ntrax = ntrax1 = 0;
  378. CHD chd;
  379. MHD mhd;
  380. DWORD ptr = 8;
  381. mhd = *(MHD*)(mf->data + 8);
  382. ptr += 6;
  383. mhd.t = rev16(mhd.t);
  384. mhd.n = rev16(mhd.n);
  385. if (mhd.t > 2)
  386. goto fail;
  387. ntrax = mhd.n;
  388. n = 0;
  389. in_trax = (TRACK**)malloc(sizeof(void*) * ntrax);
  390. for (;n < ntrax && ptr < (UINT)mf->size;n++)
  391. {
  392. chd = *(CHD*)(mf->data + ptr);
  393. ptr += 8;
  394. if (chd.c != 'krTM' || ptr > (UINT)mf->size)
  395. {
  396. ntrax = n;
  397. break;
  398. }
  399. chd.s = rev32(chd.s);
  400. //if (ptr+chd.s>(UINT)mf->size)
  401. if (chd.s > ((UINT)mf->size - ptr))
  402. {
  403. chd.s = mf->size - ptr;
  404. }
  405. //goto fail;
  406. in_trax[n] = (TRACK*)malloc(16 + chd.s);
  407. in_trax[n]->sz = chd.s;
  408. in_trax[n]->tm = 0;
  409. in_trax[n]->le = 0;
  410. in_trax[n]->pos = 0;
  411. memcpy(in_trax[n]->data, mf->data + ptr, chd.s);
  412. ptr += chd.s;
  413. AdvanceTime(in_trax[n]);
  414. }
  415. if (f2)
  416. {
  417. for (n = 0;n < ntrax;n++)
  418. {
  419. in_trax[n]->tm = ct;
  420. while (tf <= n)
  421. {
  422. do_shit(n);
  423. if (in_trax[n]->tm != -1) ct = in_trax[n]->tm;
  424. }
  425. }
  426. }
  427. else
  428. {
  429. while (tf < ntrax)
  430. {
  431. UINT nt = get_next_time(); //ct++;
  432. if (nt == -1) break;
  433. ct = nt;
  434. for (n = 0;n < ntrax && tf < ntrax;n++)
  435. {
  436. do_shit(n);
  437. }
  438. }
  439. }
  440. if (!only_ins)
  441. {
  442. mhd.t = 0x0100;
  443. mhd.n = 0; //rev16(ntrax1);
  444. chd.c = 'dhTM';
  445. chd.s = 0x06000000;
  446. WriteBuf(&chd, 8);
  447. WriteBuf(&mhd, 6);
  448. if (!(_md&CLEAN_NOTEMPO) && mf->tmap)
  449. {
  450. /* BYTE *tt=mf->tmap->BuildTrack();
  451. if (tt)
  452. {
  453. WriteBuf(tt,rev32(*(DWORD*)(tt+4))+8);
  454. ntrax1++;
  455. free(tt);
  456. }*/
  457. if (mf->tmap->BuildTrack(outbuf))
  458. {
  459. ntrax1++;
  460. }
  461. }
  462. if (!(_md&CLEAN_NOSYSEX) && mf->smap)
  463. {
  464. /* BYTE *st=mf->smap->BuildTrack();
  465. if (st)
  466. {
  467. WriteBuf(st,rev32(*(DWORD*)(st+4))+8);
  468. ntrax1++;
  469. free(st);
  470. }*/
  471. if (mf->smap->BuildTrack(outbuf))
  472. {
  473. ntrax1++;
  474. }
  475. }
  476. for (n = 0;n < 16;n++) if (out_trax[n] && hasnotes[n] && out_trax[n]->pos)
  477. {
  478. TRACK *t = out_trax[n];
  479. t->pos += EncodeDelta(t->data + t->pos, ct - t->tm);
  480. t->data[t->pos++] = 0xFF;
  481. t->data[t->pos++] = 0x2F;
  482. t->data[t->pos++] = 0;
  483. WriteTrack(t);
  484. }
  485. {
  486. WORD t = rev16(ntrax1);
  487. outbuf.write_ptr(&t, 2, 10);
  488. }
  489. if (out_size) *out_size = outbuf.get_size();
  490. if (out_data) *out_data = outbuf.finish();
  491. #if 0
  492. {
  493. HANDLE f = CreateFile("c:\\dump.mid", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
  494. DWORD bw = 0;
  495. WriteFile(f, rv, bs, &bw, 0);
  496. CloseHandle(f);
  497. }
  498. #endif
  499. }
  500. return 1;
  501. fail:
  502. // ErrorBox("WARNING: cleaner messed up");
  503. return 0;
  504. //TO DESTRUCTOR
  505. }
  506. INSTRUMENT_DESC* GetInstruments(MIDI_file* mf, BOOL do_lsb)
  507. {
  508. CCleaner c;
  509. c.only_ins = 1;
  510. c.ins_no_lsb = !do_lsb;
  511. c.Run(mf, 0, 0, 0);
  512. return c.instr;
  513. }