NAME
MIDI::Simple::Drummer - An algorithmic MIDI drummer
VERSION
version 0.0813
SYNOPSIS
use MIDI::Simple::Drummer;
# A glorified metronome:
my $d = MIDI::Simple::Drummer->new(-bpm => 100);
$d->count_in;
for(1 .. $d->phrases * $d->bars) {
$d->note($d->EIGHTH, $d->backbeat_rhythm(-beat => $_));
$d->note($d->EIGHTH, $d->tick);
}
# Shuffle:
$d = MIDI::Simple::Drummer->new(-bpm => 100);
$d->count_in;
for(1 .. $d->phrases * $d->bars) {
$d->note($d->TRIPLET_EIGHTH, $d->backbeat_rhythm(-beat => $_));
$d->rest($d->TRIPLET_EIGHTH);
$d->note($d->TRIPLET_EIGHTH, $d->tick);
}
# A rock drummer:
use MIDI::Simple::Drummer::Rock;
$d = MIDI::Simple::Drummer::Rock->new(
-bpm => 100,
-volume => 100,
-phrases => 8,
-file => 'rock-drums.mid',
);
my ($beat, $fill) = (0, 0);
my @rotate = qw( 2.1 2.2 2.4 );
$d->count_in;
for my $p (1 .. $d->phrases) {
if($p % 2 > 0) {
$beat = $d->beat(-name => 2.3, -fill => $fill);
$beat = $d->beat(-name => 2.3);
}
else {
$beat = $d->beat(-name => (@rotate)[int(rand @rotate)]);
$fill = $d->fill(-last => $fill);
}
}
$d->patterns('end fill' => \&fin);
$d->fill(-name => 'end');
$d->write;
sub fin {
my $d = shift;
$d->accent;
# Crash and kick, simultaneously.
$d->note('qn', $d->strike('Crash Cymbal 1', $d->name_of('kick')));
}
# Multi-tracking:
$d = MIDI::Simple::Drummer->new(-file => "$0.mid");
$d->patterns(b1 => \&hihat);
$d->patterns(b2 => \&backbeat);
$d->sync_tracks(
sub { $d->beat(-name => 'b1') },
sub { $d->beat(-name => 'b2') },
);
$d->write;
sub hihat { # tick
my $self = shift;
$self->note($self->EIGHTH, $self->tick) for 1 .. 2 * $self->beats;
}
sub backbeat { # kick/snare
my $self = shift;
$self->note($self->QUARTER, $self->rotate($_)) for 1 .. $self->beats;
}
DESCRIPTION
* While still viable, this module has mostly been superseded by MIDI::Drummer::Tiny.
This is a "robotic" drummer that provides algorithmic methods to make beats, rhythms, noise, what have you. It is also a glorified metronome.
This is not a traditional "drum machine" that is controlled in a mechanical or "arithmetic" sense. It is a drummer, with which you can practice, improvise, compose, record and experiment.
The "beats" are entirely constructed with Perl, and as such, any algorithmic procedure can be used to generate the phrases - Bayesian, stochastic, evolutionary, game simulation, L-system, recursive descent grammar, Markov chain...
Note that you, the programmer (and de facto drummer), should know what the kit elements are named and what the patterns do. For these things, "Use The Source, Luke." Also, check out the included style sub-classes, the eg/* files (and the *.mid files they produce).
The default drum kit is the exciting General MIDI Kit. Fortunately, you can import the .mid file into your DAW and reassign better patches.
METHODS
new
my $d = MIDI::Simple::Drummer->new(%arguments);
Return a new MIDI::Simple::Drummer
instance with these default arguments:
# MIDI parameters:
-channel = 9 # MIDI-perl drum channel
-volume = 100 # 120 max
-pan = 64 # 0L .. 64M .. 127R
-pan_width = 0 # 0 .. 64 from center
-patch = 0 # Drum kit patch number
-reverb = 20 # Effect 0-127
-chorus = 0 # "
# Rhythm metrics:
-accent = 30 # Volume increment
-bpm = 120 # 1 qn = .5 seconds = 500,000 microseconds
-phrases = 4 # Number of groups of measures
-bars = 4 # Number of measures
-beats = 4 # Number of beats in a measure
-divisions = 4 # Note values that "get the beat"
-signature = '' # beats / divisions
# The Goods™
-file => Drummer.mid # Set this to $0.mid, for instance.
-kit => Standard kit set by the API
-patterns => {} # To be filled at run-time
-score => MIDI::Simple->new_score
These arguments can all be overridden in the constuctor with accessors.
volume, pan, pan_width, bpm
$x = $d->method;
$d->method($x);
Return and set the volume, pan, pan_width and beats-per-minute methods.
MIDI pan (CC#10
) goes from 1 left to 127 right. That puts the middle at 63.
phrases, bars, beats, divisions
phrases is the number of bars (or measures) you want to play.
bars is the number of groups of beats you want to play. Each bar is one group of beats.
beats is the number of beats in a bar! This is the numerator of the time signature.
Measures are divided into the number of "note values" that constitute one beat. divisions is this number. It is also known as the denominator of the time signature; the part of the measure that "gets the beat" or simply, "the pulse."
These are all variables that you can use as rhythm metrics to control the groove. They are just numbers, not objects or lists.
signature
Get or set the string ratio of -beats over -divisions.
div_name
The name of the denominator of the time signature.
patch
The drum kit.
1: Standard. 33: Jazz. 41: Brushes. Etc.
channel
Get or set the MIDI channel.
chorus, reverb
Effects 0 (off) to 127 (full)
file
Get or set the name for the .mid file to write.
sync_tracks
Combine beats in parallel with an argument list of anonymous subroutines.
patterns
Return or set known style patterns.
score
$x = $d->score;
$x = $d->score($score);
$x = $d->score($score, 'V127');
$x = $d->score('V127');
Return or set the "score" in MIDI::Simple if provided as the first argument. If there are any other arguments, they are treated as MIDI score settings.
accent_note
$x = $d->accent_note($d->EIGHTH);
Accent a single note.
accent
$x = $d->accent;
Either return the current volume plus the accent increment or set the accent increment. This has an upper limit of MIDI fff.
duck
This is the mirror opposite of the accent
method.
strike
$x = $d->strike;
$x = $d->strike('Cowbell');
$x = $d->strike('Cowbell','Tambourine');
@x = $d->strike('Cowbell','Tambourine');
Return note values for percussion names from the standard MIDI percussion set (with "notenum2percussion" in MIDI) in either scalar or list context. (Default predefined snare patch)
option_strike
$x = $d->option_strike;
$x = $d->option_strike('Short Guiro','Short Whistle','Vibraslap');
Return a note value from a list of patches (default predefined crash cymbals). If another set of patches is given, one of those is chosen at random.
note
$d->note($d->SIXTEENTH, $d->snare);
$d->note('sn', 'n38'); # Same
Add a note to the score. This is a pass-through to "n" in MIDI::Simple.
rest
$d->rest($d->SIXTEENTH);
$d->rest('sn'); # Same
Add a rest to the score. This is a pass-through to "r" in MIDI::Simple.
metronome
$d->metronome;
$d->metronome('Mute Triangle');
Add (beats * phrases) of the Pedal Hi-Hat
, unless another patch is provided.
count_in
$d->count_in;
$d->count_in(2);
$d->count_in(1, 'Side Stick');
And a-one and a-two!</Lawrence Welk> ..11</FZ>
If No arguments are provided, the Closed Hi-Hat
patch is used.
rotate
$x = $d->rotate;
$x = $d->rotate(3);
$x = $d->rotate(5, ['Mute Hi Conga','Open Hi Conga','Low Conga']);
Rotate through a list of patches according to the given beat number. (Default backbeat patches)
backbeat_rhythm
$x = $d->backbeat_rhythm;
$x = $d->backbeat_rhythm(-beat => $y);
$x = $d->backbeat_rhythm(-backbeat => ['Bass Drum 1','Electric Snare']);
$x = $d->backbeat_rhythm(-patches => ['Cowbell','Hand Clap']);
$x = $d->backbeat_rhythm(-tick => ['Claves']);
$x = $d->backbeat_rhythm(-fill => $z);
Add a rotating backbeat to the score.
Arguments:
beat is the beat we are on.
backbeat is the list of patches to use instead of the stock bass and snare.
patches is a list of possible patches to use instead of the crash cymbals.
tick is the patch to use instead of the closed hi-hat.
fill is the fill pattern we last played.
beat
$x = $d->beat;
$x = $d->beat(-name => $n);
$x = $d->beat(-last => $y);
$x = $d->beat(-fill => $z);
$x = $d->beat(-type => 'fill');
Play a beat type and return the id for the selected pattern. Beats and fills are both just patterns but drummers think of them as distinct animals.
This method adds an anecdotal "beat" to the MIDI score. You can indicate that we filled in the previous bar, and do something exciting like crash on the first beat, by supplying the -fill => $z
argument, where $z
is the fill we just played. Similarly, the -last => $y
argument indicates that $y
is the last beat we played, so that we can maintain "context sensitivity."
Unless specifically given a pattern to play with the -name
argument, we try to play something different each time, so if the pattern is the same as the -last
, or if there is no given pattern to play, another is chosen.
For -type => 'fill'
, we append a named fill to the MIDI score.
fill
This is an alias to beat(-type => 'fill')
.
patterns
$x = $d->patterns;
$x = $d->patterns('rock_1');
@x = $d->patterns(
paraflamaramadiddle => \¶flamaramadiddle,
'foo fill' => \&foo_fill,
);
Return or set the code references to the named patterns. If no argument is given, all the known patterns are returned.
write
$x = $d->write;
$x = $d->write('Buddy-Rich.mid');
This is an alias for "write_score" in MIDI::Simple but with unimaginably intelligent bits. It returns the name of the written file if successful. If no filename is given, we use the preset -file
attribute.
KIT ACCESS
kit
$x = $d->kit;
$x = $d->kit('snare');
@x = $d->kit( clapsnare => ['Handclap','Electric Snare'],
kickstick => ['Bass Drum 1','Side Stick']);
@x = $d->kit('clapsnare');
Return or set part or all of the percussion set.
name_of
$x = $d->name_of('kick'); # "Acoustic Bass Drum"
@x = $d->name_of('crash'); # ('Chinese Cymbal', 'Crash Cymbal 1...)
Return the instrument names behind the kit nick-name lists.
hhat
$x = $d->hhat;
$x = $d->hhat('Cabasa','Maracas','Claves');
Strike or set the "hhat" patches. By default, these are the Closed Hi-Hat
, Open Hi-Hat
and the Pedal Hi-Hat.
crash
$x = $d->crash;
$x = $d->crash(@crashes);
Strike or set the "crash" patches. By default, these are the Chinese Cymbal
, Crash Cymbal 1
, Crash Cymbal 2
and the Splash Cymbal.
ride
$x = $d->ride;
$x = $d->ride(@rides);
Strike or set the "ride" patches. By default, these are the Ride Bell
, Ride Cymbal 1
and the Ride Cymbal 2.
tom
$x = $d->tom;
$x = $d->tom('Low Conga','Mute Hi Conga','Open Hi Conga');
Strike or set the "tom" patches. By default, these are the High Tom
, Hi-Mid Tom
, etc.
kick
$x = $d->kick;
$x = $d->kick('Bass Drum 1');
Strike or set the "kick" patch. By default, this is the Acoustic Bass Drum
.
tick
$x = $d->tick;
$x = $d->tick('Mute Triangle');
Strike or set the "tick" patch. By default, this is the Closed Hi-Hat
.
snare
$x = $d->snare;
$x = $d->snare('Electric Snare');
Strike or set the "snare" patches. By default, this is the Acoustic Snare.
backbeat
$x = $d->backbeat;
$x = $d->backbeat('Bass Drum 1','Side Stick');
Strike or set the "backbeat" patches. By default, these are the predefined kick
and snare
patches. But if the time signature is a multiple of three, the backbeat is set to a "kick snare kick" pattern.
CONVENIENCE METHODS
These are meant to avoid literal strings and the need to remember and type the relevant MIDI variables.
WHOLE or _1st
$x = $d->WHOLE;
$x = $d->_1st;
Return 'wn'
.
HALF or or _2nd
Return 'hn'
.
QUARTER or _4th
Return 'qn'
.
EIGHTH or _8th
Return 'en'
.
SIXTEENTH or _16th
Return 'sn'
.
THIRTYSECOND or _32nd
Return 'yn'
.
SIXTYFOURTH or _64th
Return 'xn'
.
_p2n
Return %MIDI::percussion2notenum
a la "GOODIES" in MIDI.
_n2p
Return the inverse: %MIDI::notenum2percussion
.
_default_patterns
Patterns provided by default. This is {}
, that is, nothing. This is defined in a MIDI::Simple::Drummer::* style package.
_default_kit
Kit provided by default. This is a subset of the exciting general MIDI kit. This can also be defined in a MIDI::Simple::Drummer::* style package, to use better patches.
SEE ALSO
The eg/* and t/* files, that come with this distribution
The MIDI::Simple::Drummer::* styles
MIDI::Simple itself
MIDI::Drummer::Tiny - A Moo-based simplified drum module
https://en.wikipedia.org/wiki/General_MIDI#Percussion
TO DO
Be smart about swing timing (e.g. $d->TRIPLET_XXXX).
Handle double and half time (via DIVISION hashref).
Use "relative rhythm metrics" if given a time signature.
Use "quantize" in MIDI::Score?
Keep a running clock/total to know where we are in time, at all times.
Intelligently modulate dynamics to add nuance and "humanize."
Make a MIDI::Simple::Drummer::AC\x{26A1}DC
(Phil Rudd) style.
Leverage "from_drum_tab" in MIDI::Tab or "read_score" in MIDI::Simple?
CREDITS
Paul Evans <leonerd@leonerd.org.uk<gt> for help understanding constant importing.
Kevin Goroway <kgoroway@yahoo.com<gt> for asking where the time signature was and if the rudiments package was going to happen.
Jeremy Mates for the clever Euclidian rhythm algorithm.
AUTHOR
Gene Boggs <gene@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2009-2023 by Gene Boggs.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.