Jason (jcreed) wrote,
Jason
jcreed

So, I never really got into windows programming much during my youth — by the time I actually knew how to program, I was mostly using Linux — so it's an amusing exercise to mess around with little corners of the Windows API, like for instance MIDI I/O. It's far less scary than I thought.

The following C program just dumps MIDI messages to stdout:
#include <windows.h>

void CALLBACK callback(HMIDIIN handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) {
  if (uMsg == MIM_DATA) {
    printf( "%ld %d %d %d\n", dwParam2,  dwParam1 & 0x000000FF, (dwParam1>>8) & 0x000000FF, (dwParam1>>16) & 0x000000FF);
    fflush(0);
  }
}

int main(void) {
  HMIDIIN inHandle;

  if (midiInOpen(&inHandle, 0, (DWORD)callback, 0, CALLBACK_FUNCTION)) {
    printf("There was an error opening the default MIDI In device!\n");
    exit(1);
  }
  midiInStart(inHandle);
  while(1) { Sleep(1000); }
}

and using some (sigh) perl module that someone wrote years ago, it is disgustingly convenient to transform this into a standard midi file:

#!/usr/bin/perl

use MIDI;
use strict;
use warnings;

my $patch = 0;
my $bank = 0;
my $curt = 0;

my @events = (['set_tempo', 0, 500_000], 
	      ['control_change', 0, 0, 0, $bank],
	      ['patch_change', 0, 0, $patch],
	      );

while (<>) {
    chomp;
    my ($t, $code, $note, $vel) = split;
    my $delta = int(($t - $curt) );
    if ($code == 144) { # note on
	push @events, ['note_on', $delta, 0, $note, $vel];
    }
    if ($code == 176) { # control change
	push @events, ['control_change', $delta, 0, $note, $vel];
    }
    $curt = $t;
}

my $opus = MIDI::Opus->new({ 'ticks' => 500, 'tracks' => [ MIDI::Track->new({ 'events' => \@events }) ] } );
$opus->write_to_handle( *STDOUT{IO} );


The only tricky things were finding out that I needed to link to libwinmm to compile the C program under msys, and understanding the crazy midi "ticks" field and what I needed to set it to in order to make ticks = milliseconds.

Clearly the thing to do is wrap this all in some saner language...

Anyway, here is a quick recording of the head of "Blue Monk".
Tags: music, programming
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments