UNPKG

ngx-tencent-im

Version:
1,368 lines (1,251 loc) 1.13 MB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.BenzAMRRecorder = factory()); }(this, function () { var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var recorder_build = createCommonjsModule(function (module, exports) { (function (global, factory) { module.exports = factory(); }(commonjsGlobal, (function () { var recorderWorker = function () { var recLength = 0, recBuffersL = [], recBuffersR = [], sampleRate; self.onmessage = function (e) { switch (e.data.command) { case 'init': init(e.data.config); break; case 'record': record(e.data.buffer); break; case 'exportWAV': exportWAV(e.data.type); break; case 'getBuffer': getBuffer(); break; case 'clear': clear(); break; } }; function init(config) { sampleRate = config.sampleRate; } function record(inputBuffer) { recBuffersL.push(inputBuffer[0]); recBuffersR.push(inputBuffer[1]); recLength += inputBuffer[0].length; } function exportWAV(type) { var bufferL = mergeBuffers(recBuffersL, recLength); var bufferR = mergeBuffers(recBuffersR, recLength); var interleaved = interleave(bufferL, bufferR); var dataview = encodeWAV(interleaved); var audioBlob = new Blob([dataview], {type: type}); self.postMessage({ type: 'blob', data: audioBlob }); } function getBuffer() { var buffers = []; buffers.push(mergeBuffers(recBuffersL, recLength)); buffers.push(mergeBuffers(recBuffersR, recLength)); self.postMessage({ type: 'buffer', data: buffers }); } function clear() { recLength = 0; recBuffersL = []; recBuffersR = []; } function mergeBuffers(recBuffers, recLength) { var result = new Float32Array(recLength); var offset = 0; for (var i = 0; i < recBuffers.length; i++) { result.set(recBuffers[i], offset); offset += recBuffers[i].length; } return result; } function interleave(inputL, inputR) { var length = inputL.length + inputR.length; var result = new Float32Array(length); var index = 0, inputIndex = 0; while (index < length) { result[index++] = inputL[inputIndex]; result[index++] = inputR[inputIndex]; inputIndex++; } return result; } function floatTo16BitPCM(output, offset, input) { for (var i = 0; i < input.length; i++, offset += 2) { var s = Math.max(-1, Math.min(1, input[i])); output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); } } function writeString(view, offset, string) { for (var i = 0; i < string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } } function encodeWAV(samples) { var buffer = new ArrayBuffer(44 + samples.length * 2); var view = new DataView(buffer); /* RIFF identifier */ writeString(view, 0, 'RIFF'); /* RIFF chunk length */ view.setUint32(4, 36 + samples.length * 2, true); /* RIFF type */ writeString(view, 8, 'WAVE'); /* format chunk identifier */ writeString(view, 12, 'fmt '); /* format chunk length */ view.setUint32(16, 16, true); /* sample format (raw) */ view.setUint16(20, 1, true); /* channel count */ view.setUint16(22, 2, true); /* sample rate */ view.setUint32(24, sampleRate, true); /* byte rate (sample rate * block align) */ view.setUint32(28, sampleRate * 4, true); /* block align (channel count * bytes per sample) */ view.setUint16(32, 4, true); /* bits per sample */ view.setUint16(34, 16, true); /* data chunk identifier */ writeString(view, 36, 'data'); /* data chunk length */ view.setUint32(40, samples.length * 2, true); floatTo16BitPCM(view, 44, samples); return view; } }; var recorderWorkerStr = recorderWorker.toString() .replace(/^\s*function.*?\(\)\s*{/, '') .replace(/}\s*$/, ''); // var WORKER_PATH = './recorderWorker.js'; var Recorder = function(source, cfg){ var config = cfg || {}; var bufferLen = config.bufferLen || 4096; this.context = source.context; this.node = (this.context.createScriptProcessor || this.context.createJavaScriptNode).call(this.context, bufferLen, 2, 2); var worker = new Worker((window.URL || window.webkitURL).createObjectURL(new Blob([recorderWorkerStr], {type:"text/javascript"}))); worker.onmessage = function(e){ if (e.data.type === 'blob') { currCallbackWithBlob(e.data.data); } else { currCallbackWithBuffer(e.data.data); } }; worker.postMessage({ command: 'init', config: { sampleRate: this.context.sampleRate } }); var recording = false, currCallbackWithBuffer, currCallbackWithBlob; this.node.onaudioprocess = function(e){ if (!recording) return; worker.postMessage({ command: 'record', buffer: [ e.inputBuffer.getChannelData(0), e.inputBuffer.getChannelData(1) ] }); }; this.configure = function(cfg){ for (var prop in cfg){ if (cfg.hasOwnProperty(prop)){ config[prop] = cfg[prop]; } } }; this.record = function(){ recording = true; }; this.stop = function(){ recording = false; }; this.clear = function(){ worker.postMessage({ command: 'clear' }); }; this.getBuffer = function(cb) { currCallbackWithBuffer = cb || config.callback; worker.postMessage({ command: 'getBuffer' }); }; this.exportWAV = function(cb, type){ currCallbackWithBlob = cb || config.callback; type = type || config.type || 'audio/wav'; if (!currCallbackWithBlob) throw new Error('Callback not set'); worker.postMessage({ command: 'exportWAV', type: type }); }; this.release = function() { this.stop(); this.clear(); this.configure = this.record = this.stop = this.clear = this.getBuffer = this.exportWAV = function () {}; source.disconnect(this.node); this.node.onaudioprocess = null; this.node.disconnect(); worker.terminate(); }; source.connect(this.node); this.node.connect(this.context.destination); //this should not be necessary }; Recorder.forceDownload = function(blob, filename){ var url = (window.URL || window.webkitURL).createObjectURL(blob); var link = window.document.createElement('a'); link.href = url; link.download = filename || 'output.wav'; var click = document.createEvent("Event"); click.initEvent("click", true, true); link.dispatchEvent(click); }; var recorder = Recorder; return recorder; }))); }); /** * @file 公共的 Web Audio API Context * @author BenzLeung(https://github.com/BenzLeung) * @date 2017/11/12 * Created by JetBrains PhpStorm. * * 每位工程师都有保持代码优雅的义务 * each engineer has a duty to keep the code elegant */ const AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext; let ctx = null; if (AudioContext) { ctx = new AudioContext(); } else { console.error(new Error('Web Audio API is Unsupported.')); } class RecorderControl { constructor() { this._recorderStream = null; this._recorderStreamSourceNode = null; this._recorder = null; this._isRecording = false; this._curSourceNode = null; } playPcm(samples, sampleRate, onEnded) { sampleRate = sampleRate || 8000; this.stopPcm(); this._curSourceNode = ctx['createBufferSource'](); let _samples = samples; let buffer, channelBuffer; try { buffer = ctx['createBuffer'](1, samples.length, sampleRate); } catch (e) { // iOS 不支持 22050 以下的采样率,于是先提升采样率,然后用慢速播放 if (sampleRate < 11025) { /*buffer = ctx['createBuffer'](1, samples.length * 3, sampleRate * 3); _samples = this._increaseSampleRate(samples, 3);*/ buffer = ctx['createBuffer'](1, samples.length, sampleRate * 4); this._curSourceNode['playbackRate'].value = 0.25; } else { /*buffer = ctx['createBuffer'](1, samples.length * 2, sampleRate * 2); _samples = this._increaseSampleRate(samples, 2);*/ buffer = ctx['createBuffer'](1, samples.length, sampleRate * 2); this._curSourceNode['playbackRate'].value = 0.5; } } if (buffer['copyToChannel']) { buffer['copyToChannel'](_samples, 0, 0); } else { channelBuffer = buffer['getChannelData'](0); channelBuffer.set(_samples); } this._curSourceNode['buffer'] = buffer; this._curSourceNode['loop'] = false; this._curSourceNode['connect'](ctx['destination']); this._curSourceNode.onended = onEnded; this._curSourceNode.start(); } stopPcm() { if (this._curSourceNode) { this._curSourceNode.stop(); this._curSourceNode = null; } } initRecorder() { return new Promise((resolve, reject) => { let s = stream => { this._recorderStream = stream; this._recorderStreamSourceNode = ctx.createMediaStreamSource(stream); this._recorder = new recorder_build(this._recorderStreamSourceNode); this._isRecording = false; resolve(); }; let j = e => { reject(e); }; if (!this._recorder) { if (window.navigator.mediaDevices && window.navigator.mediaDevices.getUserMedia) { window.navigator.mediaDevices.getUserMedia({ audio: true }).then(s).catch(j); } else if (window.navigator.getUserMedia) { window.navigator.getUserMedia({ audio: true }, s, j); } else { j(); } } else { resolve(); } }); } isRecording() { return this._recorder && this._isRecording; } startRecord() { if (this._recorder) { this._recorder.clear(); this._recorder.record(); this._isRecording = true; } } stopRecord() { if (this._recorder) { this._recorder.stop(); this._isRecording = false; } } generateRecordSamples() { return new Promise(resolve => { if (this._recorder) { this._recorder.getBuffer(buffers => { resolve(buffers[0]); }); } }); } releaseRecord() { if (this._recorderStream && this._recorderStream.getTracks) { this._recorderStream.getTracks().forEach(track => { track.stop(); }); this._recorderStream = null; } if (this._recorder) { this._recorder.release(); this._recorder = null; } } static getCtxSampleRate() { return ctx.sampleRate; } static decodeAudioArrayBufferByContext(array) { return new Promise((resolve, reject) => { ctx['decodeAudioData'](array, audioBuf => { // 把多声道音频 mix 成单声道 const numberOfChannels = audioBuf.numberOfChannels; let dest = new Float32Array(audioBuf.length); switch (numberOfChannels) { default: case 1: { dest = audioBuf.getChannelData(0); break; } case 2: { const left = audioBuf.getChannelData(0); const right = audioBuf.getChannelData(1); for (let i = 0, l = dest.length; i < l; i++) { dest[i] = .5 * (left[i] + right[i]); } break; } case 4: { const left = audioBuf.getChannelData(0); const right = audioBuf.getChannelData(1); const sLeft = audioBuf.getChannelData(2); const sRight = audioBuf.getChannelData(3); for (let i = 0, l = dest.length; i < l; i++) { dest[i] = .25 * (left[i] + right[i] + sLeft[i] + sRight[i]); } break; } case 6: { const left = audioBuf.getChannelData(0); const right = audioBuf.getChannelData(1); const center = audioBuf.getChannelData(2); const sLeft = audioBuf.getChannelData(4); const sRight = audioBuf.getChannelData(5); for (let i = 0, l = dest.length; i < l; i++) { dest[i] = 0.7071 * (left[i] + right[i]) + center[i] + 0.5 * (sLeft[i] + sRight[i]); } break; } } resolve(dest); }, reject); }); } /* static _increaseSampleRate(samples, multiple) { let sampleLen = samples.length; let newSamples = new Float32Array(sampleLen * multiple); for (let i = 0; i < sampleLen; i ++) { for (let j = 0; j < multiple; j ++) { newSamples[i * multiple + j] = samples[i]; } } return newSamples; }; */ } var amrnb = function() { var AMR = (function () { var AMR = { toWAV: (function (amr) { var decoded = this._decode(amr); if (!decoded) { return null } var raw = new Uint8Array(decoded.buffer, decoded.byteOffset, decoded.byteLength); var out = new Uint8Array(raw.length + this.WAV_HEADER_SIZE); var offset = 0; var write_int16 = (function (value) { var a = new Uint8Array(2); (new Int16Array(a.buffer))[0] = value; out.set(a, offset); offset += 2; }); var write_int32 = (function (value) { var a = new Uint8Array(4); (new Int32Array(a.buffer))[0] = value; out.set(a, offset); offset += 4; }); var write_string = (function (value) { var d = (new TextEncoder("utf-8")).encode(value); out.set(d, offset); offset += d.length; }); write_string("RIFF"); write_int32(4 + 8 + 16 + 8 + raw.length); write_string("WAVEfmt "); write_int32(16); var bits_per_sample = 16; var sample_rate = 8e3; var channels = 1; var bytes_per_frame = bits_per_sample / 8 * channels; var bytes_per_sec = bytes_per_frame * sample_rate; write_int16(1); write_int16(1); write_int32(sample_rate); write_int32(bytes_per_sec); write_int16(bytes_per_frame); write_int16(bits_per_sample); write_string("data"); write_int32(raw.length); out.set(raw, offset); return out }), decode: (function (amr) { var raw = this._decode(amr); if (!raw) { return null } var out = new Float32Array(raw.length); for (var i = 0; i < out.length; i++) { out[i] = raw[i] / 32768; } return out }), _decode: (function (amr) { if (String.fromCharCode.apply(null, amr.subarray(0, this.AMR_HEADER.length)) !== this.AMR_HEADER) { return null } var decoder = this.Decoder_Interface_init(); if (!decoder) { return null } var out = new Int16Array(Math.floor(amr.length / 6 * this.PCM_BUFFER_COUNT)); var buf = Module._malloc(this.AMR_BUFFER_COUNT); var decodeInBuffer = new Uint8Array(Module.HEAPU8.buffer, buf, this.AMR_BUFFER_COUNT); buf = Module._malloc(this.PCM_BUFFER_COUNT * 2); var decodeOutBuffer = new Int16Array(Module.HEAPU8.buffer, buf, this.PCM_BUFFER_COUNT); var inOffset = 6; var outOffset = 0; while (inOffset + 1 < amr.length && outOffset + 1 < out.length) { var size = this.SIZES[amr[inOffset] >> 3 & 15]; if (inOffset + size + 1 > amr.length) { break } decodeInBuffer.set(amr.subarray(inOffset, inOffset + size + 1)); this.Decoder_Interface_Decode(decoder, decodeInBuffer.byteOffset, decodeOutBuffer.byteOffset, 0); if (outOffset + this.PCM_BUFFER_COUNT > out.length) { var newOut = new Int16Array(out.length * 2); newOut.set(out.subarray(0, outOffset)); out = newOut; } out.set(decodeOutBuffer, outOffset); outOffset += this.PCM_BUFFER_COUNT; inOffset += size + 1; } Module._free(decodeInBuffer.byteOffset); Module._free(decodeOutBuffer.byteOffset); this.Decoder_Interface_exit(decoder); return out.subarray(0, outOffset) }), encode: (function (pcm, pcmSampleRate, mode) { if (pcmSampleRate < 8e3) { console.error("pcmSampleRate should not be less than 8000."); return null } if (typeof mode === "undefined") { mode = this.Mode.MR795; } var encoder = this.Encoder_Interface_init(); if (!encoder) { return null } var buf = Module._malloc(this.PCM_BUFFER_COUNT * 2); var encodeInBuffer = new Int16Array(Module.HEAPU8.buffer, buf, this.PCM_BUFFER_COUNT); buf = Module._malloc(this.AMR_BUFFER_COUNT); var encodeOutBuffer = new Uint8Array(Module.HEAPU8.buffer, buf, this.AMR_BUFFER_COUNT); var ratio = pcmSampleRate / 8e3; var inLength = Math.floor(pcm.length / ratio); var inData = new Int16Array(inLength); for (var i = 0; i < inLength; i++) { inData[i] = pcm[Math.floor(i * ratio)] * (32768 - 1); } var blockSize = this.SIZES[mode] + 1; var out = new Uint8Array(Math.ceil(inLength / this.PCM_BUFFER_COUNT * blockSize) + this.AMR_HEADER.length); out.set((new TextEncoder("utf-8")).encode(this.AMR_HEADER)); var inOffset = 0; var outOffset = this.AMR_HEADER.length; while (inOffset + this.PCM_BUFFER_COUNT < inData.length && outOffset + blockSize < out.length) { encodeInBuffer.set(inData.subarray(inOffset, inOffset + this.PCM_BUFFER_COUNT)); var n = this.Encoder_Interface_Encode(encoder, mode, encodeInBuffer.byteOffset, encodeOutBuffer.byteOffset, 0); if (n != blockSize) { console.error([n, blockSize]); break } out.set(encodeOutBuffer.subarray(0, n), outOffset); inOffset += this.PCM_BUFFER_COUNT; outOffset += n; } Module._free(encodeInBuffer.byteOffset); Module._free(encodeOutBuffer.byteOffset); this.Encoder_Interface_exit(encoder); return out.subarray(0, outOffset) }), Decoder_Interface_init: (function () { console.warn("Decoder_Interface_init not initialized."); return 0 }), Decoder_Interface_exit: (function (state) { console.warn("Decoder_Interface_exit not initialized."); }), Decoder_Interface_Decode: (function (state, inBuffer, outBuffer, bfi) { console.warn("Decoder_Interface_Decode not initialized."); }), Encoder_Interface_init: (function (dtx) { console.warn("Encoder_Interface_init not initialized."); return 0 }), Encoder_Interface_exit: (function (state) { console.warn("Encoder_Interface_exit not initialized."); }), Encoder_Interface_Encode: (function (state, mode, speech, out, forceSpeech) { console.warn("Encoder_Interface_Encode not initialized."); }), Mode: {MR475: 0, MR515: 1, MR59: 2, MR67: 3, MR74: 4, MR795: 5, MR102: 6, MR122: 7, MRDTX: 8}, SIZES: [12, 13, 15, 17, 19, 20, 26, 31, 5, 6, 5, 5, 0, 0, 0, 0], AMR_BUFFER_COUNT: 32, PCM_BUFFER_COUNT: 160, AMR_HEADER: "#!AMR\n", WAV_HEADER_SIZE: 44 }; var Module = { canvas: {}, print: (function (text) { console.log(text); }), _main: (function () { AMR.Decoder_Interface_init = Module._Decoder_Interface_init; AMR.Decoder_Interface_exit = Module._Decoder_Interface_exit; AMR.Decoder_Interface_Decode = Module._Decoder_Interface_Decode; AMR.Encoder_Interface_init = Module._Encoder_Interface_init; AMR.Encoder_Interface_exit = Module._Encoder_Interface_exit; AMR.Encoder_Interface_Encode = Module._Encoder_Interface_Encode; return 0 }) }; var Module; if (!Module) Module = (typeof Module !== "undefined" ? Module : null) || {}; var moduleOverrides = {}; for (var key in Module) { if (Module.hasOwnProperty(key)) { moduleOverrides[key] = Module[key]; } } var ENVIRONMENT_IS_WEB = typeof window === "object"; var ENVIRONMENT_IS_WORKER = typeof importScripts === "function"; var ENVIRONMENT_IS_NODE = false;/*typeof process === "object" && typeof require === "function" && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER;*/ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; if (ENVIRONMENT_IS_SHELL) { if (!Module["print"]) Module["print"] = print; if (typeof printErr != "undefined") Module["printErr"] = printErr; if (typeof read != "undefined") { Module["read"] = read; } else { Module["read"] = function read() { throw"no read() available (jsc?)" }; } Module["readBinary"] = function readBinary(f) { if (typeof readbuffer === "function") { return new Uint8Array(readbuffer(f)) } var data = read(f, "binary"); assert(typeof data === "object"); return data }; if (typeof scriptArgs != "undefined") { Module["arguments"] = scriptArgs; } else if (typeof arguments != "undefined") { Module["arguments"] = arguments; } } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { Module["read"] = function read(url) { var xhr = new XMLHttpRequest; xhr.open("GET", url, false); xhr.send(null); return xhr.responseText }; if (typeof arguments != "undefined") { Module["arguments"] = arguments; } if (typeof console !== "undefined") { if (!Module["print"]) Module["print"] = function print(x) { console.log(x); }; if (!Module["printErr"]) Module["printErr"] = function printErr(x) { console.log(x); }; } else { var TRY_USE_DUMP = false; if (!Module["print"]) Module["print"] = TRY_USE_DUMP && typeof dump !== "undefined" ? (function (x) { dump(x); }) : (function (x) { }); } if (ENVIRONMENT_IS_WORKER) { Module["load"] = importScripts; } if (typeof Module["setWindowTitle"] === "undefined") { Module["setWindowTitle"] = (function (title) { document.title = title; }); } } else { throw"Unknown runtime environment. Where are we?" } function globalEval(x) { eval.call(null, x); } if (!Module["load"] && Module["read"]) { Module["load"] = function load(f) { globalEval(Module["read"](f)); }; } if (!Module["print"]) { Module["print"] = (function () { }); } if (!Module["printErr"]) { Module["printErr"] = Module["print"]; } if (!Module["arguments"]) { Module["arguments"] = []; } if (!Module["thisProgram"]) { Module["thisProgram"] = "./this.program"; } Module.print = Module["print"]; Module.printErr = Module["printErr"]; Module["preRun"] = []; Module["postRun"] = []; for (var key in moduleOverrides) { if (moduleOverrides.hasOwnProperty(key)) { Module[key] = moduleOverrides[key]; } } var Runtime = { setTempRet0: (function (value) { tempRet0 = value; }), getTempRet0: (function () { return tempRet0 }), stackSave: (function () { return STACKTOP }), stackRestore: (function (stackTop) { STACKTOP = stackTop; }), getNativeTypeSize: (function (type) { switch (type) { case"i1": case"i8": return 1; case"i16": return 2; case"i32": return 4; case"i64": return 8; case"float": return 4; case"double": return 8; default: { if (type[type.length - 1] === "*") { return Runtime.QUANTUM_SIZE } else if (type[0] === "i") { var bits = parseInt(type.substr(1)); assert(bits % 8 === 0); return bits / 8 } else { return 0 } } } }), getNativeFieldSize: (function (type) { return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE) }), STACK_ALIGN: 16, prepVararg: (function (ptr, type) { if (type === "double" || type === "i64") { if (ptr & 7) { assert((ptr & 7) === 4); ptr += 4; } } else { assert((ptr & 3) === 0); } return ptr }), getAlignSize: (function (type, size, vararg) { if (!vararg && (type == "i64" || type == "double")) return 8; if (!type) return Math.min(size, 8); return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE) }), dynCall: (function (sig, ptr, args) { if (args && args.length) { if (!args.splice) args = Array.prototype.slice.call(args); args.splice(0, 0, ptr); return Module["dynCall_" + sig].apply(null, args) } else { return Module["dynCall_" + sig].call(null, ptr) } }), functionPointers: [], addFunction: (function (func) { for (var i = 0; i < Runtime.functionPointers.length; i++) { if (!Runtime.functionPointers[i]) { Runtime.functionPointers[i] = func; return 2 * (1 + i) } } throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS." }), removeFunction: (function (index) { Runtime.functionPointers[(index - 2) / 2] = null; }), warnOnce: (function (text) { if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; if (!Runtime.warnOnce.shown[text]) { Runtime.warnOnce.shown[text] = 1; Module.printErr(text); } }), funcWrappers: {}, getFuncWrapper: (function (func, sig) { assert(sig); if (!Runtime.funcWrappers[sig]) { Runtime.funcWrappers[sig] = {}; } var sigCache = Runtime.funcWrappers[sig]; if (!sigCache[func]) { sigCache[func] = function dynCall_wrapper() { return Runtime.dynCall(sig, func, arguments) }; } return sigCache[func] }), getCompilerSetting: (function (name) { throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work" }), stackAlloc: (function (size) { var ret = STACKTOP; STACKTOP = STACKTOP + size | 0; STACKTOP = STACKTOP + 15 & -16; return ret }), staticAlloc: (function (size) { var ret = STATICTOP; STATICTOP = STATICTOP + size | 0; STATICTOP = STATICTOP + 15 & -16; return ret }), dynamicAlloc: (function (size) { var ret = DYNAMICTOP; DYNAMICTOP = DYNAMICTOP + size | 0; DYNAMICTOP = DYNAMICTOP + 15 & -16; if (DYNAMICTOP >= TOTAL_MEMORY) { var success = enlargeMemory(); if (!success) { DYNAMICTOP = ret; return 0 } } return ret }), alignMemory: (function (size, quantum) { var ret = size = Math.ceil(size / (quantum ? quantum : 16)) * (quantum ? quantum : 16); return ret }), makeBigInt: (function (low, high, unsigned) { var ret = unsigned ? +(low >>> 0) + +(high >>> 0) * +4294967296 : +(low >>> 0) + +(high | 0) * +4294967296; return ret }), GLOBAL_BASE: 8, QUANTUM_SIZE: 4, __dummy__: 0 }; Module["Runtime"] = Runtime; var ABORT = false; var tempDouble; var tempI64; var tempRet0; function assert(condition, text) { if (!condition) { abort("Assertion failed: " + text); } } function getCFunc(ident) { var func = Module["_" + ident]; if (!func) { try { func = [eval][0]("_" + ident); } catch (e) { } } assert(func, "Cannot call unknown function " + ident + " (perhaps LLVM optimizations or closure removed it?)"); return func } var cwrap, ccall; ((function () { var JSfuncs = { "stackSave": (function () { Runtime.stackSave(); }), "stackRestore": (function () { Runtime.stackRestore(); }), "arrayToC": (function (arr) { var ret = Runtime.stackAlloc(arr.length); writeArrayToMemory(arr, ret); return ret }), "stringToC": (function (str) { var ret = 0; if (str !== null && str !== undefined && str !== 0) { ret = Runtime.stackAlloc((str.length << 2) + 1); writeStringToMemory(str, ret); } return ret }) }; var toC = {"string": JSfuncs["stringToC"], "array": JSfuncs["arrayToC"]}; ccall = function ccallFunc(ident, returnType, argTypes, args, opts) { var func = getCFunc(ident); var cArgs = []; var stack = 0; if (args) { for (var i = 0; i < args.length; i++) { var converter = toC[argTypes[i]]; if (converter) { if (stack === 0) stack = Runtime.stackSave(); cArgs[i] = converter(args[i]); } else { cArgs[i] = args[i]; } } } var ret = func.apply(null, cArgs); if (returnType === "string") ret = Pointer_stringify(ret); if (stack !== 0) { if (opts && opts.async) { EmterpreterAsync.asyncFinalizers.push((function () { Runtime.stackRestore(stack); })); return } Runtime.stackRestore(stack); } return ret }; var sourceRegex = /^function\s\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/; function parseJSFunc(jsfunc) { // Match the body and the return value of a javascript function source var parsed = jsfunc.toString().match(sourceRegex); if (!parsed) { return {}; } parsed = parsed.slice(1); return {arguments: parsed[0], body: parsed[1], returnValue: parsed[2]} } var JSsource = {}; for (var fun in JSfuncs) { if (JSfuncs.hasOwnProperty(fun)) { JSsource[fun] = parseJSFunc(JSfuncs[fun]); } } cwrap = function cwrap(ident, returnType, argTypes) { argTypes = argTypes || []; var cfunc = getCFunc(ident); var numericArgs = argTypes.every((function (type) { return type === "number" })); var numericRet = returnType !== "string"; if (numericRet && numericArgs) { return cfunc } var argNames = argTypes.map((function (x, i) { return "$" + i })); var funcstr = "(function(" + argNames.join(",") + ") {"; var nargs = argTypes.length; if (!numericArgs) { funcstr += "var stack = " + JSsource["stackSave"].body + ";"; for (var i = 0; i < nargs; i++) { var arg = argNames[i], type = argTypes[i]; if (type === "number") continue; var convertCode = JSsource[type + "ToC"]; funcstr += "var " + convertCode.arguments + " = " + arg + ";"; funcstr += convertCode.body + ";"; funcstr += arg + "=" + convertCode.returnValue + ";"; } } var cfuncname = parseJSFunc((function () { return cfunc })).returnValue; funcstr += "var ret = " + cfuncname + "(" + argNames.join(",") + ");"; if (!numericRet) { var strgfy = parseJSFunc((function () { return Pointer_stringify })).returnValue; funcstr += "ret = " + strgfy + "(ret);"; } if (!numericArgs) { funcstr += JSsource["stackRestore"].body.replace("()", "(stack)") + ";"; } funcstr += "return ret})"; return [eval][0](funcstr) }; }))(); Module["ccall"] = ccall; Module["cwrap"] = cwrap; function setValue(ptr, value, type, noSafe) { type = type || "i8"; if (type.charAt(type.length - 1) === "*") type = "i32"; switch (type) { case"i1": HEAP8[ptr >> 0] = value; break; case"i8": HEAP8[ptr >> 0] = value; break; case"i16": HEAP16[ptr >> 1] = value; break; case"i32": HEAP32[ptr >> 2] = value; break; case"i64": tempI64 = [value >>> 0, (tempDouble = value, +Math_abs(tempDouble) >= +1 ? tempDouble > +0 ? (Math_min(+Math_floor(tempDouble / +4294967296), +4294967295) | 0) >>> 0 : ~~+Math_ceil((tempDouble - +(~~tempDouble >>> 0)) / +4294967296) >>> 0 : 0)], HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1]; break; case"float": HEAPF32[ptr >> 2] = value; break; case"double": HEAPF64[ptr >> 3] = value; break; default: abort("invalid type for setValue: " + type); } } Module["setValue"] = setValue; function getValue(ptr, type, noSafe) { type = type || "i8"; if (type.charAt(type.length - 1) === "*") type = "i32"; switch (type) { case"i1": return HEAP8[ptr >> 0]; case"i8": return HEAP8[ptr >> 0]; case"i16": return HEAP16[ptr >> 1]; case"i32": return HEAP32[ptr >> 2]; case"i64": return HEAP32[ptr >> 2]; case"float": return HEAPF32[ptr >> 2]; case"double": return HEAPF64[ptr >> 3]; default: abort("invalid type for setValue: " + type); } return null } Module["getValue"] = getValue; var ALLOC_NORMAL = 0; var ALLOC_STACK = 1; var ALLOC_STATIC = 2; var ALLOC_DYNAMIC = 3; var ALLOC_NONE = 4; Module["ALLOC_NORMAL"] = ALLOC_NORMAL; Module["ALLOC_STACK"] = ALLOC_STACK; Module["ALLOC_STATIC"] = ALLOC_STATIC; Module["ALLOC_DYNAMIC"] = ALLOC_DYNAMIC; Module["ALLOC_NONE"] = ALLOC_NONE; function allocate(slab, types, allocator, ptr) { var zeroinit, size; if (typeof slab === "number") { zeroinit = true; size = slab; } else { zeroinit = false; size = slab.length; } var singleType = typeof types === "string" ? types : null; var ret; if (allocator == ALLOC_NONE) { ret = ptr; } else { ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); } if (zeroinit) { var ptr = ret, stop; assert((ret & 3) == 0); stop = ret + (size & ~3); for (; ptr < stop; ptr += 4) { HEAP32[ptr >> 2] = 0; } stop = ret + size; while (ptr < stop) { HEAP8[ptr++ >> 0] = 0; } return ret } if (singleType === "i8") { if (slab.subarray || slab.slice) { HEAPU8.set(slab, ret); } else { HEAPU8.set(new Uint8Array(slab), ret); } return ret } var i = 0, type, typeSize, previousType; while (i < size) { var curr = slab[i]; if (typeof curr === "function") { curr = Runtime.getFunctionIndex(curr); } type = singleType || types[i]; if (type === 0) { i++; continue } if (type == "i64") type = "i32"; setValue(ret + i, curr, type); if (previousType !== type) { typeSize = Runtime.getNativeTypeSize(type); previousType = type; } i += typeSize; } return ret } Module["allocate"] = allocate; function getMemory(size) { if (!staticSealed) return Runtime.staticAlloc(size); if (typeof _sbrk !== "undefined" && !_sbrk.called || !runtimeInitialized) return Runtime.dynamicAlloc(size); return _malloc(size) } Module["getMemory"] = getMemory; function Pointer_stringify(ptr, length) { if (length === 0 || !ptr) return ""; var hasUtf = 0; var t; var i = 0; while (1) { t = HEAPU8[ptr + i >> 0]; hasUtf |= t; if (t == 0 && !length) break; i++; if (length && i == length) break } if (!length) length = i; var ret = ""; if (hasUtf < 128) { var MAX_CHUNK = 1024; var curr; while (length > 0) { curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); ret = ret ? ret + curr : curr; ptr += MAX_CHUNK; length -= MAX_CHUNK; } return ret } return Module["UTF8ToString"](ptr) } Module["Pointer_stringify"] = Pointer_stringify; function AsciiToString(ptr) { var str = ""; while (1) { var ch = HEAP8[ptr++ >> 0]; if (!ch) return str; str += String.fromCharCode(ch); } } Module["AsciiToString"] = AsciiToString; function stringToAscii(str, outPtr) { return writeAsciiToMemory(str, outPtr, false) } Module["stringToAscii"] = stringToAscii; function UTF8ArrayToString(u8Array, idx) { var u0, u1, u2, u3, u4, u5; var str = ""; while (1) { u0 = u8Array[idx++]; if (!u0) return str; if (!(u0 & 128)) { str += String.fromCharCode(u0); continue } u1 = u8Array[idx++] & 63; if ((u0 & 224) == 192) { str += String.fromCharCode((u0 & 31) << 6 | u1); continue } u2 = u8Array[idx++] & 63; if ((u0 & 240) == 224) { u0 = (u0 & 15) << 12 | u1 << 6 | u2; } else { u3 = u8Array[idx++] & 63; if ((u0 & 248) == 240) { u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | u3; } else { u4 = u8Array[idx++] & 63; if ((u0 & 252) == 248) { u0 = (u0 & 3) << 24 | u1 << 18 | u2 << 12 | u3 << 6 | u4; } else { u5 = u8Array[idx++] & 63; u0 = (u0 & 1) << 30 | u1 << 24 | u2 << 18 | u3 << 12 | u4 << 6 | u5; } } } if (u0 < 65536) { str += String.fromCharCode(u0); } else { var ch = u0 - 65536; str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023); } } } Module["UTF8ArrayToString"] = UTF8ArrayToString; function UTF8ToString(ptr) { return UTF8ArrayToString(HEAPU8, ptr) } Module["UTF8ToString"] = UTF8ToString; function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { if (!(maxBytesToWrite > 0)) return 0; var startIdx = outIdx; var endIdx = outIdx + maxBytesToWrite - 1; for (var i = 0; i < str.length; ++i) { var u = str.charCodeAt(i); if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023; if (u <= 127) { if (outIdx >= endIdx) break; outU8Array[outIdx++] = u; } else if (u <= 2047) { if (outIdx + 1 >= endIdx) break; outU8Array[outIdx++] = 192 | u >> 6; outU8Array[outIdx++] = 128 | u & 63; } else if (u <= 65535) { if (outIdx + 2 >= endIdx) break; outU8Array[outIdx++] = 224 | u >> 12; outU8Array[outIdx++] = 128 | u >> 6 & 63; outU8Array[outIdx++] = 128 | u & 63; } else if (u <= 2097151) { if (outIdx + 3 >= endIdx) break; outU8Array[outIdx++] = 240 | u >> 18; outU8Array[outIdx++] = 128 | u >> 12 & 63; outU8Array[outIdx++] = 128 | u >> 6 & 63; outU8Array[outIdx++] = 128 | u & 63; } else if (u <= 67108863) { if (outIdx + 4 >= endIdx) break; outU8Array[outIdx++] = 248 | u >> 24; outU8Array[outIdx++] = 128 | u >> 18 & 63; outU8Array[outIdx++] = 128 | u >> 12 & 63; outU8Array[outIdx++] = 128 | u >> 6 & 63; outU8Array[outIdx++] = 128 | u & 63; } else { if (outIdx + 5 >= endIdx) break; outU8Array[outIdx++] = 252 | u >> 30; outU8Array[outIdx++] = 128 | u >> 24 & 63; outU8Array[outIdx++] = 128 | u >> 18 & 63; outU8Array[outIdx++] = 128 | u >> 12 & 63; outU8Array[outIdx++] = 128 | u >> 6 & 63; outU8Array[outIdx++] = 128 | u & 63; } } outU8Array[outIdx] = 0; return outIdx - startIdx } Module["stringToUTF8Array"] = stringToUTF8Array; function stringToUTF8(str, outPtr, maxBytesToWrite) { return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite) } Module["stringToUTF8"] = stringToUTF8; function lengthBytesUTF8(str) { var len = 0; for (var i = 0; i < str.length; ++i) { var u = str.charCodeAt(i); if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023; if (u <= 127) { ++len; } else if (u <= 2047) { len += 2; } else if (u <= 65535) { len += 3; } else if (u <= 2097151) { len += 4; } else if (u <= 67108863) { len += 5; } else { len += 6; } } return len } Module["lengthBytesUTF8"] = lengthBytesUTF8; function UTF16ToString(ptr) { var i = 0; var str = ""; while (1) { var codeUnit = HEAP16[ptr + i * 2 >> 1]; if (codeUnit == 0) return str; ++i; str += String.fromCharCode(codeUnit); } } Module["UTF16ToString"] = UTF16ToString; function stringToUTF16(str, outPtr, maxBytesToWrite) { if (maxBytesToWrite === undefined) { maxBy