File Coverage

blib/lib/Music/PitchNum/ABC.pm
Criterion Covered Total %
statement 36 36 100.0
branch 22 24 91.6
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 67 69 97.1


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2             #
3             # Pitch numbers from the ABC notation for notes, in a distinct module as
4             # the format is Case Sensitive, and the accidentals very different from
5             # those seen in other notation formats.
6             #
7             # Run perldoc(1) on this file for additional documentation.
8              
9             package Music::PitchNum::ABC;
10              
11 2     2   7121 use 5.010000;
  2         5  
12 2     2   7 use Moo::Role;
  2         2  
  2         7  
13 2     2   821 use POSIX qw/floor/;
  2         4091  
  2         7  
14 2     2   817 use Scalar::Util qw/looks_like_number/;
  2         2  
  2         679  
15              
16             our $VERSION = '0.08';
17              
18             ##############################################################################
19             #
20             # ATTRIBUTES
21              
22             has NOTE2NUM => (
23             is => 'rw',
24             default => sub {
25             { C => 0,
26             D => 2,
27             E => 4,
28             F => 5,
29             G => 7,
30             A => 9,
31             B => 11,
32             };
33             },
34             );
35              
36             # ABC is like ASPN only for some N+1 reason it uses a different
37             # accidental form, sigh
38             has NUM2NOTE => (
39             is => 'rw',
40             default => sub {
41             { 0 => 'C',
42             1 => '^C',
43             2 => 'D',
44             3 => '^D',
45             4 => 'E',
46             5 => 'F',
47             6 => '^F',
48             7 => 'G',
49             8 => '^G',
50             9 => 'A',
51             10 => '^A',
52             11 => 'B',
53             };
54             },
55             );
56              
57             has ignore_octave => (
58             is => 'rw',
59             coerce => sub {
60             $_[0] ? 1 : 0;
61             },
62             default => 0,
63             );
64              
65             ##############################################################################
66             #
67             # METHODS
68              
69             sub pitchname {
70 12     12 1 47 my ( $self, $number ) = @_;
71 12 100       39 die "need a number for pitchname\n" if !looks_like_number $number;
72              
73 11         33 my $octave = floor( $number / 12 ) - 1;
74 11         29 my $note = $self->NUM2NOTE->{ $number % 12 };
75              
76 11 100       22 if ( !$self->ignore_octave ) {
77 9 100       582 $note = lc $note if $octave > 4;
78 9 100       16 $note .= (q{'}) x ( $octave - 5 ) if $octave > 5;
79 9 100       15 $note .= (q{,}) x ( 4 - $octave ) if $octave < 4;
80             }
81              
82 11         78 return $note;
83             }
84              
85             sub pitchnum {
86 11     11 1 15 my ( $self, $name ) = @_;
87              
88             # already a pitch number, but nix the decimal foo
89 11 50       31 return int $name if looks_like_number $name;
90              
91 11         7 my $pitchnum;
92              
93 11 50       44 if ( $name =~
94             m/ (? (?: [_]{1,2} | [\^]{1,2} ) )? (?: (?[A-G])(?[,]+)? | (?[a-g])(?[']+)? ) /x
95             ) {
96 11     1   49 my $octave = $+{octave};
  1         399  
  1         252  
  1         135  
97 11         27 my $chrome = $+{chrome};
98 11         24 my $note = $+{note};
99              
100 11 100       43 $pitchnum = $self->NOTE2NUM->{ uc $note } + 12 * ( $note =~ m/[A-G]/ ? 5 : 6 );
101              
102 11 100       21 if ( defined $octave ) {
103 5 100       10 $pitchnum += 12 * length($octave) * ( $octave =~ m/[,]/ ? -1 : 1 );
104             }
105              
106 11 100       15 if ( defined $chrome ) {
107 4 100       11 $pitchnum += length($chrome) * ( $chrome =~ m/[_]/ ? -1 : 1 );
108             }
109             }
110              
111 11         31 return $pitchnum;
112             }
113              
114             1;
115             __END__