hmp.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. //(c) 2000-2001 Peter Pawlowski
  2. //http://www.blorp.com/~peter/
  3. //based on HMP converter from the MIDI plug-in
  4. #include <memory.h>
  5. #include <malloc.h>
  6. //windoze defines
  7. typedef unsigned long DWORD;
  8. typedef unsigned int UINT;
  9. typedef unsigned char BYTE;
  10. typedef int BOOL;
  11. typedef unsigned short WORD;
  12. #define rev16(X) (((X)&0xFF)<<8)|(((X)>>8)&0xFF)
  13. #define _rv(X) ((((DWORD)(X)&0xFF)<<24)|(((DWORD)(X)&0xFF00)<<8)|(((DWORD)(X)&0xFF0000)>>8)|(((DWORD)(X)&0xFF000000)>>24))
  14. #define _MThd 'dhTM'
  15. #define _MTrk 'krTM'
  16. #ifndef __GNUC__
  17. #pragma pack(push)
  18. #pragma pack(1)
  19. typedef struct
  20. {
  21. WORD fmt,trax,dtx;
  22. } MIDIHEADER;
  23. #pragma pack(pop)
  24. #else
  25. typedef struct
  26. {
  27. WORD fmt __attribute__ ((packed));
  28. WORD trax __attribute__ ((packed));
  29. WORD dtx __attribute__ ((packed));
  30. } MIDIHEADER;
  31. #endif
  32. //from MIDI plug-in utils
  33. class CWriteBuf //handle write-to-memory operations
  34. {
  35. public:
  36. BYTE* buf;
  37. UINT ptr,sz;
  38. void* finish(UINT* s);
  39. void freebuf();
  40. BOOL write(void* p,UINT s);
  41. BOOL writeoffs(void* p,UINT s,UINT ofs);
  42. BOOL writedwordoffs(DWORD dw,UINT ofs);
  43. BOOL writedword(DWORD d);
  44. UINT get_offs() {return ptr;}
  45. BOOL writebyte(BYTE b);
  46. void setptr(UINT p) {ptr=p;}
  47. };
  48. BOOL CWriteBuf::writedwordoffs(DWORD dw,UINT ofs)
  49. {
  50. return writeoffs(&dw,4,ofs);
  51. }
  52. void* CWriteBuf::finish(UINT* s)
  53. {
  54. void* r=0;
  55. r=realloc(buf,ptr);
  56. *s=ptr;
  57. return r;
  58. }
  59. void CWriteBuf::freebuf()
  60. {
  61. free(buf);
  62. }
  63. BOOL CWriteBuf::write(void* p,UINT s)
  64. {
  65. UINT np=ptr+s;
  66. if (np>sz)
  67. {
  68. do {
  69. sz<<=1;
  70. } while(np>sz);
  71. buf=(BYTE*)realloc(buf,sz);
  72. }
  73. if (p) memcpy(buf+ptr,p,s);
  74. ptr=np;
  75. return buf ? 1 : 0;
  76. }
  77. CWriteBuf* wb_create()
  78. {
  79. CWriteBuf* r=new CWriteBuf;
  80. if (r)
  81. {
  82. r->sz=0x1000;
  83. r->ptr=0;
  84. if (!(r->buf=(BYTE*)malloc(r->sz)))
  85. {
  86. delete r;
  87. r=0;
  88. }
  89. }
  90. return r;
  91. }
  92. BOOL CWriteBuf::writedword(DWORD dw)
  93. {
  94. return write(&dw,4);
  95. }
  96. BOOL CWriteBuf::writeoffs(void* p,UINT s,UINT ofs)
  97. {
  98. if (ofs+s > ptr) {ptr=ofs;return write(p,s);}
  99. if (!buf) return 0;
  100. if (p) memcpy(buf+ofs,p,s);
  101. return 1;
  102. }
  103. BOOL CWriteBuf::writebyte(BYTE b)
  104. {
  105. if (!buf) {ptr++;return 0;}
  106. if (ptr==sz) return write(&b,1);
  107. buf[ptr++]=b;
  108. return 1;
  109. }
  110. CWriteBuf* wb_create();
  111. static DWORD ProcessTrack(BYTE* track,CWriteBuf* buf,int size)
  112. {
  113. UINT s_sz=buf->get_offs();
  114. BYTE *pt = track;
  115. BYTE lc1 = 0,lastcom = 0;
  116. DWORD t=0,d;
  117. bool run = 0;
  118. int n1,n2;
  119. while(track < pt + size)
  120. {
  121. if (track[0]&0x80)
  122. {
  123. BYTE b=track[0]&0x7F;
  124. buf->writebyte(b);
  125. t+=b;
  126. }
  127. else
  128. {
  129. d = (track[0])&0x7F;
  130. n1 = 0;
  131. while((track[n1]&0x80)==0)
  132. {
  133. n1++;
  134. d+=(track[n1]&0x7F)<<(n1*7);
  135. }
  136. t+=d;
  137. n1 = 1;
  138. while((track[n1]&0x80)==0)
  139. {
  140. n1++;
  141. if (n1==4) return 0;
  142. }
  143. for(n2=0;n2<=n1;n2++)
  144. {
  145. BYTE b=track[n1-n2]&0x7F;
  146. if (n2!=n1) b|=0x80;
  147. buf->writebyte(b);
  148. }
  149. track+=n1;
  150. }
  151. track++;
  152. if (*track == 0xFF)//meta
  153. {
  154. buf->write(track,3+track[2]);
  155. if (track[1]==0x2F) break;
  156. }
  157. else
  158. {
  159. lc1=track[0];
  160. if ((lc1&0x80) == 0) return 0;
  161. switch(lc1&0xF0)
  162. {
  163. case 0x80:
  164. case 0x90:
  165. case 0xA0:
  166. case 0xB0:
  167. case 0xE0:
  168. if (lc1!=lastcom)
  169. {
  170. buf->writebyte(lc1);
  171. }
  172. buf->write(track+1,2);
  173. track+=3;
  174. break;
  175. case 0xC0:
  176. case 0xD0:
  177. if (lc1!=lastcom)
  178. {
  179. buf->writebyte(lc1);
  180. }
  181. buf->writebyte(track[1]);
  182. track+=2;
  183. break;
  184. default:
  185. return 0;
  186. }
  187. lastcom=lc1;
  188. }
  189. }
  190. return buf->get_offs()-s_sz;
  191. }
  192. #define FixHeader(H) {(H).fmt=rev16((H).fmt);(H).trax=rev16((H).trax);(H).dtx=rev16((H).dtx);}
  193. BYTE hmp_track0[19]={'M','T','r','k',0,0,0,11,0,0xFF,0x51,0x03,0x18,0x80,0x00,0,0xFF,0x2F,0};
  194. //buf = HMP image, br = HMP image size, out_size = output MIDI image size
  195. extern "C" void* load_hmp(BYTE* buf,DWORD br,DWORD* out_size)
  196. {
  197. MIDIHEADER mhd = {1,0,0xC0};
  198. BYTE * max = buf+br;
  199. BYTE* ptr = buf;
  200. CWriteBuf* dst=wb_create();
  201. DWORD n1,n2;
  202. dst->writedword(_rv('MThd'));
  203. dst->writedword(_rv(6));
  204. dst->write(0,sizeof(mhd));
  205. ptr = buf+0x30;
  206. mhd.trax = *ptr;
  207. dst->write(hmp_track0,sizeof(hmp_track0));
  208. while(*(WORD*)ptr != 0x2FFF && ptr < max - 4-7) ptr++;
  209. ptr+=7;
  210. if (ptr == max-4) { dst->freebuf(); delete dst; return 0; }
  211. UINT n;
  212. for(n=1;n<mhd.trax;n++)
  213. {
  214. dst->writedword(_rv('MTrk'));
  215. n1 = *(DWORD*)ptr - 12;
  216. if (ptr + n1 > max) { dst->freebuf(); delete dst; return 0; }
  217. ptr += 8;
  218. UINT ts_ofs=dst->get_offs();
  219. dst->writedword(0);
  220. if (!(n2=ProcessTrack(ptr,dst,n1)))
  221. { dst->freebuf(); delete dst; return 0; }
  222. dst->writedwordoffs(_rv(n2),ts_ofs);
  223. ptr += n1 + 4;
  224. }
  225. FixHeader(mhd);
  226. dst->writeoffs(&mhd,sizeof(mhd),8);
  227. UINT f_sz;
  228. BYTE* r=(BYTE*)dst->finish(&f_sz);
  229. delete dst;
  230. if (r)
  231. {
  232. if (out_size) *out_size=f_sz;
  233. return r;
  234. }
  235. else
  236. {
  237. return 0;
  238. }
  239. }