File Coverage

blib/lib/Music/VoicePhrase.pm
Criterion Covered Total %
statement 48 53 90.5
branch n/a
condition n/a
subroutine 13 14 92.8
pod 3 3 100.0
total 64 70 91.4


line stmt bran cond sub pod time code
1             package Music::VoicePhrase;
2             our $AUTHORITY = 'cpan:GENE';
3              
4             # ABSTRACT: Construct a measured phrase of notes
5              
6             our $VERSION = '0.0106';
7              
8 2     2   477817 use v5.36;
  2         7  
9 2     2   916 use Moo;
  2         20546  
  2         18  
10 2     2   3335 use strictures 2;
  2         3044  
  2         66  
11 2     2   646 use Carp qw(croak);
  2         4  
  2         96  
12 2     2   870 use Music::Duration::Partition ();
  2         136222  
  2         75  
13 2     2   1049 use Music::Scales qw(get_scale_MIDI);
  2         8473  
  2         163  
14 2     2   966 use Music::VoiceGen ();
  2         15137  
  2         76  
15 2     2   13 use namespace::clean;
  2         2  
  2         11  
16              
17              
18             has base => (
19             is => 'ro',
20             isa => sub { croak "$_[0] is not a valid note" unless $_[0] =~ /^[A-G][#b]?$/i },
21             default => sub { 'C' },
22             );
23              
24              
25             has scale => (
26             is => 'ro',
27             isa => sub { croak "$_[0] is not a valid scale name" unless $_[0] =~ /^\w+$/ },
28             default => sub { 'major' },
29             );
30              
31              
32             has octave => (
33             is => 'ro',
34             isa => sub { croak "$_[0] is not a valid octave" unless $_[0] =~ /^[0-9]$/ },
35             default => sub { 0 },
36             );
37              
38              
39             has pitches => (
40             is => 'lazy',
41             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
42             builder => '_build_pitches',
43             );
44              
45 1     1   2453 sub _build_pitches ($self) {
  1         2  
  1         2  
46 1         10 my @pitches = (
47             get_scale_MIDI($self->base, $self->octave, $self->scale),
48             get_scale_MIDI($self->base, $self->octave + 1, $self->scale),
49             );
50 1         106 return \@pitches;
51             }
52              
53              
54             has intervals => (
55             is => 'ro',
56             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
57             default => sub { [-3, -2, -1, 1, 2, 3] },
58             );
59              
60             has _voice => (
61             is => 'lazy',
62             builder => '_build__voice',
63             );
64              
65 1     1   1218 sub _build__voice ($self) {
  1         2  
  1         8  
66 1         14 my $voice = Music::VoiceGen->new(
67             pitches => $self->pitches,
68             intervals => $self->intervals,
69             );
70 1         3241 return $voice;
71             }
72              
73              
74             has size => (
75             is => 'ro',
76             isa => sub { croak "$_[0] is not a valid size" unless $_[0] =~ /^\d+$/ },
77             default => sub { 4 },
78             );
79              
80              
81             has pool => (
82             is => 'ro',
83             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
84             default => sub { [qw(dhn hn qn)] },
85             );
86              
87              
88             has weights => (
89             is => 'ro',
90             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
91             default => sub { [1, 2, 2] },
92             );
93              
94              
95             has groups => (
96             is => 'ro',
97             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
98             default => sub { [0, 0, 0] },
99             );
100              
101             has _rhythm => (
102             is => 'lazy',
103             builder => '_build__rhythm',
104             );
105              
106 1     1   9 sub _build__rhythm ($self) {
  1         2  
  1         2  
107 1         12 my $mdp = Music::Duration::Partition->new(
108             size => $self->size,
109             pool => $self->pool,
110             weights => $self->weights,
111             groups => $self->groups,
112             );
113             }
114              
115              
116             has motif_num => (
117             is => 'rw',
118             isa => sub { croak "$_[0] is not an integer" unless $_[0] =~ /^\d+$/ },
119             default => sub { 4 },
120             );
121              
122              
123             has motifs => (
124             is => 'rw',
125             lazy => 1,
126             builder => 'build_motifs',
127             );
128              
129              
130             has voices => (
131             is => 'rw',
132             lazy => 1,
133             builder => 'build_voices',
134             );
135              
136              
137             has queue => (
138             is => 'rw',
139             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
140             default => sub { [] },
141             );
142              
143              
144             has index => (
145             is => 'rw',
146             isa => sub { croak "$_[0] is not an integer" unless $_[0] =~ /^\d+$/ },
147             default => sub { 0 },
148             );
149              
150              
151             has note => (
152             is => 'rw',
153             isa => sub { croak "$_[0] is not a valid note" unless ref $_[0] eq 'HASH' },
154             default => sub { +{} },
155             );
156              
157              
158             has onsets => (
159             is => 'rw',
160             isa => sub { croak "$_[0] is not an array-ref" unless ref $_[0] eq 'ARRAY' },
161             default => sub { [] },
162             );
163              
164              
165             has verbose => (
166             is => 'ro',
167             isa => sub { croak "$_[0] is not a boolean" unless $_[0] =~ /^[01]$/ },
168             default => sub { 0 },
169             );
170              
171              
172             sub BUILD ($self, $args) {
173             # $self->_build_motifs;
174             }
175              
176              
177 1     1 1 3422 sub build_motifs ($self) {
  1         1  
  1         2  
178 1         18 my @motifs = $self->_rhythm->motifs($self->motif_num);
179 1         1300 return \@motifs;
180             }
181              
182              
183 1     1 1 8 sub build_voices ($self) {
  1         1  
  1         2  
184 1         14 my @voices = map { $self->_voice->rand } $self->motifs->@*;
  4         339  
185 1         84 return \@voices;
186             }
187              
188              
189 0     0 1   sub increment_index ($self) {
  0            
  0            
190 0           $self->index($self->index + 1);
191 0           return $self->index;
192             }
193              
194             1;
195              
196             __END__