1
0

midifile.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. #include "main.h"
  2. #include <intsafe.h>
  3. //#define HUNT_LEAKS
  4. #ifdef MF_USE_DMCRAP
  5. extern IDirectMusicCollection *pCDLS;
  6. #endif
  7. #ifdef HUNT_LEAKS
  8. static UINT n_files;
  9. #endif
  10. MIDI_file::MIDI_file(const char * fn) : path(fn)
  11. {
  12. flags=0;
  13. format=0;
  14. len=0;tix=0;
  15. size=0;
  16. data=0;
  17. #ifdef MF_USE_DMCRAP
  18. pSeg=0;
  19. pDLS=0;
  20. pDLSdata=0;
  21. DLSsize=0;
  22. #endif
  23. info.fmt=info.ntrax=info.tix=0;
  24. info.channels=0;
  25. info.e_type=0;
  26. loopstart=0;loopend=0;
  27. loopstart_t=0;
  28. rmi_data=0;
  29. rmi_size=0;
  30. bmp_data=0;
  31. bmp_size=0;
  32. kar_track=0;
  33. tmap=0;
  34. smap=0;
  35. #ifdef HUNT_LEAKS
  36. n_files++;
  37. #endif
  38. refcount=1;
  39. info.traxnames=0;
  40. }
  41. #ifdef MF_USE_DMCRAP
  42. extern IDirectMusicCollection *pCDLS;
  43. extern IDirectMusicLoader* pLoader;
  44. #endif
  45. static bool is_gmd(const BYTE* b,size_t s)
  46. {
  47. return s>12 && *(DWORD*)b==_rv('MIDI') && *(DWORD*)(b+8)==_rv('MDpg');
  48. }
  49. static bool is_hmi(const BYTE* b,size_t s)
  50. {
  51. return s>12 && *(DWORD*)b==_rv('HMI-') && *(DWORD*)(b+4)==_rv('MIDI') && *(DWORD*)(b+8)==_rv('SONG');
  52. }
  53. static bool is_hmp(const BYTE* b,size_t s)
  54. {
  55. if (s>8 && ((DWORD*)b)[0]==_rv('HMIM') && (((DWORD*)b)[1]==_rv('IDIP') || ((DWORD*)b)[1]==_rv('IDIR')) )
  56. {
  57. //DWORD d=*(DWORD*)(b+0x30);
  58. //return (d<0x40 && d);
  59. return 1;
  60. }
  61. else return 0;
  62. }
  63. static bool is_xmidi(const BYTE* b,size_t s)
  64. {
  65. return s>0x20 && *(DWORD*)b==_rv('FORM') && *(DWORD*)(b+8)==_rv('XDIR') && *(DWORD*)(b+0x1e)==_rv('XMID');
  66. }
  67. static bool is_rmi(const BYTE* b,size_t s)
  68. {
  69. return s>20+8+6+8 && *(DWORD*)b==_rv('RIFF') && *(DWORD*)(b+8)==_rv('RMID') && *(DWORD*)(b+12)==_rv('data');
  70. }
  71. static bool is_midi(const BYTE* b,size_t s)
  72. {
  73. return s>8+6+8 && *(DWORD*)b==_rv('MThd') && *(DWORD*)(b+4)==0x06000000 && *(DWORD*)(b+14)==_rv('MTrk');
  74. }
  75. static bool is_midi_scan(const BYTE* b,size_t s)
  76. {
  77. int x,m=s;
  78. if (m>256) m=256;
  79. m-=8+6+8;
  80. for(x=0;x<m;x++)
  81. if (is_midi(b+x,s-x)) return 1;
  82. return 0;
  83. }
  84. #define REM (unsigned int)(sz-ptr)
  85. static bool load_midi_fix(MIDI_file* mf,const BYTE* buf,size_t sz,int n_track,size_t p_ofs)
  86. {
  87. if (!cfg_recover_tracks)
  88. return 0;
  89. size_t malloc_sz;
  90. if (SizeTAdd(sz, 0x10, &malloc_sz) != S_OK)
  91. return false;
  92. BYTE* outbuf=(BYTE*)malloc(malloc_sz);
  93. if (!outbuf) return 0;
  94. size_t ptr=p_ofs;
  95. size_t bp=ptr;
  96. BYTE lc=0;
  97. while(1)
  98. {
  99. bp=ptr;
  100. if (REM<4) break;
  101. while(buf[ptr]&0x80)
  102. {
  103. if (ptr==bp+4) break;
  104. ptr++;
  105. }
  106. ptr++;
  107. if (REM<3) break;
  108. BYTE b=buf[ptr];
  109. if (b==0xFF)
  110. {
  111. ptr+=2;
  112. if (REM<4) break;
  113. unsigned int d;
  114. unsigned int l=DecodeDelta(buf+ptr,&d, sz-ptr);
  115. if (l+d>REM) break;
  116. ptr+=l+d;
  117. }
  118. else if (b==0xF0)
  119. {
  120. ptr++;
  121. if (REM<4) break;
  122. unsigned int d;
  123. unsigned int l=DecodeDelta(buf+ptr,&d, sz-ptr);
  124. if (l+d>REM) break;
  125. ptr+=l+d;
  126. }
  127. else
  128. {
  129. if (b&0x80)
  130. {
  131. lc=b&0xF0;
  132. if (lc==0xF0) break;
  133. ptr++;
  134. }
  135. else if (!lc) break;
  136. if (lc==0xC0 || lc==0xD0) ptr++;
  137. else ptr+=2;
  138. }
  139. }
  140. memcpy(outbuf,buf,ptr);
  141. ptr=bp;
  142. outbuf[ptr++]=0;
  143. outbuf[ptr++]=0xFF;
  144. outbuf[ptr++]=0x2F;
  145. outbuf[ptr++]=0;
  146. *(DWORD*)(outbuf+p_ofs-4)=rev32(ptr-p_ofs);
  147. mf->data=outbuf;
  148. mf->size=ptr;
  149. return 1;
  150. }
  151. #undef REM
  152. static bool load_midi(MIDI_file* mf,const BYTE* buf,size_t sz)
  153. {
  154. int trax=rev16(*(WORD*)(buf+4+4+2));
  155. size_t ofs=6+8;
  156. int n;
  157. for(n=0;n<trax;n++)
  158. {
  159. if (ofs>(sz-12) || *(DWORD*)(buf+ofs)!=_rv('MTrk'))
  160. {
  161. mf->flags|=FLAG_INCOMPLETE;
  162. *(WORD*)(buf+4+4+2)=rev16(n);
  163. sz=ofs;
  164. break;
  165. }
  166. if (SizeTAdd(ofs, 8, &ofs) != S_OK)
  167. return false;
  168. size_t p_ofs=ofs;
  169. DWORD next = rev32(*(DWORD*)(buf+ofs-4));
  170. if (SizeTAdd(ofs, next, &ofs) != S_OK)
  171. return false;
  172. if (ofs>sz)
  173. {
  174. mf->flags|=FLAG_INCOMPLETE;
  175. *(WORD*)(buf+4+4+2)=rev16(n+1);
  176. if (!load_midi_fix(mf,buf,sz,n,p_ofs))
  177. {
  178. *(WORD*)(buf+4+4+2)=rev16(n);
  179. sz=p_ofs-8;
  180. break;
  181. }
  182. else return 1;
  183. }
  184. }
  185. BYTE * out = (BYTE*)malloc(sz);
  186. if (!out)
  187. return 0;
  188. memcpy(out,buf,sz);
  189. mf->data=out;
  190. mf->size=sz;
  191. return 1;
  192. }
  193. static bool load_gmd(MIDI_file* mf,const BYTE* buf,size_t sz)
  194. {
  195. if (sz<=0x10) return 0;
  196. DWORD s=rev32(*(DWORD*)(buf+4));
  197. if ((sz-8)<s) return 0;
  198. DWORD ofs=rev32(*(DWORD*)(buf+12))+0x10;
  199. s-=ofs;
  200. BYTE * out=(BYTE*)malloc(s);
  201. if (!out) return 0;
  202. mf->size=s;
  203. memcpy(out,buf+ofs,s);
  204. mf->data=out;
  205. return 1;
  206. }
  207. #ifdef MF_USE_DMCRAP
  208. void ReleaseObject(IUnknown* o);
  209. #endif
  210. static bool load_rmi(MIDI_file* mf,const BYTE* source,size_t source_size)
  211. {
  212. if (source_size < 8)
  213. return 0;
  214. unsigned int sx=*(DWORD*)(source+4);
  215. size_t _p=0;
  216. BYTE * out;
  217. if (sx>source_size-8) goto _er;
  218. mf->size=*(DWORD*)(source+16);
  219. if (mf->size+20>source_size) goto _er;
  220. out=(BYTE*)malloc(mf->size);
  221. if (!out) goto _er;
  222. memcpy(out,source+20,mf->size);
  223. mf->data = out;
  224. _p=20+mf->size;
  225. if (_p&1) _p++;
  226. while(_p<source_size)
  227. {
  228. if (! mf->bmp_data && *(DWORD*)(source+_p)==_rv('DISP') && *(DWORD*)(source+_p+8)==8)//bitmap
  229. {
  230. DWORD s=*(DWORD*)(source+_p+4)-4;
  231. void * r=malloc(s);
  232. if (r)
  233. {
  234. memcpy(r,source+_p+12,s);
  235. mf->bmp_size=s;
  236. mf->bmp_data=r;
  237. }
  238. }
  239. else if (! mf->title && *(DWORD*)(source+_p)==_rv('DISP') && *(DWORD*)(source+_p+8)==1)
  240. {
  241. DWORD s=*(DWORD*)(source+_p+4)-4;
  242. char * src=(char*)(source+_p+12); //remove eol's
  243. char * dst=mf->title.buffer_get(s+1);
  244. char * src_b=src;
  245. while(src && *src && (UINT)(src-src_b)<s)
  246. {
  247. if (*src!=10 && *src!=13) *(dst++)=*src;
  248. src++;
  249. }
  250. *dst=0;
  251. mf->title.buffer_done();
  252. }
  253. else if (! mf->rmi_data && *(DWORD*)(source+_p)==_rv('LIST') && *(DWORD*)(source+_p+8)==_rv('INFO'))
  254. {
  255. DWORD s=*(DWORD*)(source+_p+4);
  256. void * r=malloc(s);
  257. if (r)
  258. {
  259. memcpy(r,source+_p+8,s);
  260. mf->rmi_size=s;
  261. mf->rmi_data=r;
  262. }
  263. }
  264. #ifdef MF_USE_DMCRAP
  265. else if (!mf->pDLSdata && *(DWORD*)(source+_p)==_rv('RIFF') && *(DWORD*)(source+_p+8)==_rv('DLS '))
  266. {
  267. int rs=*(long*)(source+_p+4)+8;
  268. if (rs+_p>source_size) break;
  269. mf->DLSsize=rs;
  270. mf->pDLSdata=(BYTE*)malloc(rs);
  271. memcpy(mf->pDLSdata,source+_p,rs);
  272. }
  273. #endif
  274. _p+=*(DWORD*)(source+_p+4)+8;
  275. if (_p&1) _p++;
  276. }
  277. return 1;
  278. _er:
  279. return 0;
  280. }
  281. bool load_xmi(MIDI_file* mf,const BYTE*,size_t);
  282. bool load_hmp(MIDI_file* mf,const BYTE*,size_t);
  283. bool load_hmi(MIDI_file* mf,const BYTE*,size_t);
  284. bool load_mus(MIDI_file* mf,const BYTE*,size_t);
  285. bool load_cmf(MIDI_file* mf,const BYTE*,size_t);
  286. bool load_mids(MIDI_file* mf,const BYTE*,size_t);
  287. bool load_gmf(MIDI_file* mf,const BYTE*,size_t);
  288. bool is_mus(const BYTE*,size_t);
  289. bool is_cmf(const BYTE*,size_t);
  290. bool is_mids(const BYTE*,size_t);
  291. bool is_gmf(const BYTE*,size_t);
  292. static bool load_midi_scan(MIDI_file* mf,const BYTE* ptr,size_t size)
  293. {
  294. int max = size-3;
  295. if (max>256) max=256;
  296. int x;
  297. for(x=0;x<256;x++)
  298. {
  299. if (*(DWORD*)(ptr+x)==_rv('MThd') && *(DWORD*)(ptr+x+4)==_rv(6))
  300. {
  301. size-=x;
  302. ptr+=x;
  303. void * buf=malloc(size);
  304. if (!buf) return 0;
  305. memcpy(buf,ptr,size);
  306. bool r=load_midi(mf,(BYTE*)buf,size);
  307. if (!r) free(buf);
  308. return r;
  309. }
  310. }
  311. return 0;
  312. }
  313. struct
  314. {
  315. bool ( * test ) (const BYTE* b,size_t s);
  316. bool ( * load ) (MIDI_file* mf,const BYTE* ptr,size_t size);
  317. } format_list[] =
  318. {
  319. {is_midi,load_midi},
  320. {is_rmi,load_rmi},
  321. {is_hmp,load_hmp},
  322. {is_hmi,load_hmi},
  323. {is_xmidi,load_xmi},
  324. {is_mus,load_mus},
  325. {is_cmf,load_cmf},
  326. {is_gmd,load_gmd},
  327. {is_mids,load_mids},
  328. {is_gmf,load_gmf},
  329. {is_midi_scan,load_midi_scan}
  330. };
  331. //static fmtfunc fmts[]={is_midi,is_rmi,is_hmp,is_hmi,is_xmidi,is_mus,is_cmf,is_gmd,is_mids,is_gmf,is_midi_scan};
  332. //loadfunc loaders[]={load_midi,load_rmi,load_hmp,load_hmi,load_xmi,load_mus,load_cmf,load_gmd,load_mids,load_gmf,load_midi_scan};
  333. #ifdef MF_USE_DMCRAP
  334. void LoadDLS(MIDI_file* mf)
  335. {
  336. if (mf->pDLSdata && ! mf->pDLS)
  337. {
  338. DMUS_OBJECTDESC ObjDesc;
  339. ZeroMemory(&ObjDesc,sizeof(ObjDesc));
  340. ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
  341. ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_MEMORY;
  342. ObjDesc.llMemLength = mf->DLSsize;
  343. ObjDesc.pbMemData = mf->pDLSdata;
  344. ObjDesc.guidClass = CLSID_DirectMusicCollection;
  345. pLoader->GetObject(&ObjDesc,IID_IDirectMusicCollection,(void**)&mf->pDLS);
  346. if (mf->pDLS)
  347. {
  348. ReleaseObject(mf->pDLS);
  349. }
  350. }
  351. }
  352. void _LoadSegment(MIDI_file* mf)
  353. {
  354. #ifdef USE_LOG
  355. log_write("_LoadSegment()");
  356. #endif
  357. mf->pSeg=0;
  358. int data_size=0;
  359. void * data_ptr=0;
  360. if (
  361. !DoCleanUp(mf,CLEAN_DM|CLEAN_DLS|(cfg_nosysex ? CLEAN_NOSYSEX : 0),&data_ptr,&data_size)
  362. )
  363. return;
  364. IDirectMusicSegment* pSeg=0;
  365. DMUS_OBJECTDESC ObjDesc;
  366. ZeroMemory(&ObjDesc,sizeof(ObjDesc));
  367. ObjDesc.dwSize=sizeof(ObjDesc);
  368. ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_MEMORY;
  369. ObjDesc.llMemLength = data_size;
  370. ObjDesc.pbMemData = (BYTE*)data_ptr;
  371. ObjDesc.guidClass=CLSID_DirectMusicSegment;
  372. #ifdef USE_LOG
  373. log_write("pLoader->EnableCache(GUID_DirectMusicAllTypes,1);");
  374. #endif
  375. pLoader->EnableCache(GUID_DirectMusicAllTypes,1);
  376. // pLoader->ClearCache(CLSID_DirectMusicSegment); //%$%&%@! this->sucks = TRUE
  377. #ifdef USE_LOG
  378. log_write("pLoader->GetObject(&ObjDesc,IID_IDirectMusicSegment,(void**)&pSeg);");
  379. #endif
  380. pLoader->GetObject(&ObjDesc,IID_IDirectMusicSegment,(void**)&pSeg);
  381. if (!pSeg)
  382. {
  383. #ifdef USE_LOG
  384. log_write("attempting memdump");
  385. #endif
  386. char tmpf[MAX_PATH] = {0};
  387. get_temp_file(tmpf);
  388. HANDLE f=CreateFileA(tmpf,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
  389. if (f!=INVALID_HANDLE_VALUE)
  390. {
  391. DWORD bw = 0;
  392. WriteFile(f,data_ptr,data_size,&bw,0);
  393. CloseHandle(f);
  394. mbstowcs(ObjDesc.wszFileName,tmpf,MAX_PATH);
  395. ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FULLPATH | DMUS_OBJ_FILENAME;
  396. pLoader->GetObject(&ObjDesc,IID_IDirectMusicSegment,(void**)&pSeg);
  397. DeleteFileA(tmpf);
  398. }
  399. }
  400. if (pSeg)
  401. {
  402. #ifdef USE_LOG
  403. log_write("got IDirectMusicSegment");
  404. log_write("pSeg->SetParam(GUID_StandardMIDIFile,-1,0,0,0);");
  405. #endif
  406. pSeg->SetParam(GUID_StandardMIDIFile,-1,0,0,0);
  407. #ifdef USE_LOG
  408. log_write("pSeg->SetStartPoint(0);");
  409. #endif
  410. pSeg->SetStartPoint(0);
  411. #ifdef USE_LOG
  412. log_write("pSeg->SetLength();");
  413. #endif
  414. {
  415. bool ok=0;
  416. if (cfg_eof_delay)
  417. {
  418. MUSIC_TIME mnt;
  419. DMUS_TEMPO_PARAM tp;
  420. if (SUCCEEDED(pSeg->GetParam(GUID_TempoParam,-1,0,mf->tix,&mnt,&tp)))
  421. {
  422. pSeg->SetLength((MUSIC_TIME)(mf->tix+(double)cfg_eof_delay*78.0/tp.dblTempo));
  423. ok=1;
  424. }
  425. }
  426. if (!ok) pSeg->SetLength(mf->tix);
  427. }
  428. mf->pSeg=pSeg;
  429. LoadDLS(mf);
  430. if (pCDLS) pSeg->SetParam(GUID_ConnectToDLSCollection,0xFFFFFFFF,0,0,(void*)pCDLS);
  431. if (mf->pDLS) pSeg->SetParam(GUID_ConnectToDLSCollection,0xFFFFFFFF,0,0,(void*)mf->pDLS);
  432. if (mf->loopstart)
  433. {
  434. pSeg->SetLoopPoints(mf->loopstart,mf->loopend);
  435. }
  436. }
  437. free(data_ptr);
  438. pLoader->EnableCache(GUID_DirectMusicAllTypes,0);
  439. }
  440. IDirectMusicSegment* LoadSegment(MIDI_file* mf)
  441. {
  442. #ifdef USE_LOG
  443. log_write("LoadSegment()");
  444. #endif
  445. if (!pLoader) return 0;
  446. IDirectMusicSegment* pSeg=0;
  447. if (!mf->pSeg) _LoadSegment(mf);
  448. if (mf->pSeg)
  449. {
  450. #ifdef USE_LOG
  451. log_write("LoadSegment() : got IDirectMusicSegment");
  452. #endif
  453. pSeg=mf->pSeg;
  454. #ifdef USE_LOG
  455. log_write("pSeg->AddRef()");
  456. #endif
  457. pSeg->AddRef();
  458. #ifdef USE_LOG
  459. log_write("pSeg->AddRef() returned");
  460. #endif
  461. }
  462. #ifdef USE_LOG
  463. log_write("LoadSegment() returning");
  464. #endif
  465. return pSeg;
  466. }
  467. #endif
  468. MIDI_file::~MIDI_file()
  469. {
  470. #ifdef MF_USE_DMCRAP
  471. if (pSeg) pSeg->Release();
  472. if (pDLS) pDLS->Release();
  473. if (pDLSdata) free(pDLSdata);
  474. #endif
  475. if (data) free((BYTE*)data);
  476. if (tmap) delete tmap;
  477. if (smap) delete smap;
  478. if (info.traxnames) delete[] info.traxnames;
  479. if (rmi_data) free(rmi_data);
  480. if (bmp_data) free(bmp_data);
  481. #ifdef HUNT_LEAKS
  482. n_files--;
  483. #endif
  484. }
  485. bool GetMidiInfo(MIDI_file*);
  486. static bool try_format(const void * data,int size,int idx)
  487. {
  488. bool rv;
  489. try {
  490. rv = format_list[idx].test((const BYTE*)data,size);
  491. } catch(...)
  492. {
  493. rv = 0;
  494. }
  495. return rv;
  496. }
  497. int MIDI_file::HeaderTest(const void * data,int size)
  498. {
  499. int n;
  500. for(n=0;n<tabsize(format_list);n++)
  501. {
  502. if (try_format(data,size,n)) return 1;
  503. }
  504. return 0;
  505. }
  506. int MIDI_file::Load(const void * data,int size)
  507. {
  508. #ifdef USE_LOG
  509. log_write("Load()");
  510. #endif
  511. {
  512. int n;
  513. int fmt=-1;
  514. for(n=0;n<tabsize(format_list);n++)
  515. {
  516. if (try_format(data,size,n)) {fmt=n;break;}
  517. }
  518. if (fmt==-1) return 0;
  519. format = fmt;
  520. }
  521. {
  522. bool r;
  523. try {
  524. r=format_list[format].load(this,(const BYTE*)data,size);
  525. } catch(...) {
  526. #ifdef USE_LOG
  527. log_write("midi loader crashed");
  528. #endif
  529. r=0;
  530. }
  531. if (!r) return 0;
  532. }
  533. return GetMidiInfo(this);
  534. }
  535. MIDI_file* MIDI_file::Create(const char* fn,const void * data, size_t size)
  536. {
  537. MIDI_file* mf=new MIDI_file(fn);
  538. if (!mf->Load(data,size))
  539. {
  540. delete mf;
  541. mf=0;
  542. }
  543. return mf;
  544. }