program nul2kan; uses SysUtils, Algemeen, MidiDoos, MidiText; var Bron,Doel : string; Octaves : integer; OTF : TextFile; zes : boolean; procedure Some_Help; begin Writeln('NUL2KAN'); Writeln; Writeln('Converts MidiFile to PianoRoll / Klavar Ascii Notation (KAN)'); Writeln; Writeln('Syntax: [program] [IMF] [OTF] [OCT]'); Writeln; Writeln('IMF = name of Input MidiFile'); Writeln('OTF = name of Output TextFile'); Writeln('OCT = number of Octaves (optional)'); Writeln('Default number of Octaves is five'); Writeln; Writeln('Visualization of the Keyboard instead of (cumulative) Notes'); Writeln('Four parts at most (ch = 0,1,2,3) only for 0-type MidiFiles'); Writeln('Velocity information most probably is lost with conversion'); Writeln('Notes range allowed = 36 - 108; lyrics displayed eventually'); end; procedure Read_Parameters(var OK : boolean); var tel : integer; woord : string; begin OK := true; tel := ParamCount; if (tel < 2) or (tel > 3) then begin Some_Help; OK := false; Exit; end; Bron := ParamStr(1); Doel := ParamStr(2); Octaves := 5; if tel = 3 then begin woord := ParamStr(3); Octaves := getnum(woord); OK := (0 < Octaves) and (Octaves < 12); if not OK then begin Some_Help; Exit; end; end; if not FileExists(Bron) then begin Writeln(Bron + ': does Not exist'); OK := false; end; AssignFile(OTF,Doel); Rewrite(OTF); end; procedure geschikt(MF : Midi; var OK : boolean); var punt,aantal,p,ch,min,max : integer; goed,muziek : boolean; noot : bytes; let : byte; begin OK := (MF.Type01 = 0) and (MF.Tracks = 1); if not OK then Writeln('Not a 0-type MidiFile with only 1 track'); punt := 14; if OK then MF.Check_Track_Header(punt,aantal,OK); min := 127; max := 0; p := punt; if OK then while (p < punt+aantal) do begin MF.Skip_Delta_Time(p); let := MF.invoer[p]; MF.Data_Any_Event(p,noot); muziek := ((noot[0] and $F0) = $90) or ((noot[0] and $F0) = $80); if muziek then begin if noot[1] < min then min := noot[1]; if noot[1] > max then max := noot[1]; end; if ($80 <= let) and (let <= $EF) then begin { Check Midi Channel HERE } goed := (let = (let and $F0)); for ch := 1 to 3 do goed := goed or (let = ((let and $F0) or ch)); if not goed then OK := false; end; end; if not OK then Writeln('Channel numbers must be 0 - 4 for KAN conversion'); OK := (36 <= min) and (max <= 108); if not OK then Writeln('Note numbers must be 36 - 108 for KAN conversion'); zes := (max > 96); end; function lege_balk : string; const deel : string = ' : : : : : '; var ff : string; k,L : integer; begin ff := ''; L := Octaves+2; if zes then L := 8; for k := 3 to L do ff := ff + deel; ff := ff + ' |'; lege_balk := ff; end; procedure Schrijven(hoog,kanaal : byte; var balk : string); const beeld : string = '123456789ABCDEF'; var getal : integer; begin getal := Pos(balk[hoog-36+1],beeld) or (1 shl kanaal); balk[hoog-36+1] := beeld[getal]; end; function Grijp(samen : lijst) : string; const twee : array[0..3] of byte = (1,2,4,8); var i,k,bin : byte; klaar : array[0..3] of boolean; greep : string; begin for k := 0 to 3 do klaar[k] := false; for k := 0 to 3 do begin if Length(samen[k]) = 0 then Continue; if klaar[k] then Continue; bin := twee[k]; klaar[k] := true; for i := k+1 to 3 do begin if samen[k] = samen[i] then begin bin := bin + twee[i]; klaar[i] := true; end; end; greep := greep + half2hex(bin) + '=' + samen[k] + ' '; end; Grijp := trim(greep); end; procedure Klavar_Ascii(MF : Midi); var reeds,aantal : integer; p,t,ch,k,L : integer; riedel,noot : bytes; uit,greep,balk : string; OK,muziek,Solo,Koor,PolyText : boolean; noten : verzameling; samen : lijst; begin Writeln(OTF,'File ',MF.Type01,' (',MF.Tracks,') ',MF.Ticks); Writeln(OTF,'Track #0'); Schoonmaken(noten); balk := lege_balk; reeds := 14; MF.Check_Track_Header(reeds,aantal,OK); p := reeds; SetLength(samen,4); PolyText := false; while p < reeds+aantal do begin { Time } t := MF.Get_Delta_Time(p); if (t > 0) then Write(OTF,t:5,' '); SetLength(riedel,0); if not Leeg(noten) then for ch := 0 to 3 do begin riedel := Akkoord(noten,ch); L := Length(riedel); if L > 0 then for k := 0 to L-1 do Schrijven(riedel[k],ch,balk); end; if (t > 0) then begin if PolyText then greep := Grijp(samen); Writeln(OTF,balk + ' ' + trim(greep)); greep := ''; for k := 0 to 3 do samen[k] := ''; end; balk := lege_balk; { Event } MF.Data_Any_Event(p,noot); muziek := ((noot[0] and $F0) = $90) or ((noot[0] and $F0) = $80); if muziek then Cumulatief(noot[0],noot[1],noot[2],noten); Solo := (noot[0] = $FF) and (noot[1] = $05); Koor := (noot[0] = $FF) and (noot[1] in [$10..$13]); if Solo then greep := plukken(noot); if Koor then samen[noot[1] and $0F] := plukken(noot); if Koor then PolyText := true; if not (Solo or Koor or muziek) then begin uit := Any_Event(noot); Writeln(OTF,uit); end; end; end; procedure HoofdRoutine; { Beginning of Main program } var MF : Midi; OK : boolean; begin Read_Parameters(OK); if not OK then Exit; MF := Midi.Create; MF.Read_MidiFile(Bron); MF.Check_Structure(OK); if not OK then Exit; geschikt(MF,OK); if not OK then Exit; Klavar_Ascii(MF); CloseFile(OTF); end; BEGIN HoofdRoutine; END.