1// WAM AudioWorkletProcessor 2// Jari Kleimola 2017-18 ([email protected]) 3// 4// work in progress 5// helper class for WASM data marshalling and C function call binding 6// also provides midi, patch data, parameter and arbitrary message support 7 8if (!AudioWorkletGlobalScope.IoWAMProcessor) { 9 class IoWAMProcessor extends AudioWorkletProcessor { 10 static get parameterDescriptors() { 11 return []; 12 } 13 14 constructor(options) { 15 options = options || {}; 16 if (options.numberOfInputs === undefined) 17 options.numberOfInputs = 1; 18 if (options.numberOfOutputs === undefined) 19 options.numberOfOutputs = 1; 20 if (options.inputChannelCount === undefined) 21 options.inputChannelCount = [2]; 22 if (options.outputChannelCount === undefined) 23 options.outputChannelCount = [2]; 24 if (options.inputChannelCount.length != options.numberOfInputs) 25 throw new Error('InvalidArgumentException'); 26 if (options.outputChannelCount.length != options.numberOfOutputs) 27 throw new Error('InvalidArgumentException'); 28 29 super(options); 30 this.bufsize = 128; 31 this.sr = AudioWorkletGlobalScope.sampleRate || sampleRate; 32 this.audiobufs = [[], []]; 33 34 var WAM = options.mod; 35 this.WAM = WAM; 36 WAM.port = this.port; 37 38 // -- construction C function wrappers 39 var wam_ctor = WAM.cwrap('createModule', 'number', []); 40 var wam_init = WAM.cwrap('wam_init', null, [ 41 'number', 42 'number', 43 'number', 44 'string', 45 ]); 46 47 // -- runtime C function wrappers 48 this.wam_terminate = WAM.cwrap('wam_terminate', null, ['number']); 49 this.wam_onmidi = WAM.cwrap('wam_onmidi', null, [ 50 'number', 51 'number', 52 'number', 53 'number', 54 ]); 55 this.wam_onpatch = WAM.cwrap('wam_onpatch', null, [ 56 'number', 57 'number', 58 'number', 59 ]); 60 this.wam_onprocess = WAM.cwrap('wam_onprocess', 'number', [ 61 'number', 62 'number', 63 'number', 64 ]); 65 this.wam_onparam = WAM.cwrap('wam_onparam', 'string', [ 66 'number', 67 'string', 68 'number', 69 ]); 70 this.wam_onsysex = WAM.cwrap('wam_onsysex', null, [ 71 'number', 72 'number', 73 'number', 74 ]); 75 this.wam_onmessageN = WAM.cwrap('wam_onmessageN', null, [ 76 'number', 77 'string', 78 'string', 79 'number', 80 ]); 81 this.wam_onmessageS = WAM.cwrap('wam_onmessageS', null, [ 82 'number', 83 'string', 84 'string', 85 'string', 86 ]); 87 this.wam_ongetparams = WAM.cwrap('wam_ongetparams', 'string', [ 88 'number', 89 'string', 90 'string', 91 ]); 92 93 // -- supress warnings for older WAMs 94 if (WAM['_wam_onmessageA']) 95 this.wam_onmessageA = WAM.cwrap('wam_onmessageA', null, [ 96 'number', 97 'string', 98 'string', 99 'number', 100 'number', 101 ]); 102 103 this.inst = wam_ctor(); 104 var desc = wam_init(this.inst, this.bufsize, this.sr, ''); 105 106 // -- audio io configuration 107 this.numInputs = options.numberOfInputs; 108 this.numOutputs = options.numberOfOutputs; 109 this.numInChannels = options.inputChannelCount; 110 this.numOutChannels = options.outputChannelCount; 111 112 var ibufs = this.numInputs > 0 ? WAM._malloc(this.numInputs) : 0; 113 var obufs = this.numOutputs > 0 ? WAM._malloc(this.numOutputs) : 0; 114 this.audiobus = WAM._malloc(2 * 4); 115 WAM.setValue(this.audiobus, ibufs, 'i32'); 116 WAM.setValue(this.audiobus + 4, obufs, 'i32'); 117 118 for (var i = 0; i < this.numInputs; i++) { 119 var numChannels = this.numInChannels[i]; 120 for (var c = 0; c < numChannels; c++) { 121 var buf = WAM._malloc(this.bufsize * 4); 122 WAM.setValue(ibufs + (i * numChannels + c) * 4, buf, 'i32'); 123 this.audiobufs[0].push(buf / 4); 124 } 125 } 126 for (var i = 0; i < this.numOutputs; i++) { 127 var numChannels = this.numOutChannels[i]; 128 for (var c = 0; c < numChannels; c++) { 129 var buf = WAM._malloc(this.bufsize * 4); 130 WAM.setValue(obufs + (i * numChannels + c) * 4, buf, 'i32'); 131 this.audiobufs[1].push(buf / 4); 132 } 133 } 134 135 this.port.onmessage = this.onmessage.bind(this); 136 this.port.start(); 137 } 138 139 onmessage(e) { 140 var msg = e.data; 141 var data = msg.data; 142 switch (msg.type) { 143 case 'midi': 144 this.onmidi(data[0], data[1], data[2]); 145 break; 146 case 'sysex': 147 this.onsysex(data); 148 break; 149 case 'patch': 150 this.onpatch(data); 151 break; 152 case 'param': 153 if (msg.value === 'undefined') 154 var real_value_return = this.onparam(msg.key, -1); 155 else 156 var real_value_return = this.onparam( 157 msg.key, 158 msg.value, 159 ); 160 this.port.postMessage({ 161 type: 'getrealparam', 162 data: { 163 param_name: msg.key, 164 real_value: real_value_return, 165 }, 166 }); 167 break; 168 case 'getparams': 169 var value_return = this.ongetparams(msg); 170 171 this.port.postMessage({ 172 type: 'getparams', 173 value: value_return, 174 }); 175 break; 176 case 'msg': 177 this.onmsg(msg.verb, msg.prop, msg.data); 178 break; 179 //case "osc": this.onmsg(msg.prop, msg.type, msg.data); break; 180 } 181 } 182 183 onmidi(status, data1, data2) { 184 this.wam_onmidi(this.inst, status, data1, data2); 185 } 186 187 onparam(key, value) { 188 return this.wam_onparam(this.inst, key, value); 189 } 190 191 ongetparams(key) { 192 return this.wam_ongetparams(this.inst, key); 193 } 194 195 onmsg(verb, prop, data) { 196 if (data instanceof ArrayBuffer) { 197 var buffer = new Uint8Array(data); 198 var len = data.byteLength; 199 var WAM = this.WAM; 200 var buf = WAM._malloc(data.byteLength); 201 for (var i = 0; i < len; i++) 202 WAM.setValue(buf + i, buffer[i], 'i8'); 203 this.wam_onmessageA(this.inst, verb, prop, buf, len); 204 WAM._free(buf); 205 } else if (typeof data === 'string') 206 this.wam_onmessageS(this.inst, verb, prop, data); 207 else this.wam_onmessageN(this.inst, verb, prop, data); 208 } 209 210 onpatch(data) { 211 var buffer = new Uint8Array(data); 212 var len = data.byteLength; 213 var WAM = this.WAM; 214 var buf = WAM._malloc(len); 215 for (var i = 0; i < len; i++) 216 WAM.setValue(buf + i, buffer[i], 'i8'); 217 this.wam_onpatch(this.inst, buf, len); 218 WAM._free(buf); 219 } 220 221 onsysex(data) { 222 var WAM = this.WAM; 223 var buf = WAM._malloc(data.length); 224 for (var i = 0; i < data.length; i++) 225 WAM.setValue(buf + i, data[i], 'i8'); 226 this.wam_onsysex(this.inst, buf, data.length); 227 WAM._free(buf); 228 } 229 230 process(inputs, outputs, params) { 231 // var WAM = this.WAM; 232 // -- inputs 233 // console.log("process number inputs: " + this.numInputs); 234 // console.log(inputs); 235 236 for (var i = 0; i < this.numInputs; i++) { 237 // console.log("process number input channels: " + this.numInChannels[i]); 238 var numChannels = this.numInChannels[i]; 239 for (var c = 0; c < numChannels; c++) {
240 var waain = inputs[i][0]; 241 242 if (!waain) { 243 return true; 244 } 245 246 var wamin = this.audiobufs[0][i * numChannels + c]; 247 if (waain === undefined) 248 break; 249 this.WAM.HEAPF32.set(waain, wamin); 250 } 251 } 252 253 this.wam_onprocess(this.inst, this.audiobus, inputs); 254 255 // -- outputs 256 // console.log("process number outputs: " + this.numOutputs); 257 for (var i = 0; i < this.numOutputs; i++) { 258 var numChannels = this.numOutChannels[i]; 259 for (var c = 0; c < numChannels; c++) { 260 var waaout = outputs[i][c]; 261 var wamout = this.audiobufs[1][i * numChannels + c]; 262 waaout.set( 263 this.WAM.HEAPF32.subarray(wamout, wamout + this.bufsize), 264 ); 265 } 266 } 267 268 return true; 269 } 270 } 271 272 // -- hack to share data between addModule() calls 273 AudioWorkletGlobalScope.IoWAMProcessor = IoWAMProcessor; 274} 275!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="17d45d05-070a-50f9-9882-9db19f45022d")}catch(e){}}(); 276//# debugId=17d45d05-070a-50f9-9882-9db19f45022d
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.