[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] 99 Bottles v1.1



#!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