File Coverage

blib/lib/Csound/Instrument.pm
Criterion Covered Total %
statement 14 73 19.1
branch 0 26 0.0
condition 0 4 0.0
subroutine 5 11 45.4
pod 0 6 0.0
total 19 120 15.8


line stmt bran cond sub pod time code
1             #_{ Encoding and name
2             =encoding utf8
3             =head1 NAME
4              
5             Csound::Instrument
6              
7             =cut
8             #_}
9             package Csound::Instrument;
10              
11 1     1   404 use warnings;
  1         3  
  1         37  
12 1     1   7 use strict;
  1         2  
  1         24  
13 1     1   7 use Carp;
  1         3  
  1         58  
14 1     1   22 use 5.10.0; # state
  1         5  
15              
16 1     1   357 use Csound::ScoreStatement::i;
  1         4  
  1         884  
17              
18             our $VERSION = $Csound::VERSION;
19              
20             #_{ Synopsis
21              
22             =head1 SYNOPSIS
23              
24             use Csound::Instrument;
25              
26             ...
27              
28             =cut
29             #_}
30             #_{ Description
31             =head DESCRIPTION
32              
33              
34             =cut
35             #_}
36             #_{ Methods
37             #_{
38             =head1 METHODS
39             =cut
40             #_}
41             sub new { #_{
42             #_{ POD
43             =head2 new
44              
45             my $composition = Csound::Composition->new(…);
46              
47             my $instr = Csound::Instrument->new(
48             {
49             composition => $composition,
50             parameters => ['amplitude', 'foo_1', 'foo_2']
51             }
52             );
53              
54             If the parameter C is passed with a reference to a L<< Csound::Composition >>, the instrument's L method is shorthand for
55             C<< $composition->play($instr, …) >>.
56              
57             Most instrument play notes. However, to indicate that an instrument doesn't play a note (such as a high hat or a noise etc.),
58             the flag C can be given.
59              
60             my $instr = Csound::Instrument->new(
61             $composition,
62             {
63             parameters => ['amplitude', 'foo_1', 'foo_2'],
64             no_note => 1
65             }
66             );
67              
68             =cut
69             #_}
70              
71 0     0 0   state $_instr_no = 0;
72              
73 0           my $class = shift;
74 0   0       my $params = shift // {};
75              
76 0           my $self = {};
77              
78 0 0         if ($params->{parameters}) {
79             $self->{parameters} = delete $params->{parameters}
80 0           }
81             else {
82 0           $self->{parameters} = [];
83             }
84 0 0         if ($params->{composition}) {
85 0 0         croak "composition must be a Csound::Composition" unless $params->{composition}->isa('Csound::Composition');
86 0           $self->{composition} = delete $params->{composition};
87             }
88              
89 0   0       $self->{no_note} = delete $params->{no_note} // 0;
90              
91 0           bless $self, $class;
92              
93 0           $self->{nr} = ++$_instr_no;
94              
95 0 0         $self->definition(delete $params->{definition}) if $params->{definition};
96              
97 0           return $self;
98              
99             } #_}
100             sub definition { #_{
101             #_{ POD
102             =head2 definition
103              
104             =cut
105             #_}
106              
107 0     0 0   my $self = shift;
108 0           my $definition = shift;
109              
110 0           $self->{definition} = $definition;
111             } #_}
112             sub play { #_{
113             #_{ POD
114             =head2 new
115              
116             $instr->play($t_start, $duration, 'f♯5', …);
117              
118             When the instrument was L with the C parameter, this is a shorthand for
119              
120             $composition->play($instr, $t_start, $duration, 'f♯5', …);
121              
122             =cut
123             #_}
124            
125 0     0 0   my $self = shift;
126              
127 0 0         croak "I don't have a composition to play this instrument on" unless $self->{composition};
128 0           $self->{composition}->play($self, @_);
129              
130             } #_}
131             sub plays_note { #_{
132             #_{ POD
133             =head2 new
134              
135             my $yes_no = $instr->plays_note();
136              
137             In most cases, an instrument will play a note.
138             When the flag/parameter C was given in L, the instrument
139             also doesn't play a note.
140              
141             =cut
142             #_}
143            
144 0     0 0   my $self = shift;
145              
146 0           return ! $self->{no_note};
147              
148             } #_}
149             sub i { #_{
150             #_{ POD
151             =head2 i
152              
153             $instr -> i($t_start, $t_len, …);
154              
155             Creates an L. It should not be called by the end user. Rather, the user
156             should call L.
157              
158             =cut
159             #_}
160              
161 0     0 0   my $self = shift;
162 0           my $t_start = shift;
163 0           my $t_len = shift;
164 0           my @params = grep { defined } @_;
  0            
165              
166 0 0         croak unless $self->isa('Csound::Instrument');
167              
168 0           my $expected_param_cnt = @{$self->{parameters}};
  0            
169 0 0         $expected_param_cnt++ if $self->plays_note();
170              
171 0 0         croak (sprintf("expected %d parameters but was given %d", $expected_param_cnt, scalar @params)) unless @params == $expected_param_cnt;
172              
173 0           my $i = Csound::ScoreStatement::i->new($self, $t_start, $t_len, @params);
174              
175 0           return $i;
176              
177             } #_}
178             sub orchestra_text { #_{
179              
180             #_{ POD
181             =head2 orchestra_text
182              
183             my $score = Csound::Score->new(…);
184             my $txt = $instr->orchestra_text($score);
185              
186             Returns the text to be written into the score.
187              
188             Sometimes, the instrument needs to have access to the score (notably for the f statements required in the C opcode family). Therefore,
189             the method needs the C<$score> parameter.
190              
191             =cut
192             #_}
193              
194 0     0 0   my $self = shift;
195 0           my $score = shift;
196 0 0         die unless $self->isa('Csound::Instrument');
197              
198 0           my $orchestra_text = sprintf("instr %d\n\n", $self->{nr});
199              
200              
201 0           my $param_no = 4;
202 0 0         if ($self->plays_note) {
203             # unless ($self->{no_note}) {
204 0           $orchestra_text .= " i_freq init cpspch(p4)\n";
205 0           $param_no++;
206             }
207              
208 0           for my $param (@{$self->{parameters}}) {
  0            
209 0           $orchestra_text .= sprintf(" i_%s init p%d\n", $param, $param_no++);
210             }
211              
212 0 0         if ($self->{definition}) {
213              
214 0           my $definition = $self->{definition};
215             # $orchestra_text .= $self->{definition};
216              
217 0           $definition =~ s{
218             \@FUNCTABLE\(\ *(\d+)((?:\ *,\ *[0-9.]+)+)\ *\)
219             }
220 0           {
221 0           my $gen_no = $1;
222 0           my $parameters = $2;
223 0           $parameters =~ s/^ *, *//;
224             my @parameters = split / *, */, $parameters;
225             # $parameters = join ' x ', @parameters;
226 0 0        
227 0 0         croak "No score defined" unless defined $score;
228             croak "No valid score passed" unless $score->isa('Csound::Score');
229 0            
230             $score->f($gen_no, @parameters)->{table_nr};
231             }gex;
232 0            
233             $orchestra_text .= $definition;
234             }
235              
236             # $orchestra_text .= "\n" if @{$self->{parameters}};
237 0            
238             $orchestra_text .= "\nendin\n";
239 0            
240             return $orchestra_text;
241              
242             } #_}
243             #_}
244             #_{ POD: Copyright
245              
246             =head1 Copyright
247              
248             Copyright © 2017 René Nyffenegger, Switzerland. All rights reserved.
249             This program is free software; you can redistribute it and/or modify it
250             under the terms of the the Artistic License (2.0). You may obtain a
251             copy of the full license at: L
252              
253             =cut
254              
255             #_}
256              
257             'tq84';