#!/usr/local/bin/perl -w # # Extract SysEx chunks from standard MIDI file # Copyright (c) 1997, Hiroyuki Ohsaki. # All rights reserved. # # $Id: $ # use strict; my $DEBUG = 0; # interpret a variable-lengt-encoded number in STR, and return the # value with decoded string length. sub get_number { my $str = shift; @_ = unpack('C*', $str); my $val = 0; my $len = 0; for (@_) { $val = ($val * 0x80) + ($_ & 0x7f); $len++; last unless ($_ & 0x80); } ($val, $len); } # parse BUF as a track data section sub do_track { my $buf = shift; my $index = 0; my $delta; my $type; my $len; while ($index < length($buf)) { # delta time ($delta, $_) = get_number(substr($buf, $index, 4)); $index += $_; # message type $type = unpack('C', substr($buf, $index, 1)); $index++; $index++ if ($type == 0xff); # meta event # data length ($len, $_) = get_number(substr($buf, $index, 4)); $index += $_; # dump sysex chunk if ($type == 0xf0 or $type == 0xf7) { print "\xf0" if ($type == 0xf0); print substr($buf, $index, $len); } $index += $len; } } my $buf = join('', <>); my $index = 0; my $type; my $len; while ($index < length($buf)) { # chunk type and data length ($type, $len) = unpack('a4N', substr($buf, $index, 8)); $index += 8; # parse track data section do_track(substr($buf, $index, $len)) if ($type eq 'MTrk'); $index += $len; }