annotate perf-test.js @ 109:9d20eb251fbc

Update again to latest plugin-terminology-free schema
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 06 Oct 2016 14:32:58 +0100
parents 4845fbb1a516
children 90bf9d9f9c95
rev   line source
c@102 1 "use strict";
c@102 2
c@102 3 var exampleModule = VampExamplePluginsModule();
c@102 4
c@102 5 // It is possible to declare both parameters and return values as
c@102 6 // "string", in which case Emscripten will take care of
c@102 7 // conversions. But it's not clear how one would manage memory for
c@102 8 // newly-constructed returned C strings -- the returned pointer from
c@102 9 // vampipeRequestJson would appear (?) to be thrown away by the
c@102 10 // Emscripten string converter if we declare it as returning a string,
c@102 11 // so we have no opportunity to pass it to vampipeFreeJson, which
c@102 12 // suggests this would leak memory if the string isn't static. Not
c@102 13 // wholly sure though. Anyway, passing and returning pointers (as
c@102 14 // numbers) means we can manage the Emscripten heap memory however we
c@102 15 // want in our request wrapper function below.
c@102 16
c@102 17 var vampipeRequestJson = exampleModule.cwrap(
c@102 18 'vampipeRequestJson', 'number', ['number']
c@102 19 );
c@102 20
c@102 21 var vampipeProcessRaw = exampleModule.cwrap(
c@102 22 "vampipeProcessRaw", "number", ["number", "number", "number", "number"]
c@102 23 );
c@102 24
c@102 25 var vampipeFreeJson = exampleModule.cwrap(
c@102 26 'vampipeFreeJson', 'void', ['number']
c@102 27 );
c@102 28
c@102 29 function note(blah) {
c@102 30 document.getElementById("test-result").innerHTML += blah + "<br>";
c@102 31 }
c@102 32
c@102 33 function comment(blah) {
c@102 34 note("<br><i>" + blah + "</i>");
c@102 35 }
c@102 36
c@102 37 function processRaw(request) {
c@102 38
c@102 39 const nChannels = request.processInput.inputBuffers.length;
c@105 40 const nFrames = request.processInput.inputBuffers[0].length;
c@102 41
c@102 42 const buffersPtr = exampleModule._malloc(nChannels * 4);
c@102 43 const buffers = new Uint32Array(
c@102 44 exampleModule.HEAPU8.buffer, buffersPtr, nChannels);
c@102 45
c@102 46 for (let i = 0; i < nChannels; ++i) {
c@102 47 const framesPtr = exampleModule._malloc(nFrames * 4);
c@102 48 const frames = new Float32Array(
c@102 49 exampleModule.HEAPU8.buffer, framesPtr, nFrames);
c@105 50 frames.set(request.processInput.inputBuffers[i]);
c@102 51 buffers[i] = framesPtr;
c@102 52 }
c@102 53
c@102 54 const responseJson = vampipeProcessRaw(
c@109 55 request.handle,
c@102 56 buffersPtr,
c@102 57 request.processInput.timestamp.s,
c@102 58 request.processInput.timestamp.n);
c@102 59
c@102 60 for (let i = 0; i < nChannels; ++i) {
c@102 61 exampleModule._free(buffers[i]);
c@102 62 }
c@102 63 exampleModule._free(buffersPtr);
c@102 64
c@105 65 const responseJstr = exampleModule.Pointer_stringify(responseJson);
c@105 66 const response = JSON.parse(responseJstr);
c@102 67
c@102 68 vampipeFreeJson(responseJson);
c@102 69
c@102 70 return response;
c@102 71 }
c@102 72
c@104 73 function makeTimestamp(seconds) {
c@104 74 if (seconds >= 0.0) {
c@104 75 return {
c@104 76 s: Math.floor(seconds),
c@104 77 n: Math.floor((seconds - Math.floor(seconds)) * 1e9 + 0.5)
c@104 78 };
c@104 79 } else {
c@104 80 const { s, n } = makeTimestamp(-seconds);
c@104 81 return { s: -s, n: -n };
c@104 82 }
c@104 83 }
c@104 84
c@104 85 function frame2timestamp(frame, rate) {
c@104 86 return makeTimestamp(frame / rate);
c@104 87 }
c@104 88
c@102 89 function request(jsonStr) {
c@102 90 note("Request JSON = " + jsonStr);
c@102 91 var m = exampleModule;
c@102 92 // Inspection reveals that intArrayFromString converts the string
c@102 93 // from utf16 to utf8, which is what we want (though the docs
c@102 94 // don't mention this). Note the *Cstr values are Emscripten heap
c@102 95 // pointers
c@102 96 var inCstr = m.allocate(m.intArrayFromString(jsonStr), 'i8', m.ALLOC_NORMAL);
c@102 97 var outCstr = vampipeRequestJson(inCstr);
c@102 98 m._free(inCstr);
c@102 99 var result = m.Pointer_stringify(outCstr);
c@102 100 vampipeFreeJson(outCstr);
c@102 101 note("Returned JSON = " + result);
c@102 102 return result;
c@102 103 }
c@102 104
c@104 105 function myFromBase64(b64) {
c@104 106 while (b64.length % 4 > 0) { b64 += "="; }
c@104 107 let conv = new Float32Array(toByteArray(b64).buffer);
c@104 108 return conv;
c@104 109 }
c@104 110
c@104 111 function convertWireFeature(wfeature) {
c@104 112 let out = {};
c@104 113 if (wfeature.timestamp != null) {
c@104 114 out.timestamp = wfeature.timestamp;
c@104 115 }
c@104 116 if (wfeature.duration != null) {
c@104 117 out.duration = wfeature.duration;
c@104 118 }
c@104 119 if (wfeature.label != null) {
c@104 120 out.label = wfeature.label;
c@104 121 }
c@105 122 const vv = wfeature.featureValues;
c@105 123 if (vv != null) {
c@105 124 if (typeof vv === "string") {
c@105 125 out.featureValues = myFromBase64(vv);
c@105 126 } else {
c@105 127 out.featureValues = new Float32Array(vv);
c@105 128 }
c@104 129 }
c@104 130 return out;
c@104 131 }
c@104 132
c@104 133 function convertWireFeatureList(wfeatures) {
c@104 134 return wfeatures.map(convertWireFeature);
c@104 135 }
c@104 136
c@104 137 function responseToFeatureSet(response) {
c@104 138 const features = new Map();
c@109 139 const processResponse = response.result;
c@104 140 const wireFeatures = processResponse.features;
c@104 141 Object.keys(wireFeatures).forEach(key => {
c@104 142 return features.set(key, convertWireFeatureList(wireFeatures[key]));
c@104 143 });
c@104 144 return features;
c@104 145 }
c@104 146
c@102 147 function test() {
c@102 148
c@104 149 const rate = 44100;
c@104 150
c@102 151 comment("Loading zero crossings plugin...");
c@109 152 let result = request('{"method":"load","params": {"key":"vamp-example-plugins:zerocrossing","inputSampleRate":' + rate + ',"adapterFlags":["AdaptAllSafe"]}}');
c@102 153
c@102 154 const blockSize = 1024;
c@102 155
c@109 156 result = request('{"method":"configure","params":{"handle":1,"configuration":{"blockSize": ' + blockSize + ', "channelCount": 1, "stepSize": ' + blockSize + '}}}');
c@102 157
c@102 158 const nblocks = 1000;
c@102 159
c@104 160 const makeBlock = (n => {
c@104 161 return {
c@104 162 timestamp : frame2timestamp(n * blockSize, rate),
c@104 163 inputBuffers : [
c@105 164 new Float32Array(Array.from(Array(blockSize).keys(),
c@105 165 n => n / blockSize))
c@104 166 ],
c@104 167 }
c@104 168 });
c@104 169
c@104 170 const blocks = Array.from(Array(nblocks).keys(), makeBlock);
c@102 171
c@102 172 comment("Now processing " + nblocks + " blocks of 1024 samples each...");
c@102 173
c@104 174 let total = 0;
c@104 175
c@102 176 let start = (new Date()).getTime();
c@102 177 comment("Start at " + start);
c@102 178
c@102 179 for (let i = 0; i < nblocks; ++i) {
c@102 180 result = processRaw({
c@109 181 "handle": 1,
c@104 182 "processInput": blocks[i]
c@102 183 });
c@104 184 let features = responseToFeatureSet(result);
c@105 185 let count = features.get("counts")[0].featureValues[0];
c@104 186 total += count;
c@102 187 }
c@102 188
c@102 189 let finish = (new Date()).getTime();
c@102 190 comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
c@102 191
c@104 192 comment("Total = " + total);
c@104 193
c@102 194 comment("Again...");
c@104 195
c@104 196 total = 0;
c@102 197
c@102 198 start = (new Date()).getTime();
c@102 199 comment("Start at " + start);
c@102 200
c@102 201 for (let i = 0; i < nblocks; ++i) {
c@102 202 result = processRaw({
c@109 203 "handle": 1,
c@104 204 "processInput": blocks[i]
c@102 205 });
c@104 206 let features = responseToFeatureSet(result);
c@105 207 let count = features.get("counts")[0].featureValues[0];
c@104 208 total += count;
c@102 209 }
c@102 210
c@102 211 finish = (new Date()).getTime();
c@102 212 comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
c@102 213
c@104 214 comment("Total = " + total);
c@104 215
c@102 216 comment("Cleaning up the plugin and getting any remaining features...");
c@109 217 result = request('{"method":"finish","params":{"handle":1}}');
c@102 218 }
c@102 219
c@102 220 window.onload = function() {
c@102 221 test();
c@102 222 }