123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- //(c) 2000-2001 Peter Pawlowski
- //http://www.blorp.com/~peter/
- //based on HMP converter from the MIDI plug-in
- #include <memory.h>
- #include <malloc.h>
- //windoze defines
- typedef unsigned long DWORD;
- typedef unsigned int UINT;
- typedef unsigned char BYTE;
- typedef int BOOL;
- typedef unsigned short WORD;
- #define rev16(X) (((X)&0xFF)<<8)|(((X)>>8)&0xFF)
- #define _rv(X) ((((DWORD)(X)&0xFF)<<24)|(((DWORD)(X)&0xFF00)<<8)|(((DWORD)(X)&0xFF0000)>>8)|(((DWORD)(X)&0xFF000000)>>24))
- #define _MThd 'dhTM'
- #define _MTrk 'krTM'
- #ifndef __GNUC__
- #pragma pack(push)
- #pragma pack(1)
- typedef struct
- {
- WORD fmt,trax,dtx;
- } MIDIHEADER;
- #pragma pack(pop)
- #else
- typedef struct
- {
- WORD fmt __attribute__ ((packed));
- WORD trax __attribute__ ((packed));
- WORD dtx __attribute__ ((packed));
- } MIDIHEADER;
- #endif
- //from MIDI plug-in utils
- class CWriteBuf //handle write-to-memory operations
- {
- public:
- BYTE* buf;
- UINT ptr,sz;
- void* finish(UINT* s);
- void freebuf();
- BOOL write(void* p,UINT s);
- BOOL writeoffs(void* p,UINT s,UINT ofs);
- BOOL writedwordoffs(DWORD dw,UINT ofs);
- BOOL writedword(DWORD d);
- UINT get_offs() {return ptr;}
- BOOL writebyte(BYTE b);
- void setptr(UINT p) {ptr=p;}
- };
- BOOL CWriteBuf::writedwordoffs(DWORD dw,UINT ofs)
- {
- return writeoffs(&dw,4,ofs);
- }
- void* CWriteBuf::finish(UINT* s)
- {
- void* r=0;
- r=realloc(buf,ptr);
- *s=ptr;
- return r;
- }
- void CWriteBuf::freebuf()
- {
- free(buf);
- }
- BOOL CWriteBuf::write(void* p,UINT s)
- {
- UINT np=ptr+s;
- if (np>sz)
- {
- do {
- sz<<=1;
- } while(np>sz);
- buf=(BYTE*)realloc(buf,sz);
- }
- if (p) memcpy(buf+ptr,p,s);
- ptr=np;
- return buf ? 1 : 0;
- }
- CWriteBuf* wb_create()
- {
- CWriteBuf* r=new CWriteBuf;
- if (r)
- {
- r->sz=0x1000;
- r->ptr=0;
- if (!(r->buf=(BYTE*)malloc(r->sz)))
- {
- delete r;
- r=0;
- }
- }
- return r;
- }
- BOOL CWriteBuf::writedword(DWORD dw)
- {
- return write(&dw,4);
- }
- BOOL CWriteBuf::writeoffs(void* p,UINT s,UINT ofs)
- {
- if (ofs+s > ptr) {ptr=ofs;return write(p,s);}
- if (!buf) return 0;
- if (p) memcpy(buf+ofs,p,s);
- return 1;
- }
- BOOL CWriteBuf::writebyte(BYTE b)
- {
- if (!buf) {ptr++;return 0;}
- if (ptr==sz) return write(&b,1);
- buf[ptr++]=b;
- return 1;
- }
- CWriteBuf* wb_create();
- static DWORD ProcessTrack(BYTE* track,CWriteBuf* buf,int size)
- {
- UINT s_sz=buf->get_offs();
- BYTE *pt = track;
- BYTE lc1 = 0,lastcom = 0;
- DWORD t=0,d;
- bool run = 0;
- int n1,n2;
- while(track < pt + size)
- {
- if (track[0]&0x80)
- {
- BYTE b=track[0]&0x7F;
- buf->writebyte(b);
- t+=b;
- }
- else
- {
- d = (track[0])&0x7F;
- n1 = 0;
- while((track[n1]&0x80)==0)
- {
- n1++;
- d+=(track[n1]&0x7F)<<(n1*7);
- }
- t+=d;
-
- n1 = 1;
- while((track[n1]&0x80)==0)
- {
- n1++;
- if (n1==4) return 0;
- }
- for(n2=0;n2<=n1;n2++)
- {
- BYTE b=track[n1-n2]&0x7F;
-
- if (n2!=n1) b|=0x80;
- buf->writebyte(b);
- }
- track+=n1;
- }
- track++;
- if (*track == 0xFF)//meta
- {
- buf->write(track,3+track[2]);
- if (track[1]==0x2F) break;
- }
- else
- {
- lc1=track[0];
- if ((lc1&0x80) == 0) return 0;
- switch(lc1&0xF0)
- {
- case 0x80:
- case 0x90:
- case 0xA0:
- case 0xB0:
- case 0xE0:
- if (lc1!=lastcom)
- {
- buf->writebyte(lc1);
- }
- buf->write(track+1,2);
- track+=3;
- break;
- case 0xC0:
- case 0xD0:
- if (lc1!=lastcom)
- {
- buf->writebyte(lc1);
- }
- buf->writebyte(track[1]);
- track+=2;
- break;
- default:
- return 0;
- }
- lastcom=lc1;
- }
- }
- return buf->get_offs()-s_sz;
- }
- #define FixHeader(H) {(H).fmt=rev16((H).fmt);(H).trax=rev16((H).trax);(H).dtx=rev16((H).dtx);}
- BYTE hmp_track0[19]={'M','T','r','k',0,0,0,11,0,0xFF,0x51,0x03,0x18,0x80,0x00,0,0xFF,0x2F,0};
- //buf = HMP image, br = HMP image size, out_size = output MIDI image size
- extern "C" void* load_hmp(BYTE* buf,DWORD br,DWORD* out_size)
- {
- MIDIHEADER mhd = {1,0,0xC0};
- BYTE * max = buf+br;
- BYTE* ptr = buf;
- CWriteBuf* dst=wb_create();
- DWORD n1,n2;
- dst->writedword(_rv('MThd'));
- dst->writedword(_rv(6));
- dst->write(0,sizeof(mhd));
- ptr = buf+0x30;
- mhd.trax = *ptr;
- dst->write(hmp_track0,sizeof(hmp_track0));
- while(*(WORD*)ptr != 0x2FFF && ptr < max - 4-7) ptr++;
- ptr+=7;
- if (ptr == max-4) { dst->freebuf(); delete dst; return 0; }
- UINT n;
- for(n=1;n<mhd.trax;n++)
- {
- dst->writedword(_rv('MTrk'));
- n1 = *(DWORD*)ptr - 12;
- if (ptr + n1 > max) { dst->freebuf(); delete dst; return 0; }
- ptr += 8;
-
- UINT ts_ofs=dst->get_offs();
- dst->writedword(0);
- if (!(n2=ProcessTrack(ptr,dst,n1)))
- { dst->freebuf(); delete dst; return 0; }
-
- dst->writedwordoffs(_rv(n2),ts_ofs);
- ptr += n1 + 4;
- }
- FixHeader(mhd);
- dst->writeoffs(&mhd,sizeof(mhd),8);
- UINT f_sz;
- BYTE* r=(BYTE*)dst->finish(&f_sz);
- delete dst;
- if (r)
- {
- if (out_size) *out_size=f_sz;
- return r;
- }
- else
- {
- return 0;
- }
- }
|