NAME

MIDI::RtController::Filter::CC - Control-change based RtController filters

VERSION

version 0.0908

SYNOPSIS

use curry;
use MIDI::RtController ();
use MIDI::RtController::Filter::CC ();

my $control = MIDI::RtController->new(
  input  => 'keyboard',
  output => 'usb',
);

my $filter = MIDI::RtController::Filter::CC->new(rtc => $control);

$filter->control(1); # CC#01 = mod-wheel
$filter->channel(0);
$filter->range_bottom(10);
$filter->range_top(100);
$filter->range_step(2);
$filter->time_step(0.25);

$control->add_filter('breathe', all => $filter->curry::breathe);

$control->run;

DESCRIPTION

MIDI::RtController::Filter::CC is a (growing) collection of control-change based MIDI::RtController filters.

Passing all to the add_filter method means that any MIDI event will trigger the filter.

In order to stop a running filter, send a CTRL-C to the console... Halting midstream, with logic, is not yet happening.

Making filters

All filter methods must accept the object, a MIDI device name, a delta-time, and a MIDI event ARRAY reference, like:

sub breathe ($self, $device, $delta, $event) {
  return 0 if $self->running;
  my ($event_type, $chan, $control, $value) = $event->@*;
  ...
  return $boolean;
}

A filter also must return a boolean value. This tells MIDI::RtController to continue processing other known filters or not.

ATTRIBUTES

rtc

$rtc = $filter->rtc;

The required MIDI::RtController instance provided in the constructor.

channel

$channel = $filter->channel;
$filter->channel($number);

The current MIDI channel value between 0 and 15.

Default: 0

control

$control = $filter->control;
$filter->control($number);

Return or set the control change number between 0 and 127.

Default: 1 (mod-wheel)

value

$value = $filter->value;
$filter->value($number);

Return or set the MIDI event value. This is a generic setting that can be used by filters to set or retrieve state. This often a whole number between 0 and 127, but can take any number.

Default: undef

trigger

$trigger = $filter->trigger;
$filter->trigger($number);

Return or set the trigger. This is a generic setting that can be used by filters to set or retrieve state. This often a whole number between 0 and 127, but can take any number.

Default: undef

initial_point

$initial_point = $filter->initial_point;
$filter->initial_point($number);

Return or set the control change initial point number between 0 and 127.

Default: 0

range_bottom

$range_bottom = $filter->range_bottom;
$filter->range_bottom($number);

The current iteration lowest number value.

Default: 0

range_top

$range_top = $filter->range_top;
$filter->range_top($number);

The current iteration highest number value.

Default: 127

range_step

$range_step = $filter->range_step;
$filter->range_step($number);

A number greater than zero representing the current iteration step size between bottom and top.

Default: 1

time_step

$time_step = $filter->time_step;
$filter->time_step($number);

The current iteration step in seconds (probably fractions).

Default: 0.25 (a quarter of a second)

step_up

$step_up = $filter->step_up;
$filter->step_up($number);

The current iteration upward step.

Default: 2

step_down

$step_down = $filter->step_down;
$filter->step_down($number);

The current iteration downward step.

Default: 1

running

$running = $filter->running;
$filter->running($boolean);

Are we running a filter?

Default: 0

METHODS

new

$filter = MIDI::RtController::Filter::CC->new(%arguments);

Return a new MIDI::RtController::Filter::CC object.

UTILITIES

add_filters

MIDI::RtController::Filter::CC::add_filters(\@filters, $controllers);

Add an array reference of filters to controller instances. For example:

[
  { # mod-wheel
    port => 'keyboard',        # what device is controlling
    type => 'breathe',         # the type of filter
    event => 'control_change', # or [qw(note_on note_off)] etc
    control => 1,              # what CC# is being controlled
    trigger => 25,             # what CC# triggers the controlling
    time_step => 0.25,         # a module attribute parameter
  },
  ...
]

In this list, port and type are required, and event is optional. These keys are metadata, and all others are assumed to be object attributes to set.

The controllers come from "open_controllers" in MIDI::RtController and is a hash reference of MIDI::RtController instances keyed by MIDI input device port names.

FILTERS

single

$control->add_filter('single', all => $filter->curry::single);

This filter sets a single control change message, over the MIDI channel.

If trigger is set, the filter checks that against the MIDI event note to see if the filter should be applied.

breathe

$control->add_filter('breathe', all => $filter->curry::breathe);

This filter sets the running flag, then iterates between the range_bottom and range_top by range_step increments, sending a control change message, over the MIDI channel every iteration.

Passing all means that any MIDI event will cause this filter to be triggered.

If trigger or value is set, the filter checks those against the MIDI event note or value, respectively, to see if the filter should be applied.

scatter

$control->add_filter('scatter', all => $filter->curry::scatter);

This filter sets the running flag, chooses a random number between the range_bottom and range_top, and sends that as the value of a control change message, over the MIDI channel, every iteration.

The initial_point is used as the first CC# message, then the randomization takes over.

If trigger or value is set, the filter checks those against the MIDI event note or value, respectively, to see if the filter should be applied.

stair_step

$control->add_filter('stair_step', all => $filter->curry::stair_step);

This filter sets the running flag, uses the initial_point for the fist CC# message, then adds step_up or subtracts step_down from that number successively, sending the value as a control change message, over the MIDI channel, every iteration.

If trigger or value is set, the filter checks those against the MIDI event note or value, respectively, to see if the filter should be applied.

ramp_up

$control->add_filter('ramp_up', all => $filter->curry::ramp_up);

This filter ramps-up a control change message, over the MIDI channel, from range_bottom until the range_top is reached.

If trigger or value is set, the filter checks those against the MIDI event note or value, respectively, to see if the filter should be applied.

ramp_down

$control->add_filter('ramp_down', all => $filter->curry::ramp_down);

This filter ramps-down a control change message, over the MIDI channel, from range_top until the range_bottom is reached.

If trigger or value is set, the filter checks those against the MIDI event note or value, respectively, to see if the filter should be applied.

SEE ALSO

The eg/*.pl program(s) in this distribution

MIDI::RtController::Filter::Tonal - Related module

MIDI::RtController::Filter::Math - Related module

MIDI::RtController::Filter::Drums - Related module

IO::Async::Timer::Periodic

Iterator::Breathe

MIDI::RtController

Moo

Types::MIDI

Types::Common::Numeric

Types::Standard

AUTHOR

Gene Boggs <gene.boggs@gmail.com>

COPYRIGHT AND LICENSE

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