NAME

Music::SimpleDrumMachine - Simple 16th-note-phrase Drummer

VERSION

version 0.0509

SYNOPSIS

use Music::SimpleDrumMachine ();

my $dm = Music::SimpleDrumMachine->new( # use defaults
  port_name => 'midi device', # required
);

# OR:
$dm = Music::SimpleDrumMachine->new(
  port_name => 'midi device',
  bpm       => 100,
  parts     => {
      part_A => \&part_A,
      part_B => \&part_B,
  },
  next_part => 'part_A',
  fills     => { fill_A => \&fill_A },
  next_fill => 'fill_A',
  verbose   => 1,
);

sub part_A {
    print "part A\n";
    my %patterns = (
        closed => [qw(1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0)],
        kick   => [qw(1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1)],
        snare  => [qw(0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0)],
    );
    my $next = 'part_B';
    return $next, \%patterns;
}
sub part_B {
    print "part B\n";
    my %patterns = (
        closed => [qw(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)],
        kick   => [qw(1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0)],
        snare  => [qw(0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0)],
    );
    my $next = 'part_A';
    return $next, \%patterns;
}
sub fill_A {
    print "Fill A\n";
    my %patterns = (
        snare => [qw(1 0 1 0 1 1 1 1 0 1 0 1 1 0 1 0)],
    );
    my $next = 'fill_A';
    return $next, \%patterns;
}

DESCRIPTION

Music::SimpleDrumMachine is a simple 16th-note-phrase drummer. By invoking this module, your MIDI device will begin playing in real-time.

* Triplets are not supported. Boo!

* Use the extra-handy eg/list_devices.pl program to see the names of the open MIDI ports on the system.

ATTRIBUTES

add_drums

add_drums => \%drums,

Add an array-ref of hash-refs of the form [{ drum => 'name', num => midi_num, chan => channel }] to the known drums in the constructor. The chan key is optional and is only necessary if you want to assign a drum to a specific channel.

beats

$beats = $dm->beats;

The number of beats in a phrase.

Default: 16

bpm

$bpm = $dm->bpm;

The beats per minute.

Default: 120

chan

$chan = $dm->chan;

The MIDI channel.

If the channel is set to -1, multi-timbral mode is turned on and channels 0, 1, ... and up are used, instead of a single channel for all the percussion.

Default: 9

divisions

$divisions = $dm->divisions;

The number of divisions of a quarter-note into the number of beat-notes. For the default, this is the number of divisions of a quarter-note to get 16ths.

Default: 4

drums

$drums = $dm->drums;
$dm->drums($drums);

The known drums (with short, abbreviated names that I made up).

Default:

kick         => 36 # Bass Drum 1
snare        => 38 # Acoustic Snare
closed       => 42 # Closed Hi Hat
fillcrash    => 49 # Crash Cymbal 1
open         => 46 # Open Hi Hat
rimshot      => 37 # Side Stick
clap         => 39 # Hand Clap
shaker       => 70 # Maracas
cowbell      => 56 # Cowbell
crash        => 57 # Crash Cymbal 2
hi_tom       => 48 # Hi Mid Tom
mid_tom      => 47 # Low Mid Tom
low_tom      => 45 # Low Tom
conga        => 63 # Open Hi Conga
kick2        => 35 # Acoustic Bass Drum
snare2       => 40 # Electric Snare
pedal        => 44 # Pedal Hi Hat
low_floor    => 41 # Low Floor Tom
hi_floor     => 43 # High Floor Tom
hihi_tom     => 50 # High Tom
ride         => 51 # Ride Cymbal 1
ride_bell    => 53 # Ride Bell
ride2        => 59 # Ride Cymbal 2
china        => 52 # Chinese Cymbal
splash       => 55 # Splash Cymbal
tamborine    => 54 # Tambourine
vibraslap    => 58 # Vibraslap
hi_bongo     => 60 # Hi Bongo
low_bongo    => 61 # Low Bongo
mute_conga   => 62 # Mute Hi Conga
low_conga    => 64 # Low Conga
hi_timbale   => 65 # High Timbale
low_timbale  => 66 # Low Timbale
hi_agogo     => 67 # High Agogo
low_agogo    => 68 # Low Agogo
cabasa       => 69 # Cabasa
whistle      => 71 # Short Whistle
long_whistle => 72 # Long Whistle
guiro        => 73 # Short Guiro
long_guiro   => 74 # Long Guiro
claves       => 75 # Claves
wood_block   => 76 # Hi Wood Block
low_block    => 77 # Low Wood Block
mute_cuica   => 78 # Mute Cuica
open_cuica   => 79 # Open Cuica
mute_tri     => 80 # Mute Triangle
open_tri     => 81 # Open Triangle

But literally any name could be used, as long as the number is a known MIDI percussion instrument number.

fill_crash

$fill_crash = $dm->fill_crash;
$dm->fill_crash($boolean);

Should we crash after a fill?

Default: 1

fills

$fills = $dm->fills;
$dm->fills($fills);

List of named code-refs of the fills to play.

Default: { _default_fill => \&_default_fill }

filling

$filling = $dm->filling;
$dm->filling($boolean);

Should we fill between parts?

Default: 1

next_fill

$next_fill = $dm->next_fill;
$dm->next_fill($next_fill);

Name of the fill to play first and set subsequently in a fill.

Default: '_default_fill'

next_part

$next_part = $dm->next_part;
$dm->next_part($next_part);

Name of the part or list of parts to play first and also set subsequently in a part.

If this is an array-reference, the named parts or fills are played in succession.

Default: '_default_part'

notes

$notes = $dm->notes;
$dm->notes($notes);

The notes to set for each drum - why not?

Default: [60, 64, 67]

parts

$parts = $dm->parts;
$dm->parts($parts);

List of named code-refs of the parts to play.

If a part has 'fill' in the name, it will be played for a single bar, on the 3rd bar of a 4-bar phrase iff the filling attribute is set to zero.

Default: { _default_part => \&_default_part }

port_name

$port = $dm->port_name;

The name of the MIDI output port. This can be the full name or a unique part of the name, like 'usb' for 'USB MIDI Interface', for instance. Case is ignored.

Default: usb

ppqn

$ppqn = $dm->ppqn;

The "pulses per quarter-note" or "clocks per beat."

Default: 24

prefill_part

$prefill_part = $dm->prefill_part;

Code-ref of the part to play for 1/2-bar fills.

Default: \&_default_part

velo_max

$velo_max = $dm->velo_max;
$dm->velo_max($max);

The maximum allowed relative velocity from the velo_off offset.

Default: 10

velo_min

$velo_min = $dm->velo_min;
$dm->velo_min($min);

The minimum allowed relative velocity from the velo_off offset.

Default: -10

velo_off

$velo_off = $dm->velo_off;
$dm->velo_off($offset);

The velocity offset.

Default: 110

verbose

$verbose = $dm->verbose;

Show progress.

Default: 0

METHODS

new

$dm = Music::SimpleDrumMachine->new(%arguments);

Create a new Music::SimpleDrumMachine object.

velocity

$dm->velocity;

Return a random velocity between the velo_min (minimum) and velo_max (maximum), starting at the velo_off offset.

So, for -10, 10, 110 (the default), a number between 100 and 120 will be returned. The triple 0, 0, 127 will return 127 every time.

SEE ALSO

The eg/*.pl programs in this distribution.

IO::Async::Loop

IO::Async::Timer::Periodic

MIDI::RtMidi::FFI::Device

Moo

Music::Duration::Partition

AUTHOR

Gene Boggs <gene.boggs@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 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.