MIDI-Perl

 view release on metacpan or  search on metacpan

lib/MIDI/Simple.pm  view on Meta::CPAN

-- or no notes at all, if Notes is empty list.

Then it moves Time ahead as appropriate.  See the section "Parameters
For n/r/noop", below.

=cut

sub n { # a note
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  &MIDI::Simple::_parse_options($it, @_);
  foreach my $note_val (@{$it->{"Notes"}}) {
    # which should presumably not be a null list
    unless($note_val =~ /^\d+$/) {
      carp "note value \"$note_val\" from Notes is non-numeric!  Skipping.";
      next;
    }
    push @{$it->{"Score"}},
      ['note',
       int(${$it->{"Time"}}),

lib/MIDI/Simple.pm  view on Meta::CPAN

This is exactly like C<n>, except it never pushes anything to Score,
but moves ahead Time.  (In other words, there is no such thing as a
rest-event; it's just a item during which there are no note-events
playing.)

=cut

sub r { # a rest
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  &MIDI::Simple::_parse_options($it, @_);
  ${$it->{"Time"}} += ${$it->{"Duration"}};
  return;
}
###########################################################################

=item noop(...parameters...)  or  $obj->noop(...parameters...)

This is exactly like C<n> and C<r>, except it never alters Score,
I<and> never changes Time.  It is meant to be used for setting the
other state variables, i.e.: Channel, Duration, Octave, Volume, Notes.

=cut

sub noop { # no operation
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  &MIDI::Simple::_parse_options($it, @_);
  return;
}

#--------------------------------------------------------------------------

=back

=cut

lib/MIDI/Simple.pm  view on Meta::CPAN

  my $it;

  if(
    defined($p1) &&
    ($p1 eq 'MIDI::Simple'  or  ref($p1) eq 'MIDI::Simple')
  ) { # I'm a method!
    print "~ new_score as a MIDI::Simple constructor\n" if $Debug;
    $it = bless {};
    &_init_score($it);
  } else { # I'm a proc!
    my $cpackage = (caller)[0];
    print "~ new_score as a proc for package $cpackage\n" if $Debug;
    if( ref($package{ $cpackage }) ) {  # Already exists in %package
      print "~  reinitting pobj $cpackage\n" if $Debug;
      &_init_score(  $it = $package{ $cpackage }  );
      # no need to call _package_object
    } else {  # Doesn't exist in %package
      print "~  new pobj $cpackage\n" if $Debug;
      $package{ $cpackage } = $it = &_package_object( $cpackage );
      # no need to call _init_score
    }

lib/MIDI/Simple.pm  view on Meta::CPAN

directly access the variables instead.

=cut

#--------------------------------------------------------------------------
# read-or-write methods

sub Score (;\@) { # yes, a prototype!
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  if(@_) {
    if($am_method){
      @{$it->{'Score'}} = @_;
    } else {
      @{$it->{'Score'}} = @{$_[0]}; # sneaky, huh!
    }
    return; # special case -- return nothing if this is a PUT
  } else {
    return @{$it->{'Score'}}; # you asked for it
  }
}

sub Cookies {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  %{$it->{'Cookies'}} = @_ if @_;  # Better have an even number of elements!
  return %{$it->{'Cookies'}};
}

sub Time {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  ${$it->{'Time'}} = $_[0] if @_;
  return ${$it->{'Time'}};
}

sub Duration {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  ${$it->{'Duration'}} = $_[0] if @_;
  return ${$it->{'Duration'}};
}

sub Channel {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  ${$it->{'Channel'}} = $_[0] if @_;
  return ${$it->{'Channel'}};
}

sub Octave {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  ${$it->{'Octave'}} = $_[0] if @_;
  return ${$it->{'Octave'}};
}

sub Tempo {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  ${$it->{'Tempo'}} = $_[0] if @_;
  return ${$it->{'Tempo'}};
}

sub Notes {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  @{$it->{'Notes'}} = @_ if @_;
  return @{$it->{'Notes'}};
}

sub Volume {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  ${$it->{'Volume'}} = $_[0] if @_;
  return ${$it->{'Volume'}};
}

#-#-#-#-#-#-#-#-##-#-#-#-#-#-#-#-#-#-#-#-##-#-#-#-#-#-#-#-##-#-#-#-#-#-#-#-
# read-only methods that return references

sub Score_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Score'};
}

sub Time_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Time'};
}

sub Duration_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Duration'};
}

sub Channel_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Channel'};
}

sub Octave_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Octave'};
}

sub Tempo_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Tempo'};
}

sub Notes_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Notes'};
}

sub Volume_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Volume'};
}

sub Cookies_r {
  my($it) = (ref($_[0]) eq "MIDI::Simple") ? (shift @_)
    : ($package{ (caller)[0] } ||= &_package_object( (caller)[0] ));
  return $it->{'Cookies'};
}

###########################################################################
###########################################################################

=head2 MIDI EVENT ROUTINES

These routines, below, add a MIDI event to the Score, with a
start-time of Time.  Example:

lib/MIDI/Simple.pm  view on Meta::CPAN


=head2 MORE ROUTINES

=over

=cut

