Skip to content

Instantly share code, notes, and snippets.

@jeffa
Created August 29, 2013 14:18
Show Gist options
  • Save jeffa/6378692 to your computer and use it in GitHub Desktop.
Save jeffa/6378692 to your computer and use it in GitHub Desktop.
Demonstration of the defunct 4ML language. This script converts the 4ML XML markup into actual MIDI events.
use strict;
use warnings;
use MIDI;
use XML::Simple;
my $xml = XMLin(\*DATA);
my $song = $xml->{SONG};
my @note = @{ $song->{NOTE} };
my $title = $song->{title} || 'unknown';
my $author = $song->{author} || 'unknown';
my (@event, $pitch, $duration, $velocity, $instrument);
for my $note (@note) {
# check for patch changes
if (exists $note->{instrument}) {
$instrument = $MIDI::patch2number{$note->{instrument}} || 1;
push @event,[patch_change => 0, 1, $instrument];
}
$pitch = scrub_pitch($note->{pitch},$pitch);
$duration = ($note->{duration} || 1) * 96;
$velocity = ($pitch eq 'rest') ? 0 : 96; # hacked silence
# add note_on/note_off pair
push @event,[note_on => 0,1,$MIDI::note2number{$pitch},$velocity];
push @event,[note_off => $duration,1,$MIDI::note2number{$pitch},0];
}
my $opus = MIDI::Opus->new({
format => 0,
ticks => $song->{bpm},
tracks => [ MIDI::Track->new({
events => [
[text_event => 0, "Title: $title"],
[text_event => 0, "Auhtor: $author"],
@event,
]
})],
});
$opus->write_to_file($song->{name}.'.mid');
# this transforms C into C4 and C:5 into C5 (etc.)
sub scrub_pitch {
my ($next,$prev) = @_;
return $prev unless $next;
my ($note,$octave) = split(':',$next,2);
return $note if lc($note) eq 'rest';
$octave ||= 4;
return "$note$octave";
}
__DATA__
<?xml version="1.0" standalone="no"?>
<!DOCTYPE OPUS SYSTEM "http://4ml.org/4ml.dtd">
<OPUS>
<SONG name="mary" title="Mary Had a Little Lamb" bpm="160">
<!-- Define the notes here -->
<NOTE pitch="E:5" />
<NOTE pitch="D:5" />
<NOTE pitch="C:5" />
<NOTE pitch="D:5" />
<NOTE pitch="E:5" />
<NOTE />
<NOTE />
<NOTE pitch="rest" />
<NOTE pitch="D:3" instrument="Harpsichord" />
<NOTE />
<NOTE />
<NOTE pitch="rest" />
<NOTE pitch="E:3" />
<NOTE pitch="G:3" />
<NOTE />
<NOTE pitch="rest" />
<NOTE pitch="E" instrument="Sitar" />
<NOTE pitch="D" />
<NOTE pitch="C" />
<NOTE pitch="D" />
<NOTE pitch="E" />
<NOTE />
<NOTE />
<NOTE />
<NOTE pitch="D" instrument="Bagpipe" />
<NOTE />
<NOTE pitch="E" />
<NOTE pitch="D" />
<NOTE pitch="C:3" duration="4" instrument="Church Organ" />
</SONG>
</OPUS>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment