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