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

[MacPerl] Midi Mouth (requires MIDI.pm)



#!perl

# "Midi Mouth" v. 0.5
# by David D. Seay <g-s@navix.net>
# October 1999
#
# REQUIRES MIDI.pm
# (available in CPAN or at
#  <http://www.lenzo.com/~sburke/pub/perl_midi/>)

# 1) save as droplet
# 2) drag and drop a midi file on it to hear it
#
# Special thanks to Sean Burke for examples on how to
#   get midi note pitches and durations using MIDI.pm
#   and for his marvelous MIDI-Perl suite for reading,
#   writing, manipulating, and composing MIDI files.

use MIDI; # by Sean Burke
use Mac::Speech;

$input_file = $ARGV[0];

$tempoFactor = .08; # increase if song is too fast
$speech = 'e ' x 100;

&get_midi;
&play_it;
exit(0);

sub get_midi {
	my $opus = MIDI::Opus->new({ 'from_file' => $input_file });
	foreach my $t ($opus->tracks) {
		my($score_r, $ticks) = MIDI::Score::events_r_to_score_r(
$t->events_r );
		foreach my $n (@$score_r) {
			next unless  $n->[0] eq 'note';
			$startTime = $n->[1];
			$duration  = $n->[2];
			$channel   = $n->[3];
			$note      = $n->[4];

			$delay = int(($duration  / 60)/2);
			$start = int(($startTime / 60)/2);

			for (;;) {
				if ($start == 0 || $start >=
$closeChanTime[$channel]) { last }
				$channel++;
			}
			$seq[$start]            .= "$channel,$note--";
			$seq[$start + $delay]   .= "$channel,x--";
			$closeChanTime[$channel] = $start + $delay;

			if ($channel > $highestChannel) { $highestChannel =
$channel }
		}
	}
}


sub play_it {
	for $chan (0..$highestChannel) {
		$channel[$chan] = NewSpeechChannel($Voice{'Zarvox'}) or die
$^E;
	}

	for $noteSeq (0..$#seq) {
		@seqNotes = split(/--/,$seq[$noteSeq]);
		for $e (0..$#seqNotes) {
			if (! $seqNotes[$e]) { next }
			($channel,$note) = split(/,/,$seqNotes[$e]);
			if($note =~ /x/) {
				StopSpeech     $channel[$channel] or die $^E;
			} elsif ($note > 0)  {
 				SetSpeechPitch $channel[$channel], $note or
die $^E;
 				SpeakText      $channel[$channel], $speech
or die $^E;
 			}
 		}
		select(undef, undef, undef, $tempoFactor);
	}

	for $chan (0..$highestChannel) {
		DisposeSpeechChannel $channel[$chan] if $channel[$chan];
	}
}


__END__




# ===== Want to unsubscribe from this list?
# ===== Send mail with body "unsubscribe" to macperl-request@macperl.org