forked from ology/Music
-
Notifications
You must be signed in to change notification settings - Fork 0
/
note-transition
62 lines (47 loc) · 1.55 KB
/
note-transition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/usr/bin/env perl
# Run this, to produce a freq file, then run stat-walk with it.
use strict;
use warnings;
use Data::Dumper;
use MIDI;
use Statistics::Frequency;
use Storable;
# Get the commandline arguments
my $file = shift || die "Usage: perl $0 tune.mid\n";
my $notes = shift || 1; # Number of notes in the preceeding list
my $opus = MIDI::Opus->new({ from_file => $file });
# Collect the MIDI events
my @events = ();
for my $i ( 0 .. scalar( $opus->tracks ) - 1 ) {
my $track = [ $opus->tracks ]->[$i];
push @events, ( grep { $_->[0] eq 'note_on' } $track->events );
}
# Setup the transition buckets
my $transitions = {};
my @preceeding;
# Gather the transitions
for my $event ( @events ) {
# The next note in succession
my $next = $event->[3];
# Add a transition if there are preceeding notes
if ( @preceeding == $notes ) {
push @{ $transitions->{ join ' ', @preceeding } }, $next;
#warn "Datum: @preceeding -> $next\n";
shift @preceeding;
}
# Add the next event to the preceeding event list
push @preceeding, $next;
}
#warn 'Note transitions: ', Dumper$transitions;
# Setup the frequency bucket
my $frequencies = {};
# Instantiate a new stat object
my $stat = Statistics::Frequency->new;
# Gather the proportional frequencies of each transition
for my $note ( keys %$transitions ) {
$stat->add_data( @{ $transitions->{$note} } );
$frequencies->{$note} = { $stat->proportional_frequencies };
$stat->clear_data;
}
warn 'Transition frequencies: ', Dumper$frequencies;
store $frequencies, "$0.dat";