| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 | <!--This file executes some benchmarks with HTML Canvas and VexFlow rendering--><!DOCTYPE html><html><head><meta charset="UTF-8"><script defer="defer">(function(){//----------------------------------------------------------------------------->// TODO// * More complex VexFlow systemsvar start = function () {  document.title = "HTML Canvas Performance Tests";  write("<h1>[OSMD] HTML Canvas Performance Tests</h1>");  var t = timer();  // Run the tests  repeat(    "Canvas creation", 100,    "create an empty huge 1920 x (1080*30) canvas.",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080 * 30;    }  );  repeat(    "Fill canvas with white", 10,    "create a huge canvas and fill it completely with white.",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080 * 30;      var ctx = canvas.getContext("2d");      ctx.fillRect(0, 0, canvas.width, canvas.height);    }  );  repeat(    "[VexFlow] Draw systems", 100,    "Draw 20 empty staves on a normal (1920x200) canvas (one instrument).",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 200;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++)        (new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        )).addClef("treble")          .setContext(ctx)          .draw();    }  );  repeat(    "[VexFlow] Draw systems", 100,    "Draw 20 empty staves on a big (1920x1080) canvas (one instrument).",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++)        (new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        )).addClef("treble")          .setContext(ctx)          .draw();    }  );  repeat(    "[VexFlow] Draw systems", 50,    "Draw 20 empty staves on a huge canvas (one instrument).",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080 * 30;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++)        (new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        )).addClef("treble")          .setContext(ctx)          .draw();    }  );  repeat(    "[VexFlow] Format & draw complex system", 50,    "Draw 20 staves with one voice, ties and beams on a big canvas.",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++) {        var stave = new Vex.Flow.Stave(10, 0, 500);        // From the VexFlow Tutorial:        stave.addClef("treble");        stave.setContext(ctx).draw();        var notes = [          new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).            addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),          new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).            addAccidental(0, new Vex.Flow.Accidental("b"))        ];        var notes2 = [          new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "8" }),          new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),          new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "16" }).            addAccidental(0, new Vex.Flow.Accidental("b"))        ];        var notes3 = [          new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "8" }),          new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }).            addAccidental(0, new Vex.Flow.Accidental("#"))        ];        var notes4 = [          new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "8" }),          new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }),        ];        // Create the beams        var beam = new Vex.Flow.Beam(notes);        var beam2 = new Vex.Flow.Beam(notes2);        var beam3 = new Vex.Flow.Beam(notes3);        var beam4 = new Vex.Flow.Beam(notes4);        // Create a tie between the last note of the first group and the        // first note of the last group.        var tie = new Vex.Flow.StaveTie({          first_note: notes[1],          last_note: notes2[0],          first_indices: [0],          last_indices: [0]        });        // Create another tie between the two chords in the tune        var tie2 = new Vex.Flow.StaveTie({          first_note: notes2[2],          last_note: notes3[0],          first_indices: [0, 1],          last_indices: [0, 1]        });        var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);        // Helper function to justify and draw a 4/4 voice        Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);        // Render beams        beam.setContext(ctx).draw();        beam2.setContext(ctx).draw();        beam3.setContext(ctx).draw();        beam4.setContext(ctx).draw();        // Render ties        tie.setContext(ctx).draw();        tie2.setContext(ctx).draw();      }    }  );  repeat(    "[VexFlow|big] Format & draw 20 staves 5 voices each.", 50,    "...",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++) {        var stave = new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        );        stave.addClef("treble");        stave.setContext(ctx).draw();        var voices = [];        for (var i = 0, voice; i < 5; i++) {          voice = new Vex.Flow.Voice({            num_beats: 4,            beat_value: 4,            resolution: Vex.Flow.RESOLUTION          });          voice.addTickables(randomNotes());          voices.push(voice);        }        var formatter = new Vex.Flow.Formatter().        joinVoices(voices).format(voices, 500);        for (var i = 0; i < 5; i++) {          voices[i].draw(ctx, stave);        }      }    }  );  repeat(    "[VexFlow|huge] Format & draw 20 staves with 5 voices each.", 50,    "...",    function(){      var canvas = document.createElement("canvas");      canvas.width = 1920;      canvas.height = 1080 * 30;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++) {        var stave = new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        );        stave.addClef("treble");        stave.setContext(ctx).draw();        var voices = [];        for (var i = 0, voice; i < 5; i++) {          voice = new Vex.Flow.Voice({            num_beats: 4,            beat_value: 4,            resolution: Vex.Flow.RESOLUTION          });          voice.addTickables(randomNotes());          voices.push(voice);        }        var formatter = new Vex.Flow.Formatter().        joinVoices(voices).format(voices, 500);        for (var i = 0; i < 5; i++) {          voices[i].draw(ctx, stave);        }      }    }  );  var tmp_canvas = document.createElement("canvas");  tmp_canvas.width = 1920;  tmp_canvas.height = 1080;  var tmp_renderer = new Vex.Flow.Renderer(tmp_canvas, Vex.Flow.Renderer.Backends.CANVAS);  var ctx = tmp_renderer.getContext();  repeat(    "[VexFlow|big] Format & draw system", 50,    "Draw a measure with a voice.",    function(){      var stave = new Vex.Flow.Stave(        Math.floor(Math.random()*tmp_canvas.width),        Math.floor(Math.random()*tmp_canvas.height),        Math.floor(Math.random()*tmp_canvas.width)      );      // From the VexFlow Tutorial:      stave.addClef("treble");      stave.setContext(ctx).draw();      var notes = [        new Vex.Flow.StaveNote({ keys: ["e##/5"], duration: "8d" }).        addAccidental(0, new Vex.Flow.Accidental("##")).addDotToAll(),        new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "16" }).        addAccidental(0, new Vex.Flow.Accidental("b"))      ];      var notes2 = [        new Vex.Flow.StaveNote({ keys: ["b/4"], duration: "8" }),        new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "16" }),        new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "16" }).        addAccidental(0, new Vex.Flow.Accidental("b"))      ];      var notes3 = [        new Vex.Flow.StaveNote({ keys: ["c/4", "e/4"], duration: "8" }),        new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }).        addAccidental(0, new Vex.Flow.Accidental("#"))      ];      var notes4 = [        new Vex.Flow.StaveNote({ keys: ["d/4"], duration: "8" }),        new Vex.Flow.StaveNote({ keys: ["e/4"], duration: "8" }),      ];      // Create the beams      var beam = new Vex.Flow.Beam(notes);      var beam2 = new Vex.Flow.Beam(notes2);      var beam3 = new Vex.Flow.Beam(notes3);      var beam4 = new Vex.Flow.Beam(notes4);      // Create a tie between the last note of the first group and the      // first note of the last group.      var tie = new Vex.Flow.StaveTie({        first_note: notes[1],        last_note: notes2[0],        first_indices: [0],        last_indices: [0]      });      // Create another tie between the two chords in the tune      var tie2 = new Vex.Flow.StaveTie({        first_note: notes2[2],        last_note: notes3[0],        first_indices: [0, 1],        last_indices: [0, 1]      });      var all_notes = notes.concat(notes2).concat(notes3).concat(notes4);      // Helper function to justify and draw a 4/4 voice      Vex.Flow.Formatter.FormatAndDraw(ctx, stave, all_notes);      // Render beams      beam.setContext(ctx).draw();      beam2.setContext(ctx).draw();      beam3.setContext(ctx).draw();      beam4.setContext(ctx).draw();      // Render ties      tie.setContext(ctx).draw();      tie2.setContext(ctx).draw();    }  );  var tmp_c1 = document.createElement("canvas");  tmp_c1.width = 1920;  tmp_c1.height = 1080 * 30;  repeat(    "[VexFlow | huge] Format & draw 20 staves with 5 voices each, reusing the canvas.", 50,    "...",    function(){      var canvas = tmp_c1;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++) {        var stave = new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        );        stave.addClef("treble");        stave.setContext(ctx).draw();        var voices = [];        for (var i = 0, voice; i < 5; i++) {          voice = new Vex.Flow.Voice({            num_beats: 4,            beat_value: 4,            resolution: Vex.Flow.RESOLUTION          });          voice.addTickables(randomNotes());          voices.push(voice);        }        var formatter = new Vex.Flow.Formatter().        joinVoices(voices).format(voices, 500);        for (var i = 0; i < 5; i++) {          voices[i].draw(ctx, stave);        }      }    }  );  var tmp_c1 = document.createElement("canvas");  tmp_c1.width = 1920;  tmp_c1.height = 100;  repeat(    "[VexFlow | normal] Format & draw 20 staves with 5 voices each, reusing the canvas.", 50,    "...",    function(){      var canvas = tmp_c1;      var renderer = new Vex.Flow.Renderer(canvas, Vex.Flow.Renderer.Backends.CANVAS);      var ctx = renderer.getContext();      for (var j=0; j < 20; j++) {        var stave = new Vex.Flow.Stave(          Math.floor(Math.random()*canvas.width),          Math.floor(Math.random()*canvas.height),          Math.floor(Math.random()*canvas.width)        );        stave.addClef("treble");        stave.setContext(ctx).draw();        var voices = [];        for (var i = 0, voice; i < 5; i++) {          voice = new Vex.Flow.Voice({            num_beats: 4,            beat_value: 4,            resolution: Vex.Flow.RESOLUTION          });          voice.addTickables(randomNotes());          voices.push(voice);        }        var formatter = new Vex.Flow.Formatter().        joinVoices(voices).format(voices, 500);        for (var i = 0; i < 5; i++) {          voices[i].draw(ctx, stave);        }      }    }  );  finish(t);}//----------------------------------------------------------------------------->// Helper functions// Init functionwindow.onload = function () {  window.setTimeout(start, 0);}var randomNotes = function () {  var notes = [];  for (var i = 0, note, key; i < 8; i ++) {    key = ("abcdefg".charAt(Math.floor(Math.random()*7))) + "/" + Math.floor(Math.random()*3+2);    note = new Vex.Flow.StaveNote({ keys: [key], duration: "8" });    notes.push(note);  }  return notes;}//----------------------------------------------------------------------------->var finish = function (t) {  window.setTimeout(function(){    write("<hr><p><b>Total Elapsed Time: ~" + Math.floor(t()/1000) + " seconds.</b></p>");    document.close();  }, 0);}// Display the result of a test on the pagefunction formatResult(label, descr, times, elapsed) {  write("<p><b>" + label + "</b>: " + descr + "<br>");  write("<i>Elapsed time: " + (elapsed/times) + "ms each (" + times + " iterations)</i></Op>");}// A simple timervar timer = function() {    var start = new Date();    return function() {      return (new Date()).getTime() - start.getTime();    }}// Repeat a testvar repeat0 = function(label, times, descr, func) {  //debugger;  var t = timer();  for (var i = 0; i < times; i++) func();  formatResult(label, descr, times, t());}var repeat = function(label, times, descr, func) {  window.setTimeout(function(){    repeat0(label, times, descr, func);  }, 0);}var write = function(x) {  var div = document.createElement("div");  div.innerHTML = x;  document.body.appendChild(div);}//----------------------------------------------------------------------------->}());</script><!---------------------------------------------------------------><script src="../node_modules/vexflow/releases/vexflow-min.js"></script><!------></head></html><!--------------------------------------------------------------->
 |