#!/usr/bin/env perl # hybrid - mix periodic and more whitenoise-y generation. probably there # may be better ways of blending the generation methods use 5.26.0; use MIDI; sub CCPAN () { 0x0A } sub COWBELL () { 56 } sub DRUMS () { 9 } sub MAXTIME () { 10240 * 8 } sub NOW () { 0 } sub QUIET () { 0 } my $file = shift // 'hybrid.midi'; my $track_count = 8; my @velo = qw( 105 80 90 80 ); sub velorand { 80 + int rand 25 } sub velostep { state $i = 0; my $v = $velo[$i]; $i = ( $i + 1 ) % @velo; $v; } sub makeatrack { state $pan = 40; # NOTE depends on track_count my $interval = 32 * ( 1 + int rand 4 ); my $periodic = 1; my $sectionlen = 1024; my $rand = 256; my $dur = 32 * ( int rand 4 ); my @events = ( [ marker => $dur ] ); my ( $epoch, $subepoch ) = ( $dur, $dur ); # the style transition ain't perfect but it works? while (1) { if ($periodic) { $subepoch += $interval; $epoch += $subepoch; if ( $subepoch >= $sectionlen ) { my $delta = $subepoch - $sectionlen; if ( $delta > 0 ) { $epoch -= $delta; push @events, [ marker => $delta ]; } $subepoch = 0; $periodic ^= 1; next; } push @events, [ control_change => NOW, DRUMS, CCPAN, $pan ], [ note_on => NOW, DRUMS, COWBELL, velostep ], [ note_off => $interval, DRUMS, COWBELL, QUIET ]; } else { my $delay = 1 + int rand $rand; $subepoch += $interval; $epoch += $subepoch; if ( $subepoch >= ( $sectionlen / 2 ) ) { my $delta = $subepoch - ( $sectionlen / 2 ); if ( $delta > 0 ) { $epoch -= $delta; push @events, [ marker => $delta ]; } $subepoch = 0; $periodic ^= 1; next; } push @events, [ control_change => NOW, DRUMS, CCPAN, $pan ], [ note_on => NOW, DRUMS, COWBELL, velostep ], [ note_off => $delay, DRUMS, COWBELL, QUIET ]; } } continue { last if $epoch >= MAXTIME; } $pan += 6; # NOTE depends on track_count MIDI::Track->new( { events => \@events } ); } sub gentracks { [ map makeatrack, 1 .. $track_count ] } MIDI::Opus->new( { tracks => gentracks } )->write_to_file($file);