line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package MIDI::Tools;
|
2
|
|
|
|
|
|
|
|
3
|
6
|
|
|
6
|
|
59107
|
use 5.005;
|
|
6
|
|
|
|
|
23
|
|
|
6
|
|
|
|
|
237
|
|
4
|
6
|
|
|
6
|
|
33
|
use strict;
|
|
6
|
|
|
|
|
12
|
|
|
6
|
|
|
|
|
197
|
|
5
|
6
|
|
|
6
|
|
29
|
use warnings;
|
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
1388
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
require Exporter;
|
8
|
6
|
|
|
6
|
|
36
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
|
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
7466
|
|
9
|
|
|
|
|
|
|
@ISA = qw(Exporter);
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export
|
12
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead.
|
13
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants.
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# This allows declaration use MIDI::Tools ':all';
|
16
|
|
|
|
|
|
|
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
|
17
|
|
|
|
|
|
|
# will save memory.
|
18
|
|
|
|
|
|
|
%EXPORT_TAGS = ( 'all' => [ qw(note_count note_range note_mean note_limit
|
19
|
|
|
|
|
|
|
note_transpose) ] );
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
@EXPORT = qw( );
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
$VERSION = '0.02';
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 NAME
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
MIDI::Tools - Various functions dealing with MIDI Events
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
use MIDI::Tools qw(...);
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# too much stuff, see below
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 ABSTRACT
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
MIDI::Tools - Various functions dealing with MIDI events
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
This is a collection of functions evaluating or transforming lists of MIDI
|
44
|
|
|
|
|
|
|
events, probably most useful for algorithmic composition. It is designed to
|
45
|
|
|
|
|
|
|
be compatible with Sean M. Burke MIDI-Perl suite of modules.
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 CAVEAT
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
This module is in an early alpha stage of development. Interfaces are not
|
50
|
|
|
|
|
|
|
written in stone yet, and stuff needs to be added. Near-future plans include:
|
51
|
|
|
|
|
|
|
Dealing with intervals. Dealing with scales (transpose in scale,
|
52
|
|
|
|
|
|
|
measure outsideness). Swingifying. Dealing with Chords.
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=cut
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head1 EVALUATING MIDI EVENTS
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
All functions take a reference to a list of MIDI events as parameter and
|
59
|
|
|
|
|
|
|
return a scalar or list of results.
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head2 $count = note_count($events);
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Returns number of note_on events (excluding those with a velocity of 0).
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub note_count {
|
68
|
10
|
|
|
10
|
1
|
24
|
my ($e) = @_;
|
69
|
|
|
|
|
|
|
|
70
|
10
|
100
|
66
|
|
|
58
|
return 0 if (!defined $e || !ref $e);
|
71
|
|
|
|
|
|
|
|
72
|
8
|
|
|
|
|
13
|
my $count = 0;
|
73
|
8
|
|
|
|
|
9
|
foreach (@{$e}) {
|
|
8
|
|
|
|
|
17
|
|
74
|
13
|
|
|
|
|
90
|
$count++
|
75
|
18
|
100
|
100
|
|
|
47
|
if (ref $_ && $#{$_} >= 4 && $_->[0] eq 'note_on' && $_->[4] > 0);
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
76
|
|
|
|
|
|
|
}
|
77
|
|
|
|
|
|
|
|
78
|
8
|
|
|
|
|
38
|
return $count;
|
79
|
|
|
|
|
|
|
}
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 ($lowest, $highest) = note_range($events);
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Returns lowest and highest pitch ocurring in note_on events, or
|
84
|
|
|
|
|
|
|
undef if no note_on events occur in $events.
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=cut
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub note_range {
|
89
|
10
|
|
|
10
|
1
|
101
|
my ($e) = @_;
|
90
|
|
|
|
|
|
|
|
91
|
10
|
100
|
66
|
|
|
48
|
return undef if (!defined $e || !ref $e);
|
92
|
|
|
|
|
|
|
|
93
|
8
|
|
|
|
|
9
|
my ($lo, $hi);
|
94
|
8
|
|
|
|
|
9
|
foreach (@{$e}) {
|
|
8
|
|
|
|
|
14
|
|
95
|
18
|
100
|
100
|
|
|
37
|
if (ref $_ && $#{$_} >= 4 && $_->[0] eq 'note_on' && $_->[4] > 0) {
|
|
13
|
|
100
|
|
|
83
|
|
|
|
|
100
|
|
|
|
|
96
|
4
|
100
|
66
|
|
|
30
|
$lo = $_->[3] if (!defined $lo || $_->[3] < $lo);
|
97
|
4
|
50
|
66
|
|
|
18
|
$hi = $_->[3] if (!defined $hi || $_->[3] > $hi);
|
98
|
|
|
|
|
|
|
}
|
99
|
|
|
|
|
|
|
}
|
100
|
|
|
|
|
|
|
|
101
|
8
|
100
|
|
|
|
36
|
return undef if (!defined $lo);
|
102
|
2
|
|
|
|
|
7
|
return ($lo, $hi);
|
103
|
|
|
|
|
|
|
}
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=head2 ($mean, $stddev) = note_mean($events);
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Returns mean and standard deviation of pitches in MIDI note_on
|
108
|
|
|
|
|
|
|
events.
|
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=cut
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub note_mean {
|
113
|
10
|
|
|
10
|
1
|
122
|
my ($e) = @_;
|
114
|
|
|
|
|
|
|
|
115
|
10
|
100
|
66
|
|
|
54
|
return undef if (!defined $e || !ref $e);
|
116
|
|
|
|
|
|
|
|
117
|
8
|
|
|
|
|
11
|
my ($count, $sum) = (0, 0);
|
118
|
8
|
|
|
|
|
11
|
foreach (@{$e}) {
|
|
8
|
|
|
|
|
18
|
|
119
|
26
|
100
|
100
|
|
|
58
|
if (ref $_ && $#{$_} >= 4 && $_->[0] eq 'note_on' && $_->[4] > 0) {
|
|
21
|
|
100
|
|
|
151
|
|
|
|
|
100
|
|
|
|
|
120
|
8
|
|
|
|
|
10
|
$count++;
|
121
|
8
|
|
|
|
|
15
|
$sum += $_->[3];
|
122
|
|
|
|
|
|
|
}
|
123
|
|
|
|
|
|
|
}
|
124
|
|
|
|
|
|
|
|
125
|
8
|
100
|
|
|
|
42
|
return undef if ($count == 0);
|
126
|
|
|
|
|
|
|
|
127
|
2
|
|
|
|
|
5
|
my $avg = $sum / $count;
|
128
|
2
|
|
|
|
|
3
|
my $variance = 0;
|
129
|
2
|
|
|
|
|
2
|
foreach (@{$e}) {
|
|
2
|
|
|
|
|
5
|
|
130
|
16
|
100
|
66
|
|
|
40
|
if (ref $_ && $#{$_} >= 4 && $_->[0] eq 'note_on' && $_->[4] > 0) {
|
|
16
|
|
66
|
|
|
130
|
|
|
|
|
100
|
|
|
|
|
131
|
8
|
|
|
|
|
23
|
$variance += ($_->[3] - $avg) * ($_->[3] - $avg);
|
132
|
|
|
|
|
|
|
}
|
133
|
|
|
|
|
|
|
}
|
134
|
2
|
|
|
|
|
3
|
$variance /= $count;
|
135
|
|
|
|
|
|
|
|
136
|
2
|
|
|
|
|
12
|
return ($avg, sqrt($variance));
|
137
|
|
|
|
|
|
|
}
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 TRANSFORMING MIDI EVENTS
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
All functions take a reference to a list of MIDI events as parameter and
|
142
|
|
|
|
|
|
|
modify the events directly.
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=head2 note_limit($events, $lowest, $highest);
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
Remove all note_on and note_off events whose pitches lie outside
|
147
|
|
|
|
|
|
|
($lowest .. $highest).
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub note_limit {
|
152
|
3
|
|
|
3
|
1
|
296
|
my ($e, $lowest, $highest) = @_;
|
153
|
|
|
|
|
|
|
|
154
|
3
|
50
|
33
|
|
|
15
|
return undef if (!defined $e || !ref $e);
|
155
|
3
|
|
|
|
|
4
|
my $i = 0;
|
156
|
3
|
|
|
|
|
4
|
while ($i <= $#{$e}) {
|
|
12
|
|
|
|
|
31
|
|
157
|
9
|
|
|
|
|
17
|
for ($e->[$i]) {
|
158
|
9
|
100
|
66
|
|
|
21
|
if (ref $_ && $#{$_} >= 4 && $_->[0] =~ '^note_o(n|ff)$' &&
|
|
9
|
|
66
|
|
|
93
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
159
|
|
|
|
|
|
|
($_->[3] < $lowest || $_->[3] > $highest)) {
|
160
|
3
|
|
|
|
|
4
|
splice(@{$e}, $i, 1);
|
|
3
|
|
|
|
|
12
|
|
161
|
|
|
|
|
|
|
} else {
|
162
|
6
|
|
|
|
|
16
|
$i++;
|
163
|
|
|
|
|
|
|
}
|
164
|
|
|
|
|
|
|
}
|
165
|
|
|
|
|
|
|
}
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
}
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head2 note_transpose($events, $semitones);
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Transpose events by a (positive or negative) number of semitones. Notes will
|
172
|
|
|
|
|
|
|
not be transposed below 0 or above 127.
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=cut
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub note_transpose {
|
177
|
9
|
|
|
9
|
1
|
613
|
my ($e, $semitones) = @_;
|
178
|
|
|
|
|
|
|
|
179
|
9
|
50
|
33
|
|
|
38
|
return undef if (!defined $e || !ref $e);
|
180
|
|
|
|
|
|
|
|
181
|
9
|
|
|
|
|
15
|
my ($count, $sum) = (0, 0);
|
182
|
9
|
|
|
|
|
10
|
foreach (@{$e}) {
|
|
9
|
|
|
|
|
19
|
|
183
|
9
|
50
|
33
|
|
|
25
|
if (ref $_ && $#{$_} >= 4 && $_->[0] =~ '^note_o(n|ff)$') {
|
|
9
|
|
33
|
|
|
72
|
|
184
|
9
|
|
|
|
|
15
|
$_->[3] += $semitones;
|
185
|
9
|
100
|
|
|
|
19
|
$_->[3] = 0 if ($_->[3] < 0);
|
186
|
9
|
100
|
|
|
|
41
|
$_->[3] = 127 if ($_->[3] > 127);
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
}
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head1 SEE ALSO
|
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
L. L.
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head1 AUTHOR
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Christian Renz, Ecrenz@web42.comE
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Copyright 2003 by Christian Renz
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
204
|
|
|
|
|
|
|
it under the same terms as Perl itself.
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=cut
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
1;
|