NAME

MIDI::RtMidi::ScorePlayer - Play a MIDI score in real-time

VERSION

version 0.0202

SYNOPSIS

use MIDI::RtMidi::ScorePlayer ();
use MIDI::Util qw(setup_score);

my $score = setup_score();

# arguments given to the part functions
my %common = (score => $score, seen => {}, etc => '...',);

# 2 measure parts
sub treble {
    my (%args) = @_;
    ...; # Setup things
    my $treble = sub {
        for my $i (1 .. 8) {
            if ($i % 2) {
                $args{score}->n('qn', '...');
            }
            else {
                $args{score}->r('qn', '...');
            }
        }
    };
    return $treble;
}
sub bass {
    my (%args) = @_;
    # to play alone, this is needed:
    $common{'tick.durations'} = [ ('hn') x 4 ];
    my $bass = sub {
    ...; # As above but different!
    };
    return $bass;
}

MIDI::RtMidi::ScorePlayer->new(
    score    => $score, # required MIDI score object
    parts    => [ \&bass, [ \&treble, \&bass ], \&bass ], # required part functions
    common   => \%common, # arguments given to the part functions
    repeats  => 4, # number of repeated synched parts (default: 1)
    sleep    => 2, # number of seconds to sleep between loops (default: 1)
    loop     => 4, # loop limit if finite (default: 1)
    infinite => 0, # loop infinitely (default: 1)
    deposit  => 'path/prefix-', # optionally make a file after each loop
    verbose  => 0, # print out text events (default: 0)
    dump     => 0, # dump the score before each play (default: 0)
)->play;

DESCRIPTION

MIDI::RtMidi::ScorePlayer plays a MIDI score in real-time.

In order to use this module, create subroutines for simultaneous MIDI parts that take a common hash of named arguments. These parts each return an anonymous subroutine that tells MIDI-perl to build up a score, by adding notes (n()) and rests (r()), etc. These musical operations are described in the MIDI modules, like MIDI::Simple.

Besides being handed the common arguments, each part function gets a handy, increasing _part number, starting at one, which can be used in the part functions. These parts are synch'd together, given the new parameters that are described in the example above.

If you wish to set the patch or channel for a part, do so inside the scope of the coderef that is returned by the part.

If you wish to play a single part, include it in the parts list by itself (i.e. not with any other tracks), AND tell MIDI::RtMidi::ScorePlayer how long (in musical durations) the part is, by adding tick.durations to the common set of part arguments. To play multiple parts simultaneously, add them to an array reference in the parts list.

Hints

Linux: If your distro does not install a service, you can use FluidSynth: fluidsynth -a alsa -m alsa_seq some-soundfont.sf2 Or try Timidity in daemon mode: timidity -iAD, but YMMV, TBH.

MacOS: You can use FluidSynth like this: fluidsynth -a coreaudio -m coremidi some-soundfont.sf2 Also, you can use Timidity, as above. A digital audio workstation (DAW) like Logic, with a software synth track selected, should work. And if you wish, you can get General MIDI with a "DLSMusicDevice" track open, and a soundfont in ~/Library/Audio/Sounds/Banks/. Make sure the soundfont is selected for the track.

Windows: This should just work out of the box.

METHODS

new

Instantiate a new MIDI::RtMidi::ScorePlayer object.

play

Play a given MIDI score in real-time.

SEE ALSO

Examples are the eg/* files in this distribution.

Also check out the t/01-methods.t file for basic usage.

MIDI::RtMidi::FFI::Device

MIDI::Util

Time::HiRes

AUTHOR

Gene Boggs <gene.boggs@gmail.com>

COPYRIGHT AND LICENSE

This software is Copyright (c) 2024 by Gene Boggs.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)