home *** CD-ROM | disk | FTP | other *** search
- #include <osbind.h>
-
- struct {
- unsigned char ident[10];
- unsigned char ainam[15][10];
- unsigned char aiset[15][8];
- unsigned char cinam[15][10];
- unsigned char ciset1[15];
- unsigned char ciset2[15];
- long fptr[5];
- unsigned char title[32];
- } mushdr;
-
- struct muevnt {
- long rltime;
- long deltime;
- char etype;
- char inst;
- char frq;
- char fill;
- } evnt[2500];
-
- unsigned char tmpbuf[16384];
-
- char *keys[] = { "none","C","G","D","A","E","B","F#","C#","F","Bb","Eb","Ab",
- "Db","Gb","Cb" };
- char *beat[] = { "none","2/2","3/2","2/4","3/4","4/4","5/4","6/8" };
-
- /* sharping and flatting for key:
- c d e f g a b */
- int keyfix[16][12] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
- 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0,
- 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0,
- 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0,
- 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
- 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0,-1,
- 0, 0, 0, 0,-1, 0, 0, 0, 0,-1, 0,-1,
- 0, 0,-1, 0,-1, 0, 0, 0, 0,-1, 0,-1,
- 0, 0,-1, 0,-1, 0, 0,-1, 0,-1, 0,-1,
- -1, 0,-1, 0,-1, 0, 0,-1, 0,-1, 0,-1,
- -1, 0,-1, 0,-1,-1, 0,-1, 0,-1, 0,-1
- };
-
- /* 96 pulses per quarter note timing */
- int ppq[] = {
- /* 1/32 1/16 1/8 (3)---1/4-----(.) 1/2 1 2*/
- 6,8,9, 12,16,18, 24,32,36, 48,64,72, 96,128,144, 192,256,288, 384,512,576, 768,
- 1024,1152, 1536,2048,2304, 3072,4096,4608, 6144,8192
- };
-
- /*************************/
- main( argc , argv )
- int argc;
- char *argv[];
- {
- int handl;
- int i,j,k;
- int tempo;
- int evntptr;
- long tmpo,tmpo1;
- register int keyf,pitch;
- register long realtime;
- int noteplay[3];
-
- handl = Fopen( argv[1] , 0 );
- if( handl < 0 ) return;
- Fread( handl , 512L , &mushdr );
-
- /* NOTES **********************/
- for( i = 0 ; i < 16384 ; i++ ) tmpbuf[i] = 0;
- if( mushdr.fptr[0] )
- Fread( handl , (unsigned long)(mushdr.fptr[0] - 512L) , tmpbuf );
- else
- Fread( handl , 16384L , tmpbuf );
-
- /* NOW, FOR THE SOUNDS */
- tempo = 60;
- tmpo1 = 0;
- realtime = 0;
- evntptr = 0;
-
- printf( "PROCESSING\n" );
-
- /* for each byte, but may jump for variable record lengths */
- for( i = 8 ; tmpbuf[i] != 0xff ; i++ ) {
- switch( tmpbuf[i] ) {
- case 0x00: /* begin/end record delimiter */
- realtime += tmpo1;
- tmpo1 = 0;
- break;
- case 0x80: /* grand staff and key signature, what does [1] do? */
- keyf = tmpbuf[i+2];
- i += 2;
- break;
- case 0x81: /* tempo (MM) */
- tempo = tmpbuf[i+1];
- i++;
- break;
- case 0x82: /* vertical bar across grand staff */
- break;
- case 0x83: /* time signature */
- i++;
- break;
- case 0x84: /* loudness */
- i+=2;
- break;
- case 0x85: /* repeat (n times) marker ||: */
- /* printf( " %d*[" , tmpbuf[i+1] );
- */ i++;
- break;
- case 0x86: /* repeat ends here :|| */
- /* printf( "]" );
- */ break;
- default: /* note subrecord, 3 bytes, instr:note */
- /* the printed value is the base note, pitch is the actual to play */
- pitch = tmpbuf[i+2];
- /* should be +/-12 per octave (oct2=0) offset for instrument */
-
-
- if( ( tmpbuf[i+1] & 0xc0 ) == 0xc0 ) /* flat */
- pitch--;
- if( ( tmpbuf[i+1] & 0xc0 ) == 0x80 ) /* sharp */
- pitch++;
-
- /* if( ( tmpbuf[i+1] & 0xc0 ) == 0x40 ) natural */
-
- if( !( tmpbuf[i+1] & 0xc0 ) ) /* adjust note value for key */
- pitch += keyfix[keyf][pitch%12]; /* only if no accidental */
-
- /* Note duration */
-
- /* the player does not yet do differing lengths,
- should be minimum between 00 records */
- tmpo = 1250L; /* for .5 milliseconds, 125 for 200Hz tics */
- tmpo = ppq[ tmpbuf[i+1] & 31 ]; /* *= */
- /* tmpo /= tempo; */
- if( !tmpo1 || tmpo < tmpo1 )
- tmpo1 = tmpo;
-
- k = 0;
- if( tmpbuf[i] & 0x40 ) /* begin tie */
- k |= 4;
- if( tmpbuf[i] & 0x20 ) /* end tie (valid to begin too */
- k |= 2;
- if( tmpbuf[i+1] & 0x20 ) /* accent */
- k |= 8;
-
- if( !( tmpbuf[i] & 0x10 ) ) { /* rest */
- evnt[ evntptr ].rltime = realtime;
- evnt[ evntptr+1 ].rltime = realtime + tmpo;
- evnt[ evntptr ].deltime = tmpo;
- evnt[ evntptr+1 ].deltime = tmpo;
- evnt[ evntptr ].etype = k;
- evnt[ evntptr+1 ].etype = k|1;
- evnt[ evntptr ].inst = tmpbuf[i]&15;
- evnt[ evntptr+1 ].inst = tmpbuf[i]&15;
- evnt[ evntptr ].frq = pitch;
- evnt[ evntptr+1 ].frq = pitch;
- evntptr += 2;
- }
-
- i+=2;
- break;
- }
-
- }
- /* unfold event table */
- printf( "SORTING\n" );
- heapsort( evnt , evntptr );
-
- evnt[ evntptr ].rltime = 0x7fffffffL;
-
- printf( "UNFOLDING-\n" );
- /* look for end of tie/beginning of tie pairs, and expand first note */
-
- printf( "RESULTS:\n" );
- initsnd();
- tmpo1 = 0;
- k = 0;
- noteplay[0]=0;
- noteplay[1]=0;
- noteplay[2]=0;
- for( i = 0 ; i < evntptr ; i++ ) {
- if( tmpo1 < evnt[i].rltime ) {
- printf( "%10D\n" , evnt[i].rltime );
-
- while( k < i ) {
- if( !( evnt[k].etype & 1 ) ) {
- if( !noteplay[0] )play(0,evnt[k].frq),noteplay[0]=evnt[k].frq;
- else if( !noteplay[1] )play(1,evnt[k].frq),noteplay[1]=evnt[k].frq;
- else if( !noteplay[2] )play(2,evnt[k].frq),noteplay[2]=evnt[k].frq;
- }
- k++;
- }
-
- p_pause( (long)( (evnt[i].rltime - tmpo1) * 625L / tempo ) );
- tmpo1 = evnt[i].rltime;
- }
-
- /* printf( "%10D %6D %2d %2d %3d\n" ,
- evnt[i].rltime, evnt[i].deltime, evnt[i].etype, evnt[i].inst, evnt[i].frq );
- */
- if( evnt[i].etype & 1 ) {
- /* if( !( evnt[i].etype & 4 ) ) { only if matching &2*/
- if( noteplay[0] == evnt[i].frq )quiet(0),noteplay[0]=0;
- else if( noteplay[1] == evnt[i].frq )quiet(1),noteplay[1]=0;
- else if( noteplay[2] == evnt[i].frq )quiet(2),noteplay[2]=0;
- /* }*/
- }
-
- }
-
- printf( "\n" );
- Fclose( handl );
-
- }
-
- /*** HOW TO PLAY NOTES ***/
-
- int notedivs[12] = { 3822, 3608, 3405, 3214, 3034, 2863,
- 2703, 2551, 2408, 2273, 2145, 2025 };
- /*****/
- initsnd()
- {
- int val;
-
- Giaccess( 0 , 8+128 );
- Giaccess( 0 , 9+128 );
- Giaccess( 0 , 10+128 );
-
- val = Giaccess( 0 , 7 );
- val &= 0xc0;
- val |= 0x38;
- Giaccess( val , 7+128 );
- }
-
- /*****/
- quiet( channel )
- register int channel;
- {
- Giaccess( 0 , channel + 8+128 );
- }
-
- /*****/
- play( channel , note )
- register int channel,note;
- {
- register int val;
- note -= 24;
-
- if( note < 0 )
- return;
-
- val = notedivs[ note % 12 ] >> (note / 12);
-
- Giaccess( 0x08 , channel + 8+128 );
- Giaccess( val & 0xff , channel + channel + 0+128 );
- Giaccess( val >> 8 , channel + channel + 1+128 );
-
- }
-
- /*************************/
- heapsort( tbl , len )
- struct muevnt *tbl;
- int len;
- {
- int l;
- int r;
- int i,j;
-
- struct muevnt ktbl;
-
- /*1*/
- l = len/2 + 1;
- r = len;
-
- while( 1 ) {
- /*2*/
- if( l > 1 ) {
- l--;
- ktbl = tbl[ l ];
- }
- else {
- ktbl = tbl[ r ];
- tbl[ r ] = tbl[ 1 ];
- r--;
- if( r == 1 ) {
- tbl[ 1 ] = ktbl;
- break;
- }
- }
- /*3*/
- j = l;
-
- while( 1 ) {
- /*4*/
- i = j;
- j = j+j;
- if( j > r )
- break;
- if( j < r && tbl[ j ].rltime < tbl[ j+1 ].rltime )
- j++;
- /*6*/
- if( ktbl.rltime >= tbl[ j ].rltime )
- break;
- /*7*/
- tbl[i] = tbl[j];
- }
- /*8*/
- tbl[i] = ktbl;
- }
-
- }
-