Imitating a Drum Circle
Ever been to the park and heard a tribe drumming in the distance? This is a drum circle. Upon closer inspection, each drummer has a single instrument (or maybe a set of bongos). Each drummer keeps a steady beat in common and in syncopation with his or her fellow drummers.
I wondered if this could be simulated somehow? There are of course decisions to be made - parts to this equation... How should the drummers enter? All at once or gradually? How should a drum be chosen or selected? And what phrase(s) should be played anyway?
Enter MIDI-Perl. Here is the program: drum-circle
Basically it does the following:
Use the modules necessary to have a drummer and rhythmic phrases.
Define the number of drummers ($max) as a number supplied by the user (or 4 by default).
Define a MIDI::Drummer::Tiny instance ($d), which will drive everything.
Set the possible drums to use (@DRUMS). In our case this is a group of toms, bongos, congas, cabasa, maracas, guiro, claves, and wood blocks.
Declare an array of phrases (@phrases), which is to be populated with code-references.
Define a 4 bar Music::Duration::Partition instance ($mdp), which we will use to generate rhythmic motifs for each drummer.
Loop from 1 to $max, appending phrases to play for each new drummer.
Add the phrases to the score such that they are played simultaneously.
Write the generated "composition" to disk, as a MIDI file named after the program "drum-circle."
Define the subroutine to generate our phrases!
This last part is shown here:
sub phrase {
my ($p) = @_; # Phrase number
# Get an unseen drum to use
my $drum = $DRUMS[int rand @DRUMS];
while ($seen{$drum}++) {
$drum = $DRUMS[int rand @DRUMS];
}
# Create a rhythmic phrase
my $motif = $mdp->motif;
# Either rest or play the motif
my $phrase = sub {
for my $n (1 .. $d->bars + 4) {
# If we are not up yet, then rest
if ($n < ($p * 4)) {
$d->rest($d->whole);
next;
}
# Otherwise play the rhythmic phrase!
for my $i (@$motif) {
# Get a fluctuating velocity between f and fff
my $vol = 'v' . (96 + int(rand 32));
$d->note($i, $drum, $vol);
}
}
};
return $phrase;
}
Here the variable $p is the number 1 to $max from our loop in step #7 above. Next, an unseen drum is selected at random. Then a quasi-random rhythmic motif is generated by Music::Duration::Partition as defined above. Finally an anonymous subroutine is returned, that just decides whether to play the generated motif or rest for a whole note.
This resting is crucial. Each drummer enters after 16 bars of the previous drummer having played. So, the second drummer enters after 4 bars, the third after 8, the fourth after 12, etc. Having everyone play at once or at random was just not a pleasant musical evolution. So I chose to have them enter one at a time.
Each run of this is different. Sometimes you get a "pleasant musical evolution", but sometimes you get all toms, or just a weird clash of rhythms. Here is one with 8 voices that is ok:
And how about another?
Ok, one more!