line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Music::Note::Role::Operators; |
2
|
|
|
|
|
|
|
$Music::Note::Role::Operators::VERSION = '0.04'; |
3
|
|
|
|
|
|
|
# ABSTRACT: Adds operator overloading, clone and interval calculation to Music::Note |
4
|
|
|
|
|
|
|
|
5
|
2
|
|
|
2
|
|
2150
|
use Storable (); |
|
2
|
|
|
|
|
5464
|
|
|
2
|
|
|
|
|
44
|
|
6
|
2
|
|
|
2
|
|
11
|
use Role::Tiny; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
11
|
|
7
|
2
|
|
|
2
|
|
1186
|
use Music::Intervals; |
|
2
|
|
|
|
|
222721
|
|
|
2
|
|
|
|
|
139
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
requires 'format'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use overload |
12
|
2
|
|
|
|
|
17
|
'>' => 'gt', |
13
|
|
|
|
|
|
|
'<' => 'lt', |
14
|
|
|
|
|
|
|
'==' => 'eq', |
15
|
|
|
|
|
|
|
'>=' => 'gte', |
16
|
|
|
|
|
|
|
'<=' => 'lte', |
17
|
|
|
|
|
|
|
'-' => 'subtract', |
18
|
|
|
|
|
|
|
fallback => 1, |
19
|
2
|
|
|
2
|
|
17
|
; |
|
2
|
|
|
|
|
3
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 NAME |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
Music::Note::Role::Operators |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head2 DESCRIPTION |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
L to be applied on top L with comparison methods |
28
|
|
|
|
|
|
|
added and overloaded operators. Also adds a clone method and a way to |
29
|
|
|
|
|
|
|
generate Music::Interval objects via a Music::Note. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head2 SYNOPSIS |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
If you're working with a L subclass: |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
package Music::MyNote; |
36
|
|
|
|
|
|
|
use parent 'Music::Note'; |
37
|
|
|
|
|
|
|
use Role::Tiny::With; |
38
|
|
|
|
|
|
|
with 'Music::Note::Role::Operators'; |
39
|
|
|
|
|
|
|
# etc |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Or if you're working in a script and just want the behaviour: |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
use Music::Note; |
44
|
|
|
|
|
|
|
use Role::Tiny (); # Don't import R::T into current namespace for cleanliness |
45
|
|
|
|
|
|
|
Role::Tiny->apply_roles_to_package('Music::Note', 'Music::Note::Role::Operators'); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head2 SUMMARY |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
Assuming you're working in a script: |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
my $note = Music::Note->new('C#'); |
52
|
|
|
|
|
|
|
my $other = Music::Note->new('E'); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $true = $other->gt($note); |
55
|
|
|
|
|
|
|
$true = $other > $note; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
$true = $note->lt($other); |
58
|
|
|
|
|
|
|
$true = $note < $other; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
$true = $note->eq($note->clone); |
61
|
|
|
|
|
|
|
$true = $note == $note->clone; |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
$true = $note->gte($note->clone); |
64
|
|
|
|
|
|
|
$true = $note >= $note->clone; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
$true = $note->lte($note->clone); |
67
|
|
|
|
|
|
|
$true = $note <= $note->clone; |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
my $interval = $note->interval($other); |
70
|
|
|
|
|
|
|
my $conveneince_interval = $note->interval(%args_for_music_interval); |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head2 CAVEAT |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Don't try to do something like C<$note == 90>>. The overloading expects a |
75
|
|
|
|
|
|
|
L on both sides. To perform comparisons versus note and not a |
76
|
|
|
|
|
|
|
note you should be doing C<< $note->format('midi') == 90 >>. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head3 AUTHOR |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Kieren Diment L |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head3 LICENSE |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
This code can be redistributed on the same terms as perl itself |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=cut |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub gt { |
89
|
3
|
|
|
3
|
0
|
4661
|
my ($self, $other) = @_; |
90
|
3
|
|
|
|
|
11
|
$self->_maybe_bail_on_comparison($other); |
91
|
3
|
|
|
|
|
10
|
return $self->format('midinum') > $other->format('midinum'); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub lt { |
95
|
3
|
|
|
3
|
0
|
988
|
my ($self, $other) = @_; |
96
|
3
|
|
|
|
|
10
|
$self->_maybe_bail_on_comparison($other); |
97
|
2
|
|
|
|
|
6
|
return $self->format('midinum') < $other->format('midinum'); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub eq { |
101
|
4
|
|
|
4
|
0
|
1149
|
my ($self, $other) = @_; |
102
|
4
|
|
|
|
|
11
|
$self->_maybe_bail_on_comparison($other); |
103
|
4
|
|
|
|
|
14
|
return $self->format('midinum') == $other->format('midinum'); |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub gte { |
107
|
1
|
|
|
1
|
0
|
308
|
my ($self, $other) = @_; |
108
|
1
|
|
|
|
|
3
|
$self->_maybe_bail_on_comparison($other); |
109
|
1
|
|
|
|
|
3
|
return $self->format('midinum') >= $other->format('midinum'); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub lte { |
113
|
2
|
|
|
2
|
0
|
323
|
my ($self, $other) = @_; |
114
|
2
|
|
|
|
|
8
|
$self->_maybe_bail_on_comparison($other); |
115
|
2
|
|
|
|
|
5
|
return $self->format('midinum') <= $other->format('midinum'); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub subtract { |
119
|
4
|
|
|
4
|
0
|
1873
|
my ($self, $other) = @_; |
120
|
4
|
|
|
|
|
11
|
$self->_maybe_bail_on_comparison($other); |
121
|
4
|
|
|
|
|
12
|
return $self->format('midinum') - $other->format('midinum'); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=head2 get_interval |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
If called with a single Music::Note as argument is returns a |
127
|
|
|
|
|
|
|
Music::Interval object |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
my $interval = $self->get_interval($other); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
If called with an arguments hash |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
my $interval = $self->get_interval(%args_for_music_interval) |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Note that this will default to 1 for the following constructor attributes, |
136
|
|
|
|
|
|
|
so if you don't want these values you'll have to explicitly set them to |
137
|
|
|
|
|
|
|
something else in the constructor. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
NOTE: It would be nice to have the subtract method return a Music::Interval |
140
|
|
|
|
|
|
|
but it's a complex module, and only seems to deal with intervals inside a |
141
|
|
|
|
|
|
|
single octave. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub get_interval { |
146
|
2
|
|
|
2
|
1
|
2473
|
my $self = shift; |
147
|
2
|
|
|
|
|
3
|
my ($other, %args); |
148
|
2
|
100
|
66
|
|
|
11
|
if (ref $_[0] && $_[0]->isa('Music::Note') ) { |
149
|
1
|
|
|
|
|
2
|
($other, %args) = @_; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
else { |
152
|
1
|
|
|
|
|
3
|
%args = @_; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
2
|
50
|
66
|
|
|
8
|
$self->_maybe_bail_on_comparison($other) unless $other || $args{notes}; |
156
|
2
|
|
100
|
|
|
33
|
$args{notes} ||= [ $self->format('isobase'), $other->format('isobase') ]; |
157
|
2
|
|
100
|
|
|
58
|
$args{$_} ||= 1 for qw/chords equalt freqs interval cents prime integer/; |
158
|
2
|
|
100
|
|
|
4
|
$args{size} ||= scalar @{$args{notes}}; |
|
1
|
|
|
|
|
16
|
|
159
|
2
|
|
|
|
|
27
|
my $interval = Music::Intervals->new(%args); |
160
|
2
|
|
|
|
|
16498
|
return $interval; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub clone { |
164
|
2
|
|
|
2
|
0
|
1155
|
return Storable::dclone($_[0]); |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub _maybe_bail_on_comparison { |
168
|
17
|
|
|
17
|
|
25
|
my ($self, $other) = @_; |
169
|
17
|
100
|
|
|
|
76
|
die "$other is not a Music::Note" unless $other->isa('Music::Note'); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
1; |