Skip to content

Instantly share code, notes, and snippets.

@jonathanstowe
Last active April 18, 2016 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathanstowe/0354b13c3eac263560ddef44c2b2e4fe to your computer and use it in GitHub Desktop.
Save jonathanstowe/0354b13c3eac263560ddef44c2b2e4fe to your computer and use it in GitHub Desktop.
#!perl6
use Audio::PortMIDI;
sub MAIN(Int :$samplerate = 44100, Int :$frequency = 440, Int :$channel = 9, Int :$device = 3, Int :$bpm = 120, :$part) {
my $event-type = NoteOn;
my $pm = Audio::PortMIDI.new;
my $stream = $pm.open-output($device, 32);
my @notes;
for $part.list -> $data-one {
if $data-one.defined {
@notes.append: Audio::PortMIDI::Event.new(:$event-type, :$channel, :$data-one, data-two => 127, timestamp => 0),
}
}
sub bits(Int $bits, Int $i where { $_ < 2**$bits }) {
my @bits;
for ^$bits -> $j {
my $k = ( $bits - 1) - $j;
@bits[$k] = ($i +& ( 1 +< $j)) ?? 1 !! 0;
}
@bits;
}
sub get-pos(Int() $gen, Int $samplerate, Int $frequency) {
bits(8,((sin(($gen/($samplerate/$frequency)) * (2 * pi)) * 127) + 127).Int)
}
my $sec = 60/($bpm * 4);
my $inc = $samplerate * $sec;
my $pos = 0;
react {
whenever Supply.interval($sec) {
my @bits = get-pos($pos, $samplerate, $frequency);
say @bits;
my Audio::PortMIDI::Event @instrs;
for ^8 -> $i {
if @bits[$i] && @notes[$i].defined {
@instrs.append: @notes[$i];
}
}
$stream.write(@instrs);
$pos += $inc;
}
}
}
# vim: expandtab shiftwidth=4 ft=perl6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment