Skip to content

Instantly share code, notes, and snippets.

@und3f
Created May 3, 2012 11:29
Show Gist options
  • Save und3f/2585104 to your computer and use it in GitHub Desktop.
Save und3f/2585104 to your computer and use it in GitHub Desktop.
MIDI interface to the internal speaker
#!/usr/bin/env perl
use strict;
use warnings;
use Audio::Beep;
use MIDI::ALSA qw(
SND_SEQ_EVENT_NOTEON
SND_SEQ_EVENT_NOTEOFF
SND_SEQ_EVENT_PORT_UNSUBSCRIBED);
MIDI::ALSA::client('Midi2Speaker', 1, 0, 0);
my $duration = shift || 20;
my @notes;
my $current_note = 0;
while (1) {
&process_midi_event while MIDI::ALSA::inputpending;
if (@notes) {
$current_note = ($current_note + 1) % @notes;
beep($notes[$current_note], $duration);
}
}
sub calculate_pitch($) {
my $note = shift;
return (440 * 2**($note / 12.0 - 4));
}
sub process_midi_event {
my ($event, $data) = (MIDI::ALSA::input())[0, 7];
if ($event == SND_SEQ_EVENT_NOTEON()) {
my ($channel, $note) = @$data;
push @notes, calculate_pitch $note;
}
elsif ($event == SND_SEQ_EVENT_NOTEOFF) {
my ($channel, $note) = @$data;
my $pitch = calculate_pitch $note;
for (my $i = 0; $i < scalar @notes; ++$i) {
if ($notes[$i] == $pitch) {
splice @notes, $i, 1;
--$current_note if $i >= $current_note;
last;
}
}
}
elsif ($event == SND_SEQ_EVENT_PORT_UNSUBSCRIBED) {
@notes = ();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment