aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_midi/mus.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/Input/in_midi/mus.cpp')
-rw-r--r--Src/Plugins/Input/in_midi/mus.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_midi/mus.cpp b/Src/Plugins/Input/in_midi/mus.cpp
new file mode 100644
index 00000000..18aeb4f4
--- /dev/null
+++ b/Src/Plugins/Input/in_midi/mus.cpp
@@ -0,0 +1,184 @@
+#include "main.h"
+#include "cvt.h"
+
+bool is_mus(const BYTE* buf,size_t s)
+{
+ if (s>0x20 && *(DWORD*)buf == '\x1ASUM')
+ {
+ int ofs = ((WORD*)buf)[3];
+ int n_ins = ((WORD*)buf)[6];
+ if (ofs>=16+(n_ins<<1) && ofs<16+(n_ins<<2) && ofs<s)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static BYTE tempodat[] = {0x00,0xFF,0x51,0x03,0x09,0xA3,0x1A};
+
+static BYTE controllers[15] = {0,0,1,7,10,11,91,93,64,67,120,123,126,127,121};
+
+#define abort _abort_
+
+struct MUS_cvt
+{
+public:
+ bool abort;
+ DWORD ct;
+ DWORD lt;
+ grow_buf out;
+
+ void AddEvent(DWORD ev,int l);
+ bool run(MIDI_file* mf,const BYTE* ptr,DWORD sz);
+};
+
+void MUS_cvt::AddEvent(DWORD ev,int l)
+{
+ DWORD dt = ct - lt;
+ int tl=3;
+ gb_write_delta(out,dt);
+ lt = ct;
+ BYTE ec=(BYTE)(ev&0xF0);
+ out.write(&ev,l);
+}
+
+bool MUS_cvt::run(MIDI_file* mf,const BYTE* ptr,DWORD sz)
+{
+#pragma pack(push)
+#pragma pack(1)
+ struct
+ {
+ char id[4];
+ WORD len;
+ WORD ofs;
+ WORD ch1,ch2;
+ WORD n_ins;
+ WORD dummy;
+ } hdr;
+#pragma pack(pop)
+ DWORD _pt=0;
+ memcpy(&hdr,ptr,sizeof(hdr));
+ const BYTE* score = ptr+sizeof(hdr)+2*hdr.n_ins;
+ long x;
+
+ static BYTE _hd_[]={'M','T','h','d',0,0,0,6, 0,0,0,1,0,0x59,'M','T','r','k'};
+ out.write(_hd_,sizeof(_hd_));
+ DWORD ts_ofs=out.get_size();
+ out.write_dword(0);
+
+ lt=0;
+ abort = 0;
+ ct = 0;
+ out.write(tempodat,sizeof(tempodat));
+
+ x=0;
+ bool t;
+ BYTE ch;
+ BYTE vols[16];
+ ZeroMemory(vols,sizeof(vols));
+ union
+ {
+ BYTE b[4];
+ DWORD dw;
+ } ev;
+ while(x<hdr.len && score[x]!=0x60)
+ {
+ ev.dw = 0;
+ t=(score[x]&0x80)?1:0;
+ ch = score[x]&0xF;
+ if (ch == 0xF) ch = 9;//hdr.ch1+1;
+ else if (ch>=9) ch++;
+ switch(score[x]&0x70)
+ {
+ case 0: //release note
+ ev.b[0]=0x80|ch;
+ ev.b[1]=score[x+1];
+ ev.b[2]=0;//vols[ch];
+ AddEvent(ev.dw,3);
+ x+=2;
+ break;
+ case 0x10: //play note
+ ev.b[0]=0x90|ch;
+ ev.b[1]=score[x+1]&0x7F;
+ if (score[x+1]&0x80)
+ {
+ vols[ch]=score[x+2];
+ x+=3;
+ }
+ else
+ {
+ x+=2;
+ }
+ ev.b[2]=vols[ch];
+ AddEvent(ev.dw,3);
+ break;
+ case 0x20: //pitch wheel
+ ev.b[0]=0xE0|ch;
+ ev.b[1]=0;
+ ev.b[2]=score[x+1]>>1;
+ AddEvent(ev.dw,3);
+ x+=2;
+ break;
+ case 0x30: //system event
+ if (score[x+1]>=10 && score[x+1]<=14)
+ {
+ ev.b[0]=0xB0|ch;
+ ev.b[1]=controllers[score[x+1]];
+ ev.b[2]=1;
+ AddEvent(ev.dw,3);
+ x+=2;
+ break;
+ }
+ else return 0;
+ case 0x40: //change controller
+ if (score[x+1])
+ {
+ if (score[x+1]<10)
+ {
+ ev.b[0]=0xB0|ch;
+ ev.b[1]=controllers[score[x+1]];
+ ev.b[2]=score[x+2];
+ AddEvent(ev.dw,3);
+ x+=3;
+ }
+ else return 0;
+ }
+ else
+ {
+ ev.b[0]=0xC0|ch;
+ ev.b[1]=score[x+2];
+ AddEvent(ev.dw,2);
+ x+=3;
+ };
+ break;
+ case 0x50:
+ case 0x70:
+ case 0x60:
+ return 0;
+ }
+ if (abort) return 0;
+ if (t)
+ {
+ DWORD dt=0;
+ do
+ {
+ dt = (dt<<7) + (score[x]&0x7F);
+ } while(score[x++]&0x80);
+ ct+=dt;
+ }
+ }
+
+ out.write_dword(0x002FFF00);
+ out.write_dword_ptr(rev32(out.get_size()-(ts_ofs+4)),ts_ofs);
+
+ mf->size = out.get_size();
+ mf->data = (BYTE*)out.finish();
+ return !!mf->data;
+}
+
+bool load_mus(MIDI_file* mf,const BYTE* ptr,size_t sz)
+{
+ MUS_cvt c;
+ return c.run(mf,ptr,sz);
+} \ No newline at end of file