annotate testdata/scripts/convert_midifileout.yeti @ 372:af71cbdab621 tip

Update bqvec code
author Chris Cannam
date Tue, 19 Nov 2019 10:13:32 +0000
parents 51c18a17404a
children
rev   line source
Chris@137 1
Chris@193 2 // Convert the output of the midifile program
Chris@193 3 // (https://code.soundsoftware.ac.uk/projects/midifile)
Chris@193 4 // into lab file like those output from the test scripts.
Chris@193 5 //
Chris@193 6 // The midifile format contains lines looking like:
Chris@193 7 //
Chris@193 8 // <t>: Note: channel <c> duration <d> pitch <p> velocity <v>
Chris@193 9 //
Chris@193 10 // where t and d are defined in terms of the timebase and
Chris@193 11 // tempo, which are (usually) given in earlier lines:
Chris@193 12 //
Chris@193 13 // Timing division: <n> ppq
Chris@193 14 // <t>: Tempo: <n>
Chris@193 15 //
Chris@222 16 // Note that we assume 4 quarter-notes per bar, we don't parse time
Chris@222 17 // signatures, and we only handle the first tempo event.
Chris@137 18 //
Chris@193 19 // The output file format looks like:
Chris@137 20 //
Chris@137 21 // onset offset frequency
Chris@193 22 //
Chris@193 23 // with times in seconds.
Chris@137 24
Chris@193 25 program convert_midifileout;
Chris@137 26
Chris@137 27 usage () =
Chris@193 28 eprintln "\nUsage: convert_midifileout file.txt\n";
Chris@137 29
Chris@137 30 toFrequency m =
Chris@137 31 440 * Math#pow(2.0, (m - 69) / 12.0);
Chris@137 32
Chris@193 33 toTime timebase tempo t =
Chris@193 34 (t / timebase) * (60 / tempo);
Chris@193 35
Chris@137 36 convert f =
Chris@137 37 (str = openInFile f "UTF-8";
Chris@193 38 var timebase = 480;
Chris@193 39 var tempo = 120;
Chris@222 40 var tempoNowFixed = false;
Chris@137 41 for (str.lines ()) do line:
Chris@193 42 bits = strSplit ": " line;
Chris@193 43 if length bits > 1 then
Chris@193 44 if bits[0] == "Timing division" then
Chris@193 45 timebase := number (strReplace " ppq" "" bits[1]);
Chris@193 46 eprintln "Set timing division to \(timebase)";
Chris@193 47 elif bits[1] == "Tempo" then
Chris@222 48 if tempoNowFixed then
Chris@222 49 failWith "Can't handle variable-tempo file";
Chris@222 50 fi;
Chris@193 51 if length bits < 3 then
Chris@193 52 failWith "Too few bits in tempo line: \(line)";
Chris@193 53 fi;
Chris@193 54 tempo := number (bits[2]);
Chris@222 55 tempoNowFixed := true;
Chris@193 56 eprintln "Set tempo to \(tempo)";
Chris@193 57 elif bits[1] == "Note" then
Chris@222 58 tempoNowFixed := true;
Chris@193 59 if length bits < 3 then
Chris@193 60 failWith "Too few bits in note line: \(line)";
Chris@193 61 fi;
Chris@193 62 noteparts = strSplit " " bits[2];
Chris@193 63 if length noteparts < 8 then
Chris@193 64 failWith "Too few note parameters in line: \(line)";
Chris@193 65 fi;
Chris@193 66 onset = toTime timebase tempo (number bits[0]);
Chris@193 67 duration = toTime timebase tempo (number noteparts[3]);
Chris@193 68 frequency = toFrequency (number noteparts[5]);
Chris@193 69 println "\(onset)\t\(onset + duration)\t\(frequency)";
Chris@193 70 fi;
Chris@193 71 fi;
Chris@137 72 done;
Chris@137 73 str.close ());
Chris@137 74
Chris@137 75 case (list _argv) of
Chris@137 76 file::[]: convert file;
Chris@137 77 _: usage ();
Chris@137 78 esac;
Chris@137 79