Path: utzoo!mnetor!uunet!husc6!rutgers!mtune!codas!killer!csccat!jack From: jack@csccat.UUCP (Jack Hudler) Newsgroups: comp.sys.hp Subject: Re: Music (Voices) on the 300s Message-ID: <357@csccat.UUCP> Date: 19 Feb 88 12:03:42 GMT References: <254@encad.Wichita.NCR.COM> <5247@spool.cs.wisc.edu> Reply-To: jack@csccat.UUCP (Jack Hudler) Distribution: na Organization: Computer Support Corporation. Dallas,Texas Lines: 1115 Keywords: music notes tones 300 **** SOURCES **** In article <5247@spool.cs.wisc.edu> matt@cs.wisc.edu (Mad Matt Schaefer) writes: >In article <254@encad.Wichita.NCR.COM> jpederse@encad.Wichita.NCR.COM (John Pedersen) writes: >>Some time back, someone posted a short C program for the s300 that played >>some tune like "Baby Elephant Walk" or something like that. I kept another >>article that did some basic chords on the system, but didn't save the posting >>that had the tune. Will I saved it.. Use it for a mail received cutness. Here it is in the original shar. A version in LISP and C. Jack@csccat #!/bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Contents: README Makefile dbsetup.sl music.c beeper.c mytune.h echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' For those who my not know, the beeper on gators/bobcats have four independent voices. Three of these have a programmable tone, and the fouth is a noise generator. Someone wrote some low level code to talk to the beeper. I wrote some PSL code that allows you to write music in an easy to read format (See example in the file dbsetup.sl). More recently, I translated the functions into C and wrote a function that would take the lisp lists and generate C data structures that could be interpreted by the C code. Anyone who is running Horizon (nmode? prism? whatever...) should be able to write music immediately. Everyone else can build the example C program and hear what the machine can do. Perhaps someone without nmode will be inspired to write a nicer front end. @//E*O*F README// chmod u=rw,g=r,o=r README echo x - Makefile sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//' it: music music.o: music.c mytune.h cc -c music.c beeper.o: beeper.c cc -c beeper.c music: music.o beeper.o cc -o music music.o beeper.o shar: shar -c README Makefile dbsetup.sl music.c beeper.c mytune.h > music.shar @//E*O*F Makefile// chmod u=rw,g=rw,o=r Makefile echo x - dbsetup.sl sed 's/^@//' > "dbsetup.sl" <<'@//E*O*F dbsetup.sl//' %Get Compiled C code (lisp:load-ofile "/usr/local/src/nmode/beeper/beeper.o" :libs "") (lisp:ff beep "_beep" :parms (nil nil nil nil)) (lisp:ff noise "_noise" :parms (nil nil nil nil)) (lisp:ff beep-or-noise-duration-left "_beep_or_noise_left" :parms (nil)) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Set up tempo variable and note values %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % (when (null (find-package "music")) % (make-package "music")) % % (setf music::old-package *package*) % (in-package 'music) % % (import 'pnth (find-package "music")) (setf tempo 100) (setf whole 1000) (setf half (/ whole 2)) (setf quarter (/ half 2)) (setf eighth (/ quarter 2)) (setf sixteenth (/ eighth 2)) (setf thirtysecond (/ sixteenth 2)) (setf dot-quarter (+ quarter eighth)) (setf dot-half (+ half quarter)) (setf dot-eighth (+ eighth sixteenth)) (setf triplet (/ quarter 3)) (setf rest -1) (setf r -1) (setf C 0) (setf C-sharp 1) (setf cs 1) (setf D 2) (setf ds 3) (setf E-flat 3) (setf Ef 3) (setf E 4) (setf F 5) (setf F-sharp 6) (setf Fs 6) (setf G 7) (setf G-sharp 8) (setf Gs 8) (setf A-flat 8) (setf Af 8) (setf A 9) (setf B-flat 10) (setf Bf 10) (setf B 11) (setf tw whole) (setf th half) (setf tq quarter) (setf te eighth) (setf ts sixteenth) (setf ts1 (+ ts 1)) (setf tdh dot-half) (setf tdq dot-quarter) (setf tde dot-eighth) (setf tt triplet) (setf scale % (vector % (vector 1 510 770 896 959 992) % (vector 50 540 784 902 962 994) % (vector 100 570 798 909 966 996) % (vector 150 600 811 914 970 998) % (vector 200 630 823 922 973 999) % (vector 250 650 837 928 975 1000) % (vector 300 670 849 934 978 1001) % (vector 350 690 857 939 981 1002) % (vector 390 710 866 945 984 1003) % (vector 420 723 874 950 986 1004) % (vector 450 740 882 953 988 1005) % (vector 480 760 891 956 990 1006) % ) (vector (vector 0 386 705 864 943 984)% c (vector 0 422 722 873 948 0) % c# (vector 0 456 739 881 952 0) % d (vector 0 487 755 889 956 0) % d# (vector 12 518 770 897 960 0) % e (vector 69 546 784 904 963 0) % f (vector 123 573 798 911 967 0) % f# (vector 173 598 810 916 970 0) % g (vector 220 622 822 922 973 0) % g# (vector 266 645 834 928 976 0) % a (vector 308 665 844 933 978 0) % a# (vector 348 685 854 938 981 0) % b ) ) (de get-note (pitch octave) (let ((real-pitch (+ pitch pitch-offset)) (real-octave (+ octave octave-offset)) ) (when (>= real-pitch 12) (setf real-pitch (- real-pitch 12)) (setf real-octave (+ real-octave 1)) ) (when (< real-pitch 0) (setf real-pitch (+ real-pitch 12)) (setf real-octave (- real-octave 1)) ) (vector-fetch (vector-fetch scale real-pitch) real-octave) )) % (de get-note (pitch octave) % (vector-fetch (vector-fetch scale pitch) octave) % ) (de note (pitch octave voice duration) (if (eq pitch -1) % it is a rest; (beep voice 0 0 (/ (* 10 duration) tempo)) % otherwise; (beep voice (get-note pitch octave) vol (/ (* 10 duration) tempo)) )) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Set-up Musical Environment %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (setq vol 11) % Volume Setting (setf octave-offset 0) (setf pitch-offset 0) %Last note finished, now go on (defun go-on () (repeat (beep-or-noise-duration-left 1) (= (beep-or-noise-duration-left 1) 0)) ) (defun go-on-voice (voice-num) (repeat (beep-or-noise-duration-left voice-num) (= (beep-or-noise-duration-left voice-num) 0)) ) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Music structure: % % For each voice, there are parallel lists for the notes, the octaves, % and the times; % % A stanza is a list of either 3,6,9,or 12 lists; (depending on how many % voices you use; % % sample stanza: % % (setf stanza % (list (list a b b-flat f-sharp) % (list 1 1 2 1 ) % (list whole whole half quarter) % % (list a b b-flat g ) % (list 2 2 3 2 ) % (list whole whole half quarter) % ) % ) % % Music task structure: % % [ element # % time-to-go 0 % voice-num 1 % ( notes ) 2 % ( octave ) 3 % ( time ) 4 % ] % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (defun play-stanza (stanza) (let ((time-to-go-idx 0) (voice-num-idx 1) (notes-idx 2) (octaves-idx 3) (times-idx 4) (queue nil) (voice-num nil) (wait-time nil) (temp nil) ) % translate music symbols to numbers; % (for (in list stanza) (do % (for (on i list) (do % (when (null (numberp (car i))) % (setf (car i) (cdr (assoc (car i) music-symbols))) % ) % )) % )) % build a task for each voice; (setf voice-num 1) (while stanza (push (vector 0 voice-num (first stanza) (second stanza) (third stanza) ) queue) (setf voice-num (+ voice-num 1)) (setf stanza (pnth stanza 4)) ) % while there are voices to be played; (while queue % give more data to voices that are ready; (for (in task queue) (with notes octaves times time-to-go) (do % a voice ready for another note; (when (eq 0 (vector-fetch task time-to-go-idx)) (setf notes (vector-fetch task notes-idx)) (setf octaves (vector-fetch task octaves-idx)) (setf times (vector-fetch task times-idx)) (setf time-to-go (first times)) % play a note on this voice; (note (first notes) (first octaves) (vector-fetch task voice-num-idx) time-to-go) (vector-store task time-to-go-idx time-to-go) (vector-store task octaves-idx (rest octaves)) (vector-store task times-idx (rest times)) (vector-store task notes-idx (rest notes)) ) )) % find the task with the shortest time and we'll decrement % the other tasks by its time and wait on it; (setf wait-time 10000) (for (in task queue) (do (when (< (setf temp (vector-fetch task time-to-go-idx)) wait-time) (setf wait-time temp) (setf voice-num (vector-fetch task voice-num-idx)) ) )) % update the time of all tasks; (for (in task queue) (do (vector-store task time-to-go-idx (- (vector-fetch task time-to-go-idx) wait-time) ) )) % wait on the voice that will be done first; (go-on-voice voice-num) % remove voices with no more notes; (setf temp queue) (for (in task temp) (do (when (null (vector-fetch task notes-idx)) (setf queue (delete task queue)) ) )) ) )) % end of function play-stanza; % (setf stanza1 (list % % first trumpet % (list e f fs g e e d cs cs a af g fs d d c b b) % (list 1 1 1 1 2 2 2 2 2 1 1 1 1 2 2 2 1 1) % (list te te te tq tq te tq tq th te te te tq tq te tq tq th) % % % second trumpet % (list c d ef e g g f e e r r r r r r r r r) % (list 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1) % (list te te te tq tq te tq tq th te te te tq tq te tq tq th) % )) %(setf stanza2 (list % (list g fs f e g c a c d g bf ef c ef f g r g g a g d c) % (list 1 1 1 1 1 2 1 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2) % (list te te te te te te tq te tq te te te tq te tq tw tq te te te te tq te) % )) % %(let () % (setf tempo 100) % (play-stanza stanza1) % (play-stanza stanza2) % ) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Baby Elephant Walk % % from the Paramount Picture "HATARI" % (c) 1961, 1962, 1968 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % melody; (setf stanza1 (list (list f a c f a g f d b c r f a c f a g f d) (list 2 2 3 3 3 3 3 3 2 3 0 2 2 3 3 3 3 3 3) (list tde ts1 te te te te te te te te tdh tde ts1 te te te te te te) %harmony; (list c gs a c gs a c gs a c c gs a c gs a c gs a) (list 1 0 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0) (list tq te te tq te te tq te te te te te te tq te te tq te te) (list f gs a f gs a f gs a f f gs a f gs a f gs a) (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (list tq te te tq te te tq te te te te te te tq te te tq te te) )) %melody; (setf stanza2 (list (list c d af d af f r) (list 3 3 2 3 2 2 0) (list tdh te (+ te tdh te) te te te tdh) %harmony; (list c c gs a c cs d f f cs d f f cs d f f cs d f f cs d) (list 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1) (list te te te te tq te te te te te te te te te te te te te te te te te te) (list f f gs a f cs d bf bf cs d bf bf cs d bf bf cs d bf bf cs d) (list 0 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1) (list te te te te tq te te te te te te te te te te te te te te te te te te) )) %melody; (setf stanza3 (list (list f a c f a g f d b c r r c g g e c r c) (list 2 2 3 3 3 3 3 3 2 3 0 0 3 3 3 3 3 0 3) (list tde ts1 te te te te te te te te th te te tq tq te te te te) %harmony; (list c gs a c gs a c gs a c c ds e g g ds e g g ds e) (list 1 0 0 1 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1) (list tq te te tq te te tq te te te te te te te te te te te te te te) (list f gs a f gs a f gs a f f ds e c c ds e c c ds e) (list 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1) (list tq te te tq te te tq te te te te te te te te te te te te te te) )) %melody; (setf stanza4 (list (list f f ef f ef c bf gs b b bf b bf af f c ef f) (list 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2) (list tq tq ts ts1 ts ts1 te te tq tq ts ts1 ts ts1 te te te te) %harmony; (list f f cs d f c c gs a c c) (list 1 1 1 1 1 1 1 0 0 1 1) (list te te te te th te te te te th tq) (list bf bf cs d bf f f gs a f f) (list 0 0 1 1 0 0 0 0 0 0 0) (list te te te te th te te te te th tq) )) (let () (setf octave-offset 0) (setf pitch-offset 0) (setf vol 10) (setf tempo 80) (play-stanza stanza1) (play-stanza stanza2) (play-stanza stanza3) (play-stanza stanza4) ) (setf stanza-counter 0) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % generate C structures to play the tune; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (de print-stanza (stanza stanza-name) (let ((notes nil) (octaves nil) (durations nil) (voice-names (make-vector 3 "NULL")) (voice-num 0) ) (while stanza (vector-store voice-names voice-num (bldmsg "&voice%d" stanza-counter)) (setf notes (first stanza)) (setf octaves (second stanza)) (setf durations (third stanza)) (setf stanza (pnth stanza 4)) (printf "int notes%d[] =%n {" stanza-counter) (for (in i notes) (do (printf "%d," i) )) (printf "-42};%n") (printf "int octaves%d[] =%n {" stanza-counter) (for (in i octaves) (do (printf "%d," i) )) (printf "-42};%n") (printf "int durations%d[] =%n {" stanza-counter) (for (in i durations) (do (printf "%d," i) )) (printf "-42};%n") (printf "struct voice_def voice%d = { notes%d, octaves%d, durations%d};%n" stanza-counter stanza-counter stanza-counter stanza-counter); (setf stanza-counter (+ stanza-counter 1)) (setf voice-num (+ voice-num 1)) ) (printf "struct stanza_def %s = { %s, %s, %s, %s};%n" stanza-name (vector-fetch voice-names 0) (vector-fetch voice-names 1) (vector-fetch voice-names 2) (vector-fetch voice-names 3)) )) % (in-package old-package) @//E*O*F dbsetup.sl// chmod u=rw,g=rw,o=r dbsetup.sl echo x - music.c sed 's/^@//' > "music.c" <<'@//E*O*F music.c//' #include #define tempo 80 struct voice_def { int *notes; int *octaves; int *durations; }; struct stanza_def { struct voice_def *voice1; struct voice_def *voice2; struct voice_def *voice3; struct voice_def *voice4; }; struct voice_task { int time_to_go; int voice_num; int *notes; int *octaves; int *durations; }; #include "mytune.h" int vol = 11; int octave_offset = 0; int pitch_offset = 0; int scale[12][6] = { 0, 386, 705, 864, 943, 984, 0, 422, 722, 873, 948, 0, 0, 456, 739, 881, 952, 0, 0, 487, 755, 889, 956, 0, 12, 518, 770, 897, 960, 0, 69, 546, 784, 904, 963, 0, 123, 573, 798, 911, 967, 0, 173, 598, 810, 916, 970, 0, 220, 622, 822, 922, 973, 0, 266, 645, 834, 928, 976, 0, 308, 665, 844, 933, 978, 0, 348, 685, 854, 938, 981, 0}; beep_or_noise_duration_left(val) int val; { beep_or_noise_left(val); } get_note(pitch,octave) int pitch,octave; { int real_pitch; int real_octave; real_pitch = pitch + pitch_offset; real_octave = octave + octave_offset; if (real_pitch >= 12) { real_pitch = real_pitch - 12; real_octave = real_octave + 1; } if (real_pitch < 0) { real_pitch = real_pitch + 12; real_octave = real_octave - 1; } return(scale[real_pitch][real_octave]); } note(pitch, octave, voice, duration) int pitch, octave, voice, duration; { if (pitch == -1) beep(voice,0,0,(10 * duration)/tempo); else beep(voice, get_note(pitch,octave), vol, (10 * duration)/tempo); } go_on_voice(voice_num) int voice_num; { while(beep_or_noise_duration_left(voice_num)) ; } load_voice(task,data,voice_num) struct voice_task *task; struct voice_def *data; int voice_num; { if (data == NULL) (*task).time_to_go = -1; else { (*task).time_to_go = 0; (*task).voice_num = voice_num; (*task).notes = (*data).notes; (*task).octaves = (*data).octaves; (*task).durations = (*data).durations; } } play_stanza(stanza) struct stanza_def *stanza; { struct voice_def *voice1,*voice2,*voice3,*voice4; struct voice_task voices[4]; int num_voices, note_id, octave, voice_num, duration, wait_time; int i,j; /** load up the voice task structures **/ load_voice(&voices[0],(*stanza).voice1,1); load_voice(&voices[1],(*stanza).voice2,2); load_voice(&voices[2],(*stanza).voice3,3); load_voice(&voices[3],(*stanza).voice4,4); /** how many voices do we have data for? **/ for (i=0; i<4; i++) if (voices[i].time_to_go == -1) break; num_voices = i; /** while we still have some voices to give data to **/ while (num_voices > 0) { /** find voices that are ready for another note **/ for (i=0; i "beeper.c" <<'@//E*O*F beeper.c//' /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; File: beeper.c ; SCCS: %A% %G% %U% ; Description: Access Gator/Bobcat beeper ; Created: 2-Aug-85 ; Modified: 7-Aug-85 17:00:34 ; Language: C ; Package: PSL ; Status: Experimental (Do Not Distribute) ; ; (c) Copyright 1985, Hewlett-Packard Company, all rights reserved. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */ /* Public functions: beep noise beep_or_noise_left We offer three voices and a noise source. Each sound is controllable in pitch, volume and duration. Pitch goes from 0 to 1023, volume goes from 0 to 15, duration is between 0 and 255 10msec intervalls. A duration of 0 turns the voice on continuously. A volume of 0 turns it off. The manufacturing specs give details on the programming interface. Here is a summary: The beeper is accessed through ioctl calls. The request argument is either "Send data to beeper" or "Read voice values from beeper". The argument is a pointer to a 4 byte buffer. These four bytes are defined here. R0-R3: Register address field. In the order R2, R1, R0: 0 0 0: Voice 1 frequency 0 0 1: Voice 1 attenuation 0 1 0: Voice 2 frequency 0 1 1: Voice 2 attenuation 1 0 0: Voice 3 frequency 1 0 1: Voice 3 attenuation 1 1 0: Noise control 1 1 1: Noise attentuation F0-F9: 10 bits pitch A0-A3: Attenuation D0-D7: Duration in 10msec's The placement of data in the buffer is a bit srewy: Byte 0 (Frequency 1): 1 R2 R1 R0 F3 F2 F1 F0 LSB Byte 1(Frequency 2): 0 0 F9 F8 F7 F6 F5 F4 Byte 2 (Attenuator) : 1 R2 R1 R0 A3 A2 A1 A0 Byte 3 (Duration) : D7 D6 D5 D4 D3 D2 D1 D0 The volume is inversely proportional to the attenuation. In order to provide rising numbers for rising loudness to the user, we expect a volume and modify to get the attenuation. The same goes for the pitch. In order to calculate frequency of the pitch, use: 83333/(pitch-1023) It is possible at any time to request the time any voice has left to run. This is done by: F4: Read voice1 timer F5: Read voice2 timer F6: Read voice3 timer F7: Read voice4 timer (noise) Noise is generated using a shift register. The following controls are possible for noise: - Attenuation - Duration - Periodic or white noise - 3 shift rates or output of voice 4 as shift rate Bytes 0 and 1 of the data buffer must both have identical contents to control the noise. Attenuation and duration are as in the other voices. Bytes 0 and 1 should look like this: 1 R2 R1 R0 0 FB NF1 NF0 LSB R2, R1 and R0 must be 1, 1 and 0. If FB is 0, periodic noise is generated. If FB is 1, white noise is produced. NF1 and NF2 control the shift rate of the noise generator: NF1 NF2 Shift Rate -------------------------- 0 0 M/64 0 1 M/128 1 0 M/256 1 1 Uses tone generator 3 output M is related to the clock rate. The voice start routines return 0 if all is well, -1 if we had trouble accessing the device file for the beeper and -2 if given parameters were out of range: */ #include #include /********************************************************************* *DEFINES: * *********************************************************************/ #define ALL_OK 0 #define ACCESS_PROBLEM -1 #define BAD_RANGE -2 #define BEEPER_DEVICE "/dev/rhil" #define VOICE1_FREQ_REG 0x80 /* Top nibbles for byte0 for all voices: */ #define VOICE2_FREQ_REG 0xA0 #define VOICE3_FREQ_REG 0xC0 #define NOISE_FREQ_REG 0xE0 #define VOICE1_VOL_REG 0x90 /* Top nibbles for byte2 for all voices: */ #define VOICE2_VOL_REG 0xB0 #define VOICE3_VOL_REG 0xD0 #define NOISE_VOL_REG 0xF0 #define MIN_VOICE 1 /* Legal ranges for parms from user: */ #define MAX_VOICE 3 #define MIN_PITCH 0 #define MAX_PITCH 1023 #define MIN_DURATION 0 #define MAX_DURATION 255 #define MIN_VOLUME 0 #define MAX_VOLUME 15 #define MIN_TYPE 0 #define MAX_TYPE 1 #define MIN_RATE 0 #define MAX_RATE 3 static int beeper_fd = -1; /********************************************************************* * PUBLIC FUNCTIONS: * *********************************************************************/ /***************************************************************************** * * * Beep using specified voice: * * * * TAKES: * * * * VOICE : from 1 to 3 * * PITCH : from 0 to 1023 (incl) * * VOLUME : from 0 to 15 (incl). Zero turns voice off. * * DURATION : from 0 to 255 (incl). Zero turns voice on continuously. * * * * RETURNS: * * * * 0 : All ok * * -1 : Cannot access beeper device file * * -2 : Parameter out of range * * * ******************************************************************************/ beep(voice,pitch,volume,duration) int voice,pitch,volume,duration; { unsigned char buffer[4]; /* Check ranges of parameters: */ if ( (voice < MIN_VOICE) || (voice > MAX_VOICE) || (pitch < MIN_PITCH) || (pitch > MAX_PITCH) || (volume < MIN_VOLUME) || (volume > MAX_VOLUME) || (duration < MIN_DURATION) || (duration > MAX_DURATION) ) return(BAD_RANGE); /* Check whether beeper device has already been opened: */ if (beeper_fd < 0) if ((beeper_fd = open(BEEPER_DEVICE,O_RDWR)) < 0) return(ACCESS_PROBLEM); /* Init the voice dependent data bytes. Note the inversion of user's volume and pitch specs to attenuation: */ volume = MAX_VOLUME - volume; pitch = MAX_PITCH - pitch; switch (voice) { case 1: buffer[0] = VOICE1_FREQ_REG | (pitch & 0x0000000f); buffer[2] = VOICE1_VOL_REG | (volume & 0x0000000f); break; case 2: buffer[0] = VOICE2_FREQ_REG | (pitch & 0x0000000f); buffer[2] = VOICE2_VOL_REG | (volume & 0x0000000f); break; case 3: buffer[0] = VOICE3_FREQ_REG | (pitch & 0x0000000f); buffer[2] = VOICE3_VOL_REG | (volume & 0x0000000f); break; }; /* The high 6 bits of the pitch go into byte 1: */ buffer[1] = 0x0000003f & (pitch >> 4); /* Duration: */ buffer[3] = duration; if (ioctl(beeper_fd,EFTSBP,buffer) < 0) return(ACCESS_PROBLEM); return(ALL_OK); } /* end function beep */ /*----------------------------------------------------*/ /****************************************************************************** * Produce noise. * * * * TAKES: * * * * TYPE : from 0 to 1. 0 is periodic noise. 1 is white noise. * * RATE : from 0 to 3. 0 is M/64. 1 is M/128. 2 is M/256. 3 means rate * * determined by output of voice 3. * * VOLUME : from 0 to 15 (incl). Zero turns voice off. * * DURATION : from 0 to 255 (incl). Zero turns voice on continuously. * * * * RETURNS: * * * * 0 : All ok * * -1 : Cannot access beeper device file * * -2 : Parameter out of range * ******************************************************************************/ noise(type,rate,volume,duration) int type,rate,volume,duration; { unsigned char buffer[4]; /* Check ranges of parameters: */ if ( (type < MIN_TYPE) || (type > MAX_TYPE) || (rate < MIN_RATE) || (rate > MAX_RATE) || (volume < MIN_VOLUME) || (volume > MAX_VOLUME) || (duration < MIN_DURATION) || (duration > MAX_DURATION) ) return(BAD_RANGE); /* Check whether beeper device has already been opened: */ if (beeper_fd < 0) if ((beeper_fd = open(BEEPER_DEVICE,O_RDWR)) < 0) return(ACCESS_PROBLEM); /* Invert the volume provided by the user getting the attenuation: */ volume = MAX_VOLUME - volume; type = type << 2; buffer[0] = NOISE_FREQ_REG | (type | rate); /* Byte one must be identical to byte 0: */ buffer[1] = buffer[0]; buffer[2] = NOISE_VOL_REG | (volume & 0x0000000f); buffer[3] = duration; if (ioctl(beeper_fd,EFTSBP,buffer) < 0) return(ACCESS_PROBLEM); return(ALL_OK); } /* end function noise */ /*----------------------------------------------------*/ /**************************************************************************** * * * Read how many 10msec intervalls are left till a voice has * * beeped to the end. This routine is good for noise also. * * * * TAKES: * * * * voice : from 1 to 4 * * * * RETURNS: * * * * 0 : Beeper has finished * * >0 : Number of 10msec intervalls * * -1 : Cannot access beeper device file * * -2 : Parameter out of range * *****************************************************************************/ beep_or_noise_left(voice) int voice; { unsigned char buffer[4]; /* Check for legal parameter range. The '+1' is to include noise generator: */ if ( (voice < MIN_VOICE) || (voice > (MAX_VOICE + 1)) ) return(BAD_RANGE); /* Check whether beeper device has already been opened: */ if (beeper_fd < 0) if ((beeper_fd = open(BEEPER_DEVICE,O_RDWR)) < 0) return(ACCESS_PROBLEM); /* Get the timer values into the buffer bytes: */ if (ioctl(beeper_fd,EFTRT,buffer) < 0) return(ACCESS_PROBLEM); return((int) buffer[voice-1]); } /* end function beep_or_noise_left */ /*---------------------------------------------------*/ @//E*O*F beeper.c// chmod u=rw,g=rw,o=r beeper.c echo x - mytune.h sed 's/^@//' > "mytune.h" <<'@//E*O*F mytune.h//' int notes0[] = {5,9,0,5,9,7,5,2,11,0,-1,5,9,0,5,9,7,5,2,-42}; int octaves0[] = {2,2,3,3,3,3,3,3,2,3,0,2,2,3,3,3,3,3,3,-42}; int durations0[] = {187,63,125,125,125,125,125,125,125,125,750,187,63,125,125,125,125,125,125,-42}; struct voice_def voice0 = { notes0, octaves0, durations0}; int notes1[] = {0,8,9,0,8,9,0,8,9,0,0,8,9,0,8,9,0,8,9,-42}; int octaves1[] = {1,0,0,1,0,0,1,0,0,1,1,0,0,1,0,0,1,0,0,-42}; int durations1[] = {250,125,125,250,125,125,250,125,125,125,125,125,125,250,125,125,250,125,125,-42}; struct voice_def voice1 = { notes1, octaves1, durations1}; int notes2[] = {5,8,9,5,8,9,5,8,9,5,5,8,9,5,8,9,5,8,9,-42}; int octaves2[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-42}; int durations2[] = {250,125,125,250,125,125,250,125,125,125,125,125,125,250,125,125,250,125,125,-42}; struct voice_def voice2 = { notes2, octaves2, durations2}; struct stanza_def stanza1 = { &voice0, &voice1, &voice2, NULL}; int notes3[] = {0,2,8,2,8,5,-1,-42}; int octaves3[] = {3,3,2,3,2,2,0,-42}; int durations3[] = {750,125,1000,125,125,125,750,-42}; struct voice_def voice3 = { notes3, octaves3, durations3}; int notes4[] = {0,0,8,9,0,1,2,5,5,1,2,5,5,1,2,5,5,1,2,5,5,1,2,-42}; int octaves4[] = {1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-42}; int durations4[] = {125,125,125,125,250,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,-42}; struct voice_def voice4 = { notes4, octaves4, durations4}; int notes5[] = {5,5,8,9,5,1,2,10,10,1,2,10,10,1,2,10,10,1,2,10,10,1,2,-42}; int octaves5[] = {0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,-42}; int durations5[] = {125,125,125,125,250,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,-42}; struct voice_def voice5 = { notes5, octaves5, durations5}; struct stanza_def stanza2 = { &voice3, &voice4, &voice5, NULL}; int notes6[] = {5,9,0,5,9,7,5,2,11,0,-1,-1,0,7,7,4,0,-1,0,-42}; int octaves6[] = {2,2,3,3,3,3,3,3,2,3,0,0,3,3,3,3,3,0,3,-42}; int durations6[] = {187,63,125,125,125,125,125,125,125,125,500,125,125,250,250,125,125,125,125,-42}; struct voice_def voice6 = { notes6, octaves6, durations6}; int notes7[] = {0,8,9,0,8,9,0,8,9,0,0,3,4,7,7,3,4,7,7,3,4,-42}; int octaves7[] = {1,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,-42}; int durations7[] = {250,125,125,250,125,125,250,125,125,125,125,125,125,125,125,125,125,125,125,125,125,-42}; struct voice_def voice7 = { notes7, octaves7, durations7}; int notes8[] = {5,8,9,5,8,9,5,8,9,5,5,3,4,0,0,3,4,0,0,3,4,-42}; int octaves8[] = {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,-42}; int durations8[] = {250,125,125,250,125,125,250,125,125,125,125,125,125,125,125,125,125,125,125,125,125,-42}; struct voice_def voice8 = { notes8, octaves8, durations8}; struct stanza_def stanza3 = { &voice6, &voice7, &voice8, NULL}; int notes9[] = {5,5,3,5,3,0,10,8,11,11,10,11,10,8,5,0,3,5,-42}; int octaves9[] = {3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,-42}; int durations9[] = {250,250,62,63,62,63,125,125,250,250,62,63,62,63,125,125,125,125,-42}; struct voice_def voice9 = { notes9, octaves9, durations9}; int notes10[] = {5,5,1,2,5,0,0,8,9,0,0,-42}; int octaves10[] = {1,1,1,1,1,1,1,0,0,1,1,-42}; int durations10[] = {125,125,125,125,500,125,125,125,125,500,250,-42}; struct voice_def voice10 = { notes10, octaves10, durations10}; int notes11[] = {10,10,1,2,10,5,5,8,9,5,5,-42}; int octaves11[] = {0,0,1,1,0,0,0,0,0,0,0,-42}; int durations11[] = {125,125,125,125,500,125,125,125,125,500,250,-42}; struct voice_def voice11 = { notes11, octaves11, durations11}; struct stanza_def stanza4 = { &voice9, &voice10, &voice11, NULL}; @//E*O*F mytune.h// chmod u=rw,g=rw,o=r mytune.h exit 0 -- See above (214)661-8960