annotate test/node-load-test.js @ 176:eaf46e7647a0 tip master

Update for latest Emscripten - Pointer_stringify has apparently been deprecated for a while, and was removed in v1.38.27
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 27 Feb 2019 11:29:53 +0000
parents a91b4defa581
children
rev   line source
c@127 1 "use strict";
c@127 2
c@127 3 function note(blah) {
c@127 4 console.log(blah);
c@127 5 }
c@127 6
c@129 7 if (process.argv.length < 3 || process.argv.length > 4) {
c@129 8 note("\nUsage: " + process.argv[0] + " <librarypath> [<pluginkey>]");
c@129 9 note("e.g. " + process.argv[0] + " ./VampExamplePlugins.js");
c@127 10 note("e.g. " + process.argv[0] + " ./VampExamplePlugins.js vamp-example-plugins:zerocrossing");
c@129 11 throw "Wrong number of command-line args (1 or 2 expected)"
c@127 12 }
c@127 13
c@127 14 var libraryPath = process.argv[2];
c@129 15
c@129 16 var pluginKey = "";
c@129 17 if (process.argv.length > 3) {
c@129 18 pluginKey = process.argv[3];
c@129 19 }
c@127 20
c@127 21 var base64 = require("./base64");
c@127 22
c@127 23 note("Loading library \"" + libraryPath + "\"...");
c@127 24 var extractor = require(libraryPath);
c@127 25
cannam@175 26 extractor().then(function(extractorModule) {
c@127 27
cannam@175 28 var piperRequestJson = extractorModule.cwrap(
cannam@175 29 'piperRequestJson', 'number', ['number']
cannam@175 30 );
c@127 31
cannam@175 32 var piperProcessRaw = extractorModule.cwrap(
cannam@175 33 "piperProcessRaw", "number", ["number", "number", "number", "number"]
cannam@175 34 );
c@127 35
cannam@175 36 var piperFreeJson = extractorModule.cwrap(
cannam@175 37 'piperFreeJson', 'void', ['number']
cannam@175 38 );
c@127 39
cannam@175 40 function processRaw(request) {
cannam@175 41
cannam@175 42 const nChannels = request.processInput.inputBuffers.length;
cannam@175 43 const nFrames = request.processInput.inputBuffers[0].length;
c@127 44
cannam@175 45 const buffersPtr = extractorModule._malloc(nChannels * 4);
cannam@175 46 const buffers = new Uint32Array(
cannam@175 47 extractorModule.HEAPU8.buffer, buffersPtr, nChannels);
cannam@175 48
cannam@175 49 for (let i = 0; i < nChannels; ++i) {
cannam@175 50 const framesPtr = extractorModule._malloc(nFrames * 4);
cannam@175 51 const frames = new Float32Array(
cannam@175 52 extractorModule.HEAPU8.buffer, framesPtr, nFrames);
cannam@175 53 frames.set(request.processInput.inputBuffers[i]);
cannam@175 54 buffers[i] = framesPtr;
cannam@175 55 }
cannam@175 56
cannam@175 57 const responseJson = piperProcessRaw(
cannam@175 58 request.handle,
cannam@175 59 buffersPtr,
cannam@175 60 request.processInput.timestamp.s,
cannam@175 61 request.processInput.timestamp.n);
cannam@175 62
cannam@175 63 for (let i = 0; i < nChannels; ++i) {
cannam@175 64 extractorModule._free(buffers[i]);
cannam@175 65 }
cannam@175 66 extractorModule._free(buffersPtr);
cannam@175 67
cannam@176 68 const responseJstr = extractorModule.UTF8ToString(responseJson);
cannam@175 69 const response = JSON.parse(responseJstr);
cannam@175 70
cannam@175 71 piperFreeJson(responseJson);
cannam@175 72
cannam@175 73 return response;
c@127 74 }
c@127 75
cannam@175 76 function makeTimestamp(seconds) {
cannam@175 77 if (seconds >= 0.0) {
cannam@175 78 return {
cannam@175 79 s: Math.floor(seconds),
cannam@175 80 n: Math.floor((seconds - Math.floor(seconds)) * 1e9 + 0.5)
cannam@175 81 };
c@127 82 } else {
cannam@175 83 const { s, n } = makeTimestamp(-seconds);
cannam@175 84 return { s: -s, n: -n };
c@127 85 }
c@127 86 }
c@127 87
cannam@175 88 function frame2timestamp(frame, rate) {
cannam@175 89 return makeTimestamp(frame / rate);
cannam@175 90 }
c@127 91
cannam@175 92 function request(req) {
cannam@175 93 var jsonStr = JSON.stringify(req);
cannam@175 94 var m = extractorModule;
cannam@175 95 // Inspection reveals that intArrayFromString converts the string
cannam@175 96 // from utf16 to utf8, which is what we want (though the docs
cannam@175 97 // don't mention this). Note the *Cstr values are Emscripten heap
cannam@175 98 // pointers
cannam@175 99 let inCstr = m.allocate(m.intArrayFromString(jsonStr), 'i8', m.ALLOC_NORMAL);
cannam@175 100 let outCstr = piperRequestJson(inCstr);
cannam@175 101 m._free(inCstr);
cannam@176 102 const responseJstr = m.UTF8ToString(outCstr);
cannam@175 103 const response = JSON.parse(responseJstr);
cannam@175 104 piperFreeJson(outCstr);
cannam@175 105 return response;
cannam@175 106 }
c@127 107
cannam@175 108 function myFromBase64(b64) {
cannam@175 109 while (b64.length % 4 > 0) { b64 += "="; }
cannam@175 110 let conv = new Float32Array(base64.toByteArray(b64).buffer);
cannam@175 111 return conv;
c@129 112 }
c@129 113
cannam@175 114 function convertWireFeature(wfeature) {
cannam@175 115 let out = {};
cannam@175 116 if (wfeature.timestamp != null) {
cannam@175 117 out.timestamp = wfeature.timestamp;
c@127 118 }
cannam@175 119 if (wfeature.duration != null) {
cannam@175 120 out.duration = wfeature.duration;
cannam@175 121 }
cannam@175 122 if (wfeature.label != null) {
cannam@175 123 out.label = wfeature.label;
cannam@175 124 }
cannam@175 125 const vv = wfeature.featureValues;
cannam@175 126 if (vv != null) {
cannam@175 127 if (typeof vv === "string") {
cannam@175 128 out.featureValues = myFromBase64(vv);
cannam@175 129 } else {
cannam@175 130 out.featureValues = new Float32Array(vv);
c@127 131 }
c@127 132 }
cannam@175 133 return out;
cannam@175 134 }
c@127 135
cannam@175 136 function convertWireFeatureList(wfeatures) {
cannam@175 137 return wfeatures.map(convertWireFeature);
cannam@175 138 }
c@127 139
cannam@175 140 function responseToFeatureSet(response) {
cannam@175 141 const features = new Map();
cannam@175 142 const processResponse = response.result;
cannam@175 143 const wireFeatures = processResponse.features;
cannam@175 144 Object.keys(wireFeatures).forEach(key => {
cannam@175 145 return features.set(key, convertWireFeatureList(wireFeatures[key]));
cannam@175 146 });
cannam@175 147 return features;
cannam@175 148 }
cannam@175 149
cannam@175 150 function checkSuccess(response) {
cannam@175 151 if (response.error) {
cannam@175 152 console.log("Request type " + response.method + " failed: " +
cannam@175 153 response.error.message);
cannam@175 154 throw response.error.message;
c@127 155 }
cannam@175 156 }
c@127 157
cannam@175 158 function test() {
cannam@175 159
cannam@175 160 let start = (new Date()).getTime();
cannam@175 161
cannam@175 162 const rate = 44100;
cannam@175 163
cannam@175 164 note("Listing plugins...");
cannam@175 165 let response = request({
cannam@175 166 method: "list"
cannam@175 167 });
cannam@175 168 checkSuccess(response);
cannam@175 169
cannam@175 170 if (pluginKey === "") {
cannam@175 171 pluginKey = response.result.available[0].key;
cannam@175 172 note("Loading first plugin \"" + pluginKey + "\"...");
cannam@175 173 } else {
cannam@175 174 note("Loading requested plugin \"" + pluginKey + "\"...");
cannam@175 175 }
cannam@175 176
cannam@175 177 response = request({
cannam@175 178 method: "load",
cannam@175 179 params: {
cannam@175 180 key: pluginKey,
cannam@175 181 inputSampleRate: rate,
cannam@175 182 adapterFlags: ["AdaptAllSafe"]
cannam@175 183 }
cannam@175 184 });
cannam@175 185
cannam@175 186 // note("Load request returned: " + JSON.stringify(response) + "\n");
cannam@175 187
cannam@175 188 checkSuccess(response);
cannam@175 189
cannam@175 190 var blockSize = response.result.defaultConfiguration.framing.blockSize;
cannam@175 191 var stepSize = response.result.defaultConfiguration.framing.stepSize;
cannam@175 192
cannam@175 193 response = request({
cannam@175 194 method: "configure",
cannam@175 195 params: {
cannam@175 196 handle: 1,
cannam@175 197 configuration: {
cannam@175 198 framing: {
cannam@175 199 blockSize: blockSize,
cannam@175 200 stepSize: stepSize,
cannam@175 201 },
cannam@175 202 channelCount: 1
cannam@175 203 }
cannam@175 204 }
cannam@175 205 });
cannam@175 206 checkSuccess(response);
cannam@175 207
cannam@175 208 blockSize = response.result.framing.blockSize;
cannam@175 209 stepSize = response.result.framing.stepSize;
cannam@175 210
cannam@175 211 const nblocks = 1000;
cannam@175 212
cannam@175 213 const makeBlock = (n => {
cannam@175 214 return {
cannam@175 215 timestamp : frame2timestamp(n * blockSize, rate),
cannam@175 216 inputBuffers : [
cannam@175 217 new Float32Array(Array.from(Array(blockSize).keys(),
cannam@175 218 n => n / blockSize))
cannam@175 219 ],
cannam@175 220 }
cannam@175 221 });
cannam@175 222
cannam@175 223 const blocks = Array.from(Array(nblocks).keys(), makeBlock);
cannam@175 224
cannam@175 225 note("Now processing " + nblocks + " blocks of 1024 samples each...");
cannam@175 226
cannam@175 227 let featureCount = 0;
cannam@175 228
cannam@175 229 for (let i = 0; i < nblocks; ++i) {
cannam@175 230 response = processRaw({
cannam@175 231 "handle": 1,
cannam@175 232 "processInput": blocks[i]
cannam@175 233 });
cannam@175 234 let features = responseToFeatureSet(response);
cannam@175 235 for (let featureList of features.values()) {
cannam@175 236 featureCount += featureList.length;
cannam@175 237 }
cannam@175 238 }
cannam@175 239
cannam@175 240 note("Cleaning up the plugin and getting any remaining features...");
cannam@175 241 response = request({
cannam@175 242 method: "finish",
cannam@175 243 params: {
cannam@175 244 handle: 1
cannam@175 245 }
cannam@175 246 });
cannam@175 247 checkSuccess(response);
cannam@175 248
c@127 249 let features = responseToFeatureSet(response);
c@127 250 for (let featureList of features.values()) {
c@127 251 featureCount += featureList.length;
c@127 252 }
cannam@175 253
cannam@175 254 note("Done, total number of features across all outputs = " + featureCount);
cannam@175 255
cannam@175 256 let finish = (new Date()).getTime();
cannam@175 257 note("Total time taken " + (finish - start) + " ms");
c@127 258 }
c@127 259
cannam@175 260 test();
cannam@175 261 });
c@127 262
c@132 263