mbedでmidi(Format 0)を再生
Diff: midi.cpp
- Revision:
- 0:7c17c3b3a8d7
- Child:
- 1:250e7251f8fc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/midi.cpp Tue Jul 15 09:45:03 2014 +0000 @@ -0,0 +1,377 @@ +#include "mbed.h" +#include "midi.h" +#define STEP 8 +Serial pc(USBTX,USBRX);//tx,rx +midi::midi(PinName _bzr):bzr(_bzr) +{ + //frequency of equal temperament(octave:4) + freq[0]=261.626;//C(do) + freq[1]=277.183;//C# + freq[2]=293.665;//D + freq[3]=311.127;//D# + freq[4]=329.628;//E + freq[5]=349.228;//F + freq[6]=369.994;//F# + freq[7]=391.995;//G + freq[8]=415.305;//G# + freq[9]=440.000;//A + freq[10]=466.164;//A# + freq[11]=493.883;//B + + table=new float[STEP]; + for(int i=0; i<STEP; i++)table[i]=sin(i/(STEP/8.0)*atan(1.0)); + + + +} +/* +midi::~midi(){ + delete(cache); +} +*/ +template<class X> +void midi::change_endian(X *raw,int byte) +{ + X tmp=0; + for(int i=0; i<byte; i++)for(int j=0; j<8; j++)tmp+=((*raw&(1<<((byte-i-1)*8+j)))>>((byte-i-1)*8+j))<<(i*8+j); + *raw=tmp; +} + +void midi::read(const char *path) +{ + + FILE *mid,*cache; + short int pbend; + 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; + 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); + change_endian(&crochet,2); + + + + + + fseek(mid, 4, SEEK_CUR); + 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(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; + //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==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; + //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: + 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 end1; + 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; + //fseek(mid, 1, SEEK_CUR); + 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 { + + + //fseek(mid, 1, SEEK_CUR); + //fread(&tmp,1,1,mid); + +MIDIEVENT: + if(0x80<=tmp&&tmp<=0xEF)prev=tmp; + 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); + + tm.push_back(time); + //ev.push_back(109); + ca.push_back(ch); + fq.push_back(0); + //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); + + + tm.push_back(time); + //ev.push_back(109); + ca.push_back(ch); + fq.push_back(frequency[ch]); + //vo.push_back(vel/127.0); + } + + 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; + fseek(mid, -1, SEEK_CUR); + pc.printf(" ->%x\r\n",tmp); + goto MIDIEVENT; + } + } + } +end1: + fclose(mid); + + pc.printf("Loading complete.\r\n"); +} + + + + +void midi::play() +{ + + //FILE *fp; + AnalogOut buzzer(bzr); + int time, /*event, */ch; + float *frequency/*,tmp,tmp2,vel[16]*/; + //if((fp = fopen(path, "r")) == NULL)goto end; + //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; + + + pi=tm.begin(); + time=*pi; + tm.pop_front(); + + pi=ev.begin(); + event=*pi; + ev.pop_front(); + + pi=ca.begin(); + ch=*pi; + ca.pop_front(); + + pd=fq.begin(); + frequency[ch]=*pd; + fq.pop_front(); + + pd=vo.begin(); + vel[ch]=*pd; + vo.pop_front(); +*/ + + t.reset(); + t.start(); + time=0; + while(1) { +//static int count=0; +//pc.printf("%d\r\n",count++); + 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(); +*/ + pch=ca.begin(); + ch=*pch; + ca.pop_front(); + + + + pf=fq.begin(); + frequency[ch]=*pf; + fq.pop_front(); + /* + pd=vo.begin(); + vel[ch]=*pd; + vo.pop_front(); + */ + //pc.printf("%d %d %d %lf %lf\r\n",time,event,ch,frequency[ch],vel[ch]); + } else break; + } + float voltage=0; + 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); +} \ No newline at end of file