💾 Archived View for thrig.me › blog › 2023 › 08 › 11 › midiwarble.pl captured on 2023-09-08 at 17:06:59.
-=-=-=-=-=-=-
#!/usr/bin/env perl # midiwarble - how does the pitch_wheel_change thing even work? map a # sin() function to pitch_wheel_change events so that the effect can be # heard and different devices tested. the actual message splits the # value across two bytes, and some devices may only use some portion of # those bytes use 5.36.0; use Getopt::Long 'GetOptions'; use Math::Trig ':pi'; use MIDI; # ranges for some of these are detailed in the MIDI::Event docs. the # patch should be instruments that sustain (woodwinds, strings) and # probably not the wood block or snare drum # # things to check here include how small can range be before you can't # hear the changes, what happens as you maximize the range, what # different patch sound like, what happens when the step is tiny but the # range very large, etc my $chan = 0; # MIDI channel my $circle = 12; # how many $step to complete a circle my $midinum = 69; # A note my $patch = 16; # drawbar organ my $range = 1000; # -8192 .. 8191, though see the MIDI docs my $repeat = 3; # how many times to go through a circle my $step = 24; # MIDI dtime between wheel change events my $ticks = 96; # some MIDI thing my $velocity = 120; # pretty loud GetOptions( 'circle=i' => \$circle, 'channel=i' => \$chan, 'patch=i' => \$patch, 'pitch=i' => \$midinum, 'range=i' => \$range, 'step=i' => \$step, 'ticks=i' => \$ticks, 'velocity=i' => \$velocity, ) or exit 64; my $file = shift // 'out.midi'; my @events = ( [ 'patch_change', 0, $chan, $patch ], [ 'note_on', 0, $chan, $midinum, $velocity ] ); my $when = 0; my $whole = $step * $circle; my $max = $whole * $repeat; while ( $when <= $max ) { my $wheel = $range * sin( $when * pi2 / $whole ); # timidity shows text_event so those may be good to mark when the # wheel is what, but fluidsynth (or at least my wrapper for it) does # not show those push @events, [ 'pitch_wheel_change', $step, $chan, $wheel ]; $when += $step; } push @events, [ 'note_off', $step, $chan, $midinum, 0 ]; MIDI::Opus->new( { format => 0, ticks => $ticks, tracks => [ MIDI::Track->new( { events => \@events } ) ] } )->write_to_file($file);