adding text events to a midi file

[email protected] ("Sean M. Burke") Sun, 28 Jul 2002 16:18:32 -0600
Newsgroups perl.midi
Message-ID <[email protected]>
Here's a code snippet that maybe someone on the list might find useful:


[someone wrote to me, asking:]
>I know this is a stupid question but I am still having trouble following 
>the doc. How do I add an event (eg. text_event) to an existing MIDI file 
>after I opened it with MIDI::Opus->new?

Not a stupid question at all!  I hope this illustrates things:


use strict;
my $file = "test123.mid";
use MIDI; # uses MIDI::Opus et al

# Generate a little test file just for us to play with:
make_dumb_midi();

print "Before:\n";
dump_file($file);

add_text(qq<I like pie!  Who says I don't!?>);

print "After:\n";
dump_file($file);
exit;


# Add the text event(s) to the beginning:
sub add_text {
   my @text = @_;
   return unless @text;
   my $opus = MIDI::Opus->new({ 'from_file' => $file });
   my $tracks = $opus->tracks_r;
   die "$file has no tracks?!" unless @$tracks;
   die "First track of $file isn't a music track?!"
    unless $tracks->[0]->type eq 'MTrk';
   unshift  # Add to the start of the 0th track:
    @{ $tracks->[0]->events_r },
    map ['text_event',0, $_], @text
   ;
   $opus->write_to_file($file);
   sleep 0;
   die "Where'd the file go!?" unless -e $file and -s _;
}

sub dump_file {
   my $filename = $_[0];
   MIDI::Opus->new({ from_file=>$filename })
    ->dump({ dump_tracks=>1 });
   return;
}

sub make_dumb_midi {
   my $chimes_track = MIDI::Track->new({ 'events' => [
      ['patch_change', 0, 1, 0],
      map( (['note_on',0,1,$_->[0],96],
            ['note_off',$_->[1],1,$_->[0],0]
           ),
           [25,96],[29,96],[27,96],[20,192]
         )
   ]});
   my $chimes = MIDI::Opus->new( {
    'format' => 0, 'ticks' => 96,
    'tracks' => [ $chimes_track ] }
   );
   $chimes->write_to_file($file);
   sleep 0;
   die "Where'd the file go!?" unless -e $file and -s _;
}

__END__

Output:
MIDI::Opus->new({
   'format' => 0,
   'ticks'  => 96,
   'tracks' => [   # 1 tracks...

     # Track #0 ...
     MIDI::Track->new({
       'type' => 'MTrk',
       'events' => [  # 9 events.
         ['patch_change', 0, 1, 0],
         ['note_on', 0, 1, 25, 96],
         ['note_off', 96, 1, 25, 0],
         ['note_on', 0, 1, 29, 96],
         ['note_off', 96, 1, 29, 0],
         ['note_on', 0, 1, 27, 96],
         ['note_off', 96, 1, 27, 0],
         ['note_on', 0, 1, 20, 96],
         ['note_off', 192, 1, 20, 0],
       ]
     }),

   ]
});
After:
MIDI::Opus->new({
   'format' => 0,
   'ticks'  => 96,
   'tracks' => [   # 1 tracks...

     # Track #0 ...
     MIDI::Track->new({
       'type' => 'MTrk',
       'events' => [  # 10 events.
         ['text_event', 0, 'I like pie!  Who says I don\'t!?'],
         ['patch_change', 0, 1, 0],
         ['note_on', 0, 1, 25, 96],
         ['note_off', 96, 1, 25, 0],
         ['note_on', 0, 1, 29, 96],
         ['note_off', 96, 1, 29, 0],
         ['note_on', 0, 1, 27, 96],
         ['note_off', 96, 1, 27, 0],
         ['note_on', 0, 1, 20, 96],
         ['note_off', 192, 1, 20, 0],
       ]
     }),

   ]
});



--
Sean M. Burke    http://www.spinn.net/~sburke/