mbedでmidi(Format 0)を再生

Files at this revision

API Documentation at this revision

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(&note,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(&note,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(&note,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(&note,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(&note,1,1,mid);
+
+                fread(&vel,1,1,mid);
+                //if(ch)break;
+                if(vel==0) {
+                    fread(&note,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(&note,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