mbedでmidi(Format 0)を再生
Revision 1:250e7251f8fc, committed 2014-08-09
- Comitter:
- Naoto_111
- Date:
- Sat Aug 09 09:29:31 2014 +0000
- Parent:
- 0:7c17c3b3a8d7
- Commit message:
- play_realtime???; ???????1????????????4
Changed in this revision
midi.cpp | Show annotated file Show diff for this revision Revisions of this file |
midi.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 7c17c3b3a8d7 -r 250e7251f8fc midi.cpp --- a/midi.cpp Tue Jul 15 09:45:03 2014 +0000 +++ b/midi.cpp Sat Aug 09 09:29:31 2014 +0000 @@ -1,6 +1,6 @@ #include "mbed.h" #include "midi.h" -#define STEP 8 +#define STEP 20 Serial pc(USBTX,USBRX);//tx,rx midi::midi(PinName _bzr):bzr(_bzr) { @@ -18,9 +18,10 @@ freq[10]=466.164;//A# freq[11]=493.883;//B - table=new float[STEP]; + //sine + table=new double[STEP]; for(int i=0; i<STEP; i++)table[i]=sin(i/(STEP/8.0)*atan(1.0)); - + } @@ -29,6 +30,7 @@ delete(cache); } */ + template<class X> void midi::change_endian(X *raw,int byte) { @@ -37,6 +39,14 @@ *raw=tmp; } +int midi::powi(int a) +{ + int tmp=1; + for(int i=0; i<a; i++)tmp=tmp<<1; + return tmp; +} + + void midi::read(const char *path) { @@ -45,31 +55,16 @@ long int dtime,len; int time,ch; float frequency[16]; - char note,ctrl,value,prgm,prsr; - unsigned char tmp2[64]; - char vel; - unsigned char tmp; - char prev; + char note,ctrl,value,prgm,prsr,vel,prev; + unsigned char tmp,tmp2[64]; + time=tmp=prev=tempo=chmax=0; if((mid = fopen(path, "rb")) == NULL)goto end1; - - - - - - - - - - - - fseek(mid, 10, SEEK_SET); fread(&tracks,2,1,mid); - //fseek(mid, 2, SEEK_CUR); fread(&crochet,2,1,mid); change_endian(&tracks,2); @@ -83,32 +78,29 @@ fread(&len,4,1,mid); change_endian(&len,4); while(1) { - //fseek(mid, 1, SEEK_CUR); fread(&tmp,1,1,mid); dtime=0; int i; for(i=0; i<4; i++) { int flag= (tmp&128)==0 ? 1:0; - + if(tmp&128)tmp2[i]=tmp-0x80; else tmp2[i]=tmp; if(flag)break; - //fseek(mid, 1, SEEK_CUR); fread(&tmp,1,1,mid); } for(int j=0; j<=i; j++)dtime+=((long int)tmp2[j]<<(7*(i-j))); time+=(int)tempo*((float)dtime/crochet); - - //fseek(mid, 1, SEEK_CUR); + fread(&tmp,1,1,mid); //pc.printf("%d %d\r\n",time,tm.size()*4*1+fq.size()*4*1+ca.size()); -if(tm.size()>640){ - pc.printf("Memory shortage!\r\n"); - goto end1; - -} + if(tm.size()>640) { + pc.printf("Memory shortage!\r\n"); + goto end1; + + } if(tmp==0xF0) { len=0; i=0; @@ -116,10 +108,9 @@ for(i=0; i<4; i++) { int flag= (tmp&128)==0 ? 1:0; - + tmp2[i]=((tmp<<1)>>1); if(flag)break; - //fseek(mid, 1, SEEK_CUR); fread(&tmp,1,1,mid); } @@ -136,13 +127,11 @@ int flag= (tmp&128)==0 ? 1:0; tmp2[i]=((tmp<<1)>>1); if(flag)break; - //fseek(mid, 1, SEEK_CUR); fread(&tmp,1,1,mid); } for(int j=i; j>=0; j--)len+=((long int)tmp2[j]<<(7*j)); fseek(mid, len, SEEK_CUR); } else if(tmp==0xFF) { - //fseek(mid, 1, SEEK_CUR); fread(&tmp,1,1,mid); switch(tmp) { case 0x00: @@ -197,7 +186,6 @@ int flag= (tmp&128)==0 ? 1:0; tmp2[i]=((tmp<<1)>>1); if(flag)break; - //fseek(mid, 1, SEEK_CUR); fread(&tmp,1,1,mid); } @@ -222,7 +210,6 @@ if(0x80<=tmp&&tmp<=0x8F) { //note off ch=tmp-0x80; if(chmax<ch)chmax=ch; - //fseek(mid, 1, SEEK_CUR); fread(¬e,1,1,mid); fseek(mid, 1, SEEK_CUR); @@ -233,11 +220,9 @@ //vo.push_back(0); } else if(0x90<=tmp&&tmp<=0x9F) { //note on ch=tmp-0x90; - //fseek(mid, 1, SEEK_CUR); fread(¬e,1,1,mid); frequency[ch]=freq[note%12]*pow(2.0,(note/12-5.0)); - //fseek(mid, 1, SEEK_CUR); fread(&vel,1,1,mid); @@ -250,29 +235,22 @@ else if(0xA0<=tmp&&tmp<=0xAF) { //polyphonic key pressure ch=tmp-0xA0; - //fseek(mid, 1, SEEK_CUR); fread(¬e,1,1,mid); - //fseek(mid, 1, SEEK_CUR); fread(&vel,1,1,mid); } else if(0xB0<=tmp&&tmp<=0xBF) { //control change ch=tmp-0xB0; - //fseek(mid, 1, SEEK_CUR); fread(&ctrl,1,1,mid); - //fseek(mid, 1, SEEK_CUR); fread(&value,1,1,mid); } else if(0xC0<=tmp&&tmp<=0xCF) { //program change ch=tmp-0xC0; - //fseek(mid, 1, SEEK_CUR); fread(&prgm,1,1,mid); } else if(0xD0<=tmp&&tmp<=0xDF) { //channel pressure ch=tmp-0x90; - //fseek(mid, 1, SEEK_CUR); fread(&prsr,1,1,mid); } else if(0xE0<=tmp&&tmp<=0xEF) { //pitch bend ch=tmp-0xE0; - //fseek(mid, 1, SEEK_CUR); fread(&pbend,2,1,mid); } else { //running status tmp=prev; @@ -291,7 +269,7 @@ -void midi::play() +void midi::play(/*int repeat*/) { //FILE *fp; @@ -302,31 +280,31 @@ //if(fscanf(fp,"%d\n",&tracks)==EOF)goto end; frequency=new float[chmax+1]; for(int i=0; i<=chmax; i++)frequency[i]=0; - -/* - if(!tm.empty())goto end; + + /* + if(!tm.empty())goto end; - pi=tm.begin(); - time=*pi; - tm.pop_front(); + pi=tm.begin(); + time=*pi; + tm.pop_front(); - pi=ev.begin(); - event=*pi; - ev.pop_front(); + pi=ev.begin(); + event=*pi; + ev.pop_front(); - pi=ca.begin(); - ch=*pi; - ca.pop_front(); + pi=ca.begin(); + ch=*pi; + ca.pop_front(); - pd=fq.begin(); - frequency[ch]=*pd; - fq.pop_front(); + pd=fq.begin(); + frequency[ch]=*pd; + fq.pop_front(); - pd=vo.begin(); - vel[ch]=*pd; - vo.pop_front(); -*/ + pd=vo.begin(); + vel[ch]=*pd; + vo.pop_front(); + */ t.reset(); t.start(); @@ -337,22 +315,22 @@ int now=t.read_us(); while(1) { if(time<=now) { - + if(tm.empty())return; - + pi=tm.begin(); time=*pi; if(time>=now)break; tm.pop_front(); -/* - pi=ev.begin(); - event=*pi; - ev.pop_front(); -*/ + /* + pi=ev.begin(); + event=*pi; + ev.pop_front(); + */ pch=ca.begin(); ch=*pch; ca.pop_front(); - + pf=fq.begin(); @@ -370,8 +348,227 @@ for(int i=0; i<=chmax; i++)voltage+=/*vel[i]*/(0.5/(chmax+1))*table[(int)(STEP*frequency[i]*now/1000000)%STEP]; //for(int i=0;i<tracks;i++)voltage+=(0.5/tracks)*sin(2*pi*frequency[i]*now/1000000); buzzer=0.5+voltage; - + } //end: //fclose(fp); +} + + + + +void midi::play_realtime(const char *path/*, int repeat*/) +{ + FILE *mid; + short int pbend; + long int dtime,len,time,ch; + char note,ctrl,value,prgm,prsr,vel,prev; + unsigned char tmp,tmp2[64]; + AnalogOut buzzer(bzr); + + time=tmp=prev=tempo=chmax=0; + + if((mid = fopen(path, "rb")) == NULL)return; + + fseek(mid, 10, SEEK_SET); + fread(&tracks,2,1,mid); + fread(&crochet,2,1,mid); + + change_endian(&tracks,2); + change_endian(&crochet,2); + + fseek(mid, 4, SEEK_CUR); + fread(&len,4,1,mid); + change_endian(&len,4); + t.reset(); + t.start(); + while(1) { + fread(&tmp,1,1,mid); + +//delta time + dtime=0; + int i; + for(i=0; i<4; i++) { + int flag= (tmp&128)==0 ? 1:0; + + if(tmp&128)tmp2[i]=tmp-0x80; + else tmp2[i]=tmp; + if(flag)break; + fread(&tmp,1,1,mid); + } + for(int j=0; j<=i; j++)dtime+=((long int)tmp2[j]<<(7*(i-j))); + time+=(int)tempo*((double)dtime/crochet); + + + while(t.read_us()<time) { + double voltage=0; + for(list<int>::iterator i =no.begin(); i!=no.end(); i++)voltage+=/*vel[i]*/(0.5/4)*table[(int)(STEP* (freq[*i%12]*powi(*i/12-5)) *t.read_us()/1000000)%STEP]; + buzzer=0.5+voltage; + } + +//event + fread(&tmp,1,1,mid); + + //meta event + if(tmp==0xF0) { + len=0; + i=0; + fread(&tmp,1,1,mid); + + for(i=0; i<4; i++) { + int flag= (tmp&128)==0 ? 1:0; + + tmp2[i]=((tmp<<1)>>1); + if(flag)break; + fread(&tmp,1,1,mid); + + } + + for(int j=i; j>=0; j--)len+=((long int)tmp2[j]<<(7*j)); + + fseek(mid, len, SEEK_CUR); + + } else if(tmp==0xF7) { + len=0; + i=0; + fread(&tmp,1,1,mid); + for(i=0; i<4; i++) { + int flag= (tmp&128)==0 ? 1:0; + tmp2[i]=((tmp<<1)>>1); + if(flag)break; + fread(&tmp,1,1,mid); + } + for(int j=i; j>=0; j--)len+=((long int)tmp2[j]<<(7*j)); + fseek(mid, len, SEEK_CUR); + } else if(tmp==0xFF) { + fread(&tmp,1,1,mid); + switch(tmp) { + case 0x00: + case 0x59: + fseek(mid, 3, SEEK_CUR); + break; + + case 0x20: + case 0x21: + fseek(mid, 2, SEEK_CUR); + break; + + case 0x54: + fseek(mid, 6, SEEK_CUR); + break; + + case 0x2F://End of Track + + goto end2; + break; + + case 0x51://Tempo + fseek(mid, 1, SEEK_CUR); + fread(&tempo,3,1,mid); + change_endian(&tempo,3); + //pc.printf("tempo=%x\r\n",tempo); + break; + + case 0x58://Time Signature + fseek(mid, 5, SEEK_CUR); + break; + + /*case 0x59://Key Signature + + break; + */ + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x7F: + len=0; + i=0; + fread(&tmp,1,1,mid); + + for(i=0; i<4; i++) { + int flag= (tmp&128)==0 ? 1:0; + tmp2[i]=((tmp<<1)>>1); + if(flag)break; + fread(&tmp,1,1,mid); + + } + + for(int j=i; j>=0; j--)len+=((unsigned long int)tmp2[j]<<(7*j)); + + fseek(mid, len, SEEK_CUR); + + break; + + default: + break; + } + } else {//midi event + + + //fseek(mid, 1, SEEK_CUR); + //fread(&tmp,1,1,mid); + +MIDIEVENT: + if(0x80<=tmp&&tmp<=0xEF)prev=tmp;//running status + if(0x80<=tmp&&tmp<=0x8F) { //note off + ch=tmp-0x80; + fread(¬e,1,1,mid); + fseek(mid, 1, SEEK_CUR); + //if(ch)break; + list<int>::iterator i =no.begin(); + for(; i!=no.end(); i++)if(*i==note)break; + no.erase(i); + } else if(0x90<=tmp&&tmp<=0x9F) { //note on + ch=tmp-0x90; + fread(¬e,1,1,mid); + + fread(&vel,1,1,mid); + //if(ch)break; + if(vel==0) { + fread(¬e,1,1,mid); + fseek(mid, 1, SEEK_CUR); + list<int>::iterator i =no.begin(); + for(; i!=no.end(); i++)if(*i==note)break; + no.erase(i); + + } else no.push_back(note); + } + + else if(0xA0<=tmp&&tmp<=0xAF) { //polyphonic key pressure + ch=tmp-0xA0; + fread(¬e,1,1,mid); + fread(&vel,1,1,mid); + } else if(0xB0<=tmp&&tmp<=0xBF) { //control change + ch=tmp-0xB0; + fread(&ctrl,1,1,mid); + fread(&value,1,1,mid); + } else if(0xC0<=tmp&&tmp<=0xCF) { //program change + ch=tmp-0xC0; + fread(&prgm,1,1,mid); + } else if(0xD0<=tmp&&tmp<=0xDF) { //channel pressure + ch=tmp-0x90; + fread(&prsr,1,1,mid); + } else if(0xE0<=tmp&&tmp<=0xEF) { //pitch bend + ch=tmp-0xE0; + fread(&pbend,2,1,mid); + } else { //running status + tmp=prev; + fseek(mid, -1, SEEK_CUR); + pc.printf(" ->%x\r\n",tmp); + goto MIDIEVENT; + } + } + + + + } + +end2: + fclose(mid); } \ No newline at end of file
diff -r 7c17c3b3a8d7 -r 250e7251f8fc midi.h --- a/midi.h Tue Jul 15 09:45:03 2014 +0000 +++ b/midi.h Sat Aug 09 09:29:31 2014 +0000 @@ -9,17 +9,20 @@ midi(PinName _bzr); //~midi(); void read(const char *path); - void play(); + void play(/*int repeat*/); + void play_realtime(const char *path/*, int repeat*/); private: - list<int> tm; + list<int> tm;//tempo //list<int> ev; - list<char> ca; - list<float> fq; + list<char> ca;//channel + list<float> fq;//frequency //list<float> vo; + list<int> no;//note list<char>::iterator pch; list<int>::iterator pi; list<float>::iterator pf; + list<int>::iterator pn; Timer t; PinName bzr; int chmax; @@ -27,9 +30,10 @@ unsigned short int tracks; unsigned short int crochet; long int tempo; - float freq[12]; - float *table; + double freq[12]; + double *table; template<class X> void change_endian(X *raw,int byte); + int powi(int a); }; #endif \ No newline at end of file