audio-thread.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // from https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletNode
  2. function create_thread(func) {
  3. }
  4. class AudioThread extends AudioWorkletProcessor {
  5. constructor(options) {
  6. super();
  7. const self = this;
  8. this.port.onmessageerror = (e) => {
  9. this.port.postMessage('Error: ' + JSON.stringify(e));
  10. };
  11. const mod = options.processorOptions.mod;
  12. const memory = options.processorOptions.memory;
  13. const importObject = {
  14. env: { memory },
  15. imports: {
  16. imported_func: arg => console.log('thread: ' + arg),
  17. create_thread,
  18. glViewport: function(x, y, width, height) { },
  19. glScissor: function(x, y, width, height) { },
  20. glGetIntegerv: function(pname, data) { },
  21. glGetFloatv: function(pname, data) { },
  22. glGetString: function(name) { },
  23. glDrawElements: function(mode, count, type, offset) { },
  24. glDrawElementsInstanced: function(mode, count, type, indices, instancecount) { },
  25. glVertexAttribDivisor: function(index, divisor) { },
  26. glBindFramebuffer: function(target, framebuffer) { },
  27. glFramebufferTexture2D: function(target, attachment, textarget, texture, level) { },
  28. glGenFramebuffers: function(n, framebuffers) { },
  29. glGenRenderbuffers: function(n, renderbuffers) { },
  30. glBindRenderbuffer: function(target, renderbuffer) { },
  31. glRenderbufferStorage: function(target, internalformat, width, height) { },
  32. glFramebufferRenderbuffer: function(target, attachment, renderbuffertarget, renderbuffer) { },
  33. glReadPixels: function(x, y, width, height, format, type, data) { },
  34. glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) { },
  35. glEnable: function(cap) { },
  36. glDisable: function(cap) { },
  37. glColorMask: function(red, green, blue, alpha) { },
  38. glClearColor: function(red, green, blue, alpha) { },
  39. glDepthMask: function(flag) { },
  40. glClearDepthf: function(depth) { },
  41. glStencilMask: function(mask) { },
  42. glClearStencil: function(s) { },
  43. glClear: function(mask) { },
  44. glBindBuffer: function(target, buffer) { },
  45. glUseProgram: function(program) { },
  46. glStencilMaskSeparate: function(face, mask) { },
  47. glStencilOpSeparate: function(face, fail, zfail, zpass) { },
  48. glStencilFuncSeparate: function(face, func, ref, mask) { },
  49. glDepthFunc: function(func) { },
  50. glCullFace: function(mode) { },
  51. glBlendFuncSeparate: function(src_rgb, dst_rgb, src_alpha, dst_alpha) { },
  52. glBlendEquationSeparate: function(mode_rgb, mode_alpha) { },
  53. glGenBuffers: function(n, buffers) { },
  54. glBufferData: function(target, size, data, usage) { },
  55. glCreateProgram: function() { },
  56. glAttachShader: function(program, shader) { },
  57. glBindAttribLocation: function(program, index, name) { },
  58. glLinkProgram: function(program) { },
  59. glGetProgramiv: function(program, pname, params) { },
  60. glGetProgramInfoLog: function(program) { },
  61. glCreateShader: function(type) { },
  62. glShaderSource: function(shader, count, source, length) { },
  63. glCompileShader: function(shader) { },
  64. glGetShaderiv: function(shader, pname, params) { },
  65. glGetShaderInfoLog: function(shader) { },
  66. glBufferSubData: function(target, offset, size, data) { },
  67. glEnableVertexAttribArray: function(index) { },
  68. glVertexAttribPointer: function(index, size, type, normalized, stride, offset) { },
  69. glDisableVertexAttribArray: function(index) { },
  70. glGetUniformLocation: function(program, name) { },
  71. glUniform1i: function(location, v0) { },
  72. glUniform2i: function(location, v0, v1) { },
  73. glUniform3i: function(location, v0, v1, v2) { },
  74. glUniform4i: function(location, v0, v1, v2, v3) { },
  75. glUniform1iv: function(location, count, value) { },
  76. glUniform2iv: function(location, count, value) { },
  77. glUniform3iv: function(location, count, value) { },
  78. glUniform4iv: function(location, count, value) { },
  79. glUniform1f: function(location, v0) { },
  80. glUniform2f: function(location, v0, v1) { },
  81. glUniform3f: function(location, v0, v1, v2) { },
  82. glUniform4f: function(location, v0, v1, v2, v3) { },
  83. glUniform1fv: function(location, count, value) { },
  84. glUniform2fv: function(location, count, value) { },
  85. glUniform3fv: function(location, count, value) { },
  86. glUniform4fv: function(location, count, value) { },
  87. glUniformMatrix3fv: function(location, count, transpose, value) { },
  88. glUniformMatrix4fv: function(location, count, transpose, value) { },
  89. glTexParameterf: function(target, pname, param) { },
  90. glActiveTexture: function(texture) { },
  91. glBindTexture: function(target, texture) { },
  92. glTexParameteri: function(target, pname, param) { },
  93. glGetActiveUniform: function(program, index, bufSize, length, size, type, name) { },
  94. glGenTextures: function(n, textures) { },
  95. glTexImage2D: function(target, level, internalformat, width, height, border, format, type, data) { },
  96. glPixelStorei: function(pname, param) { },
  97. glCompressedTexImage2D: function(target, level, internalformat, width, height, border, imageSize, data) { },
  98. glDrawBuffers: function(n, bufs) { },
  99. glGenerateMipmap: function(target) { },
  100. glFlush: function() { },
  101. glDeleteBuffers: function(n, buffers) { },
  102. glDeleteTextures: function(n, textures) { },
  103. glDeleteFramebuffers: function(n, framebuffers) { },
  104. glDeleteProgram: function(program) { },
  105. glDeleteShader: function(shader) { },
  106. js_fprintf: function(format) {
  107. console.log(read_string(format));
  108. },
  109. js_fopen: function(filename) {
  110. return 0;
  111. },
  112. js_ftell: function(stream) {
  113. return 0;
  114. },
  115. js_fseek: function(stream, offset, origin) {
  116. return 0;
  117. },
  118. js_fread: function(ptr, size, count, stream) {
  119. return 0;
  120. },
  121. js_time: function() {
  122. return window.performance.now();
  123. },
  124. js_pow: function(x) {
  125. return Math.pow(x);
  126. },
  127. js_floor: function(x) {
  128. return Math.floor(x);
  129. },
  130. js_sin: function(x) {
  131. return Math.sin(x);
  132. },
  133. js_cos: function(x) {
  134. return Math.cos(x);
  135. },
  136. js_tan: function(x) {
  137. return Math.tan(x);
  138. },
  139. js_log: function(base, exponent) {
  140. return Math.log(base, exponent);
  141. },
  142. js_exp: function(x) {
  143. return Math.exp(x);
  144. },
  145. js_sqrt: function(x) {
  146. return Math.sqrt(x);
  147. },
  148. js_eval: function(str) { }
  149. }
  150. };
  151. WebAssembly.instantiate(mod, importObject).then((instance) => {
  152. this.port.postMessage('Running audio thread');
  153. self.audio_func = instance.exports.audio_func;
  154. self.audio_pointer = instance.exports.malloc(16 * 1024);
  155. this.port.postMessage('Audio pointer: ' + self.audio_pointer);
  156. this.port.postMessage('Memory byteLength: ' + memory.buffer.byteLength);
  157. self.audio_data = new Float32Array(
  158. memory.buffer,
  159. self.audio_pointer,
  160. 16 * 256
  161. );
  162. });
  163. }
  164. process(inputs, outputs, parameters) {
  165. const output = outputs[0];
  166. const data = output[0];
  167. //for (let i = 0; i < data.length; ++i) {
  168. // data[i] = Math.random() * 2 - 1;
  169. //}
  170. if (this.audio_func) {
  171. let offset = 0;
  172. for (;;) {
  173. const length = Math.min(data.length - offset, this.audio_data.length);
  174. this.audio_func(this.audio_pointer + offset, length);
  175. for (let i = 0; i < length; ++i) {
  176. data[offset + i] = this.audio_data[i];
  177. }
  178. if (offset + this.audio_data.length >= data.length) {
  179. break;
  180. }
  181. offset += this.audio_data.length;
  182. }
  183. }
  184. return true;
  185. }
  186. }
  187. registerProcessor('audio-thread', AudioThread);