aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Input/in_midi/hmi.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Input/in_midi/hmi.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Input/in_midi/hmi.cpp')
-rw-r--r--Src/Plugins/Input/in_midi/hmi.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_midi/hmi.cpp b/Src/Plugins/Input/in_midi/hmi.cpp
new file mode 100644
index 00000000..07b25523
--- /dev/null
+++ b/Src/Plugins/Input/in_midi/hmi.cpp
@@ -0,0 +1,206 @@
+#include "main.h"
+#include "cvt.h"
+
+#define _MThd 'dhTM'
+#define _MTrk 'krTM'
+
+#define tempo 0x188000
+
+#define Q_MAX 128
+
+struct HMI_cvt
+{
+public:
+ struct
+ {
+ DWORD tm;
+ BYTE ch,n;
+ } q_rel[Q_MAX];
+
+ void inline q_add(BYTE ch,BYTE nt,DWORD t)
+ {
+ UINT n=0;
+ while(q_rel[n].tm!=-1) n++;
+ q_rel[n].tm=t;
+ q_rel[n].ch=ch;
+ q_rel[n].n=nt;
+ }
+ grow_buf buf;
+
+ UINT DoTrack(const BYTE* t,UINT *_bw);
+ void DoQueue(DWORD ct,DWORD& tw,BYTE& _run);
+ bool run(MIDI_file * mf,const BYTE* _buf,DWORD sz);
+};
+
+
+#define FixHeader(H) {(H).fmt=rev16((H).fmt);(H).trax=rev16((H).trax);(H).dtx=rev16((H).dtx);}
+
+void HMI_cvt::DoQueue(DWORD ct,DWORD& tw,BYTE& _run)
+{
+ UINT n,mt,_n;
+_t:
+ mt=-1;
+ for(n=0;n<Q_MAX;n++)
+ {
+ if (q_rel[n].tm<mt) {_n=n;mt=q_rel[n].tm;}
+ }
+ if (mt>ct) return;
+ gb_write_delta(buf,mt-tw);
+ tw=mt;
+ BYTE _e=q_rel[_n].ch|0x90;
+ if (_e!=_run) buf.write_byte(_run=_e);
+ buf.write_byte(q_rel[_n].n);
+ buf.write_byte(0);
+ q_rel[_n].tm=-1;
+ goto _t;
+}
+
+extern BYTE ff7loopstart[12];
+
+UINT HMI_cvt::DoTrack(const BYTE* t,UINT *_bw)
+{
+ {
+ UINT n;
+ for(n=0;n<Q_MAX;n++) q_rel[n].tm=-1;
+ }
+ DWORD pt=0;
+ DWORD ct=0,tw=0;
+ BYTE run=0;
+ BYTE _run=0;
+ DWORD bw_s=buf.get_size();
+ while(1)
+ {
+ {
+ unsigned int _d;
+ pt+=DecodeDelta(t+pt,&_d);
+ ct+=_d;
+ }
+ DoQueue(ct,tw,_run);
+ BYTE c=t[pt];
+ if (c==0xFF)
+ {
+ DoQueue(-2,tw,_run);
+ if (t[pt+1]==0x2f)
+ {
+ pt+=3;
+ buf.write_dword(0x002FFF00);
+ break;
+ }
+ return -1;
+
+ }
+ else if (c==0xF0)
+ {
+ gb_write_delta(buf,ct-tw);
+ tw=ct;
+ UINT _p=pt;
+ while(t[pt]!=0xF7) pt++;
+ pt++;
+ buf.write(t+_p,pt-_p);
+ }
+ else if (c==0xFE)
+ {
+ c=t[pt+1];
+ if (c==0x10)
+ {
+ pt+=t[pt+4]+9;
+ }
+ else if (c==0x14)
+ {
+ pt+=4;
+ gb_write_delta(buf,ct-tw);
+ tw=ct;
+ buf.write(ff7loopstart,12);
+ }
+ else if (c==0x15) pt+=8;
+ else return -1;
+ }
+ else
+ {
+ gb_write_delta(buf,ct-tw);
+ tw=ct;
+ if (c&0x80) {pt++;run=c;}
+ else c=run;
+ if (c!=_run) buf.write_byte(_run=c);
+ buf.write_byte(t[pt++]);
+ BYTE c1=c&0xF0;
+ if (c1!=0xC0 && c1!=0xD0) buf.write_byte(t[pt++]);
+ if (c1==0x90)
+ {
+ BYTE b=t[pt-2];
+ unsigned int _t;
+ pt+=DecodeDelta(t+pt,&_t);
+ q_add(c&0xF,b,_t+ct);
+ }
+ }
+ }
+ (*_bw)+=buf.get_size()-bw_s;
+ return pt;
+}
+
+extern BYTE hmp_track0[19]; //hmp.cpp
+
+bool HMI_cvt::run(MIDI_file* mf,const BYTE* _buf,DWORD sz)
+{
+ const BYTE *ptr=_buf;
+
+ while(*(DWORD*)ptr!='CART')
+ {
+ ptr++;
+ if (ptr==_buf+sz) {return 0;}
+ }
+
+ buf.write(0,14);
+
+ ptr-=8;
+ UINT ntrax=1;
+ UINT nft=*(DWORD*)(_buf+0xE4);
+
+ buf.write(hmp_track0,sizeof(hmp_track0));
+
+ UINT n;
+ for(n=0;n<nft;n++)
+ {
+ if (ptr>_buf+sz) return 0;
+ UINT _b=0;
+ ntrax++;
+ buf.write_dword(_rv('MTrk'));
+ DWORD _s=buf.get_size();
+ buf.write(0,4);
+ {
+ const BYTE* p1=ptr+ptr[0x4B];
+ const BYTE* _p=p1+p1[1];
+ p1+=2;
+ while(_p[-1]==' ') _p--;
+ _b=(_p-p1)+4;
+
+ BYTE tmp[3]={0,0xFF,1};
+ buf.write(tmp,3);
+ gb_write_delta(buf,_p-p1);
+ buf.write(p1,_p-p1);
+ p1=_p;
+ }
+ ptr+=ptr[0x57];
+ {
+ DWORD d=DoTrack(ptr,&_b);
+ if (d==-1) return 0;
+ ptr+=d;
+ }
+ buf.write_dword_ptr(rev32(_b),_s);
+ }
+ buf.write_dword_ptr(_rv('MThd'),0);
+ buf.write_dword_ptr(_rv(6),4);
+
+ MIDIHEADER mhd={0x0100,rev16(ntrax),0xC000};
+ buf.write_ptr(&mhd,sizeof(mhd),8);
+
+ mf->size = buf.get_size();
+ mf->data = (BYTE*)buf.finish();
+ return !!mf->data;
+}
+
+bool load_hmi(MIDI_file* mf,const BYTE* _buf,size_t sz)
+{
+ HMI_cvt c;
+ return c.run(mf,_buf,sz);
+} \ No newline at end of file