later...package MarkovDiddly; use strict; ########################################### # Variable Length Markov Diddly Stream ########################################### my @tunes = (# a bunch of common tunes "e2,4,e2,2,b2,2,e2,2,b2,2,e2,2,e2,2,b2,2,a2,2,fs2,2,d2,2,e2,4,e2,2 +,b2,4,cs3,2,d3,2,cs3,2,b2,2,a2,2,fs2,2,d2,2,e2,4,e2,2,b2,2,e2,2,b2,2, +e2,2,e2,2,b2,2,a2,2,fs2,2,d2,2,g2,4,g2,2,fs2,2,g2,2,a2,2,b2,2,a2,2,g2 +,2,fs2,2,e2,2,d2,2", "d2,2,g2,2,g2,2,b2,2,g2,2,g2,2,a2,2,g2,2,a2,2,b2,2,g2,2,g2,2,e3,2, +g3,2,e3,2,d3,2,b2,2,g2,2,a2,2,g2,2,a2,2,b2,2,g2,2,e2,2,d2,2,g2,2,g2,2 +,b2,2,g2,2,g2,2,a2,2,g2,2,a2,2,b2,2,g2,2,g2,2,e3,2,g3,2,e3,2,d3,2,b2, +2,g2,2,a2,2,g2,2,fs2,2,g2,6", "d2,4,d2,2,a2,6,b2,2,a2,2,g2,2,a2,2,b2,2,a2,2,d2,4,d2,2,a2,6,b2,2, +a2,2,g2,2,e2,2,g2,2,e2,2,d2,4,d2,2,a2,6,b2,2,a2,2,g2,2,a2,2,b2,2,c3,2 +,d2,2,c3,2,b2,2,c3,2,b2,2,a2,2,b2,2,a2,2,g2,2,e2,2,g2,2,e2,2", "d3,2,e3,2,d3,2,b2,4,g2,2,a2,4,g2,2,e2,4,d2,2,g2,4,g2,2,g2,2,a2,2, +b2,2,d3,4,b2,2,a2,6,d3,2,e3,2,d3,2,b2,4,g3,2,fs2,4,e3,2,c3,4,e3,2,d3, +2,e3,2,d3,2,c3,2,b2,2,a2,2,g2,12", "b2,2,g2,2,g2,2,d2,2,g2,2,g2,2,b2,2,g2,2,b2,2,d3,2,c3,2,b2,2,c3,2, +a2,2,a2,2,fs2,2,a2,2,a2,2,c3,2,a2,2,c3,2,e3,2,d3,2,c3,2,b2,2,g2,2,g2, +2,d2,2,g2,2,g2,2,b2,2,g2,2,b2,2,d3,2,c3,2,b2,2,c3,2,b2,2,c3,2,a2,2,d3 +,2,c3,2,b2,2,g2,2,g2,2,g2,2,d3,2,c3,2", "fs2,4,b2,2,b2,2,cs3,2,d3,2,cs3,4,a2,2,a2,2,b2,2,cs3,2,d3,4,b2,2,b +2,2,cs3,2,d3,2,e3,2,fs3,2,e3,2,d3,2,cs3,2,b2,2,fs2,4,b2,2,b2,2,cs3,2, +d3,2,cs3,4,a2,2,a2,2,b2,2,cs3,2,d3,2,cs3,2,d3,2,e3,2,d3,2,e3,2,fs3,2, +b2,2,b2,2,b2,6", "a2,2,fs2,2,a2,2,a2,2,fs2,2,a2,2,b2,2,g2,2,b2,2,b2,2,g2,2,b2,2,a2, +2,fs2,2,a2,2,a2,2,d3,2,e3,2,fs3,2,e3,2,d3,2,b2,2,d3,2,b2,2,a2,2,fs2,2 +,a2,2,a2,2,fs2,2,a2,2,b2,2,g2,2,b2,2,b2,2,g2,2,b2,2,d3,2,e3,2,fs3,2,a +3,2,fs3,2,e3,2,fs3,2,b2,2,b2,2,b2,2,d3,2,b2,2", "a2,2,d2,2,d2,2,b2,2,d2,2,d2,2,c3,6,c3,2,b2,2,a2,2,g2,2,a2,2,b2,2, +a2,2,g2,2,fs2,2,g2,2,fs2,2,g2,2,e2,2,fs2,2,g2,2,a2,2,d2,2,d2,2,b2,2,d +2,2,d2,2,c3,6,c3,2,b2,2,a2,2,g2,2,a2,2,b2,2,a2,2,g2,2,fs2,2,g2,12", "e2,2,fs2,2,e2,2,b2,4,b2,2,b2,2,a2,2,fs2,2,d3,6,e2,2,fs2,2,e2,2,b2 +,4,b2,2,b2,2,a2,2,fs2,2,fs2,4,e2,2,e2,2,fs2,2,e2,2,b2,4,b2,2,b2,2,a2, +2,fs2,2,d3,6,b2,2,cs3,2,d3,2,e3,4,b2,2,b2,2,a2,2,fs2,2,fs2,4,e2,2", "d2,4,a2,2,fs2,4,a2,2,d2,4,a2,2,fs2,4,a2,2,d3,4,e3,2,fs3,4,e3,2,d3 +,4,cs3,2,b2,4,a2,2,e3,6,fs3,6,g3,6,fs3,6,e3,4,d3,2,cs3,4,b2,2,a2,2,b2 +,2,a2,2,g2,2,fs2,2,e2,2", "d2,4,e2,2,fs2,4,g2,2,a2,4,b2,2,a2,4,fs2,2,a2,4,b2,2,a2,4,fs2,2,a2 +,4,b2,2,a2,4,fs2,2,d2,4,e2,2,fs2,4,g2,2,a2,4,b2,2,a2,4,d3,2,cs3,4,b2, +2,a2,4,fs2,2,d2,12", "g2,2,g2,2,g2,2,g2,6,g2,2,g2,2,g2,2,g2,4,d3,2,b2,4,g2,2,b2,4,d3,2, +g3,4,d3,2,b2,4,g2,2,d2,2,d2,2,d2,2,d2,6,d2,2,d2,2,d2,2,d2,4,a2,2,fs2, +4,d2,2,fs2,4,a2,2,c3,4,a2,2,fs2,4,d2,2", "a2,6,a2,6,a2,2,fs2,2,d3,2,a2,2,fs2,2,d2,2,g2,6,g2,6,g2,2,e2,2,fs2 +,2,g3,2,fs2,2,e2,2,a2,6,a2,6,a2,2,fs2,2,d3,2,a2,2,fs2,2,d2,2,e2,2,fs2 +,2,g2,2,fs2,2,g2,2,e2,2,d2,12", "a2,2,d2,2,d2,2,b2,2,d2,2,d2,2,c3,6,c3,2,b2,2,a2,2,g2,2,a2,2,b2,2, +a2,2,g2,2,fs2,2,g2,2,fs2,2,g2,2,e2,2,fs2,2,g2,2,a2,2,d2,2,d2,2,b2,2,d +2,2,d2,2,c3,6,c3,2,b2,2,a2,2,g2,2,a2,2,b2,2,a2,2,g2,2,fs2,2,g2,12", ); sub new { my $class = shift(); my $length = shift() || 4; # a good ave +rage my %self = ('length'=>$length); foreach (@tunes) { # read the e +xisting tunes... chomp; my @line = split /,/; my @notes = ("START") x $length; # cyclic buffe +r of notes my @pitches = ("START") x $length; # cyclic buf +fer of pitches my @durs = ("START") x $length; # cyclic bu +ffer of durations while (@line) { shift (@notes);shift (@pitches);shift (@durs); my ($pitch,$dur) = (shift(@line),shift(@line)); push @notes, "$pitch,$dur"; push @pitches,$pitch; push @durs,$dur; $self{notes}{key($length,@notes)}{$notes[$#notes]}++; $self{pitches}{key($length,@pitches)}{$pitches[$#pitches]} +++; $self{durs}{key($length,@durs)}{$durs[$#durs]}++; } shift (@notes);shift (@pitches);shift (@durs); $self{notes}{key($length,@notes)}{"END"}++; $self{pitches}{key($length,@pitches)}{"END"}++; $self{durs}{key($length,@durs)}{"END"}++; } $self{nbuffer} = [("START") x $length]; $self{pbuffer} = [("START") x $length]; $self{dbuffer} = [("START") x $length]; bless \%self,$class; } # get a full sequence to end sub sequence { my ($self,$buffer,$probs) = @_; my @seq; do {push @seq,$self->get_next(1,$buffer,$probs);} while ($seq[$#se +q] ne "END"); $self->set_buffer($buffer); pop @seq; #remove 'END' tag @seq; } sub get_tune { sequence(shift(),"nbuffer","notes");} sub get_pitches { sequence(shift(),"pbuffer","pitches");} sub get_durations { sequence(shift(),"dbuffer","durs");} # receive a buffer & a bunch of probabilities, # return an item (and rotate the buffer) # only allow possibility of 'END' token if requested sub get_next { my ($self,$end,$buffer,$probs) = @_; $self->set_buffer($buffer) unless (@{$self->{$buffer}}); my @buffer = @{$self->{$buffer}}; shift(@buffer); my %next = %{$self->{$probs}{key($self->{length},@buffer)}}; + my @next = map {($_) x $next{$_}} keys %next; # 1 entry per 'pr +ob' my $n = $next[int(rand(@next))]; unless ($end) { unless (grep {$_ ne "END"} @next) { # only 1 option left, $self->set_buffer($buffer); # so go to beginnin +g return $self->get_next($end,$buffer,$probs); } while ($n eq 'END') {$n = $next[int(rand(@next))]}; } push @buffer, $n; $self->set_buffer($buffer,@buffer); return $buffer[$#buffer]; } # 'stream' functions - get_next_xxx(allow_end_token) sub get_next_note {get_next(shift(),shift(),"nbuffer","notes");} sub get_next_pitch {get_next(shift(),shift(),"pbuffer","pitches");} sub get_next_duration {get_next(shift(),shift(),"dbuffer","durs");} # set the intitial states sub set_notes {set_buffer(shift,"nbuffer",@_);} sub set_pitches {set_buffer(shift,"pbuffer",@_);} sub set_durations {set_buffer(shift,"dbuffer",@_);} sub set_buffer { my ($self,$buffer,@buffer) = @_; shift(@buffer) while (@buffer > $self->{length}); unshift(@buffer,"START") while (@buffer < $self->{length}); $self->{$buffer} = \@buffer; } sub key {my $l=shift();my @arr = @_;return join(" ",@arr[0..$l - 2]);} + 1;
Cheers,package main; use strict; use MarkovDiddly; my $t6 = MarkovDiddly->new(6); # will closely an resemble e +xisting tune print "tune (6): ",join(" ",$t6->get_tune()),"\n\n"; print "pitches (6): ",join(" ",$t6->get_pitches()),"\n\n"; print "durations (6): ",join(" ",$t6->get_durations()),"\n\n"; my $t2 = MarkovDiddly->new(2); # will be more random print "tune (2): ",join(" ",$t2->get_tune()),"\n\n"; # grab a load of predictable notes with more random durations $t6->set_pitches(qw(d2 g2 g2 b2 g2 g2)); my @tune = map {$t6->get_next_pitch().",".$t2->get_next_duration()." " +} (0..30); print "mixture (6/2): ",join(",",@tune),"\n"; exit;
In reply to Re: Re: Markov Diddly
by benn
in thread Markov Diddly
by benn
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |