view yeti/scratch/generateTemplatesC.yeti @ 135:8db5e4ab56ce

Ground-truth data in CSV and lab format, converted from the MIDI using Sonic Visualiser and then to lab using the script here
author Chris Cannam
date Thu, 08 May 2014 12:59:09 +0100
parents 97b77e7cb94c
children 840c0d703bbb e3373d367bda
line wrap: on
line source

program generateTemplatesC;

vec = load may.vector;

instruments = [
    "bassoon",
    "cello",
    "clarinet",
    "flute",
    "guitar",
    "horn",
    "oboe",
    "tenorsax",
    "violin",
    "piano-maps-SptkBGCl",
//!!! restore these?
//    "piano1",
//    "piano2",
//    "piano3",
];

hardcodedRanges = [
    "bassoon": { lowest = 15, highest = 51 },
    "cello": { lowest = 15, highest = 60 },
    "clarinet": { lowest = 29, highest = 68 },
    "flute": { lowest = 39, highest = 72 },
    "guitar": { lowest = 19, highest = 55 },
    "horn": { lowest = 20, highest = 56 },
    "oboe": { lowest = 37, highest = 70 },
    "tenorsax": { lowest = 23, highest = 54 },
    "violin": { lowest = 34, highest = 72 },
    "piano-maps-SptkBGCl": { lowest = 16, highest = 72 },
    "piano1": { lowest = 16, highest = 72 },
    "piano2": { lowest = 16, highest = 72 },
    "piano3": { lowest = 16, highest = 72 },
];

overallLowest = 15;
overallHighest = 72;

dataDir = "../../data";
includeDir = "\(dataDir)/include";

warning = "/* Do not edit this file: it was automatically generated */";

noteCount = 88;
templateHeight = 545;
shiftRange = 2;

convert instrument lines ostr =
   (notes = map do line:
                vec.fromList (map number (strSplit "," line))
            done lines;
    if (length notes) != noteCount then
        failWith "Wrong number of notes in instrument \(instrument): found (\(length notes), expected \(noteCount)";
    fi;
    for notes do n:
        if (vec.length n) != templateHeight then
            failWith "Wrong number of values in template while processing instrument \(instrument): found \(vec.length n), expected \(templateHeight)";
        fi
    done;
    levels = map vec.sum notes;
//    first = length levels - length (find (>0) levels);
//    last = length (find (>0) (reverse levels)) - 1;
    first = hardcodedRanges[instrument].lowest;
    last = hardcodedRanges[instrument].highest;
    ostr.writeln warning;
    ostr.writeln "";
    ostr.writeln "{\n    \"\(instrument)\",\n    \(first),\n    \(last),";
    ostr.writeln "    {";
    for notes do note:
        ostr.write "        { ";
        for [0..shiftRange-1] do s:
            ostr.write "0.0, ";
        done;
        for (vec.list note) do v:
            ostr.write "\(v), ";
        done;
        for [0..shiftRange-1] do s:
            ostr.write "0.0, ";
        done;
        ostr.writeln "},";
    done;
    ostr.writeln "    }";
    ostr.writeln "},";
    ostr.close ()); 

writeMainHeader () =
   (ostr = openOutFile "\(includeDir)/templates.h" "UTF-8";
    for [
        warning,
        "",
        "#ifndef SILVET_DATA_TEMPLATES_H",
        "#define SILVET_DATA_TEMPLATES_H",
        "",
        "/* note: intended to parse as both C and C++ */",
        "",
        "#define SILVET_TEMPLATE_COUNT      \(length instruments)   /* Number of instruments */",
        "#define SILVET_TEMPLATE_NOTE_COUNT \(noteCount)   /* Number of notes per instrument */ ",
        "#define SILVET_TEMPLATE_HEIGHT     \(templateHeight)  /* Frequency bins per template */",
        "#define SILVET_TEMPLATE_MAX_SHIFT  \(shiftRange)    /* Zeros at either end of template */ ",
        "#define SILVET_TEMPLATE_SIZE       \(templateHeight + 2 * shiftRange)  /* Height + 2 * max shift space */ ",
        "",
        "typedef struct {",
        "    const char *name;",
        "    int lowest;",
        "    int highest;",
        "    double data[SILVET_TEMPLATE_NOTE_COUNT][SILVET_TEMPLATE_SIZE];",
        "} silvet_template_t;",
        "",
        "static int silvet_templates_lowest_note = \(overallLowest);",
        "static int silvet_templates_highest_note = \(overallHighest);",
        "",
        "static silvet_template_t silvet_templates[SILVET_TEMPLATE_COUNT] = {",
    ] ostr.writeln;
    for instruments do instrument:
        ostr.writeln "#include \"\(instrument).h\"";
    done;
    for [
        "};",
        "",
        "#endif",
    ] ostr.writeln;
    ostr.close ()); 

convertAll () = 
   (writeMainHeader ();
    for instruments do instrument:
        i = openInFile "\(dataDir)/\(instrument).csv" "UTF-8";
        o = openOutFile "\(includeDir)/\(instrument).h" "UTF-8";
        eprintln "converting instrument \"\(instrument)\"...";
        convert instrument (i.lines ()) o;
    done);

convertAll ();