zap@indic.se (Jonas Petersson) (04/04/91)
[I believe this has been discussed before] From what I've heard, it is possible to get quite good sound out of a 375/400 (and probably other models too) - using XBeep() and changing it's frequency is not what I would call good... Could someone send me some information on how to do this. Thanks in advance / Jonas -- /// "Are you THE Zaphod Beeblebrox ????" # zap@indic.se __ /// # Air Quality Surveillance \\\/// "No, just A Zaphod Beeblebrox. # "I can feel it coming \/// Didn't you hear - I come in sixpacks !" # in the air..."
ken@hpcupt3.cup.hp.com (Kenneth M. Sumrall) (04/10/91)
>From what I've heard, it is possible to get quite good sound out of a >375/400 (and probably other models too) - using XBeep() and changing it's >frequency is not what I would call good... Could someone send me some >information on how to do this. > Here is something I picked up off the net about 3 years ago. It plays music in three part harmony from ascii text music files. Enjoy. | Ken Sumrall | Internet: ken%hpda@hplabs.hp.com | | HP California Language Labs | UUCP: ...!hplabs!hpda!ken | | "I'd stomp desert dope heads for some gas in my moped!" - Bill the Cat | | "What a stupid world" -Calvin (speaking to Hobbes) | #---------------------------------- cut here ---------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Ken Sumrall <ken@hpclkms> on Tue Apr 9 19:40:07 1991 # # This archive contains: # READ_ME chop.fant fug2 play.c # prel3 # # Error checking via wc(1) will be performed. # Error checking via sum(1) will be performed. LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH if sum -r </dev/null >/dev/null 2>&1 then sumopt='-r' else sumopt='' fi echo x - READ_ME cat >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): <key sig> <quarter notes per minute> <line of music for voice 1> <line of music for voice 2 or blank line> <line of music for voice 3 or blank 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: <pitch>[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 set `sum $sumopt <READ_ME`; if test $1 -ne 46191 then echo ERROR: READ_ME checksum is $1 should be 46191 fi set `wc -lwc <READ_ME` if test $1$2$3 != 906093307 then echo ERROR: wc results of READ_ME are $* should be 90 609 3307 fi chmod 644 READ_ME echo x - chop.fant cat >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 set `sum $sumopt <chop.fant`; if test $1 -ne 48646 then echo ERROR: chop.fant checksum is $1 should be 48646 fi set `wc -lwc <chop.fant` if test $1$2$3 != 285011406 then echo ERROR: wc results of chop.fant are $* should be 28 501 1406 fi chmod 444 chop.fant echo x - fug2 cat >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 set `sum $sumopt <fug2`; if test $1 -ne 62501 then echo ERROR: fug2 checksum is $1 should be 62501 fi set `wc -lwc <fug2` if test $1$2$3 != 143191082 then echo ERROR: wc results of fug2 are $* should be 14 319 1082 fi chmod 444 fug2 echo x - play.c cat >play.c <<'@EOF' #include <string.h> #include <stdio.h> #include <fcntl.h> #include <signal.h> #include <math.h> #include <time.h> #include <sys/hilioctl.h> #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<lns_act; voice++) new_meas &= !strcmp(tok[voice][linepos[voice]], "|"); for(voice=0; voice<lns_act; voice++) { tok_ptr = tok[voice][linepos[voice]]; if( tok_ptr && strcmp(tok_ptr,"|") && time_left[voice]==0 || new_meas ) { /* np_set(voice, tok[voice][++linepos[voice]]); v_on(voice); */ v_on(voice, tok[voice][++linepos[voice]]); } } delay = 0x7fffffff; for(voice=0; voice<lns_act; voice++) if ((time_left[voice]<delay) && time_left[voice]) delay=time_left[voice]; if (delay != 0x7fffffff) { wait_note(delay); for(voice=0; voice<lns_act; voice++) if(time_left[voice]) time_left[voice] -= delay; } } goto loop; } void v_on (vnum, cnote) int vnum; char *cnote; { char *notestr, *modstr, *octstr, *attenstr; char *noteptr, *modptr, *octptr, *attenptr, *tm_ptr; int bnote, mod, note, tvar; double count; int intcount, voice; if (cnote == NULL) return ; notestr="C D EF G A B R|"; modstr="bn#"; octstr="0123456"; attenstr="0123456789"; noteptr=strchr(notestr, *cnote); if( noteptr!=NULL ) { bnote = noteptr - notestr; if(key) bnote = bnote - (strchr(flat_str, *noteptr) != NULL); else bnote = bnote + (strchr(sharp_str, *noteptr) != NULL); } else bnote = 14; modptr=strpbrk(modstr, cnote); if( modptr!=NULL ) mod = modptr - modstr - 1; else mod = 0; octptr=strpbrk(cnote, octstr); /* NOTE ORDER of params in strpbrk */ if( octptr!=NULL ) { oct[vnum] = *octptr - 0x30; attenptr = octptr+1; } else attenptr = cnote; attenptr = strpbrk(attenptr, attenstr); if(attenptr != NULL) atten[vnum] = *attenptr - 0x30; /* tvar = strlen(cnote)-1; if (tvar > 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 set `sum $sumopt <play.c`; if test $1 -ne 18955 then echo ERROR: play.c checksum is $1 should be 18955 fi set `wc -lwc <play.c` if test $1$2$3 != 2265815005 then echo ERROR: wc results of play.c are $* should be 226 581 5005 fi chmod 644 play.c echo x - prel3 cat >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 set `sum $sumopt <prel3`; if test $1 -ne 51957 then echo ERROR: prel3 checksum is $1 should be 51957 fi set `wc -lwc <prel3` if test $1$2$3 != 273641639 then echo ERROR: wc results of prel3 are $* should be 27 364 1639 fi chmod 444 prel3 exit 0