Chris@34
|
1 "use strict";
|
Chris@34
|
2
|
Chris@34
|
3 var VampExamplePlugins = require("./VampExamplePlugins");
|
Chris@34
|
4 var exampleModule = VampExamplePlugins();
|
Chris@34
|
5
|
Chris@34
|
6 // It is possible to declare both parameters and return values as
|
Chris@34
|
7 // "string", in which case Emscripten will take care of
|
Chris@34
|
8 // conversions. But it's not clear how one would manage memory for
|
Chris@34
|
9 // newly-constructed returned C strings -- the returned pointer from
|
Chris@34
|
10 // vampipeRequestJson would appear (?) to be thrown away by the
|
Chris@34
|
11 // Emscripten string converter if we declare it as returning a string,
|
Chris@34
|
12 // so we have no opportunity to pass it to vampipeFreeJson, which
|
Chris@34
|
13 // suggests this would leak memory if the string isn't static. Not
|
Chris@34
|
14 // wholly sure though. Anyway, passing and returning pointers (as
|
Chris@34
|
15 // numbers) means we can manage the Emscripten heap memory however we
|
Chris@34
|
16 // want in our request wrapper function below.
|
Chris@34
|
17
|
Chris@34
|
18 var vampipeRequestJson = exampleModule.cwrap(
|
Chris@34
|
19 'vampipeRequestJson', 'number', ['number']
|
Chris@34
|
20 );
|
Chris@34
|
21
|
Chris@34
|
22 var vampipeProcessRaw = exampleModule.cwrap(
|
Chris@34
|
23 "vampipeProcessRaw", "number", ["number", "number", "number", "number"]
|
Chris@34
|
24 );
|
Chris@34
|
25
|
Chris@34
|
26 var vampipeFreeJson = exampleModule.cwrap(
|
Chris@34
|
27 'vampipeFreeJson', 'void', ['number']
|
Chris@34
|
28 );
|
Chris@34
|
29
|
Chris@34
|
30 function note(blah) {
|
Chris@34
|
31 console.log(blah);
|
Chris@34
|
32 }
|
Chris@34
|
33
|
Chris@34
|
34 function comment(blah) {
|
Chris@34
|
35 console.log(blah);
|
Chris@34
|
36 }
|
Chris@34
|
37
|
Chris@34
|
38 function processRaw(request) {
|
Chris@34
|
39
|
Chris@34
|
40 const nChannels = request.processInput.inputBuffers.length;
|
Chris@34
|
41 const nFrames = request.processInput.inputBuffers[0].values.length;
|
Chris@34
|
42
|
Chris@34
|
43 const buffersPtr = exampleModule._malloc(nChannels * 4);
|
Chris@34
|
44 const buffers = new Uint32Array(
|
Chris@34
|
45 exampleModule.HEAPU8.buffer, buffersPtr, nChannels);
|
Chris@34
|
46
|
Chris@34
|
47 for (let i = 0; i < nChannels; ++i) {
|
Chris@34
|
48 const framesPtr = exampleModule._malloc(nFrames * 4);
|
Chris@34
|
49 const frames = new Float32Array(
|
Chris@34
|
50 exampleModule.HEAPU8.buffer, framesPtr, nFrames);
|
Chris@34
|
51 frames.set(request.processInput.inputBuffers[i].values);
|
Chris@34
|
52 buffers[i] = framesPtr;
|
Chris@34
|
53 }
|
Chris@34
|
54
|
Chris@34
|
55 const responseJson = vampipeProcessRaw(
|
Chris@34
|
56 request.pluginHandle,
|
Chris@34
|
57 buffersPtr,
|
Chris@34
|
58 request.processInput.timestamp.s,
|
Chris@34
|
59 request.processInput.timestamp.n);
|
Chris@34
|
60
|
Chris@34
|
61 for (let i = 0; i < nChannels; ++i) {
|
Chris@34
|
62 exampleModule._free(buffers[i]);
|
Chris@34
|
63 }
|
Chris@34
|
64 exampleModule._free(buffersPtr);
|
Chris@34
|
65
|
Chris@34
|
66 const response = JSON.parse(
|
Chris@34
|
67 exampleModule.Pointer_stringify(responseJson));
|
Chris@34
|
68
|
Chris@34
|
69 vampipeFreeJson(responseJson);
|
Chris@34
|
70
|
Chris@34
|
71 return response;
|
Chris@34
|
72 }
|
Chris@34
|
73
|
Chris@34
|
74 function request(jsonStr) {
|
Chris@34
|
75 note("Request JSON = " + jsonStr);
|
Chris@34
|
76 var m = exampleModule;
|
Chris@34
|
77 // Inspection reveals that intArrayFromString converts the string
|
Chris@34
|
78 // from utf16 to utf8, which is what we want (though the docs
|
Chris@34
|
79 // don't mention this). Note the *Cstr values are Emscripten heap
|
Chris@34
|
80 // pointers
|
Chris@34
|
81 var inCstr = m.allocate(m.intArrayFromString(jsonStr), 'i8', m.ALLOC_NORMAL);
|
Chris@34
|
82 var outCstr = vampipeRequestJson(inCstr);
|
Chris@34
|
83 m._free(inCstr);
|
Chris@34
|
84 var result = m.Pointer_stringify(outCstr);
|
Chris@34
|
85 vampipeFreeJson(outCstr);
|
Chris@34
|
86 note("Returned JSON = " + result);
|
Chris@34
|
87 return result;
|
Chris@34
|
88 }
|
Chris@34
|
89
|
Chris@34
|
90 function test() {
|
Chris@34
|
91
|
Chris@34
|
92 comment("Loading zero crossings plugin...");
|
Chris@34
|
93 let result = request('{"type":"load","content": {"pluginKey":"vamp-example-plugins:zerocrossing","inputSampleRate":44100,"adapterFlags":["AdaptAllSafe"]}}');
|
Chris@34
|
94
|
Chris@34
|
95 const blockSize = 1024;
|
Chris@34
|
96
|
Chris@34
|
97 result = request('{"type":"configure","content":{"pluginHandle":1,"configuration":{"blockSize": ' + blockSize + ', "channelCount": 1, "stepSize": ' + blockSize + '}}}');
|
Chris@34
|
98
|
Chris@34
|
99 const nblocks = 1000;
|
Chris@34
|
100
|
Chris@34
|
101 let processInputBuffers = [new Float32Array(
|
Chris@34
|
102 Array.from(Array(blockSize).keys(), n => n / blockSize))
|
Chris@34
|
103 ];
|
Chris@34
|
104
|
Chris@34
|
105 comment("Now processing " + nblocks + " blocks of 1024 samples each...");
|
Chris@34
|
106
|
Chris@34
|
107 let start = (new Date()).getTime();
|
Chris@34
|
108 comment("Start at " + start);
|
Chris@34
|
109
|
Chris@34
|
110 for (let i = 0; i < nblocks; ++i) {
|
Chris@34
|
111 let ts = { "s": i, "n": 0 }; // wholly bogus, but ZC plugin doesn't use it
|
Chris@34
|
112 result = processRaw({
|
Chris@34
|
113 "pluginHandle": 1,
|
Chris@34
|
114 "processInput": {
|
Chris@34
|
115 "timestamp": ts,
|
Chris@34
|
116 "inputBuffers": processInputBuffers
|
Chris@34
|
117 }
|
Chris@34
|
118 });
|
Chris@34
|
119 }
|
Chris@34
|
120
|
Chris@34
|
121 let finish = (new Date()).getTime();
|
Chris@34
|
122 comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
|
Chris@34
|
123
|
Chris@34
|
124 comment("Again...");
|
Chris@34
|
125
|
Chris@34
|
126 start = (new Date()).getTime();
|
Chris@34
|
127 comment("Start at " + start);
|
Chris@34
|
128
|
Chris@34
|
129 for (let i = 0; i < nblocks; ++i) {
|
Chris@34
|
130 let ts = { "s": i, "n": 0 }; // wholly bogus, but ZC plugin doesn't use it
|
Chris@34
|
131 result = processRaw({
|
Chris@34
|
132 "pluginHandle": 1,
|
Chris@34
|
133 "processInput": {
|
Chris@34
|
134 "timestamp": ts,
|
Chris@34
|
135 "inputBuffers": processInputBuffers
|
Chris@34
|
136 }
|
Chris@34
|
137 });
|
Chris@34
|
138 }
|
Chris@34
|
139
|
Chris@34
|
140 finish = (new Date()).getTime();
|
Chris@34
|
141 comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
|
Chris@34
|
142
|
Chris@34
|
143 comment("Cleaning up the plugin and getting any remaining features...");
|
Chris@34
|
144 result = request('{"type":"finish","content":{"pluginHandle":1}}');
|
Chris@34
|
145 }
|
Chris@34
|
146
|
Chris@34
|
147 test();
|
Chris@34
|
148
|