File Coverage

blib/lib/MIDI/Trans.pm
Criterion Covered Total %
statement 12 285 4.2
branch 0 110 0.0
condition 0 61 0.0
subroutine 4 35 11.4
pod 0 27 0.0
total 16 518 3.0


line stmt bran cond sub pod time code
1             package MIDI::Trans;
2              
3 1     1   4959 use 5.006;
  1         2  
  1         33  
4 1     1   4 use strict;
  1         1  
  1         24  
5 1     1   3 use warnings;
  1         4  
  1         31  
6              
7 1     1   594 use MIDI::Simple;
  1         17350  
  1         2539  
8              
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12              
13             # Items to export into callers namespace by default. Note: do not export
14             # names by default without a very good reason. Use EXPORT_OK instead.
15             # Do not simply export all your public functions/methods/constants.
16              
17             # This allows declaration use MIDI::Trans ':all';
18             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
19             # will save memory.
20             our %EXPORT_TAGS = ( 'all' => [ qw(
21            
22             ) ] );
23              
24             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
25              
26             our @EXPORT = qw(
27            
28             );
29             our $VERSION = '0.15';
30              
31              
32             # Preloaded methods go here.
33              
34             sub new {
35              
36 0     0 0   my $class = shift;
37 0   0       my $self=bless {}, ref($class)||$class;
38              
39 0           $self->_init(@_);
40              
41 0           return $self;
42              
43             }
44              
45             sub _init {
46              
47 0     0     my $self = shift;
48 0           my $opt_HR = shift;
49              
50             # default values
51              
52 0           $self->{'Raise_Error'} = 0;
53 0           $self->{'ERRx1'} = undef;
54 0           $self->{'ElementDelimiter'} = '\s+';
55 0           $self->{'SentenceDelimiter'} = '\.|\!|\?|';
56 0           $self->{'NoteCallBack'} = undef;
57 0           $self->{'VolumeCallBack'} = undef;
58 0           $self->{'DurationCallBack'} = undef;
59 0           $self->{'TempoCallBack'} = undef;
60 0           $self->{'AllAttributes'} = 1;
61 0           $self->{'OpenFiles'} = ();
62 0           $self->{'CurElem'} = undef;
63 0           $self->{'CurPos'} = undef;
64 0           $self->{'Channel'} = 1;
65 0           $self->{'Events'} = ();
66 0           $self->{'qn_len'} = 96;
67 0           $self->{'BaseMilliseconds'} = 60000000;
68 0           $self->{'Tempo'} = 120;
69 0           $self->{'CCorp'} = undef;
70 0           $self->{'TransObj'} = undef;
71            
72 0           foreach my $key ('Raise_Error','ElementDelimiter','NoteCallBack','VolumeCallBack','DurationCallBack','SentenceDelimiter','AllAttributes','Channel','qn_len', 'TempoCallBack', 'Tempo') {
73 0 0         map {$self->{$_}=$opt_HR->{$_}} ($key) if(defined($opt_HR->{"$key"}));
  0            
74             }
75            
76 0           return(1);
77             }
78              
79              
80             sub error {
81              
82 0     0 0   my $self = shift;
83 0 0         return($self->{'ERRx1'}) if(!defined($_[0]));
84              
85 0 0         if($self->raise_error()) {
86 0           die("[MIDI::Trans] ERROR: $_[0]\n");
87             } else {
88 0           $self->{'ERRx1'} = $_[0];
89 0           return($self->{'ERRx1'});
90             }
91             }
92              
93             sub raise_error {
94              
95 0     0 0   my $self = shift;
96            
97 0 0         $self->{'Raise_Error'} = $_[0] if(defined($_[0]));
98 0           return($self->{'Raise_Error'});
99             }
100              
101              
102             sub delimiter {
103              
104 0     0 0   my $self = shift;
105            
106 0 0         $self->{'ElementDelimiter'} = $_[0] if(defined($_[0]));
107 0           return($self->{'ElementDelimiter'});
108             }
109              
110             sub sentence_delimiter {
111              
112 0     0 0   my $self = shift;
113              
114 0 0         $self->{'SentenceDelimiter'} = $_[0] if(defined($_[0]));
115 0           return($self->{'SentenceDelimiter'});
116             }
117              
118             sub all_attributes {
119              
120 0     0 0   my $self = shift;
121 0 0         $self->{'AllAttributes'} = $_[0] if(defined($_[0]));
122 0           return($self->{'AllAttributes'});
123             }
124              
125             sub channel {
126              
127 0     0 0   my $self = shift;
128 0 0         $self->{'Channel'} = $_[0] if(defined($_[0]));
129 0           return($self->{'Channel'});
130             }
131              
132             sub read_corpus {
133              
134 0     0 0   my $self = shift;
135 0           my $hRef = shift;
136            
137 0 0 0       if(!defined($hRef) || ref($hRef) ne 'HASH') {
138 0           $self->error("[read_corpus] ERROR: HASHREF Argument Required.");
139 0           return(undef);
140             }
141              
142 0           my($data,$file);
143 0           my $lines = 0;
144 0           my $delim = $self->delimiter();
145 0           my $sent_delim = $self->sentence_delimiter();
146              
147 0 0 0       if(exists($hRef->{'File'}) && defined($hRef->{'File'})) {
    0 0        
148              
149 0           $file = $hRef->{'File'};
150            
151 0 0         if(open(TRFH,$file)) {
152            
153 0           while(<TRFH>) {
154 0           chomp;
155 0           $data .= $_;
156 0           $lines++;
157             }
158            
159 0           close(TRFH);
160            
161 0 0         return(1) if(length($data) < 1);
162            
163             # could not open file...
164             } else {
165 0           $self->error("[read_corpus] ERROR: Could not open $hRef->{'File'} -> $!");
166 0           return(undef);
167             }
168              
169             } elsif(exists($hRef->{'String'}) && defined($hRef->{'String'})) {
170 0           $data = $hRef->{'String'};
171 0 0         return(1) if(length($data) < 1);
172             }
173            
174              
175 0           my %hash = ();
176            
177 0 0 0       $hash{'Name'} = $hRef->{'Name'} || $file if(defined($file));
178 0 0 0       $hash{'Name'} = $hRef->{'Name'} || 'String' if(!defined($file));
179              
180             # if we calculate all attributes...
181              
182 0 0         if ($self->all_attributes()) {
183 0           my @Sentences = split(/(?:$sent_delim)/,$data);
184 0           $hash{'NumSent'} = $#Sentences + 1;
185              
186 0           undef(@Sentences);
187              
188 0           my @words = split(/\b/,$data);
189 0           $hash{'NumWords'} = $#words + 1;
190              
191 0           undef(@words);
192             } else {
193             # otherwise... set to undef
194 0           $hash{'NumSent'} = 0;
195 0           $hash{'NumWords'} = 0;
196             }
197              
198             # get our elements on the delimiter
199              
200 0           my @elems = split(/(?:$delim)/,$data);
201 0           $hash{'NumElems'} = $#elems + 1;
202 0           $hash{'Elems'} = \@elems;
203              
204 0           push(@{ $self->{'OpenFiles'} },\%hash);
  0            
205            
206 0           return(1);
207             }
208              
209              
210             sub sentences {
211              
212 0     0 0   my $self = shift;
213            
214 0           my $cur_corp = $self->_cur_corpus();
215            
216 0           return($self->{'OpenFiles'}[$cur_corp]->{'NumSent'});
217             }
218              
219             sub words {
220              
221 0     0 0   my $self = shift;
222            
223 0           my $cur_corp = $self->_cur_corpus();
224            
225 0           return($self->{'OpenFiles'}[$cur_corp]->{'NumWords'});
226             }
227              
228             sub elements {
229              
230 0     0 0   my $self = shift;
231            
232 0           my $cur_corp = $self->_cur_corpus();
233            
234 0           return($self->{'OpenFiles'}[$cur_corp]->{'NumElems'});
235             }
236              
237             sub _cur_corpus {
238              
239 0     0     my $self = shift;
240            
241 0 0         $self->{'CCorp'} = $_[0] if(defined($_[0]));
242 0           return($self->{'CCorp'});
243             }
244              
245              
246             sub current_elem {
247              
248 0     0 0   my $self = shift;
249              
250 0 0         $self->{'CurElem'} = $_[0] if(defined($_[0]));
251 0           return($self->{'CurElem'});
252             }
253              
254             sub current_pos {
255              
256 0     0 0   my $self = shift;
257              
258 0 0         $self->{'CurPos'} = $_[0] if(defined($_[0]));
259 0           return($self->{'CurPos'});
260             }
261              
262              
263             sub note_callback {
264 0     0 0   my $self = shift;
265              
266 0 0         $self->{'NoteCallBack'} = $_[0] if(defined($_[0]));
267 0           return($self->{'NoteCallBack'});
268             }
269              
270              
271             sub tempo_callback {
272 0     0 0   my $self = shift;
273              
274 0 0         $self->{'TempoCallBack'} = $_[0] if(defined($_[0]));
275 0           return($self->{'TempoCallBack'});
276             }
277              
278              
279             sub duration_callback {
280 0     0 0   my $self = shift;
281              
282 0 0         $self->{'DurationCallBack'} = $_[0] if(defined($_[0]));
283 0           return($self->{'DurationCallBack'});
284             }
285              
286              
287             sub volume_callback {
288 0     0 0   my $self = shift;
289              
290 0 0         $self->{'VolumeCallBack'} = $_[0] if(defined($_[0]));
291 0           return($self->{'VolumeCallBack'});
292             }
293              
294              
295             sub qn_len {
296              
297 0     0 0   my $self = shift;
298            
299 0 0         $self->{'qn_len'} = $_[0] if(defined($_[0]));
300 0           return($self->{'qn_len'});
301             }
302              
303             sub trans_obj {
304              
305 0     0 0   my $self = shift;
306            
307 0 0         $self->{'TransObj'} = $_[0] if(defined($_[0]));
308 0           return($self->{'TransObj'});
309             }
310            
311              
312             sub round {
313              
314 0     0 0   my $self = shift;
315 0           my $val = shift;
316            
317 0 0         $val = $val < int($val) + .5 ? int($val) : int($val) + 1;
318            
319 0           return($val);
320             }
321              
322              
323             sub _get_num_by_name {
324              
325 0     0     my $self = shift;
326 0           my $name = shift;
327            
328 0 0         return(undef) if(!defined($name));
329            
330 0           my $aRef = \@{ $self->{'OpenFiles'} };
  0            
331            
332 0           foreach (0..$#{ $aRef }) {
  0            
333 0           my $hRef = \%{ $aRef->[$_] };
  0            
334 0 0         return($_) if($hRef->{'Name'} eq $name);
335             }
336            
337 0           return(undef);
338             }
339              
340              
341             sub tempo {
342              
343 0     0 0   my $self = shift;
344            
345 0 0         $self->{'Tempo'} = $_[0] if(defined($_[0]));
346 0           return($self->{'Tempo'});
347             }
348              
349             sub base_milliseconds {
350              
351 0     0 0   my $self = shift;
352            
353 0 0         $self->{'BaseMilliseconds'} = $_[0] if(defined($_[0]));
354 0           return($self->{'BaseMilliseconds'});
355             }
356              
357              
358             sub process {
359              
360 0     0 0   my $self = shift;
361 0           my $hRef = shift;
362            
363 0           my $num = undef;
364              
365              
366 0 0         if($#{ $self->{'OpenFiles'} } < 0) {
  0            
367 0           $self->error("[process] No Files/Strings Have Been Read\n");
368 0           return(undef);
369             }
370            
371 0 0 0       if(exists($hRef->{'Name'}) && defined($hRef->{'Name'})) {
    0 0        
372 0           my $name = $hRef->{'Name'};
373 0           $num = $self->_get_num_by_name("$name");
374 0 0         if(!defined($num)) {
375 0           $self->error("[process] No Data Found With Name '$name'");
376 0           return(undef);
377             }
378             } elsif(exists($hRef->{'Num'}) && defined($hRef->{'Num'})) {
379 0           $num = $hRef->{'Num'};
380 0 0         if(!defined($self->{'OpenFiles'}[$num])) {
381 0           $self->error("[process] No Data Found In Entry #$num");
382 0           return(undef);
383             }
384             } else {
385 0           $num = 0;
386             }
387              
388 0           my $aRef = \@{ $self->{'OpenFiles'}[$num]->{'Elems'} };
  0            
389              
390 0           $self->_cur_corpus($num);
391            
392 0 0         if(defined($self->tempo_callback)) {
393 0           my $tempo_c = $self->tempo_callback();
394 0           my $tempo = &$tempo_c();
395 0           $self->tempo($tempo);
396             }
397            
398 0           foreach my $elem (0..$#{ $aRef }) {
  0            
399 0           $self->current_elem($aRef->[$elem]);
400 0           $self->current_pos($elem);
401              
402 0           my $note_c = $self->note_callback();
403 0           my $vol_c = $self->volume_callback();
404 0           my $dur_c = $self->duration_callback();
405            
406 0           my $note = &$note_c($aRef->[$elem],$elem);
407 0           my $vol = &$vol_c($aRef->[$elem],$elem);
408 0           my $dur = &$dur_c($aRef->[$elem],$elem);
409            
410 0           $self->_store_events($num,$note,$vol,$dur);
411             }
412            
413 0           return(1);
414             }
415              
416             sub _store_events {
417              
418 0     0     my $self = shift;
419 0           my $num = shift;
420 0           my $note = shift;
421 0           my $vol = shift;
422 0           my $dur = shift;
423              
424 0 0 0       return(undef) if(!defined($num) || !defined($note) || !defined($vol) || !defined($dur));
      0        
      0        
425            
426 0 0         $self->{'Events'}{$num} = () if(!exists($self->{'Events'}{$num}));
427            
428 0           push(@{ $self->{'Events'}{$num} },[$note,$vol,$dur]);
  0            
429 0           return(1);
430             }
431            
432             sub create_score {
433              
434 0     0 0   my $self = shift;
435 0           my $num = shift;
436            
437 0 0         $num = 0 if(!defined($num));
438              
439 0 0         if(!defined($self->{'Events'}{$num})) {
440 0           $self->error("[create_score] No Events Have Been Generated For Entry #$num");
441 0           return(undef);
442             }
443              
444 0           my $aRef = \@{ $self->{'Events'}{$num} };
  0            
445            
446 0           my $scoreObj = MIDI::Simple->new_score({ 'Tempo' => $self->qn_len() });
447            
448 0           my $tempo_qn = $self->tempo();
449              
450 0           my $bm = $self->base_milliseconds();
451            
452 0           my $tempo_act = $self->round($self->base_milliseconds() / $tempo_qn);
453 0           my $channel = $self->channel();
454              
455 0           $scoreObj->set_tempo($tempo_act);
456            
457 0           foreach my $elem (0..$#{ $aRef }) {
  0            
458 0           my $eRef = \@{ $aRef->[$elem] };
  0            
459 0 0         next if($#{ $eRef } < 0);
  0            
460 0 0         if($eRef->[0] eq 'rest') {
461 0           $scoreObj->r("c$channel","v$eRef->[1]","d$eRef->[2]");
462             } else {
463 0           $scoreObj->n("c$channel","v$eRef->[1]","d$eRef->[2]","n$eRef->[0]");
464             }
465             }
466            
467 0           return($scoreObj);
468             }
469              
470             sub reset_error {
471              
472 0     0 0   my $self = shift;
473 0           $self->{'ERRx1'} = undef;
474 0           return(1);
475             }
476              
477             sub write_file {
478              
479 0     0 0   my $self = shift;
480 0           my $file = shift;
481 0           my $scoreObj = shift;
482            
483 0 0 0       if(!defined($file) || !defined($scoreObj)) {
484 0           $self->error("[write_file] Arguments FILE, OBJECT expected");
485 0           return(undef);
486             }
487            
488 0           eval { $scoreObj->write_score($file); };
  0            
489            
490 0 0         if($@) {
491 0           $self->error("[write_file] MIDI::Simple Returned: $@");
492 0           return(undef);
493             }
494            
495 0           return(1);
496             }
497              
498             sub trans {
499              
500 0     0 0   my $self = shift;
501 0           my $hRef = shift;
502            
503 0   0       my $file_o = $hRef->{'Outfile'} || './out.midi';
504 0           my $file = $hRef->{'File'};
505 0   0       my $vol_c = $hRef->{'Volume'} || $self->volume_callback();
506 0   0       my $note_c = $hRef->{'Note'} || $self->note_callback();
507 0   0       my $dur_c = $hRef->{'Duration'} || $self->duration_callback();
508 0   0       my $tempo_c = $hRef->{'TempoCallBack'} || $self->tempo_callback();
509 0   0       my $delim = $hRef->{'Delimiter'} || $self->delimiter();
510 0   0       my $tempo = $hRef->{'Tempo'} || $self->tempo();
511            
512 0 0         if(!defined($file)) {
513 0           $self->error("[trans] FILE Argument not specified");
514 0           return(undef);
515             }
516            
517 0 0 0       if(!defined($dur_c) || !defined($note_c) || !defined($vol_c)) {
    0 0        
518 0           $self->error("[trans] DURATION, NOTE, and VOLUME callbacks must be specified");
519 0           return(undef);
520             } elsif(!defined($tempo_c) && !defined($tempo)) {
521 0           $self->error("[trans] Either TEMPO or TEMPOCALLBACK must be specified");
522 0           return(undef);
523             }
524              
525 0           my $new_object = MIDI::Trans->new( {
526             'VolumeCallBack' => $vol_c,
527             'DurationCallBack' => $dur_c,
528             'NoteCallBack' => $note_c,
529             'TempoCallBack' => $tempo_c,
530             'Tempo' => $tempo,
531             'Delimiter' => $delim });
532            
533 0 0         if(!defined($new_object)) {
534 0           $self->error("[trans] Error Creating Object");
535 0           return(undef);
536             }
537              
538 0           $self->trans_obj($new_object);
539            
540 0 0         $self->tempo_callback($tempo_c) if(!defined($tempo));
541 0 0         $self->tempo($tempo) if(defined($tempo));
542              
543 0 0         if($new_object->read_corpus({ 'File' => "$file" })) {
544 0 0         if($new_object->process({ 'Name' => "$file" })) {
545 0           my $scoreObj = $new_object->create_score(0);
546 0 0         if(defined($scoreObj)) {
547 0 0         if($new_object->write_file($file_o,$scoreObj)) {
548 0           return(1);
549             } else {
550 0           $self->error($new_object->error());
551 0           return(undef);
552             }
553             } else {
554 0           $self->error($new_object->error());
555 0           return(undef);
556             }
557             } else {
558 0           $self->error($new_object->error());
559 0           return(undef);
560             }
561             } else {
562 0           $self->error($new_object->error());
563 0           return(undef);
564             }
565            
566 0           return(undef);
567             }
568              
569              
570             1;
571             __END__
572             # Below is stub documentation for your module. You better edit it!
573              
574             =head1 NAME
575              
576             MIDI::Trans - Perl extension for quick and easy text->midi conversion.
577              
578             =head1 SYNOPSIS
579              
580             use MIDI::Trans;
581            
582             my $TranObj = MIDI::Trans->new( {
583             'Delimiter' => '\s+',
584             'Note' => \&note,
585             'Volume' => sub { return(127); },
586             'Duration' => \&somesub,
587             'Tempo' => sub { ... }
588             } );
589              
590             if($TransObj->trans( { 'File' => 'text.txt', 'Outfile' => 'out.mid' })) {
591             print("success\n");
592             } else {
593             my $error = $TransObj->error();
594             die("ERR: $error\n");
595             }
596            
597              
598             sub note {
599             # do something
600             # return a value between 0 and 127
601             # or string 'rest' (sans quotes) for
602             # a rest event
603             }
604            
605             sub duration {
606             # return some number of quarter notes
607             }
608              
609              
610             =head1 DESCRIPTION
611              
612             MIDI::Trans serves as a quick development foundation for text to midi
613             conversion algorithms utilizing MIDI::Simple for output. Using MIDI::Trans, you
614             create callbacks for generating note, volume, duration and tempo values.
615             As your corpus is read, these callbacks are utilized to generate your
616             midi score by MIDI::Trans. MIDI::Trans is modelled after the text conversion
617             aspects of TransMid (http://www.digitalkoma.com/church/projects/transmid/),
618             but designed to be more useful to a wider range of tasks, with less overhead.
619              
620             If you're in a big hurry, and haven't any need for great control
621             over the process, simply read the 'Plug and Play Usage' and 'CallBacks'
622             sections below to get a jump, and your converter implemented in a just a few
623             minutes, with just a few statements.
624              
625             A corpus can be defined as either a string, or text file. MIDI::Trans
626             will then split that corpus into elements based on an element delimiter,
627             provided via argument, and determine some attributes of the corpus based
628             on other data, which can be supplied by the developer. The corpus is
629             then processed, element by element through the use of CallBacks you
630             specify. The normal flow of development looks like this:
631              
632             Define Parameters For Conversion
633             Define Functions To Generate Note, Duration, Volume, Tempo
634             from parameters and element values.
635             Specify and process corpus
636             Create score
637             Write Output
638              
639              
640             ... this section not yet complete...
641              
642             =head2 EXPORT
643              
644             None by default.
645              
646             =head1 PLUG AND PLAY USAGE
647              
648             A MIDI::Trans converter can be written in as few as three statements:
649              
650             use MIDI::Trans;
651            
652             my $TransObj = MIDI::Trans->new( {
653             'Tempo' => 140,
654             'VolumeCallBack' => sub { return(127); },
655             'NoteCallBack' => sub { $cnt++; return $cnt % 4 ? 88 : 'rest'; },
656             'DurationCallBack' => sub { return(16); },
657             });
658            
659             $TransObj->trans({ 'File' => './test.txt', 'Outfile' => 'test.mid' });
660              
661             Obviously, this isn''t very functional and the more compact we
662             make our code, the less functionality there is available to us.
663              
664             However, if your conversion process doesn''t rely too heavily on
665             controlling the the act of conversion its self, this single method
666             will do everything you need for the process of conversion.
667              
668             Let's discuss what we've done here:
669              
670             The new() method is called, which initializes the parameters
671             for the converter. The object returned makes its self
672             available to the callbacks, assuming that you''ve created the
673             variable referencing the object in the same namespace as, or at
674             least scoped as visible to, the callbacks'' function definition.
675            
676             The trans() method acts as a wrapper around the step by step
677             process of converting the document. It doesn''t give you the
678             ability to control some of the information gathering aspects,
679             nor does it let you handle more than one corpus with a single
680             object, but what it lacks in functionality, it makes up for in
681             ease.
682            
683             =head2 THE TRANS METHOD
684              
685             trans HASHREF
686              
687             Has one argument, which is required: either a reference to, or
688             an anonymous hash. This hash contains information required to
689             perform the conversion. If any values have already been defined
690             via the new() method, they do not have to be re-defined here.
691             Some names are short-hand for the configuration keys of new(),
692             marked with an asterisk (*), they are otherwise the same.
693            
694             trans() spawns a new instance of MIDI::Trans, this object
695             must be used for attribute and configuration methods for
696             the operation being performed with trans(). That is to
697             say, that if you are using trans(), you must also use the
698             trans_obj() method (see below) to return the object operating.
699            
700             Returns true (1) on success or sets the error() message then
701             returns undef otherwise.
702            
703             The following keys are valid for the hash:
704            
705             'File'
706             The file path to read as the corpus. This
707             key is required.
708            
709             'Outfile'
710             The file to save MIDI output to.
711             Default value is './out.midi'
712            
713             'Delimiter'
714             The element delimiter in the corpus.
715             Default value is '\s+'
716            
717             'Tempo'
718             The tempo to use for the score,
719             you can specify either 'Tempo' or
720             'TempoCallBack' keys, but one
721             must be specified. Will override
722             the value of 'TempoCallBack'.
723            
724             'TempoCallBack'
725             Subroutine reference, or anonymous
726             sub block that will return a tempo
727             value. See CallBacks section below.
728            
729             'Volume'*
730             Subroutine reference, or anonymous
731             sub block that will return a valid
732             volume value.
733            
734             'Note'*
735             Subroutine reference, or anonymous
736             sub block that will return a valid
737             note value.
738              
739             'Duration'*
740             Subroutine reference, or anonymous
741             sub block that will return a valid
742             duration value.
743              
744              
745             USAGE:
746            
747             if( $TransObj->trans( {
748             'File' => './test.txt',
749             'Volume' => sub { ... },
750             'Note' => sub { ... },
751             'Duration' => \&some_sub,
752             'Tempo' => 120 } )
753             ) {
754             # do something
755             } else {
756             my $errmsg = $TransObj->error();
757             die("$errmsg\n");
758             }
759            
760             OR:
761            
762             my %hash = (
763             'File' => './test.txt',
764             'Volume' => sub { ... },
765             'Note' => sub { ... },
766             'Duration' => \&some_sub,
767             'Tempo' => 120
768             );
769            
770             if( $TransObj->trans(\%hash) ) { ... }
771            
772             Both methods are equivalent.
773            
774              
775             See the CallBacks section, below, for more information
776             about the CallBacks.
777            
778              
779             =head2 THE TRANS_OBJ METHOD
780              
781             Given that you need to have an active MIDI::Trans object
782             to use the attribute and information methods, and that
783             trans() creates a new MIDI::Trans object, the trans_obj()
784             method has been provided to you for accessing the
785             usually-needed methods.
786              
787             trans_obj
788              
789             Returns the blessed object being utilized by the
790             trans() method, all methods are available to this
791             object, but with data specific to the current
792             trans() object.
793            
794             USAGE:
795              
796             if( $TransObj->trans( { 'TempoCallBack' => \&tempo, ... } ) ) {
797             ...
798             }
799            
800             sub tempo {
801             # a callback called from trans()
802             my $cur_obj = $TransObj->trans_obj();
803            
804             my $num_sent = $cur_obj->sentences();
805            
806             ...
807             }
808            
809              
810            
811             =head1 CALLBACKS
812              
813              
814             If MIDI::Trans is like the skeleton for your conversion
815             application, then the CallBacks you define act as the
816             nervous system. The real logic lies in the combination
817             of information and statistics generated by the corpus, your
818             use of configurable options, and the callbacks you define.
819              
820             =head2 PASSING CALLBACKS AS ARGUMENTS
821              
822             CallBacks must be passed as either references or anonymous
823             sub blocks. The following forms are all valid:
824             (examples use the callback configuration methods)
825              
826             $TransObj->volume_callback( sub { ... } );
827              
828             --
829            
830             sub some_sub {
831             ...
832             }
833            
834             $TransObj->volume_callback(\&some_sub);
835              
836             --
837            
838             $hashRef->{'key'} = sub { ... };
839              
840             $TransObj->volume_callback($hashRef->{'key'});
841            
842             --
843            
844             my $sub = sub {
845             ...
846             };
847            
848             $TransObj->volume_callback($sub);
849              
850              
851             =head2 CALLBACK DESCRIPTION
852              
853             Most CallBacks are passed two arguments:
854              
855             The Current Element
856             The Current Position
857            
858             The Tempo CallBack is passed no
859             arguments.
860              
861             Each CallBack is expected
862             to return a spefic type and range of data
863             as a return value. Each type is discussed
864             here. Please note that these are just examples
865             and in no way reflect the complexity or
866             interaction available to you.
867              
868             =head3 Volume CallBacks
869              
870             Volume CallBacks return a numeric value to
871             represent the absolute volume of the
872             current element in a range of 0-127.
873              
874             Volume CallBacks are called once
875             every element, after Note CallBacks.
876            
877             Example:
878            
879             sub VolCallBack {
880              
881             my $elem = shift;
882             my $enum = shift;
883              
884             # in this callback, volume is
885             # determined by measuring the
886             # length of the input, then
887             # comparing that against a
888             # constant value, and using that
889             # comparison as a multiplier against
890             # our maximum volume level.
891            
892             my $lpct = length($elem) / 24;
893             $lpct = 1 if($lpct > 1);
894            
895             # here, we use the round() method supplied
896             # by MIDI::Trans
897            
898             my $value = $TransObj->round(127 * $lpct);
899            
900             return($value);
901             }
902            
903              
904             =head3 Note CallBacks
905              
906             Note CallBacks return a scalar value to
907             represent a note or rest event. The value
908             of the event is either a number, in the case
909             of a note, or a string - 'rest', in the case
910             of a rest event. For a note event, you
911             must specify the absolute value of the
912             note as an integer in the range of 0-127.
913             For a rest event, simply return a string with
914             the value 'rest'.
915              
916             Note CallBacks are called once every element.
917             They are processed before Volume and Duration.
918            
919             Example:
920            
921             sub NoteCallBack {
922            
923             my $elem = shift;
924             my $enum = shift;
925            
926             my $return;
927            
928             # here, if the corpus contains
929             # an element with the string 'Eighty-
930             # Eight', then a note value of 88
931             # will be returned, rest otherwise.
932            
933             if($elem =~ /Eighty-Eight/) {
934             $return = 88;
935             } else {
936             $return = 'rest';
937             }
938              
939             return($return);
940             }
941              
942              
943             =head3 Duration CallBacks
944              
945             Duration CallBacks return a numeric value
946             to represent the duration of the current event,
947             in quarter notes. So the actual duration of
948             the event, in seconds, is determined by the value of
949             the qn_len() configuration method and the tempo
950             returned by your Tempo CallBack.
951            
952             This method is called once every element, after all
953             others.
954              
955             Example:
956            
957             sub DurCallBack {
958            
959             my $elem = shift;
960             my $enum = shift;
961              
962             return(length($elem));
963            
964             }
965            
966              
967             =head3 Tempo CallBacks
968              
969             Tempo CallBacks return a numeric value
970             to represent the number of quarter notes
971             per minute to be used in the score. The
972             actual 'tempo' supplied to MIDI::Simple is
973             the result of the following equation:
974            
975             round($base_ms / $tempo);
976            
977             Where round() is the included round()
978             method, $base_ms is the value of the
979             configuration attribute base_milliseconds(),
980             and $tempo is the tempo returned by your
981             Tempo CallBack.
982            
983             Tempo is called once per processing
984             a corpus, before all other CallBacks.
985              
986             Please note, that there are no arguments
987             to this CallBack, as it is executed BEFORE
988             any elements are processed.
989            
990             Example:
991            
992             sub TempoCallBack {
993              
994             my $num_sents = $TransObj->sentences();
995             my $num_words = $TransObj->words();
996            
997             # this CallBack utilizes Attribute
998             # Retrieval methods to determine
999             # num of words and sentences in the
1000             # corpus, then uses these values
1001             # to form a percentage of a constant
1002             # maximum tempo.
1003            
1004             my $w_to_s_pct = $num_sents / $num_words;
1005            
1006             my $max_tempo = 200;
1007            
1008             my $tempo = $TransObj->round($max_tempo * $w_to_s_pct);
1009            
1010             return($tempo);
1011             }
1012              
1013              
1014             =head1 CORPUS ATTRIBUTES
1015              
1016             Several Attributes of your corpus may be gleaned
1017             when read. This is controlled by the 'AllAttributes'
1018             configuration value, set by either new() or the
1019             configuration method all_attributes(). Currently,
1020             those attributes are :
1021              
1022             # of Sentences *
1023             # of Words *
1024             # of Elements
1025            
1026             (Those marked by an asterisk can be
1027             turned off to reduce memory consumption)
1028            
1029             The Sentence Delimiter can be defined as a
1030             configuration value. The word boundary may not.
1031              
1032             =head3 ATTRIBUTE RETRIEVAL METHODS
1033              
1034             The following methods retrive attributes
1035             about the corpus being processed. They
1036             can only be used inside of your CallBacks,
1037             they are not available elsewhere.
1038            
1039             sentences()
1040            
1041             Returns the number of sentences
1042             in the corpus.
1043            
1044             words()
1045            
1046             Returns the number of words in
1047             the corpus.
1048            
1049             elements()
1050            
1051             Returns the number of total elements
1052             in the corpus.
1053              
1054              
1055             =head1 METHODS
1056              
1057             new HASHREF
1058              
1059             Creates a new instance of the class. Returns a blessed object
1060             on success, undef on error. One argument is allowed, a hash
1061             reference or anonymous hash, which contains configuration
1062             information for the object.
1063            
1064             The following keys are allowable in the hash, and their values:
1065              
1066             'Raise_Error'
1067             Boolean, die() on any error with message
1068             0 = false (default), 1 = true
1069            
1070             'ElementDelimiter'
1071             Default delimiter used to seperate elements from
1072             the corpus. Should be a valid regular expression
1073             as would fit in (?:).
1074             Default value is '\s+'
1075            
1076             'SentenceDelimiter'
1077             Default delimiter for end of sentence. Follows
1078             same rules as ElementDelimiter.
1079             Default value is '\.|\?|\!'
1080            
1081             'NoteCallBack'
1082             Default callback for obtaining note values.
1083             Should be a reference to, or anonymous, sub
1084             routine. See the section regarding CallBacks
1085             above.
1086             Default value is undef
1087            
1088             'VolumeCallBack'
1089             Default CallBack for obtaining volume values.
1090            
1091             'DurationCallBack'
1092             Default CallBack for obtaining duration values.
1093            
1094             'TempoCallBack'
1095             Default CallBack for obtaining tempo values.
1096            
1097             'Channel'
1098             Default Channel for MIDI output.
1099             Default value is '1'
1100            
1101             'qn_len'
1102             Default number of ticks per quarter note.
1103             It is safe to leave this unmodified.
1104             See MIDI::Simple for more information.
1105             Default value is '96'
1106            
1107             'AllAttributes'
1108             Boolean, whether or not all attributes of
1109             the corpus should be measured when reading
1110             it. Can be used to lessen memory usage.
1111             See the Attributes section below for more
1112             information.
1113             0 = False, 1 = True (default)
1114            
1115             'BaseMilliseconds'
1116             The base number of ms in a minute. This
1117             is used for timing and tempo purposes.
1118             It is safe to leave this value unmodified.
1119             Default value is '60000000'
1120            
1121              
1122              
1123             USAGE:
1124            
1125             my $TransObj = MIDI::Trans->new( {
1126             'VolumeCallBack' => \&vol,
1127             'AllAttributes' => 0
1128             });
1129            
1130              
1131             OR:
1132            
1133            
1134             my %attrs = ( 'AllAttributes' => 1, 'VolumeCallBack' => \&vol );
1135            
1136             my $TranObj = MIDI::Trans->new(\%attrs);
1137            
1138              
1139              
1140             error()
1141              
1142             Returns the last set error message, or undef if no error
1143             message has been set.
1144            
1145              
1146             USAGE:
1147            
1148             my $errmsg = $TransObj->error();
1149              
1150              
1151            
1152             reset_error()
1153              
1154             Removes the current error message. Causes error() to return
1155             undef. Always returns true (1).
1156            
1157             USAGE:
1158            
1159             $TransObj->reset_error();
1160              
1161              
1162            
1163             trans HASHREF
1164              
1165             The 'wrapper' function for quick use of MIDI::Trans, for more
1166             information, see the section entitled Plug and Play Usage
1167             above.
1168            
1169              
1170              
1171             trans_obj
1172              
1173             See the section entitled Plug and Play Usage above.
1174            
1175              
1176             read_corpus HASHREF
1177              
1178             Reads, parses, and collects attributes about a given corpus
1179             (your input data). The corpus may be specified either as a
1180             file to read, or a string to parse. Returns true (1) on sucess,
1181             and sets the error message then returns undef on error.
1182            
1183             More than one corpus may be open at a given time.
1184            
1185             A single argument must be specified, which is either a hash
1186             reference or an anonymous hash. The hash contains information
1187             about the corpus. Three keys are possible:
1188            
1189             'Name'
1190             The 'handy' name, or name you wish to
1191             specify for the corpus. This is useful
1192             when opening more than one corpus that
1193             is a string type.
1194             If the corpus type is a string, the
1195             name will default to 'String', otherwise
1196             the name will default to the file name.
1197            
1198             'File'
1199             When this key is provided, it specifies
1200             that the corpus type is a file. This
1201             key will override the 'String' key,
1202             even if the value is undef -- resulting
1203             in an error. The value for this key
1204             should be the path to the file you
1205             want to parse.
1206            
1207             'String'
1208             When this key is provided, it specifies
1209             that the corpus type is a string. This
1210             key is overriden by the 'File' key. The
1211             string should be passed as the value.
1212            
1213            
1214             USAGE:
1215            
1216             if( $TransObj->read_corpus({ 'File' => './corpus.txt' }) ) {
1217             ...
1218             } else {
1219             my $error = $TransObj->error();
1220             die("$error\n");
1221             }
1222              
1223             OR
1224            
1225             my %corp_dat = ( 'File' => './corpus.txt', 'Name' => 'Corpus1' );
1226            
1227             if( $TransObj->read_corpus(\%corp_dat) ) { ... }
1228            
1229            
1230             NOTE:
1231            
1232             The corpus when read, is stored in a list of
1233             available corpuses(ii?). This list is ordered,
1234             in the order they were read, numerically. This
1235             is the preferred method for identifying a corpus
1236             to other methods, but most also accept a Name
1237             value to identify the corpus, which may be
1238             easier to track. The numbering begins at 0.
1239            
1240             TODO: Convert all methods to a naming convention.
1241            
1242            
1243            
1244             process HASHREF
1245              
1246             Actually performs processing on a given corpus. Runs
1247             all of the callbacks, as needed, either on a per-corpus
1248             or per-element basis. Generates the data that will be
1249             used to create a MIDI score later. Only a single corpus
1250             may be specified. Returns true (1) if successful and
1251             sets the error message then returns undef otherwise.
1252            
1253             A single argument must be specified, which is either a hash
1254             reference or an anonymous hash. The hash contains information
1255             identifying the corpus. There are two keys possible:
1256            
1257             'Name'
1258             The name as given the corpus -- see read_corpus
1259             above. Overrides the 'Num' key. The value should
1260             be the name of the corpus.
1261            
1262             'Num'
1263             The number of the corpus. See the NOTE section
1264             of read_corpus, above. Is overriden by the 'Name'
1265             key.
1266            
1267            
1268             USAGE:
1269            
1270             if( $TransObj->process( { 'Name' => 'Corpus1' }) ) {
1271             ..
1272             } else {
1273             my $errmsg = $TransObj->error();
1274             die("$errmsg\n");
1275             }
1276            
1277             OR:
1278            
1279             my %corp_dat = ( 'Num' => 1 );
1280            
1281             if( $TransObj->process(\%corp_dat) ) { ... }
1282            
1283              
1284              
1285             create_score NUM
1286              
1287             Creates a score from the data generated by process(),
1288             suitable for writing to a file (see write_file() below).
1289             If the corpus hasn't been parsed, or the processing hasn't
1290             occured yet, and error will occur. Returns the
1291             MIDI::Simple object from the score on success and
1292             sets the error message then returns undef on failure.
1293            
1294             One argument, the identifying number of the corpus
1295             must be specified. (See the NOTE section of read_corpus()
1296             above)
1297            
1298             USAGE:
1299            
1300             my $scoreObj;
1301             if( $scoreObj = $TransObj->create_score(0) ) {
1302             ...
1303             } else {
1304             my $errmsg = $TransObj->error();
1305             die("$errmsg\n");
1306             }
1307            
1308              
1309              
1310             write_file SCORE_OBJECT
1311              
1312             Writes a score to a file, given the score object
1313             returned from create_score. Returns true (1) on
1314             success and sets the error message then returns
1315             undef on failure.
1316            
1317             USAGE:
1318            
1319             if( $TransObj->write_file($scoreObj) ) {
1320             ...
1321             } else {
1322             my $errmsg = $TransObj->error();
1323             die("$errmsg\n");
1324             }
1325              
1326              
1327              
1328             round DECIMAL
1329              
1330             Returns the nearest rounded integer given
1331             decimal or integer input.
1332            
1333             USAGE:
1334              
1335             # returns 2
1336            
1337             my $x = $TransObj->round(1.5);
1338            
1339             # returns 1
1340            
1341             my $x = $TransObj->round(1.38573927541);
1342            
1343              
1344              
1345              
1346             =head2 CALLBACK CONFIGURATION METHODS
1347              
1348             These methods allow you to configure the CallBacks
1349             currently in use by MIDI::Trans, they also allow
1350             you to retrieve a reference to the CallBack in
1351             question. All methods accept an argument of either
1352             a subroutine reference or anonymous subroutine block.
1353             All methods return their subref.
1354            
1355              
1356             volume_callback()
1357              
1358             Sets / Returns the callback for volume
1359            
1360             USAGE:
1361            
1362             my $vol_cb = $TransObj->volume_callback(\&somesub);
1363            
1364            
1365            
1366             note_callback()
1367              
1368             Sets / Returns the callback for notes
1369              
1370             USAGE:
1371              
1372             my $note_cb = $TransObj->note_callback(\&somesub);
1373              
1374              
1375              
1376             duration_callback()
1377              
1378             Sets / Returns the callback for duration
1379              
1380             USAGE:
1381              
1382             my $dur_cb = $TransObj->duration_callback(\&somesub);
1383              
1384              
1385              
1386             tempo_callback()
1387              
1388             Sets / Returns the callback for tempo
1389              
1390             USAGE:
1391              
1392             my $tempo_cb = $TransObj->tempo_callback(\&somesub);
1393              
1394              
1395              
1396             =head2 INFORMATIONAL AND CONFIGURATION METHODS
1397              
1398             These methods, in conjunction with methods such as
1399             round() (described under the main METHODS heading),
1400             are useful for modifying the way MIDI::Trans is
1401             operating, as well as assisting your callbacks in
1402             performing their operation, and retrieving operating
1403             values. All of these (as well as others) may be
1404             utilized in your CallBacks. Be careful, however of
1405             calling process() within a CallBack, as this may
1406             result in an infinite loop.
1407            
1408              
1409             current_elem()
1410              
1411             Returns the current element from the list of
1412             elements in the corpus. This would typically
1413             be used by your callbacks for determining what
1414             to generate.
1415            
1416             USAGE:
1417            
1418             my $element = $TransObj->current_elem();
1419            
1420              
1421              
1422             current_pos()
1423              
1424             Returns the position of the current element
1425             in the document, starting at zero. That is,
1426             on the 50th element of the corpus, current_pos()
1427             would return '49'.
1428            
1429             USAGE:
1430              
1431             my $pos = $TransObj->current_pos();
1432            
1433            
1434              
1435             raise_error()
1436              
1437             Sets, or returns the current value of the
1438             'Raise_Error' attribute.
1439            
1440             USAGE:
1441            
1442             my $RE = $TransObj->raise_error(1);
1443            
1444              
1445              
1446             delimiter()
1447              
1448             Sets, or returns the current value of the
1449             'Delimiter' attribute.
1450              
1451             USAGE:
1452              
1453             my $Del = $TransObj->delimiter(1);
1454              
1455              
1456              
1457              
1458             sentence_delimiter()
1459              
1460             Sets, or returns the current value of the
1461             'SentenceDelimiter' attribute.
1462              
1463             USAGE:
1464              
1465             my $SD = $TransObj->sentence_delimiter('\!\?');
1466              
1467              
1468              
1469              
1470             all_attributes()
1471              
1472             Sets, or returns the current value of the
1473             'AllAttributes' attribute.
1474              
1475             USAGE:
1476              
1477             my $AA = $TransObj->all_attributes(1);
1478              
1479              
1480              
1481              
1482             channel()
1483              
1484             Sets, or returns the current value of the
1485             'Channel' attribute.
1486              
1487             USAGE:
1488              
1489             my $Chan = $TransObj->channel(1);
1490              
1491              
1492              
1493              
1494             qn_len()
1495              
1496             Sets, or returns the current value of the
1497             'qn_len' attribute.
1498              
1499             USAGE:
1500              
1501             my $QL = $TransObj->qn_len(1);
1502              
1503              
1504              
1505              
1506             tempo()
1507              
1508             Sets, or returns the current value of the
1509             'Tempo' attribute. This is usually set
1510             by your tempo CallBack, but can also
1511             be set with a default value using the new()
1512             attribute. You can use this function to
1513             override tempo, but this may have little,
1514             if any, effect on create_events().
1515              
1516             USAGE:
1517              
1518             my $Del = $TransObj->delimiter(1);
1519              
1520              
1521              
1522              
1523              
1524             =head1 AUTHOR
1525              
1526             C. Church <lt>dolljunkie@digitalkoma.com<gt>
1527              
1528             =head1 SEE ALSO
1529              
1530             L<perl>.
1531              
1532             =cut