home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
music
/
songdump
/
songtran.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-07-03
|
7KB
|
320 lines
#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;
}
}