-
Notifications
You must be signed in to change notification settings - Fork 5
/
euclidean-beats
86 lines (72 loc) · 2.03 KB
/
euclidean-beats
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env perl
use strict;
use warnings;
# Play Euclidean word sets where the onsets for snare and kick, are
# unique prime numbers less than or equal to the total number of beats.
use Data::Dumper::Compact qw(ddc);
use Math::Prime::Util::PrimeIterator ();
use MIDI::Drummer::Tiny ();
use Music::CreatingRhythms ();
my $n = shift || 16; # number of terms
my $loops = shift || 8; # times to loop
my $bpm = shift || 90; # beats per minute
my $vol = shift || 100; # volume 0-127
# get the euclidean pattern generator
my $mcr = Music::CreatingRhythms->new;
# get a drummer!
my $d = MIDI::Drummer::Tiny->new(
file => "$0.mid",
bpm => $bpm,
volume => $vol,
bars => $loops,
);
# get a list of primes less than or equal to N
my @primes;
my $it = Math::Prime::Util::PrimeIterator->new;
my $p = $it->iterate;
while ($p <= $n) {
push @primes, $p;
$p = $it->iterate;
}
# get the number of onsets for the kick drum
my $kick_p = 0;
while ($kick_p < 3) {
$kick_p = $primes[ int rand @primes ];
}
# get the number of onsets for the snare drum
my $snare_p = $kick_p;
while ($snare_p >= $kick_p) {
$snare_p = $primes[ int rand @primes ];
}
# play all the parts simultaneously
$d->sync(
\&hihat,
\&snare_drum,
\&kick_drum,
);
# write the score to a midi file
$d->write;
sub hihat {
my $x = int $n / 2;
my $sequence = [ (1) x $x ];
print '1/8th Hihat: ', ddc($sequence);
_add_to_score($d, $d->eighth, $d->closed_hh, $sequence);
}
sub snare_drum {
my $sequence = $mcr->euclid($snare_p, $n);
print "1/16th Snare ($snare_p, $n): ", ddc($sequence);
_add_to_score($d, $d->sixteenth, $d->snare, $sequence);
}
sub kick_drum {
my $sequence = $mcr->euclid($kick_p, $n);
print "1/16th Kick ($kick_p, $n): ", ddc($sequence);
_add_to_score($d, $d->sixteenth, $d->kick, $sequence);
}
sub _add_to_score {
my ($d, $duration, $patch, $sequence) = @_;
for (1 .. $d->bars) {
for my $i (@$sequence) {
$i ? $d->note($duration, $patch) : $d->rest($duration);
}
}
}