#!perl # "99 Bottles" v. 1.1 # by David D. Seay g-s@navix.net # November 1999 # # To exit press cmd '.' repeatedly until the song stops. # # Song gets slower and notes get lower as song progresses. # package Main; use Mac::Speech; use Mac::Events; use Mac::Events qw(@Event $CurrentEvent); use Mac::LowMem; $Event[keyDown] = \&key_down; # $bottles_at_start = 6; # 99; # @noteNames = split(" ", "c d e f g a b C D E F G A B C1"); @scalePitches = split(",", "48,50,52,53,55,57,59,60,62,64,65,67,69,71,72"); for $p (0..$#scalePitches) { $pitch{$noteNames[$p]} = $scalePitches[$p]; } $tempo_factor = .45; # Increase if ends of words are clipped # NOTE DURATIONS $dur{'s'} = .15 * $tempo_factor; # eighth note $dur{ds} = .37 * $tempo_factor; # eighth note $dur{e} = .50 * $tempo_factor; # eighth note $dur{de} = .80 * $tempo_factor; # dotted eighth note $dur{'q'} = 1.0 * $tempo_factor; # quarter note $dur{dq} = 1.5 * $tempo_factor; # dotted quarter note $dur{h} = 2.0 * $tempo_factor; # half note $dur{he} = 2.5 * $tempo_factor; # half note + an eighth $dur{dh} = 3.0 * $tempo_factor; # dotted half note $dur{dhe} = 3.5 * $tempo_factor; # dotted half note + an eighth $dur{w} = 4.0 * $tempo_factor; # whole note # SONG FORMAT - note items must be delimited by tabs # 1) word or syllable to be sung # 2) pitch (how high or low) # 3) duration (how long # # Hint: You can use a spreadsheet program to enter a new song. # 1) Put each note's info on a separate row. # 2) Column 1 = word; Column 2 = pitch; Column 2 = duration # 2) Select all of the spreadsheet cells. # 3) Paste into the '$song' variable below. # $song = <<"EOF"; 99 C q bottles of C q beer on the C q wall C q 99 D q bottles of a q beer D h take one b q down and b q pass it a b q round b q 98 g q bottles a de of b s beer on the C q wall C h EOF $voice = $Voice{"Zarvox"}; $channel1 = NewSpeechChannel($voice) or die $^E; for $loop (1..$bottles_at_start) { $bottles = $bottles_at_start + 1 - $loop; $verse = $song; $bottlesM1 = $bottles - 1; $verse =~ s/98/$bottlesM1/g; $verse =~ s/99/$bottles/g; if ($bottles == 2) { $verse =~ s/bottles\ta/bottle\ta/gi; } elsif ($bottles == 1) { $verse =~ s/bottles of/bottle of/gi; $verse =~ s/one/it/gi; } @song = split("\n",$verse); for $n (0..$#song) { if ($song[$n] eq "") { next } ($phrase,$note,$dur) = split("\t",$song[$n]); SetSpeechPitch $channel1, $pitch{$note} - ($loop * .1); SpeakText $channel1, $phrase or die $^E; select(undef, undef, undef, $dur{$dur} + ($loop * .01)); WaitNextEvent(); } while (SpeechBusy()) { WaitNextEvent() } } DisposeSpeechChannel $channel1; sub key_down { my($ev) = @_; $k = chr($ev->character); if (($CurrentEvent->modifiers & 256) == 256 && $k eq ".") { StopSpeech $channel1 or die $^E; DisposeSpeechChannel $channel1; exit(0); } } ===== Want to unsubscribe from this list? ===== Send mail with body "unsubscribe" to macperl-request@macperl.org