START ESCWYP MUSIC VIDEOS
This is a Perl script to generate pictures from MIDI files. MIDI files contain a
computer readable descripton of musical pieces. Music can be seen as a series of
notes. From this series you can make statistic measurements, like the porbability
for one note, say C following another note, say F. These probabilities for all
possible combinations of notes can be represented as a Matrix, which in turn can be 
represented as a picture, where diffrent colours correspond to different probabilities.
You will need some Perl libraries to run the script:
MIDI, Math::MatrixReal, Image::Imlib2, Math::Gradient, Image::Magick, PDL.
And in the directory where you call the script you need the files
klavl.png, klavu.png, klavl12.png and klavu12.png.
Here is a tar-Archive and a zip-Archive that contain the klav*.png and the Perl script.
Then you can call

> perl mitramat.pl SOME_MIDI_FILE.mid

wich will produce SOME_MIDI_FILE.png and SOME_MIDI_FILE-12.png, the former containing
transitions between all notes and the latter breaking it down to one octave.
Also some other files will be produced. Yes.
You can give any number of MIDI files as arguments - they all will be processed.

------------------------------------------------- mitramat.pl -----------------------

# Copyright 2010,2017, Jean Rene Dawin
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.

{
    use MIDI;
    use Math::MatrixReal;
    use IO::File;
    use IO::Handle;
    use Image::Imlib2;
    use Switch;
    use warnings;
    use Math::Gradient qw(multi_gradient);
    use Image::Magick;
    use PDL;
    use PDL::Complex;
    use PDL::LinearAlgebra;
    use PDL::LinearAlgebra::Real;
    use PDL::LinearAlgebra::Complex;
    use PDL::Transform;
    use PDL::Transform::Cartography;

    my @zwoelfer = ();
    $yia = 0;
    for($_ = 0; $_<128; $_++){
	$yia++;
	push(@zwoelfer,$yia);
	if ($yia==12){
	    $yia=0;
	}    
    }
    
    my @that = ();
    my @sortiert = ();
    my $matrace = new Math::MatrixReal(128,128);
    my $matrace12 = new Math::MatrixReal(12,12);
    my $pictmatrace = new Math::MatrixReal(128,128);
    my $pictmatrace12 = new Math::MatrixReal(12,12);
    my @keys_minor_major = (["C major","G major","D major","A major","E major","B major","F sharp major","C sharp major","F major","B flat major","E flat major","A flat major","D flat major","G flat major","C flat major"],["a minor","e minor","b minor","f sharp minor","c sharp minor","g sharp minor","d sharp minor","a sharp minor","d minor","g minor","c minor","f minor","b flat minor","e flat minor","a flat minor"]);
    my @keys_moll_dur = (["C-Dur","G-Dur","D-Dur","A-Dur","E-Dur","H-Dur","Fis-Dur","Cis-Dur","F-Dur","B-Dur","Es-Dur","As-Dur","Des-Dur","Ges-Dur","Ces-Dur"],["a-moll","e-moll","h-moll","fis-moll","cis-moll","gis-moll","dis-moll","ais-moll","d-moll","g-moll","c-moll","f-moll","b-moll","es-moll","as-moll"]);
    my @keys_numbers = ([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
    my $fpt = pdl zeros 12;

    sub flup{
        $a->[0]<=>$b->[0];
    }

    sub auskunft {

	@kurz = @_;
	if(! $kurz[0]){
	   print "Auskunft: No file.\n";
	   return -1;
	}
	$opus = MIDI::Opus->new( {
	    "from_file" => $kurz[0],
	    "include" => \@MIDI::Event::All_events
		
				 } ); 
	
	@trackliste = $opus->tracks;
	$track_zahl = @trackliste;
	print $track_zahl, " Zahl\n";
	$tich = $opus->ticks;
	print "TICKS/viertel: ",$tich,"\n";
	@anzahlen = ();
	for ($ai = 0; $ai < $track_zahl; $ai++){
	    
	    push(@anzahlen, 0);

	}

	@fraktionen = (1,2/3,1/2,3/8,1/3,1/4,3/16,1/6,1/8,3/32,1/12,1/16,3/64,1/24,1/32,3/128,1/48,1/64,3/256,1/96,1/128);
	foreach(@fraktionen){
	    print $_," ";
	}
	print "FR\n";

	$track_zahl = 0;
	$mai = 0;
	@time_signature = ();
	@keys = ();

	foreach(@trackliste){
	    @i = $_->events;
	    $score_r = MIDI::Score::events_r_to_score_r( \@i );
	    @blubber = ();
	    $kanal = 0;
	    $track_name = "";
	    $instrument_name = "";
	    $hatnote = 0;
	    $juin = 0;

	    foreach my $note_r (@$score_r) {

		@blubber = &_dump_quote(@$note_r);
		print "BLUBSIZE $#blubber\n";
		
		if ($blubber[0] eq "'track_name'"){
		    $track_name = $blubber[2];
		}
		if ($blubber[0] eq "'instrument_name'"){
		    $instrument_name = $blubber[2];
		}
		if ($blubber[0] eq "'note'"){
                    # [1] = Time, [3] = Channel, [4] = Note, [2] = Duration
		    push(@that,[$blubber[1],$blubber[3],$blubber[4],$blubber[2]]);
		    print "[",$blubber[0],", ",$blubber[1],", ",$blubber[2],", ",$blubber[3],", ",$blubber[4],", ",$blubber[5],"] ",$blubber[2]/$tich," ";
		    if($mai>0){
			if($that[$mai-1][0]<$blubber[1]){
			    $ft = ($blubber[1]-$that[$mai-1][0])/$tich;
			    print $ft;
			    print " VNI\n";
			}else{
			    print "\n";
			}
		    }else{
			print "\n";
		    }
		    
		    $kleinste_signature = 0;
		    $laeufer = 0;
		    foreach (@time_signature){
			if($_->[0]<=$blubber[1]){
			    $kleinste_signature = $laeufer;
			}
			$laeufer++;
		    }
		    
		    print "LAE ",$kleinste_signature,"\n";

		    $anzahlen[$blubber[3]]++;
		    $kanal = $blubber[3];
		    $hatnote = 1;
		    $mai++;
		    $juin++;
 		}
		if ($blubber[0] eq "'set_tempo'"){
		    print "[";
		    for $_ (@blubber){
		        print "$_, ";
		    }
		    print "]\n";
		}
		if ($blubber[0] eq "'time_signature'"){
		    print "[",$blubber[0],", ",$blubber[1],", ",$blubber[2],", ",$blubber[3],", ",$blubber[4],", ",$blubber[5],"]\n";
		    push (@time_signature,[$blubber[1],$blubber[2],$blubber[3]]);
		}
		if ($blubber[0] eq "'key_signature'"){
		    print "[";
		    for $_ (@blubber){
		        print "$_, ";
		    }
		    print "]\n";
		    if ($blubber[2]<0){
			push(@keys, $keys_minor_major[$blubber[3]][(-1)*$blubber[2]+7]);
		    }else{
			push(@keys, $keys_minor_major[$blubber[3]][$blubber[2]]);
		    }
		    
		}
	    }
	    if($hatnote){
		$track_zahl++;
		print "KANAL ",$kanal,": ",$anzahlen[$kanal]," ANZAHL ",$track_name," GG",$instrument_name," JJ\n";
		print $track_zahl,"\n";
	    }
	}

	$k = 0;
	foreach (@anzahlen){
	    $k+=$_;
	}
	print $k," gesamtzahl in ",$track_zahl," Tracks\n";

	@sortiert = sort flup @that;
        #for($_ = 0; $_ < $#that; ++$_){
        #    print "that ", $that[$_][0], " ", $that[$_][1], " sortiert ", $sortiert[$_][0], " ", $sortiert[$_][1], "\n";
        #}
    }

    sub keyinfo{

	@kurz = @_;
	$opus = MIDI::Opus->new( {
	    "from_file" => $kurz[0],
	    "include" => \@MIDI::Event::All_events
		
				 } ); 
	
	@trackliste = $opus->tracks;
	@keys = ();

	foreach(@trackliste){
	    @i = $_->events;
	    $score_r = MIDI::Score::events_r_to_score_r( \@i );

	    @blubber = ();
	    foreach my $note_r (@$score_r) {
		
		@blubber = &_dump_quote(@$note_r);
		if ($blubber[0] eq "'key_signature'"){

		    $trig = 0;

		    if ($blubber[2]<0){
			$piu = $keys_minor_major[$blubber[3]][(-1)*$blubber[2]+7];
			
			foreach(@keys){
			    if($_ eq $piu){
				$trig = 1;
			    }
			}
			if (!$trig){
				push(@keys, $piu);
				$keys_numbers[$blubber[3]][(-1)*$blubber[2]+7]++;
				
			}			
		    }else{
			$piu = $keys_minor_major[$blubber[3]][$blubber[2]];
			
			foreach(@keys){
			    if($_ eq $piu){
				$trig = 1;
			    }
			}
			if (!$trig){
				push(@keys, $piu);
				$keys_numbers[$blubber[3]][$blubber[2]]++;
				
			}	
		    }
		    
		}
	    }
	}
	@keys;
    }    

    sub sammeln {

	@that = ();	
	@sortiert = ();
	@kurz = @_;
	
	if(! $kurz[0]){
	   print "Sammeln: No file.\n";
	   return -1;
	}
	$opus = MIDI::Opus->new( {
	    "from_file" => $kurz[0],
	    "include" => \@MIDI::Event::All_events
		
				 } ); 
       
	@trackliste = $opus->tracks;
	$track_zahl = @trackliste;
	$tich = $opus->ticks;
	@anzahlen = ();
	for ($ai = 0; $ai < $track_zahl; $ai++){
	    
	    push(@anzahlen, 0);

	}

	$track_zahl = 0;

	foreach(@trackliste){
	    @i = $_->events;
	    $score_r = MIDI::Score::events_r_to_score_r( \@i );

	    $kanal = 0;
	    $track_name = "";
	    $instrument_name = "";
	    $hatnote = 0;

	    foreach my $note_r (@$score_r) {
		@blubber = &_dump_quote(@$note_r);
		if ($blubber[0] eq "'note'"){
		    
		    push(@that,[$blubber[1],$blubber[3],$blubber[4]]);
		    $anzahlen[$blubber[3]]++;
		    $kanal = $blubber[3];
		    $hatnote = 1;
 		}
	    }
	    if($hatnote){
		$track_zahl++;		
	    }	    
	}
	$gesamtzahl = 0;
	foreach (@anzahlen){
	    $gesamtzahl+=$_;
	}
	
	@sortiert = sort flup @that;

	($gesamtzahl,$track_zahl);
    }

    sub einpacken {
	
	$matrace->zero();
	$pictmatrace->zero();
	$matrace12->zero();
	$pictmatrace12->zero();

	
	my $mei = 0;
	my $mei12 = 0;
	my $lauf1 = 0;
	my $lauf2 = 0;
	$duplikat = 0;
	$merken = 0;
	$graf = 0;
	switch($_[0]){
	    case "unsortiert" {
		for ($_ = 0 ; $_ < $#that ;$_++){
		    if($duplikat){
			$lauf1 = $merken;
			$lauf2 = $_+1;
		    }else{
			$lauf1 = $_;
			$lauf2 = $lauf1+1;
		    }
		    if ($that[$lauf2][0] > $that[$lauf1][0] && $that[$lauf2][1] == $that[$lauf1][1]){
			$mei = ($matrace->element($that[$lauf1][2],$that[$lauf2][2]))+1;
			$mei12 = ($matrace12->element($zwoelfer[$that[$lauf1][2]],$zwoelfer[$that[$lauf2][2]]))+1;
			$graf++;
			$matrace->assign($that[$lauf1][2],$that[$lauf2][2],$mei);
			$matrace12->assign($zwoelfer[$that[$lauf1][2]],$zwoelfer[$that[$lauf2][2]],$mei12);
			
			$duplikat = 0;
		    }else{
			if ($that[$lauf2][1] != $that[$lauf1][1]){
			    $duplikat = 0;
			}else{
			    $duplikat = 1;
			    $merken = $lauf1;
			}
		    }
		    
		}
		print $graf," unsortiert\n";
	    }
	
	    case "sortiert" {
		for ($_ = 0 ; $_ < $#sortiert ;$_++){
		    if($duplikat){
			$lauf1 = $merken;
			$lauf2 = $_+1;
		    }else{
			$lauf1 = $_;
			$lauf2 = $lauf1+1;
		    }
		    
		    if ($sortiert[$lauf2][0] > $sortiert[$lauf1][0] ){
			$mei = ($matrace->element($sortiert[$lauf1][2],$sortiert[$lauf2][2]))+1;
			$mei12 = ($matrace12->element($zwoelfer[$sortiert[$lauf1][2]],$zwoelfer[$sortiert[$lauf2][2]]))+1;

			$graf++;
			$matrace->assign($sortiert[$lauf1][2],$sortiert[$lauf2][2],$mei);
			$matrace12->assign($zwoelfer[$sortiert[$lauf1][2]],$zwoelfer[$sortiert[$lauf2][2]],$mei12);
			
			$duplikat = 0;
		    }else{
			$duplikat = 1;
			$merken = $lauf1;
		    }
		    
		}
		print $graf," sortiert\n";
	    
	    }
	}
	
	$pictmatrace->copy($matrace);
	$pictmatrace12->copy($matrace12);
	
	for ($_ = 1 ; ($_ < 128) ;$_++){
	    $hiap = ($matrace->row($_))->norm_p(1);
	 
	    if ($hiap==0){
		$hiap=1;
	    }
	    
	    for ($za = 1 ; ($za < 128) ; $za++){
		$matrace->assign($_,$za,$matrace->element($_,$za)/$hiap);
	    }
	}

	for ($_ = 1 ; ($_ < 13) ;$_++){
	    $hiap12 = ($matrace12->row($_))->norm_p(1);
	    if ($hiap12==0){
		$hiap12=1;
	    }
	    
	    for ($za12 = 1 ; ($za12 < 13) ; $za12++){
		$matrace12->assign($_,$za12,$matrace12->element($_,$za12)/$hiap12);
	    }
	}

	$tio = pdl zeros(12,12);
	$einheits = pdl identity(12);

	$nullzeilen = 1;
	
	for($i=1;$i < 13;$i++){
	    $zeilsum = 0;
	    for($j=1;$j < 13;$j++){
		$jeanne = $matrace12->element($i,$j);
		set($tio,$j-1,$i-1,$jeanne);
		$zeilsum += $jeanne;
	    }
	    $nullzeilen *= $zeilsum;
	}

	@anzahl_array = ();
	for($_ = 0; $_<128; $_++){
	    push(@anzahl_array,0);
	}    
    	
	for($i=1;$i < 129;$i++){
	    $zeilsum = 0;
	    for($j=1;$j < 129;$j++){
		
		if($matrace->element($i,$j) > 0){
		    if($anzahl_array[$i-1]== 0){
			$anzahl_array[$i-1] = 1;
		    }
		    if($anzahl_array[$j-1]== 0){
			$anzahl_array[$j-1] = 1;
		    }
		}
	    }
	}
	
	$noten_gebraucht = 0;    
	map { $noten_gebraucht += $_ } @anzahl_array;
	if($nullzeilen > 0){
	    $L = $einheits - $tio;
	    $ev = meigen($L);
	    
	    $ev_im = im $ev;
	    $ev_re = re $ev;
	    
	    $Z = pdl identity(12);
	    for($i=0;$i < 12;$i++){
		if($ev_re->index($i)>0.0001){
		    
		    $ev_n = (at($ev_re,$i)*at($ev_re,$i)+at($ev_im,$i)*at($ev_im,$i));
		    $eins_durch_ev_c = at($ev_re,7)/$ev_n +i*at($ev_im,7)/$ev_n;
		    $Z = $Z x ($einheits - (($eins_durch_ev_c*$einheits) x$L));
		    
		}
	    }
	    $L_kreuz = minv($L + $Z) - $Z;
	    $L_kreuz_re = re $L_kreuz;
	    $L_kreuz_im = im $L_kreuz;
	    $eins_LL_kreuz = $einheits-($L x $L_kreuz);
	    $eins_LL_kreuz_re = re $eins_LL_kreuz;
	    $eins_LL_kreuz_im = im $eins_LL_kreuz;
	    
	    for($i=0;$i < 12;$i++){
		$LK_c = at($L_kreuz_re,$i,$i) + i*at($L_kreuz_im,$i,$i);
		$ELLK_c = at($eins_LL_kreuz_re,$i,$i) + i*at($eins_LL_kreuz_im,$i,$i);
		if(re $ELLK_c>0.0001){
		    set($fpt,$i,re $LK_c/$ELLK_c);
		}
	    }
	    
	    $entropie = 0;
	    $complexity = 0; 
	    for($i=0;$i < 12;$i++){
		$sandrine = 1;
		$estelle = at($eins_LL_kreuz_re,$i,1);
		if($estelle > 0){
	    	    $entropie += -1*$estelle*log($estelle)/log(12);
		}
		for($j = 0; $j < 12; $j++){ 
		    $sandrine *= $matrace12->element($i+1,$j+1) ** $matrace12->element($i+1,$j+1);
		}
		if($estelle/$sandrine > 0){
		    $complexity += -1*$estelle*log($estelle/$sandrine)/log(12);
	        }
	    }
	    ($matrace,$matrace12,$graf,$entropie,$complexity);
	}else{
	    ($matrace,$matrace12,$graf,-1,-1);
	}
    }

    # This function is a slightly modified version from the MIDI:: Module.
    # The original version returns a string. This version returns an array.
    sub _dump_quote {
	# Used variously by some MIDI::* modules.  Might as well keep it here.
	my @stuff = @_;
	return
	    
	    map
	{ # the cleaner-upper function
	    if(!length($_)) { # empty string
		"''";
	    } elsif(
		$_ eq '0' or m/^-?(?:[1-9]\d*)$/s  # integers
		
		# Was just: m/^-?\d+(?:\.\d+)?$/s
		# but that's over-broad, as let "0123" thru, which is
		# wrong, since that's octal 0123, == decimal 83.
		
		# m/^-?(?:(?:[1-9]\d*)|0)(?:\.\d+)?$/s and $_ ne '-0'
		# would let thru all well-formed numbers, but also
		# non-canonical forms of them like 0.3000000.
		# Better to just stick to integers I think.
		) {
		$_;
	    } elsif( # text with junk in it
		     s<([^\x20\x21\x23\x27-\x3F\x41-\x5B\x5D-\x7E])>
		     <'\\x'.(unpack("H2",$1))>eg
		) {
			 "\"$_\"";
	    } else { # text with no junk in it
		s<'><\\'>g;
		"\'$_\'";
	    }
	}
	@stuff;
	
    }
    
    sub schnippname{
	$filename = substr($_[0],0,length($_[0])-4);
	$fix = length($filename);
	$temp2 = "";
	for ($ia = $fix; $ia > 0; $ia--){
	    $temp = chop($filename);
	    
	    if ($temp eq "/"){	
		    $filename = $temp2;
		    $ia = 0;
	    }else{
		$temp2 = $temp.$temp2;
	    }
	}
	$filename = $temp2;
    }

    
    sub schnippkomp{
	$filename = substr($_[0],3,length($_[0])-6);
    }

    sub schreiben {    

	my $filename;
	if($_[1]){
	   $filename = $_[1];
        }else{
	   $filename = &schnippname($_[0]);
        }
	print $filename,"\n";

	$fht = new IO::File $filename."-t", "w";

	my $io = new IO::Handle;
	
	my $rand_dicke = 1;
	my $pixel_dicke = 3;
	my $kachel_dicke = $rand_dicke+$pixel_dicke;
	my $rand_farbe = 210;
	my $pixel_farbe = 255;
        my $leer_farbe = 255;
	my $seite_128 = 128*($kachel_dicke);
	my $seite_12 = 12*($kachel_dicke);
	
	my $image = Image::Imlib2->new($seite_128+$rand_dicke, $seite_128 + $rand_dicke);
	my $image12 = Image::Imlib2->new($seite_12 + $rand_dicke, $seite_12 + $rand_dicke);

	my(@hot_spots) = ([ 102, 255, 255 ], [ 153, 255, 0 ], [ 255, 255, 0 ], [ 255, 102, 0 ], [ 255, 51, 0 ]);
	
	my(@gradient) = Math::Gradient::multi_array_gradient(101, @hot_spots);
	for $ist (0 .. $#gradient){
	    for $jst (0 .. 2){
		$gradient[$ist][$jst] = int($gradient[$ist][$jst]);
	    }
	}
	print $#gradient," Yon\n";
	my $scalim = Image::Imlib2->new(15, 140);
	for ($rhsc = 0; $rhsc < 11; $rhsc++){
	    $image->set_colour($gradient[$rhsc*10][0],$gradient[$rhsc*10][1],$gradient[$rhsc*10][2],255);
	    $scalim->fill_rectangle(0, $rhsc*14, 15, ($rhsc+1)*14);
	}
	$scalim->set_quality(10);
	$scalim->save("Scala".".png");

	$min_x = 128;
	$max_x = 0;
	$min_y = 128;
	$max_y = 0;
	    
	for ($_ = 1 ; ($_ < 129) ;$_++){
	    
	    for ($za = 1 ; ($za < 129) ; $za++){
		
		for ($spalte = 0 ; ($spalte < $kachel_dicke) ; $spalte++){
		    for ($zeile = 0 ; ($zeile < $kachel_dicke) ; $zeile++){
		    
			if($zeile < $rand_dicke){		
			    $image->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
			    $image->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
			}else{
			    if($spalte < $rand_dicke){
				$image->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
				$image->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
			    }else{
				
				if ($pictmatrace->element($_,$za)>0){
				    
				    if($za < $min_x){$min_x = $za;}
				    if($za > $max_x){$max_x = $za;}
				    if($_ < $min_y){$min_y = $_;}
				    if($za > $min_x){$max_y = $_;}

				    $image->set_colour($gradient[int(100*$matrace->element($_,$za))][0],$gradient[int(100*$matrace->element($_,$za))][1],$gradient[int(100*$matrace->element($_,$za))][2],255);
				    $image->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
				}else{
				    $image->set_colour($leer_farbe,$leer_farbe,$leer_farbe,$leer_farbe);
				    $image->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
				}
			    }
			}
		    }
		    if($za == 128){
			$image->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
			$image->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
		    }
		}
	    }
		
	    if($_ == 128){
		$image->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
		for($lief_z = 0;$lief_z < $rand_dicke;$lief_z++){
		    for($lief_s = 0;$lief_s < ($seite_128+$rand_dicke);$lief_s++){
			$image->draw_point($lief_s,$seite_128 + $lief_z);
		    }
		}
	    }
	}

	print "i_x ",$min_x," A_x ",$max_x," i_y ",$min_y," A_y ",$max_y,"\n";
	    
	$rmin_x = ($min_x - 1)*$kachel_dicke;
	$rmax_x = $max_x*$kachel_dicke+$rand_dicke;
	$rmin_y = ($min_y - 1)*$kachel_dicke;
	$rmax_y = $max_y*$kachel_dicke+$rand_dicke;
	
	$image->set_quality(10);
	$image->save($filename.".png");
	
	my($ck_image, $err);

	$ck_image = Image::Magick->new;
	$err = $ck_image->Read($filename.".png");
	warn "$err" if $err;
	
	$err = $ck_image->Crop(x=>$rmin_x, y=>$rmin_y, width=>$rmax_x-$rmin_x, height=>$rmax_y-$rmin_y);
	warn "$err" if "$err";
	
	$err = $ck_image->Write($filename.".png");
	warn "$err" if "$err";

	my($klavl, $errl);
	my($klavu, $erru);

	$klavl = Image::Magick->new;
	$errl = $klavl->Read("klavl.png");
	warn "$errl" if "$errl";
	$errl = $klavl->Crop(x=>0, y=>$rmin_y, width=>21, height=>$rmax_y-$rmin_y);
	warn "$errl" if "$errl";
	$errl = $klavl->Write("klavltmp.png");
	warn "$errl" if "$errl";

	$klavu = Image::Magick->new;
	$erru = $klavu->Read("klavu.png");
	warn "$erru" if "$erru";
	$erru = $klavu->Crop(x=>$rmin_x, y=>0, width=>$rmax_x-$rmin_x, height=>18);
	warn "$erru" if "$erru";
	$erru = $klavu->Write("klavutmp.png");
	warn "$erru" if "$errl";
	$filament = $filename.".png";
	$filamenttmp = $filename."tmp.png";
	system("convert -background white $filament klavutmp.png -append -background white $filamenttmp");
	system("convert -background white klavltmp.png $filamenttmp +append -background white $filament");
	system("rm $filamenttmp");


	for ($_ = 1 ; ($_ < 13) ;$_++){
	    
	    for ($za = 1 ; ($za < 13) ; $za++){
		
		for ($spalte = 0 ; ($spalte < $kachel_dicke) ; $spalte++){
		    for ($zeile = 0 ; ($zeile < $kachel_dicke) ; $zeile++){
		    
			if($zeile < $rand_dicke){		
			    $image12->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
			    $image12->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
			}else{
			    if($spalte < $rand_dicke){
				$image12->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
				$image12->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
			    }else{
				
				if ($pictmatrace12->element($_,$za)>0){

				    $image12->set_colour($gradient[int(100*$matrace12->element($_,$za))][0],$gradient[int(100*$matrace12->element($_,$za))][1],$gradient[int(100*$matrace12->element($_,$za))][2],255);
				    $image12->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
				}else{
				    $image12->set_colour($leer_farbe,$leer_farbe,$leer_farbe,$leer_farbe);
				    $image12->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
				}
			    }
			}
		    }
		    if($za == 12){
			$image12->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
			$image12->draw_point($zeile+(($za-1)*$kachel_dicke), $spalte+(($_-1)*$kachel_dicke));
		    }
		}
	    }
	    
	    if($_ == 12){
		$image12->set_colour($rand_farbe,$rand_farbe,$rand_farbe,255);
		for($lief_z = 0;$lief_z < $rand_dicke;$lief_z++){
		    for($lief_s = 0;$lief_s < ($seite_12+$rand_dicke);$lief_s++){
			$image12->draw_point($lief_s,$seite_12 + $lief_z);
		    }
		}
	    }
	}
	
	
	$image12->set_quality(10);
	$image12->save($filename."-12.png");

	$filament12 = $filename."-12.png";
	$filament12tmp = $filename."-12tmp.png";

	system("convert -background white $filament12 klavu12.png -append -background white $filament12tmp");
	system("convert -background white klavl12.png $filament12tmp +append -background white $filament12");
	system("rm $filament12tmp");


	$fht_io = new IO::Handle;
	$fht_io->fdopen($fht, "w");
	for($i=0;$i < 12;$i++){
	    $fht_io->print($i+1," ",at($fpt,$i),"\n");
	}
	$fht_io->close;
    }
    
    sub dkl {

	my $dkl = 0;
	
	for ($_ = 1 ; ($_ < ($_[0]->dim())[0]+1) ;$_++){
	    for ($za = 1 ; ($za < ($_[0]->dim())[1]+1) ; $za++){
		
		
		$m1_ij = $_[0]->element($_,$za);
		$m2_ij = $_[1]->element($_,$za);
		
		if ($m1_ij > 0 && $m2_ij > 0){
		    $dkl += $m1_ij*log($m1_ij/$m2_ij);
		    
		}
	    }
	}
	$dkl;
    }
 
    sub frob {
	
	my $frob = 0;

	$mult01 = $_[0]->multiply($_[1]);
	$mult10 = $_[1]->multiply($_[0]);
	$mult01-> subtract($mult01,$mult10);
	$zaehler = $mult01->norm_frobenius();
	$nenner = $_[0]->norm_frobenius()*$_[1]->norm_frobenius();
	$frob = (1/sqrt(2))*($zaehler/$nenner);
    }


    if(@ARGV){

	my $opt_sorted = 1;
	my $opt_unsorted = 0;
	my $opt_number = 0;

	if($ARGV[0] eq "i"){
	    &auskunft($ARGV[1]);
	}
	
	else{
            if(! -f $ARGV[0]){
                if($ARGV[0] =~ /\b(nu|un|sn|ns|n)\b/){
	            $opt_number = 1;
	        }
	        if($ARGV[0] =~ /\b(nu|un|u)\b/){
	            $opt_unsorted = 1;
	        }
	        shift;
	    }
	    $arglength = @ARGV;
	    print ($arglength,"\n");
	    print ("Super\n");
	    $lookup = new IO::File "Lookuptable", "w";
	    $tmp_io = new IO::Handle;
	    $tmp_io->fdopen($lookup, "w");
	    
            my $z = 1;
            while(@ARGV){
                if(-f $ARGV[0]){
                    ($gesz,$trz) = &sammeln($ARGV[0]);
                    if($opt_unsorted == 1){
                        @hy = &einpacken("unsortiert");
                    }else{
                        @hy = &einpacken("sortiert");
                    }
                    if($opt_number == 1){
                        &schreiben($ARGV[0],$z);
                    }else{
                        &schreiben($ARGV[0]);
                    }
                    $tmp_io->print ($z," ",&schnippname($ARGV[0])," ",$hy[2]," Noten in ",$trz," Tracks ", $gesz, " ", ,$hy[3]," ",$hy[4]," ",$noten_gebraucht,"\n");
                    $z++;
                }
                shift;
	    }
	    $tmp_io->close;
	}

    }else{
        print("No Input. Try one of these:\n\n");
        print("$0 FILE.mid [FILE2.mid ...]\n");
        print("-> Create Transition-Matrix-Image from midi file(s) with events\n");
        print("   from all channels mixed and sorted by time. This is the default.\n\n");
        print("$0 s FILE.mid [FILE2.mid ...]\n");
        print("-> Same as above. Explicit option for 'sorted'.\n\n");
        print("$0 u FILE.mid [FILE2.mid ...]\n");
        print("-> Create Transition-Matrix-Image from midi file(s) with events\n");
        print("   from different channels treated separately.\n");
        print("   (globally unsorted / sorted by time by channel).\n\n");
        print("$0 n FILE.mid [FILE2.mid ...]\n");
        print("-> Use numbers for output file names. Can be combined with 'u' or 's'\n");
        print("   e.g. : $0 nu FILE.mid [FILE2.mid ...]\n\n");
        print("$0 i FILE.mid\n");
        print("-> Print info about midi file.\n");
    }
    exit;
}


START ESCWYP MUSIC VIDEOS