💾 Archived View for thrig.me › blog › 2023 › 08 › 11 › whee.pl captured on 2024-05-10 at 12:21:49.

View Raw

More Information

⬅️ Previous capture (2023-09-28)

-=-=-=-=-=-=-

#!/usr/bin/env perl
# whee.pl - experiment with the MIDI pitch_wheel_change thing
use 5.36.0;
use MIDI;
sub CHAN ()  { 0 }
sub NOW ()   { 0 }
sub QUIET () { 0 }

my $file = shift // 'out.midi';

# 500_000 is 120 - 400_000 is 150 and 460 seems about right?
my @Events = [ set_tempo => NOW, 460_000 ];

# a little bit of velocity randomization
sub velo { 96 + int( rand 4 + rand 4 + rand 4 ) }

# first pitch is held constant, second is stretched up and then back
# down. Meshuggah does something like this in "Bleed"
sub pitch_mangle ( $p1, $p2, $step = 2048, $delta = 24 ) {
    my $wheel = 0;
    while ( $wheel < 8191 ) {
        push @Events,
          [ pitch_wheel_change => NOW, CHAN, 0 ],
          [ note_on            => NOW, CHAN, $p2, velo ],
          [ note_off           => $delta, CHAN, $p2, QUIET ],
          [ pitch_wheel_change => NOW, CHAN, $wheel ],
          [ note_on            => NOW, CHAN, $p1, velo ],
          [ note_off           => $delta, CHAN, $p1, QUIET ];
        $wheel += $step;
    }
    $wheel = 8191;
    while ( $wheel > 0 ) {
        push @Events,
          [ pitch_wheel_change => NOW, CHAN, $wheel ],
          [ note_on            => NOW, CHAN, $p2, velo ],
          [ note_off           => $delta, CHAN, $p2, QUIET ],
          [ pitch_wheel_change => NOW, CHAN, 0 ],
          [ note_on            => NOW, CHAN, $p1, velo ],
          [ note_off           => $delta, CHAN, $p1, QUIET ];
        $wheel -= $step;
    }
}

while ( readline *DATA ) {
    next if m/^\s*$/;
    if (m/^(\d+) (\d+)/a) {
        pitch_mangle( $1, $2 );
    } else {
        die "dunno: $_\n";
    }
}

MIDI::Opus->new(
    { tracks => [ MIDI::Track->new( { events => \@Events } ) ] } )
  ->write_to_file($file);

# the pitch pairs. with more work these could be note names that get
# changed into suitable MIDI pitch numbers, or they could be read in
# from standard input, etc
__DATA__
69 69
69 69
69 72
69 74
69 76
69 76
69 81
69 81

76 76
76 79
76 76
76 79
69 81
69 81
76 77
76 77

74 76
74 76
76 77
76 77
69 76
69 81
69 76
69 81

69 76
69 74
68 76
67 71
66 69
65 72
64 67
64 69