Path: utzoo!mnetor!uunet!seismo!sundc!pitstop!sun!decwrl!decvax!ucbvax!hplabs!hpcea!hpfcdc!hpfcrn!paulc From: paulc@hpfcrn.HP.COM (Paul Christofanelli) Newsgroups: comp.sys.hp Subject: Re: Music (Voices) on the 300s Message-ID: <2440001@hpfcrn.HP.COM> Date: 24 Feb 88 17:58:15 GMT References: <254@encad.Wichita.NCR.COM> Organization: HP/UDL Ft. Collins CO. Lines: 479 Here's yet another program to play the 300 beeper, complete with some truncated examples. It's not quite complete (e.g., it doesn't play the noise generator) and certainly not very elegant, but I think it requires a little less work to get a tune up and playing than the Lisp beeper player. The interesting thing that I found was that it is able to pretty much play real-time by reading the notes directly from an ascii file. Anyway, unpack the shar file, read the READ_ME and try out some of the example music fragments. It's kind of fun to type in sheet music and listen to it, but translating gets a little tedious after a while (which is why I never finished the pieces). Also, as usual, this stuff is completely unsupported. Have fun! Paul Christofanelli ...hpfcla!paulc # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # This archive contains: # READ_ME play.c chop.fant prel3 # fug2 # # Modification/access file times will be preserved. # Error checking via wc(1) will be performed. LANG=""; export LANG echo x - READ_ME sed 's/^@//' >READ_ME <<'@EOF' To use this stuff, you need to first compile play.c with cc -o play play.c -lm To play something, type: play < playfile (e.g. play < chop.fant) The "playfile" has the basic format of (starting from the first line): @. @. @. The key signature is in the form "n#" or "nb" where n goes from 0 to 7. # of course means "sharp", b means "flat". Quarter note beats per minute is just that; it's in the form n, where n is almost any reasonable number. Note that 10 milliseconds is the smallest duration available. Music lines come in groups of three (3 voices). A blank line indicates termination of that group, the other voices are not played. If all 3 voices are played in a group, DO NOT leave a blank line (bug). A music line is of the form: | measure | measure | measure | ... (blanks must be present around the |). A measure is just: note note note ... (blanks must surround notes) A note is: [modifier][octave][length][.][attenuation] Pitch is: A B C D E F G R R is a rest. It only needs to be used between notes in a measure or between the beginning of the measure and the first note. The program doesn't play anything after the last note in a measure, but waits for all voices in the 3 measure group to complete. Modifier is: b (flat) n (natural) or # (sharp) Note that n doesn't currently work (has no effect); if the note would be sharped (or flatted) in the key, you must use b or # to modify it back to the natural state. Double-sharp or double-flat is accomplished by just using a sharp or flat on a note which would already be sharped or flatted in the current key. octave is: 0 1 2 3 4 5 6 Middle C translates to C2. Some choices (e.g. A0) will be out of range and create squawks. length is: t s e q h w l x d t = 32nd note s = 16th note e = 8th note q, h, w = guess l = 12th note x = 6th note d = 3rd note . means to multiply the note value by 1.5 attenuation is: 0 1 2 3 4 5 6 7 8 9 0 is the loudest. Only pitch needs to be specified on every note; the other parameters take on the same values they had on the previous note. The note "parsing" is somewhat of a hack, so watch out. The only ambiguity is between the octave and attenuation, so if the attenuation is to be changed, the octave must be specified. Other than these 2, the parameters can be put in any order (I think). There is (yet) no way to handle tied notes. This creates the biggest problem on tied notes across measures. The . can often be used to handle tied notes within measures. Speaking of measures, you'll notice that a "time signature" is not used in this program. You have to keep track of the notes within a measure. The measure concept provides a 'reset' point so that the beginning of each measure in the 3 measure group happens at the same point in time. Also, the convention that sharped, flatted, or naturaled notes do not change througout the measure is *NOT* adhered to (it's a dumb convention anyway). Have fun, but remember, the program isn't very forgiving! @EOF if test "`wc -lwc play.c <<'@EOF' #include #include #include #include #include #include #include #define hlfstp=1.05946309435 static int atten[3] = {5, 5, 5}; static int oct[3] = {2, 2, 2}; static int time_left[3] = {0, 0, 0}; static int tim_val[3] = {0, 0, 0}; int q_base=75; int r8042; static int n_val[9] = {3,6,12,24,48,96,8,16,24}; char *tm_str = "tseqhwlxd"; char *sharp_str = "FCGDAEB"; char *flat_str = "BEADGCF"; int key; /* 0 means sharp key, 1 means flat key */ char *sep = " \t"; main(argc, argv) int argc; char *argv[]; { char linebuf[4][160]; int lns_act; char *tok[3][80]; char *tok_ptr; int tok_no; int linepos[3]; int voice; int new_meas, delay; int i; char *key_str = "01234567"; void np_set(); void v_on(); void wait_note(); if( (r8042=open("/dev/rhil",O_RDWR)) == -1) { printf("**Can't open device files\n"); exit(1); } if (gets(linebuf[0])==NULL) exit(0); tok_ptr = strpbrk(key_str, linebuf[0]); if (tok_ptr==NULL) tok_ptr=key_str; i = tok_ptr - key_str; if (strchr(linebuf[0], '#')) { key = 0; *(sharp_str+i)=NULL; } else { key = 1; *(flat_str+i)=NULL; } if (gets(linebuf[0])==NULL) exit(0); q_base = atoi(linebuf[0]); loop: lns_act = 0; while ( (lns_act<3) && (gets(linebuf[lns_act]) != NULL) ) if ( (tok[lns_act][0]=strtok(linebuf[lns_act], sep)) != NULL ) { for (tok_no=1; (tok[lns_act][tok_no]=strtok(NULL, sep)) != NULL; tok_no++) ; linepos[lns_act] = 0; lns_act++; } else if ( lns_act ) break; if (lns_act==0) exit(0); for( i=lns_act; i<3; i++) { tok[i][0] = NULL; linepos[i] = 0; } while( tok[0][linepos[0]] || tok[1][linepos[1]] || tok[2][linepos[2]] ) { new_meas = 1; for(voice=0; voice 1) { attenptr = strchr(attenstr, *(cnote+tvar)); if(attenptr != NULL) atten[vnum] = *attenptr - 0x30; } */ tm_ptr=strpbrk(tm_str, cnote); if (bnote>=14) time_left[vnum]=0; else { if (tm_ptr!=NULL) tim_val[vnum] = (250 * n_val[tm_ptr-tm_str]) / q_base; if (strpbrk(".", cnote)) tim_val[vnum] = (tim_val[vnum]*3)/2; time_left[vnum] = tim_val[vnum]; } if (bnote <= 12) { note = oct[vnum]*12 + (bnote+3) + mod; /* 3 is added so that note 0 can be used for 'A' (55HZ) */ count = 83333.0 / (55.00 * pow(hlfstp, (double)note)); /* Convert double to integer */ intcount = (int) count; voice = (time_left[vnum]) | ((0x90+vnum*32+atten[vnum]) << 8) | ((intcount>>4) << 16) | ((0x80+vnum*32+intcount%16) << 24) ; ioctl(r8042, EFTSBP, &voice); } } void wait_note(time) int time; /* time is in 10's of milliseconds */ { struct timeval timeout; timeout.tv_sec = (time/100); timeout.tv_usec = (time%100)*10000; /* 300 has a min wait of 20 milliseconds */ select(0, 0, 0, 0, &timeout); } @EOF if test "`wc -lwc chop.fant <<'@EOF' 4# 200 | G1w5 | | | | G0w5 | C1l G C2 E C G1 C G C2 E C G1 | C G C2 E C G1 C G C2 E C G1 | | R2s G2 A G F# G C3 E D C D C B#2 C3 E G | R G2 A G F# G C3 E D C D C B#2 C3 E G | | C1l G C2 E C G1 E G C2 E C G1 | C1l G C2 E C G1 E G C2 E C G1 | | Rs A2 C3 D F A C4 D B A G F E D F C | B#3 D4 A3 G F A E D F C B#2 D3 A2 G B A | | D A C2 F C A1 F C2 D A D C | G0 D1 F B# F D G0 D1 F B# D | | Rs G2 A G F# G C3 E D C D C B#2 C3 E G | R G2 A# G F# G C3 E D C D C B#2 C3 E G | | C1l G C2 E C G1 E G C2 E C G1 | C G A# E A# G E G A C2 A1 G | | D E D C# D B A# G F# E4 D C# B3 A G F | A# G B C# E D G A#2 C3 B2 D3 F#2 A G F# G | | D G B D2 B1 G D A# C2 F# C A1 | G0 D1 G B G D G0 D1 G B G D | | G G3 B#2 C3 F2 F3 B#2 C3 E#2 E#3 B#2 C3 F2 F3 B#2 C3 | | A0 C1 F A F C A0 C1 F A F C | | C2 C3 F2 A D D3 F2 A E E3 G2 B G G3 B2 E3 | G2 G3 B#2 C3 F2 F3 B#2 C3 E#2 E#3 B#2 C3 F2 F3 B#2 C3 | | B0 F1 A B A F E0 B E1 G E B0 | A0 C1 F A F C A0 C1 F A F C | | E#2 E#3 B2 D3 F2 F3 B2 D3 A2 A3 B2 E3 G2 G3 B2 E3 | G2 G3 B#2 C3 F2 F3 B#2 C3 E#2 E#3 B#2 C3 F2 F3 B#2 C3 | | B0 D1 A B A D E0 B E1 G E B0 | A0 C1 F A F C A0 C1 F A F C | | C2 C3 F2 A D D3 F2 A E E3 G2 B G G3 B2 E3 | G2 G3 B#2 C3 F2 F3 B#2 C3 D D4 F3 A C C4 F3 A | | B0 F1 A B A F E0 B E1 G E B0 | A C1 F A F C A0 D1 F A F D | @EOF if test "`wc -lwc prel3 <<'@EOF' 7# 150 | E3s9 C G2 C3 E C | F C F C F C | G C G C G C | A C A C A C | G C G C G C | | C1q9 C2e | D1q C2e | E1q C2e | F1q C2e | E1q C2e | | C0e9 C1e | D0e D1e | E0e E1e | F0e F1e | E0e E1e | | F E D E F D | E D C D E C | D E D C B2 A | G2q2 G3e | A2q G3e | | D1q C2e | C1q C2e | C2e B1s0 A G A | B G D G B G | C2 G1 C2 G1 C2 G1 | | B2q G3e | Cq Ge | B2q G3e | A2q F#3e | | D2 G1 D2 G1 D2 G1 | E2 G1 E2 G1 E2 G1 | D2 G1 D2 G1 D2 G1 | C2 B1 A B C2 A1 | | G2q G3e | G3e F3s0 E D E | | B A G A B G | A Bb A G F E | | F3s Ds A2s D3s Fs Ds | Gs Ds Gs Ds Gs Ds | As Ds As Ds As Ds | Bbs Ds Bbs Ds Bbs Ds | As Ds As Ds As Ds | | D1q2 D2e | E1q D2e | F1q D2e | G1q D2e | F1q D2e | | Gs Fs Es Fs Gs Es | Fs Es Ds Es Fs Ds | Es Fs Es Ds Cs B2s | A2q2 A3e | B2q A3e | | E1q C#2e | D1q D2e | De C2s0 B1s As Bs | C2s A1s Es As C2s A1s | D2s A1s D2s A1s D2s A1s | | C3q A3e | Dq Ae | Cq A3e | B2q G#3e | | E2s A1s E2s A1s E2s A1s | F2s A1s F2s A1s F2s A1s | E2s A1s E2s A1s E2s A1s | D2s Cs B1s C2s Ds B1s | | A2q A3e | A3e0 G3e F#e | | C2s B1s As Bs C2s A1s | D#2s C#s B1s C#2s D#s B1s | @EOF if test "`wc -lwc fug2 <<'@EOF' 3b 75 | | | Re G3s9 F# Ge C E Gs F# Ge A# | | Re C3s9 B#2 C3e G2 A C3s B#2 C3e D | G2 C3s B#2 C3e D F2s G Aq Gs F | E C3 B#2 A# G F E D Ce E3 D C | | D Gs F# Ge A# Cs D Eq Ds Cs | B2e E3s D Ee G2 A F3s E Fe A#2 | B G3s F Ge B#2 C3 Ds E Fq | | B2 A# B C3 F#2 G A# F# | Gq Rs C D E F G Ae. Ds E F | G A# Be. Es F G A G F E De C3s B#2 | | Fe Es D C2 B A G Fe A3 G F | E D E F B#2 C3 D B#2 | C3 Gs F#s Ge D Eq Re E#e | | C3q Rq Re F3 E D | Re A2 G F G Fs E Fe D | Gq Re B#e C3 Cs B#2 C3e G2 | | Re C2s9 B#1 C2e G1 A C2s B#1 C2e D | G1 C2s B#1 C2e D F2s G Aq Gs F | E C2 B#1 A# G F E D C D E D C B0 A G | | F Fs E# Fe C Dq Re De | E Es D Ee B2 C3 Es D Ee F | B2 E3s D Ee F A2s B C3q B2s A | | Aq Re A#e B Bs A# Be F | Gq Re G A A G F | Re A1 B C2 Re A1s G Ae F | | F B1 A G F E D C B0 C1 D C B0 A G F | E1 A G F E Db C B0 Ae C2 B1 A | G F G A D E F D | @EOF if test "`wc -lwc