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.0107';
7              
8 2     2   453861 use v5.36;
  2         5  
9 2     2   1009 use Moo;
  2         13470  
  2         13  
10 2     2   3251 use strictures 2;
  2         2668  
  2         60  
11 2     2   650 use Carp qw(croak);
  2         4  
  2         79  
12 2     2   860 use Music::Duration::Partition ();
  2         129727  
  2         82  
13 2     2   1005 use Music::Scales qw(get_scale_MIDI);
  2         8345  
  2         122  
14 2     2   886 use Music::VoiceGen ();
  2         14459  
  2         49  
15 2     2   15 use namespace::clean;
  2         3  
  2         6  
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   2345 sub _build_pitches ($self) {
  1         1  
  1         1  
46 1         7 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         93 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   1214 sub _build_voice ($self) {
  1         1  
  1         20  
66 1         15 my $voice = Music::VoiceGen->new(
67             pitches => $self->pitches,
68             intervals => $self->intervals,
69             );
70 1         2934 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   7 sub _build__rhythm ($self) {
  1         2  
  1         1  
107 1         13 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 3300 sub build_motifs ($self) {
  1         2  
  1         1  
178 1         13 my @motifs = $self->_rhythm->motifs($self->motif_num);
179 1         1806 return \@motifs;
180             }
181              
182              
183 1     1 1 7 sub build_voices ($self) {
  1         1  
  1         1  
184 1         13 my @voices = map { $self->voice->rand } $self->motifs->@*;
  4         314  
185 1         83 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__