| MIDI-Morph documentation | Contained in the MIDI-Morph distribution. |
MIDI::Morph - Musical transition tool
Version 0.01
use MIDI::Morph;
my $m = MIDI::Morph->new(from => $from_score, to => $to_score);
$new_score = $m->Morph(0.4);
The aim of MIDI::Morph is to provide an easy-to-use composition tool that allows
transitions between two gestalten (musical snippets). The data handled by
this module is in MIDI::Score format (at this moment, only note events
are considered).
This is an alpha release, features and API will be extended and changed iteratively.
my $m = MIDI::Morph->new(from => $from, to => $to);
Creates a new morpher object.
AutoMap is called automatically by MIDI::Morph and provides a mapping from
the notes in the from structure to the notes in the to structure.
Currently, it is a simple mapping 1st<->1st, 2nd<->2nd, but this will
become more sophisticated in future.
$m->Morph($position);
Morph creates a structure that reflects a transition point between from (0)
and to (1). Currently the transition is linear.
MIDI::Morph::event_distance($event1, $event2, $weights);
This function calculates the distance between two events. The events passed
should be note events as described in MIDI::Score. The weights are passed
as a hash reference with the keys start, end, pitch and velocity.
This parameter is optional; the default weights are 1, 1, 1 and 0 respectively.
These weights can be used in case you want to measure the distance between two events in different terms.
my $event = morph_single_event($from_event, $to_event, $position);
This helper function morphs two single events.
Christian Renz, <crenz @ web42.com>
Please report any bugs or feature requests to
bug-midi-morph@rt.cpan.org, or through the web interface at
http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MIDI-Morph.
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.
Copyright 2005 Christian Renz <crenz @ web42.com> , All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| MIDI-Morph documentation | Contained in the MIDI-Morph distribution. |
package MIDI::Morph; use warnings; use strict; our @ISA = qw(Exporter); our @EXPORT_OK = qw(event_distance);
our $VERSION = '0.02';
sub new { my $class = shift; my %params = @_; my $self = {}; return undef unless ref $params{from} eq 'ARRAY' && ref $params{to} eq 'ARRAY'; foreach (qw(from to)) { $self->{$_} = $params{$_}; } return bless $self, $class; }
sub AutoMap { my ($self) = @_; $self->{map} = []; foreach (0 .. $#{$self->{from}}) { $self->{map}->[$_] = [$_]; } }
sub Morph { my ($self, $position) = @_; $self->AutoMap() unless (ref $self->{map}); my @morph = (); foreach (0 .. $#{$self->{map}}) { push @morph, morph_single_event($self->{from}->[$_], $self->{to}->[$_], $position); } return [@morph]; }
our %distance_default_weights = ( start => 1, end => 1, pitch => 1, velocity => 0); our %distance_weights = %distance_default_weights; sub event_distance { my ($a, $b, $weights) = @_; # 'note', position, duration, channel, pitch, velocity # 0 1 2 3 4 5 return undef unless ref $a eq 'ARRAY' && ref $b eq 'ARRAY'; return undef unless scalar @$a == 6 && scalar @$a == 6; return undef unless $a->[0] eq 'note' && $b->[0] eq 'note'; my %weights = %distance_weights; if (ref $weights eq 'HASH') { foreach (keys %weights) { $weights{$_} = $weights->{$_} if defined $weights->{$_}; } } # use Data::Dumper qw(Dumper); # print STDERR "\n\n" . Dumper({ # weights => \%weights, # a => $a, # b => $b # }). "\n\n"; return abs($a->[1] - $b->[1]) * $weights{start} + abs(($a->[1] + $a->[2]) - ($b->[1] + $b->[2])) * $weights{end} + abs($a->[4] - $b->[4]) * $weights{pitch} + abs($a->[5] - $b->[5]) * $weights{velocity}; }
sub morph_single_event { my ($from, $to, $position) = @_; return undef unless ref $from eq 'ARRAY' && ref $to eq 'ARRAY'; return undef unless $from->[0] eq 'note' && $to->[0] eq 'note'; my @event = @$from; # leave channel untouched, change start, duration, pitch, velocity foreach (1, 2, 4, 5) { my $diff = $to->[$_] - $from->[$_]; $event[$_] = $from->[$_] + $position * $diff; } return [@event]; }
42;