1
0

xmi.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "main.h"
  2. #include "cvt.h"
  3. #pragma pack(push)
  4. #pragma pack(1)
  5. typedef struct
  6. {
  7. DWORD mthd,hdsize;
  8. MIDIHEADER mhd;
  9. } FILEHEADER;
  10. typedef struct
  11. {
  12. DWORD mtrk,size;
  13. } TRACKHEADER;
  14. #pragma pack(pop)
  15. struct XMI_cvt
  16. {
  17. public:
  18. grow_buf out;
  19. bool _end;
  20. DWORD tr_sz;
  21. DWORD cur_time,wr_time;
  22. // DWORD loopstart;
  23. bool hasevents;
  24. void q_add(BYTE ch,BYTE note,DWORD tm);
  25. void WriteDelta(DWORD _d);
  26. void DoQueue();
  27. DWORD ProcessNote(const BYTE* e);
  28. DWORD ProcessDelta(const BYTE* d);
  29. DWORD WriteEvent(const BYTE* e);
  30. bool run(MIDI_file* mf,const BYTE*,DWORD);
  31. #pragma pack(push)
  32. #pragma pack(1)
  33. #define Q_MAX 512
  34. struct
  35. {
  36. DWORD time;
  37. BYTE note;
  38. BYTE channel;
  39. } ch_q[Q_MAX];
  40. #pragma pack(pop)
  41. };
  42. #define WriteBuf(A,B) out.write(A,B)
  43. #define WriteBufB(A) out.write_byte(A)
  44. #define WriteBufD(A) out.write_dword(A)
  45. //WORD _fastcall rev16(WORD);
  46. DWORD _fastcall rev32(DWORD);
  47. #define FixHeader(H) {(H).fmt=rev16((H).fmt);(H).trax=rev16((H).trax);(H).dtx=rev16((H).dtx);}
  48. #define MThd 'dhTM'
  49. #define MTrk 'krTM'
  50. #define EVNT 'TNVE'
  51. void XMI_cvt::q_add(BYTE ch,BYTE note,DWORD tm)
  52. {
  53. UINT n,_n=-1;
  54. for(n=0;n<Q_MAX;n++)
  55. {
  56. if (ch_q[n].note==note && ch_q[n].channel==ch && ch_q[n].time!=-1)
  57. {
  58. /*if (ch_q[n].time>tm) */ch_q[n].time=tm;
  59. // q_notes++;
  60. return;
  61. }
  62. else if (ch_q[n].time==-1) _n=n;
  63. }
  64. if (_n!=-1)
  65. {
  66. ch_q[_n].channel=ch;
  67. ch_q[_n].time=tm;
  68. ch_q[_n].note=note;
  69. // q_notes++;
  70. }
  71. }
  72. void XMI_cvt::WriteDelta(DWORD _d)
  73. {
  74. DWORD d=_d-wr_time;
  75. wr_time=_d;
  76. int st=out.get_size();
  77. gb_write_delta(out,d);
  78. tr_sz+=out.get_size()-st;
  79. }
  80. DWORD _inline ReadDelta1(const BYTE* d,DWORD* _l)
  81. {
  82. DWORD r=d[0],l=0;
  83. while(!(d[l+1]&0x80))
  84. {
  85. r+=d[++l];
  86. }
  87. *_l=l+1;
  88. return r;
  89. }
  90. void XMI_cvt::DoQueue()
  91. {
  92. while(1)
  93. {
  94. DWORD _i=-1;
  95. DWORD _mt=-1;
  96. UINT i;
  97. for(i=0;i<Q_MAX;i++)
  98. {
  99. if (ch_q[i].time<_mt) {_i=i;_mt=ch_q[i].time;}
  100. }
  101. if (_mt<=cur_time)
  102. {
  103. WriteDelta(_mt);
  104. BYTE t[3]={(BYTE)(0x80|ch_q[_i].channel),ch_q[_i].note,0};
  105. WriteBuf(t,3);
  106. ch_q[_i].time=-1;
  107. tr_sz+=3;
  108. // q_notes--;
  109. }
  110. else break;
  111. }
  112. }
  113. DWORD XMI_cvt::ProcessNote(const BYTE* e)
  114. {
  115. DoQueue();
  116. WriteDelta(cur_time);
  117. WriteBuf(e,3);
  118. tr_sz+=3;
  119. DWORD l=3;
  120. unsigned int _d;
  121. l+=DecodeDelta(e+l,&_d);
  122. if (e[2]) q_add(e[0]&0xF,e[1],cur_time+_d);
  123. return l;
  124. }
  125. DWORD XMI_cvt::ProcessDelta(const BYTE* d)
  126. {
  127. DWORD l;
  128. cur_time+=ReadDelta1(d,&l);
  129. return l;
  130. }
  131. DWORD XMI_cvt::WriteEvent(const BYTE* e)
  132. {
  133. if ((e[0]&0xF0)==0xF0 && e[0]!=0xFF && e[0]!=0xF0)//hack
  134. {
  135. UINT l=1;
  136. while(!(e[l]&0x80)) l++;
  137. return l;
  138. }
  139. else if (e[0]==0xFF)
  140. {
  141. if (e[1]==0x2F)
  142. {
  143. DWORD _ct=cur_time;
  144. cur_time=-2;
  145. DoQueue();
  146. // loopstart=_ct-wr_time;
  147. cur_time=_ct;
  148. DWORD _ev=0x002FFF00;
  149. WriteBuf(&_ev,4);
  150. tr_sz+=4;
  151. _end=1;
  152. return 3;
  153. }
  154. else
  155. {
  156. UINT l=e[2];
  157. if (l&0x80)
  158. {
  159. l=((l<<7)|e[3])+1;
  160. }
  161. return 3+l;
  162. }
  163. }
  164. DoQueue();
  165. WriteDelta(cur_time);
  166. if (e[0]==0xF0)
  167. {
  168. unsigned int d;
  169. UINT l = 1 + DecodeDelta(e+1,&d);
  170. l+=d;
  171. WriteBuf(e,l);
  172. tr_sz+=l;
  173. return l;
  174. }
  175. DWORD l;
  176. //hasevents=1;
  177. if ((e[0]&0xF0)==0xC0 || (e[0]&0xF0)==0xD0) l=2;
  178. else l=3;
  179. WriteBuf(e,l);
  180. tr_sz+=l;
  181. return l;
  182. }
  183. BYTE xmi_track0[19]={'M','T','r','k',0,0,0,11,0,0xFF,0x51,0x03,0x20,0x8d,0xb7,0,0xFF,0x2F,0};
  184. void ReleaseObject(IUnknown* o);
  185. bool XMI_cvt::run(MIDI_file * mf,const BYTE* buf,DWORD sz)
  186. {
  187. // q_notes=0;
  188. FILEHEADER fhd=
  189. {
  190. MThd,
  191. 0x06000000,
  192. 0x0100,0x0000,0x0001
  193. };
  194. WriteBuf(&fhd,sizeof(fhd));
  195. UINT ptr=0x22;
  196. DWORD _sz;
  197. DWORD sp;
  198. UINT ntrax=1;
  199. WriteBuf(xmi_track0,sizeof(xmi_track0));
  200. while(ptr<sz-4 && *(DWORD*)(buf+ptr)!=EVNT) ptr++;
  201. if (*(DWORD*)(buf+ptr)!=EVNT) goto fail;
  202. // loopstart=0;
  203. _track:
  204. cur_time=wr_time=0;
  205. WriteBufD(_rv('MTrk'));
  206. sp=out.get_size();
  207. WriteBufD(0);
  208. ntrax++;
  209. tr_sz=0;
  210. ptr+=4;
  211. _sz=ptr+4+rev32(*(DWORD*)(buf+ptr));
  212. if (_sz>sz+1) goto fail;
  213. ptr+=4;
  214. _end=0;
  215. {
  216. UINT n;
  217. for(n=0;n<Q_MAX;n++) ch_q[n].time=-1;
  218. }
  219. hasevents=0;
  220. while(ptr<sz-1 && !_end)
  221. {
  222. if ((buf[ptr]&0x80)==0)
  223. {
  224. ptr+=ProcessDelta(buf+ptr);
  225. }
  226. if ((buf[ptr]&0xF0)==0x90)
  227. {
  228. hasevents=1;
  229. ptr+=ProcessNote(buf+ptr);
  230. }
  231. else ptr+=WriteEvent(buf+ptr);
  232. }
  233. if (!hasevents) {out.truncate(sp-4);ntrax--;}
  234. else out.write_dword_ptr(rev32(tr_sz),sp);
  235. if (ptr&1) ptr++;
  236. if (ptr>=sz) goto _e;
  237. if (*(DWORD*)(buf+ptr)==_rv('FORM') && *(DWORD*)(buf+ptr+8)==_rv('XMID'))
  238. {
  239. ptr+=12;
  240. _te: if (ptr&1) ptr++;
  241. if (*(DWORD*)(buf+ptr)==_rv('EVNT')) goto _track;
  242. else if (*(DWORD*)(buf+ptr)==_rv('TIMB'))
  243. {
  244. ptr+=8+rev32(*(DWORD*)(buf+ptr+4));
  245. if (ptr<sz) goto _te;
  246. }
  247. }
  248. _e:
  249. {
  250. WORD w=rev16(ntrax);
  251. out.write_ptr(&w,2,10);
  252. if (ntrax>1)
  253. w=0x200;
  254. out.write_ptr(&w,2,8);
  255. }
  256. mf->size = out.get_size();
  257. mf->data = (BYTE*)out.finish();
  258. if (!mf->data) return 0;
  259. // if (loopstart>0x10) mf->loopstart=loopstart;
  260. #ifdef MF_USE_DMCRAP
  261. if (sz>ptr+0x20 && *(DWORD*)(buf+ptr)==_rv('FORM') && *(DWORD*)(buf+ptr+8)==_rv('XDLS'))
  262. {
  263. DWORD rs=rev32(*(DWORD*)(buf+_sz+4));
  264. if (rs+12+_sz>sz) goto _ret;
  265. if (*(DWORD*)(buf+ptr+0x14)!=_rv('DLS ')) goto _ret;
  266. mf->DLSsize=rs;
  267. mf->pDLSdata=(BYTE*)malloc(rs);
  268. memcpy(mf->pDLSdata,buf+_sz+12,rs);
  269. }
  270. #endif
  271. _ret:
  272. return 1;
  273. fail:
  274. return 0;
  275. }
  276. bool load_xmi(MIDI_file * mf,const BYTE* buf,size_t sz)
  277. {
  278. XMI_cvt c;
  279. return c.run(mf,buf,sz);
  280. }