forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			203 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			203 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | // from https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletNode
 | ||
|  | 
 | ||
|  | function create_thread(func) { | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | class AudioThread extends AudioWorkletProcessor { | ||
|  |   constructor(options) { | ||
|  |     super(); | ||
|  | 
 | ||
|  |     const self = this; | ||
|  | 
 | ||
|  |     this.port.onmessageerror = (e) => { | ||
|  |       this.port.postMessage('Error: ' + JSON.stringify(e)); | ||
|  |     }; | ||
|  | 
 | ||
|  |     const mod = options.processorOptions.mod; | ||
|  |     const memory = options.processorOptions.memory; | ||
|  |      | ||
|  |     const importObject = { | ||
|  |       env: { memory }, | ||
|  |       imports: { | ||
|  |         imported_func: arg => console.log('thread: ' + arg), | ||
|  |         create_thread, | ||
|  |         glViewport: function(x, y, width, height) { }, | ||
|  |         glScissor: function(x, y, width, height) { }, | ||
|  |         glGetIntegerv: function(pname, data) { }, | ||
|  |         glGetFloatv: function(pname, data) { }, | ||
|  |         glGetString: function(name) { }, | ||
|  |         glDrawElements: function(mode, count, type, offset) { }, | ||
|  |         glDrawElementsInstanced: function(mode, count, type, indices, instancecount) { }, | ||
|  |         glVertexAttribDivisor: function(index, divisor) { }, | ||
|  |         glBindFramebuffer: function(target, framebuffer) { }, | ||
|  |         glFramebufferTexture2D: function(target, attachment, textarget, texture, level) { }, | ||
|  |         glGenFramebuffers: function(n, framebuffers) { }, | ||
|  |         glGenRenderbuffers: function(n, renderbuffers) { }, | ||
|  |         glBindRenderbuffer: function(target, renderbuffer) { }, | ||
|  |         glRenderbufferStorage: function(target, internalformat, width, height) { }, | ||
|  |         glFramebufferRenderbuffer: function(target, attachment, renderbuffertarget, renderbuffer) { }, | ||
|  |         glReadPixels: function(x, y, width, height, format, type, data) { }, | ||
|  |         glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) { }, | ||
|  |         glEnable: function(cap) { }, | ||
|  |         glDisable: function(cap) { }, | ||
|  |         glColorMask: function(red, green, blue, alpha) { }, | ||
|  |         glClearColor: function(red, green, blue, alpha) { }, | ||
|  |         glDepthMask: function(flag) { }, | ||
|  |         glClearDepthf: function(depth) { }, | ||
|  |         glStencilMask: function(mask) { }, | ||
|  |         glClearStencil: function(s) { }, | ||
|  |         glClear: function(mask) { }, | ||
|  |         glBindBuffer: function(target, buffer) { }, | ||
|  |         glUseProgram: function(program) { }, | ||
|  |         glStencilMaskSeparate: function(face, mask) { }, | ||
|  |         glStencilOpSeparate: function(face, fail, zfail, zpass) { }, | ||
|  |         glStencilFuncSeparate: function(face, func, ref, mask) { }, | ||
|  |         glDepthFunc: function(func) { }, | ||
|  |         glCullFace: function(mode) { }, | ||
|  |         glBlendFuncSeparate: function(src_rgb, dst_rgb, src_alpha, dst_alpha) { }, | ||
|  |         glBlendEquationSeparate: function(mode_rgb, mode_alpha) { }, | ||
|  |         glGenBuffers: function(n, buffers) { }, | ||
|  |         glBufferData: function(target, size, data, usage) { }, | ||
|  |         glCreateProgram: function() { }, | ||
|  |         glAttachShader: function(program, shader) { }, | ||
|  |         glBindAttribLocation: function(program, index, name) { }, | ||
|  |         glLinkProgram: function(program) { }, | ||
|  |         glGetProgramiv: function(program, pname, params) { }, | ||
|  |         glGetProgramInfoLog: function(program) { }, | ||
|  |         glCreateShader: function(type) { }, | ||
|  |         glShaderSource: function(shader, count, source, length) { }, | ||
|  |         glCompileShader: function(shader) { }, | ||
|  |         glGetShaderiv: function(shader, pname, params) { }, | ||
|  |         glGetShaderInfoLog: function(shader) { }, | ||
|  |         glBufferSubData: function(target, offset, size, data) { }, | ||
|  |         glEnableVertexAttribArray: function(index) { }, | ||
|  |         glVertexAttribPointer: function(index, size, type, normalized, stride, offset) { }, | ||
|  |         glDisableVertexAttribArray: function(index) { }, | ||
|  |         glGetUniformLocation: function(program, name) { }, | ||
|  |         glUniform1i: function(location, v0) { }, | ||
|  |         glUniform2i: function(location, v0, v1) { }, | ||
|  |         glUniform3i: function(location, v0, v1, v2) { }, | ||
|  |         glUniform4i: function(location, v0, v1, v2, v3) { }, | ||
|  |         glUniform1iv: function(location, count, value) { }, | ||
|  |         glUniform2iv: function(location, count, value) { }, | ||
|  |         glUniform3iv: function(location, count, value) { }, | ||
|  |         glUniform4iv: function(location, count, value) { }, | ||
|  |         glUniform1f: function(location, v0) { }, | ||
|  |         glUniform2f: function(location, v0, v1) { }, | ||
|  |         glUniform3f: function(location, v0, v1, v2) { }, | ||
|  |         glUniform4f: function(location, v0, v1, v2, v3) { }, | ||
|  |         glUniform1fv: function(location, count, value) { }, | ||
|  |         glUniform2fv: function(location, count, value) { }, | ||
|  |         glUniform3fv: function(location, count, value) { }, | ||
|  |         glUniform4fv: function(location, count, value) { }, | ||
|  |         glUniformMatrix3fv: function(location, count, transpose, value) { }, | ||
|  |         glUniformMatrix4fv: function(location, count, transpose, value) { }, | ||
|  |         glTexParameterf: function(target, pname, param) { }, | ||
|  |         glActiveTexture: function(texture) { }, | ||
|  |         glBindTexture: function(target, texture) { }, | ||
|  |         glTexParameteri: function(target, pname, param) { }, | ||
|  |         glGetActiveUniform: function(program, index, bufSize, length, size, type, name) { }, | ||
|  |         glGenTextures: function(n, textures) { }, | ||
|  |         glTexImage2D: function(target, level, internalformat, width, height, border, format, type, data) { }, | ||
|  |         glPixelStorei: function(pname, param) { }, | ||
|  |         glCompressedTexImage2D: function(target, level, internalformat, width, height, border, imageSize, data) { }, | ||
|  |         glDrawBuffers: function(n, bufs) { }, | ||
|  |         glGenerateMipmap: function(target) { }, | ||
|  |         glFlush: function() { }, | ||
|  |         glDeleteBuffers: function(n, buffers) { }, | ||
|  |         glDeleteTextures: function(n, textures) { }, | ||
|  |         glDeleteFramebuffers: function(n, framebuffers) { }, | ||
|  |         glDeleteProgram: function(program) { }, | ||
|  |         glDeleteShader: function(shader) { }, | ||
|  |         js_fprintf: function(format) { | ||
|  |           console.log(read_string(format)); | ||
|  |         }, | ||
|  |         js_fopen: function(filename) { | ||
|  |           return 0; | ||
|  |         }, | ||
|  |         js_ftell: function(stream) { | ||
|  |           return 0; | ||
|  |         }, | ||
|  |         js_fseek: function(stream, offset, origin) { | ||
|  |           return 0; | ||
|  |         }, | ||
|  |         js_fread: function(ptr, size, count, stream) { | ||
|  |           return 0; | ||
|  |         }, | ||
|  |         js_time: function() { | ||
|  |           return window.performance.now(); | ||
|  |         }, | ||
|  |         js_pow: function(x) { | ||
|  |           return Math.pow(x); | ||
|  |         }, | ||
|  |         js_floor: function(x) { | ||
|  |           return Math.floor(x); | ||
|  |         }, | ||
|  |         js_sin: function(x) { | ||
|  |           return Math.sin(x); | ||
|  |         }, | ||
|  |         js_cos: function(x) { | ||
|  |           return Math.cos(x); | ||
|  |         }, | ||
|  |         js_tan: function(x) { | ||
|  |           return Math.tan(x); | ||
|  |         }, | ||
|  |         js_log: function(base, exponent) { | ||
|  |           return Math.log(base, exponent); | ||
|  |         }, | ||
|  |         js_exp: function(x) { | ||
|  |           return Math.exp(x); | ||
|  |         }, | ||
|  |         js_sqrt: function(x) { | ||
|  |           return Math.sqrt(x); | ||
|  |         }, | ||
|  |         js_eval: function(str) { } | ||
|  |       } | ||
|  |     }; | ||
|  | 
 | ||
|  |     WebAssembly.instantiate(mod, importObject).then((instance) => { | ||
|  |       this.port.postMessage('Running audio thread'); | ||
|  |       self.audio_func = instance.exports.audio_func; | ||
|  |       self.audio_pointer = instance.exports.malloc(16 * 1024); | ||
|  |       this.port.postMessage('Audio pointer: ' + self.audio_pointer); | ||
|  |       this.port.postMessage('Memory byteLength: ' + memory.buffer.byteLength); | ||
|  |       self.audio_data = new Float32Array( | ||
|  |         memory.buffer, | ||
|  |         self.audio_pointer, | ||
|  |         16 * 256 | ||
|  |       ); | ||
|  |     }); | ||
|  |   } | ||
|  | 
 | ||
|  |   process(inputs, outputs, parameters) { | ||
|  |     const output = outputs[0]; | ||
|  | 
 | ||
|  |     const data = output[0]; | ||
|  | 
 | ||
|  |     //for (let i = 0; i < data.length; ++i) {
 | ||
|  |     //  data[i] = Math.random() * 2 - 1;
 | ||
|  |     //}
 | ||
|  | 
 | ||
|  |     if (this.audio_func) { | ||
|  |       let offset = 0; | ||
|  |       for (;;) { | ||
|  |         const length = Math.min(data.length - offset, this.audio_data.length); | ||
|  |         this.audio_func(this.audio_pointer + offset, length); | ||
|  |         for (let i = 0; i < length; ++i) { | ||
|  |           data[offset + i] = this.audio_data[i]; | ||
|  |         } | ||
|  | 
 | ||
|  |         if (offset + this.audio_data.length >= data.length) { | ||
|  |           break; | ||
|  |         } | ||
|  |         offset += this.audio_data.length; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     return true; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | registerProcessor('audio-thread', AudioThread); |