#!/usr/local/bin/tclmidi
#
#	mid2sapp
#	$Id: mid2sapp,v 1.3 1995/09/17 00:09:37 white Exp white $
#
#	Attempt to turn a midi song into sapphire
#	Requires the tclmidi package
#
#	Usage: mid2sapp filename >textfile
#
#	Written by J.Finnis (white@elf.dircon.co.uk)
#	Thanks to Andrew Bulhak
#
#	Generates playnote commands for instance inst<n>,
#	where <n> is the track number. Supports any number
#	of tracks.
#	You'll have to add instance definitions yourself,
#	and an include of Equal440.sc.
#
#	Reads a configuration file, mid2sapp.cnf (if present)
#	which contains the following lines:
#
#	DrumTrack <n> : 
#		specifies that <n> is a drum track, indicating that
#		each key has a different, unpitched sound. Rather than
#		generating "playnote <key> on instance inst<n>",
#		mid2sapp will generate
#		"playnote C3 on instance druminst<key>"
#
#

set confname "mid2sapp.cnf"

set notenames {c c# d d# e f f# g g# a a# b C}
set drumtracks {}
set offset 0

if [file exists $confname] {
	set conff [open $confname r]
	while {![eof $conff]} {
		set conline [split [gets $conff]]
		switch [lindex $conline 0] {
			"DrumTrack" { lappend drumtracks [lindex $conline 1] }
		}
	}
}

foreach a $argv {
	set val 0
	if {[string index $a 0]	== "-"} {
		if {[string length $a] > 2} {set val [string range $a 2 end]}
		switch [string index $a 1] {
			"o"	{set offset $val}
			default { error "bad command line argument $a"}
		}
	} else { set fname $a}
}


set f [open $fname r]
set mf [midiread $f]
midirewind $mf
puts "-- Sapphire score generated from $fname by mid2sapp \$Revision: 1.3 $"

puts "-- drum tracks : $drumtracks, offset : $offset"

set config [midiconfig $mf tracks division format]
set tracks [lindex [lindex $config 0] 1]
set division [lindex [lindex $config 1] 1]
set format [lindex [lindex $config 2] 1]
set tempodone 0
set maxn 0
for {set i 0} {$i < $tracks} {incr i} {
	puts ""
	while {[set event [midiget $mf $i next]] != "EOT"} {
		set t [expr [lindex $event 0] + $offset * 64]
		switch [lindex $event 1] {
		"Note" {
			set p [lindex $event 3]
			set vel [expr [lindex $event 4].0 / 128]
			set duration [lindex $event 5]
			set tmp [expr $t + $duration]
			if {$tmp > $maxn} { set maxn $tmp }
			set inst [lindex $event 2]
			if {[lsearch $drumtracks $inst] != -1} {
				puts "note /00:00:$t/ druminst$p Equal440 C3 /00:00:$duration/ $vel;"
			} else {
				set oct [expr $p / 12 - 3]
				set nt [lindex $notenames [expr $p % 12]]
				puts "note /00:00:$t/ inst$inst Equal440 $nt$oct /00:00:$duration/ $vel;"}
			}
		"MetaTempo" {set tmp [lindex $event 2]
			if {$tempodone} {
				puts "-- WARNING - tempo change to $tmp at $t"
			} else {puts "tempo $tmp;" 
			set tempodone 1}}
		"MetaTime" {set sig1 [lindex $event 2]
			set sig2 [lindex $event 3]
			puts "signature $sig1 $sig2;"}
		"MetaEndOfTrack" {}
		"MetaKey" {}
		"MetaSequencerSpecific" {}
		default {puts "--OTHER : $event"}
		}
	}
}
puts "end at /00:00:$maxn/;"
midifree $mf
close $f