Midi to Csound code for Charles Cave as promised
[email protected] (Dave Turner) Fri, 20 Jun 2003 20:37:41 +0000
| Newsgroups | perl.midi |
|---|---|
| Message-ID | <a05100304bb191df6a821@[81.174.192.245]> |
Charles,
the code below works, and with more effort on my part would need no
human intervention on the csound-ish file it produces. Great minds
think alike, so far a number of years now I have been happily using
note names in exactly the same way that Sean has in my csound include
files so MIDI::number2note does exactly what I need it to.
I have no idea what a MUP file looks like, but now you have seen what
I have done you should be able to work out what you need to do.
DaveT
#!perl
# midi2csound this converts the midi track to a Csound score
# and might in the future create a crude orc file to go with it
# using MacPerl 5.6.1r2 for Mac OS 9.2.2
use warnings;
use strict;
use MIDI;
my $DRIVE = 'Stuff:';
my $PATH = 'temptemp:';
my $MIDI = 'old_100th0.mid'; # I had to convert the type 1 midi file
to a Type 0 midi file
my $SCO = $MIDI.'.sco'; # needs code to remove the .mid and replace
it with .sco
my $BUF;
my $IN_FILE = $DRIVE.$PATH.$MIDI;
my $opus = MIDI::Opus->new({ 'from_file' => $IN_FILE });
my $event_r = $opus->tracks_r->[0]->events_r;
my $score_r = MIDI::Score::events_r_to_score_r($event_r);
=item MIDI vs Csound
the notes look like this:-
['note', 1006, 93, 2, 83, 123],
'note', start_time, duration, channel, midi_note, velocity
csound looks like this:-
i1 0.17083 0.1500 220.00000 32131
instrument start_time, duration, frequency, loudness
1) each channel is deemed to be one instrument, worry about patch changes later
2) we need to convert the midi note number to a frequency
use the array @MIDI::number2note from MIDI.pm
12_TET.sco will convert the note name to
frequency for us
3) we need the number of ticks to calculate note durations
4) 32131 / 127 = 253
so multiply the velocity by 253 to get loudness
the above line from MIDI score would become:-
i2 1006/ticks 93/ticks 83=B6 123*253
$score_r IS the score I want to mess with.
How do I get at it, 1 line at a time?
=cut
$BUF = dump_score_to_file( $score_r);
print "file $DRIVE$PATH$SCO created \n";
###########################################################################
sub dump_score_to_file {
my $score_r = $_[0];
open(OUT,">>", $DRIVE.$PATH.$SCO); # create or append newfile
print OUT ";produced from $DRIVE$PATH$MIDI using midi2csound.pl \n" ;
print OUT ";\@notes = # ", scalar(@$score_r), " notes...\n";
foreach my $note_r (@$score_r) {
if ( ${ $note_r } [0] eq 'note' ) { # it is a note - deal with it
print OUT 'i' ;
print OUT ${ $note_r } [3] + 1; # channel number becomes
instrument number
print OUT ' ';
print OUT ${ $note_r } [1] / 384; # note start time (yes 384
is a 'magic' number!)
print OUT ' ';
print OUT ${ $note_r } [2] / 384; # note duration
print OUT ' ';
print OUT ( $MIDI::number2note{ ${ $note_r } [4] } ) ; # the actual note
print OUT ' ';
print OUT (${ $note_r } [5] * 253) ; # note loudness
print OUT "\n";
}
else { # comment out anything not a note
print OUT ';' ;
print OUT " [", &MIDI::_dump_quote(@$note_r), "],\n" if @$note_r;
}
} # end of foreach
print OUT "e \n";
close(OUT);
return;
} # end of sub dump_score_to_file
###########################################################################
exit;