sub _test_proc {
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  print " am method: $am_method\n it: $it\n params: <", join(',',@_), ">\n";
}

###########################################################################

=item $opus = write_score I<filespec>

=item $opus = $obj->write_score(I<filespec>)

Writes the score to the filespec (e.g, "../../samples/funk2.midi", or

lib/MIDI/Simple.pm  view on Meta::CPAN

the function C<make_opus>, below, and if you capture the output of
write_score, you'll get the opus created, if you want it for anything.
(Also: you can also use a filehandle-reference instead of the
filespec: C<write_score *STDOUT{IO}>.)

=cut

sub write_score {
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  my($out, $ticks, $score_r) =
    ( $_[0], (${$it->{'Tempo'}} || 96), $it->{'Score'} );

  croak "First parameter to MIDI::Simple::write_score can't be null\n"
    unless( ref($out) || length($out) );
  croak "Ticks can't be 0" unless $ticks;

  carp "Writing a score with no notes!" unless @$score_r;
  my $opus = $it->make_opus;
# $opus->dump( { 'dump_tracks' => 1 } );

lib/MIDI/Simple.pm  view on Meta::CPAN

  # If ever you want just a single track as a score, here's how:
  #my $score_r =  ( MIDI::Score::events_r_to_score_r($track->events_r) )[0];
  my( $score_r, $time) = MIDI::Score::events_r_to_score_r($track->events_r);
  #print scalar(@$score_r), " notes in score\n";

  my $it;
  if($am_cons) { # just make a new object and return it.
    $it = MIDI::Simple->new_score;
    $it->{'Score'} = $score_r;
  } else { # need to fudge it back into the pobj
    my $cpackage = (caller)[0];
    #print "~ read_score as a proc for package $cpackage\n";
    if( ref($package{ $cpackage }) ) {  # Already exists in %package
      print "~  reinitting pobj $cpackage\n" if $Debug;
      &_init_score(  $it = $package{ $cpackage }  );
      # no need to call _package_object
    } else {  # Doesn't exist in %package
      print "~  new pobj $cpackage\n" if $Debug;
      $package{ $cpackage } = $it = &_package_object( $cpackage );
      # no need to call _init_score
    }

lib/MIDI/Simple.pm  view on Meta::CPAN

          my $phrase_number = ($measure + -1) % 4;
          my @phrase = @{$phrases[$phrase_number]};
          foreach my $note (@phrase) { $it->n($note); }
        }

=cut

sub synch {
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );

  my @subs = grep(ref($_) eq 'CODE', @_);

  print " My subs: ", map("<$_> ", @subs), ".\n"
   if $Debug;
  return unless @subs;
  # my @end_times = (); # I am the Lone Array of the Apocalypse!
  my $orig_time = ${$it->{'Time'}};
  my $max_time  = $orig_time;
  foreach my $sub (@subs) {

lib/MIDI/Simple.pm  view on Meta::CPAN

tick parameter (AKA "divisions") to $ticks.  The opus is,
incidentally, format 0, with one track.

=cut

sub make_opus {
  # Make a format-0 one-track MIDI out of this score.

  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );

  my($ticks, $score_r) = (${$it->{'Tempo'}}, $it->{'Score'});
  carp "Encoding a score with no notes!" unless @$score_r;
  my $events_r = ( MIDI::Score::score_r_to_events_r($score_r) )[0];
  carp "Creating a track with no events!" unless @$events_r;

  my $opus =
    MIDI::Opus->new({ 'ticks'  => $ticks,
                      'format' => 0,
                      'tracks' => [ MIDI::Track->new({

lib/MIDI/Simple.pm  view on Meta::CPAN

as it is (currently) just a call to C<&MIDI::Score::dump_score>; but in
the future I may (should?) make it output in C<n>/C<r> notation.  In
the meantime I assume you'll use this, if at all, only for debugging
purposes.

=cut

sub dump_score {
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  return &MIDI::Score::dump_score( $it->{'Score'} );
}

###########################################################################
###########################################################################

=back

=head2 FUNCTIONS

lib/MIDI/Simple.pm  view on Meta::CPAN


Items in LIST which aren't note specifications are passed thru
unaltered.

=cut

sub interval { # apply an interval to a list of notes.
  my(@out);
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  my($interval_r, @notes) = @_;

  croak "first argument to &MIDI::Simple::interval must be a listref\n"
   unless ref($interval_r);
  # or a valid key into a hash %Interval?

  foreach my $note (@notes) {
    my(@them, @status, $a_flag, $note_number);
    @status = &is_note_spec($note);
    unless(@status) { # not a note spec

lib/MIDI/Simple.pm  view on Meta::CPAN

  $package_opus = Self;
  funkify($package_opus);

=cut

sub Self { # pointless as a method -- but as a sub, useful if
  # you want to access your current package's object.
  # Juuuuuust in case you need it.
  my($am_method, $it) = (ref($_[0]) eq "MIDI::Simple")
    ? (1, shift @_)
    : (0, ($package{ (caller)[0] } ||= &_package_object( (caller)[0] )) );
  return $it;
}

=back

=cut

###########################################################################

=head1 COPYRIGHT 



( run in 0.452 second using v1.01-cache-2.11-cpan-a3c8064c92c )