ViaThinkSoft CodeLib
This article is in:
CodeLib → Programming aids → Perl
Im SMF-0-Format von MIDI sind alle MIDI-Events - sowohl globale Events als auch die Ereignisse für die einzelnen Instrumente - in einem Track zusammengefasst.
Möchte man nun Ereignisse eines Instruments herausfiltern, stellt sich das durchaus schwierig dar, da die Zeit, bei der ein bestimmtes Ereignis eintreten soll, relativ angegeben ist (relativ zum vorhergehenden Ereignis).
Im SMF-1 MIDI-Format hingegen wird jedem Instrument ein Track zugeordnet, auf dem nur Ereignisse für dieses spezielle Instrument verzeichnet sind. Die Zeit, wann welches Ereignis eintreten soll, ist hierbei ebenfalls relativ angegeben - jedoch nur relativ zu anderen Events, die diesem Track zugeordnet sind und somit für das gleiche Instrument bestimmt sind. Somit können sich beispielsweise einfacher Melodien herausfiltern.
Hier finden Sie eine Perl-Funktion, die eine MIDI SMF-0 - Datei in eine MIDI SMF-1 - Datei umwandelt.
Diese Funktion wird von uns bereits im myMoozle Web Crawler eingesetzt. MyMoozle ist unsere semantische Musiksuchmaschine.
Wir verwenden das MIDI - Perl-Modul von der Seite http://search.cpan.org/~conklin/MIDI-Perl-0.82
http://www.mymoozle.com
Möchte man nun Ereignisse eines Instruments herausfiltern, stellt sich das durchaus schwierig dar, da die Zeit, bei der ein bestimmtes Ereignis eintreten soll, relativ angegeben ist (relativ zum vorhergehenden Ereignis).
Im SMF-1 MIDI-Format hingegen wird jedem Instrument ein Track zugeordnet, auf dem nur Ereignisse für dieses spezielle Instrument verzeichnet sind. Die Zeit, wann welches Ereignis eintreten soll, ist hierbei ebenfalls relativ angegeben - jedoch nur relativ zu anderen Events, die diesem Track zugeordnet sind und somit für das gleiche Instrument bestimmt sind. Somit können sich beispielsweise einfacher Melodien herausfiltern.
Hier finden Sie eine Perl-Funktion, die eine MIDI SMF-0 - Datei in eine MIDI SMF-1 - Datei umwandelt.
Diese Funktion wird von uns bereits im myMoozle Web Crawler eingesetzt. MyMoozle ist unsere semantische Musiksuchmaschine.
Wir verwenden das MIDI - Perl-Modul von der Seite http://search.cpan.org/~conklin/MIDI-Perl-0.82
http://www.mymoozle.com
sub MIDI_SMF0toSMF1 {
#
# MIDI_SMF0toSMF1
# (c) Copyright 2010 ViaThinkSoft - intelligent software for everyone
#
# @param $opus - a MIDI Opus in format 0 (http://search.cpan.org/~conklin/MIDI-Perl-0.82/lib/MIDI/Opus.pm)
# @return a MIDI Opus in format 1
#
# This function converts a SMF0 MIDI Opus into a SMF1 MIDI Opus
my $opus = $_[0];
if ($opus->format ne 0) {
die('MIDI is not in format 0!');
}
my $newOpus = MIDI::Opus->new({ 'format' => 1 , 'ticks' => $opus->ticks});
my %channelToTrack = (-1 => '0');
my %addTime = (-1 => 0);
# Add a NULL track for non-channel events
push(@{$newOpus->tracks_r}, MIDI::Track->new);
my @tracks = $opus->tracks;
foreach my $track (@tracks) {
foreach my $event ($track->events) {
my $e = $event->[0]; # event name
my $t = $event->[1]; # delta time
my $c; # channel id
if ( ($e eq 'note_off') || ($e eq 'note_on') || ($e eq 'key_after_touch') ||
($e eq 'control_change') || ($e eq 'patch_change') || ($e eq 'channel_after_touch') ||
($e eq 'pitch_wheel_change') ) {
$c = $event->[2]; # channel
# check if there already exists a channel->track assignment for the new opus,
# if not, create a new track
if (! exists $channelToTrack{$c}) {
push(@{$newOpus->tracks_r}, MIDI::Track->new);
$channelToTrack{$c} = scalar($newOpus->tracks)-1;
my @trackNameEvent = ('track_name', 0, 'Tr. '.($channelToTrack{$c}+1));
push(@{$newOpus->tracks_r->[$channelToTrack{$c}]->events_r}, \@trackNameEvent);
if (!$quiet) {print "(MIDI_SMF0toSMF1) new track, so add from -1: ".$addTime{-1}."\n";}
$addTime{$c} = $addTime{-1};
}
} else {
$c = -1;
}
# Add the accumulated time interval for the current channel/track
$event->[1] += $addTime{$c};
# Add the event to the track in the new opus
push(@{$newOpus->tracks_r->[$channelToTrack{$c}]->events_r}, $event);
# Update the accumulated times for the other tracks
foreach my $key (keys %addTime) {
if ( ($c ne $key) || ($c eq -1) ) {
$addTime{$key} += $t; # add delta time of current event
}
}
# Reset the accumulated time of the current channel/track
if ($c ne -1) {
$addTime{$c} = 0;
}
}
}
return $newOpus;
}
Victor-Phillip Negoescu
ViaThinkSoft Gründer
ViaThinkSoft Gründer