summaryrefslogtreecommitdiff
path: root/index.htm.bak
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-01-06 23:41:27 +0100
committerMitya Selivanov <automainint@guattari.tech>2025-01-06 23:41:27 +0100
commiteab2433a2daee814492548b95f16892adde0908d (patch)
treee08d2b82fc3525d937bb64475da5543b4628158c /index.htm.bak
parent3359f068dc9e8ac036f0f709aeccf11dfba3cf03 (diff)
downloadreduced_system_layer-eab2433a2daee814492548b95f16892adde0908d.zip
Impl rendering in AudioWorklet
Diffstat (limited to 'index.htm.bak')
-rw-r--r--index.htm.bak415
1 files changed, 415 insertions, 0 deletions
diff --git a/index.htm.bak b/index.htm.bak
new file mode 100644
index 0000000..cb1f474
--- /dev/null
+++ b/index.htm.bak
@@ -0,0 +1,415 @@
+<!DOCTYPE html>
+<html style="height: 100%; overflow: hidden; overflow-x: hidden;">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <link rel='icon' type='image/gif' href='/favicon.gif'>
+ <title> Reduced System Layer </title>
+ </head>
+ <body style="margin: 0; height: 100%; overflow: hidden; overflow-x: hidden;">
+ <canvas style="margin: 0; width: 100%; height: 100%;" id="frame" oncontextmenu="event.preventDefault()"></canvas>
+ <script type="worklet">
+ registerProcessor(
+ 'Sound_Ring',
+ class Sound_Ring extends AudioWorkletProcessor {
+ constructor(options) {
+ super();
+
+ this.ring = options.processorOptions.ring;
+
+ this.position = 0;
+ this.max_num_frames = this.ring.byteLength / 4;
+ }
+
+ process(input, output, parameters) {
+ let num_channels = output[0].length;
+ let num_samples = output[0][0].length;
+ let num_frames = num_samples * num_channels;
+
+ if (num_frames > this.max_num_frames) {
+ console.error("Sound buffer overflow");
+ return true;
+ }
+
+ let frames = new Float32Array(this.ring);
+
+ if (num_frames <= this.max_num_frames - this.position)
+ for (let j = 0; j < num_channels; ++j)
+ for (let i = 0; i < num_samples; ++i)
+ output[0][j][i] = frames[this.position + i * num_channels + j];
+ else {
+ let part_one = this.max_num_frames - this.position;
+ let part_two = num_frames - part_one;
+
+ for (let j = 0; j < num_channels; ++j) {
+ for (let i = 0; i < part_one; ++i)
+ output[0][j][i] = frames[this.position + i * num_channels + j];
+ for (let i = 0; i < part_two; ++i)
+ output[0][j][part_one + i] = frames[i * num_channels + j];
+ }
+ }
+
+ this.position = (this.position + num_frames) % this.max_num_frames;
+ return true;
+ }
+ }
+ );
+ </script>
+ <script type="text/javascript">
+ let key_map = {
+ "Backspace" : 8,
+ "Tab" : 9,
+ "Enter" : 10,
+ "ControlLeft" : 11,
+ "ControlRight" : 12,
+ "ShiftLeft" : 13,
+ "ShiftRight" : 14,
+ "AltLeft" : 15,
+ "AltRight" : 16,
+ "ArrowLeft" : 17,
+ "ArrowRight" : 18,
+ "ArrowUp" : 19,
+ "ArrowDown" : 20,
+ "Pause" : 21,
+ "Insert" : 22,
+ "Home" : 23,
+ "End" : 24,
+ "PageUp" : 25,
+ "PageDown" : 26,
+ "Escape" : 27,
+ "PrintScreen" : 28,
+ "Space" : 32,
+ "MetaLeft" : 33,
+ "MetaRight" : 34,
+ "Quote" : 39,
+ "Comma" : 44,
+ "Minus" : 45,
+ "Period" : 46,
+ "Slash" : 47,
+ "Digit0" : 48,
+ "Digit1" : 49,
+ "Digit2" : 50,
+ "Digit3" : 51,
+ "Digit4" : 52,
+ "Digit5" : 53,
+ "Digit6" : 54,
+ "Digit7" : 55,
+ "Digit8" : 56,
+ "Digit9" : 57,
+ "Semicolon" : 59,
+ "Equal" : 61,
+ "BracketLeft" : 91,
+ "Backslash" : 92,
+ "BracketRight" : 93,
+ "Backquote" : 96,
+ "KeyA" : 97,
+ "KeyB" : 98,
+ "KeyC" : 99,
+ "KeyD" : 100,
+ "KeyE" : 101,
+ "KeyF" : 102,
+ "KeyG" : 103,
+ "KeyH" : 104,
+ "KeyI" : 105,
+ "KeyJ" : 106,
+ "KeyK" : 107,
+ "KeyL" : 108,
+ "KeyM" : 109,
+ "KeyN" : 110,
+ "KeyO" : 111,
+ "KeyP" : 112,
+ "KeyQ" : 113,
+ "KeyR" : 114,
+ "KeyS" : 115,
+ "KeyT" : 116,
+ "KeyU" : 117,
+ "KeyV" : 118,
+ "KeyW" : 119,
+ "KeyX" : 120,
+ "KeyY" : 121,
+ "KeyZ" : 122,
+ "Delete" : 127,
+ "F1" : 145,
+ "F2" : 146,
+ "F3" : 147,
+ "F4" : 148,
+ "F5" : 149,
+ "F6" : 150,
+ "F7" : 151,
+ "F8" : 152,
+ "F9" : 153,
+ "F10" : 154,
+ "F11" : 155,
+ "F12" : 156,
+ "F13" : 157,
+ "F14" : 158,
+ "F15" : 159,
+ "F16" : 160,
+ "F17" : 161,
+ "F18" : 162,
+ "F19" : 163,
+ "F20" : 164,
+ "F21" : 165,
+ "F22" : 166,
+ "F23" : 167,
+ "F24" : 168,
+ };
+
+ function key_from_code(code) {
+ if (code in key_map)
+ return key_map[code];
+ return 0;
+ };
+
+ function mod_from_event(ev) {
+ let mod = 0;
+ if (ev.ctrlKey) mod |= 1;
+ if (ev.shiftKey) mod |= 2;
+ if (ev.altKey) mod |= 4;
+ if (ev.metaKey) mod |= 8;
+ return mod;
+ };
+
+ function string_from_memory(bytes, offset) {
+ let len = 0;
+ while (bytes[offset + len] != 0)
+ ++len;
+ return new TextDecoder("utf8").decode(bytes.subarray(offset, offset + len));
+ }
+
+ async function run(attrs) {
+ let wait_for_events = false;
+ let sleep_duration = 0;
+
+ let canvas;
+ let program;
+ let memory;
+ let pixels_address;
+ let context;
+ let animation_frame;
+
+ let sound_ready = false;
+ let sound_context;
+ let sound_init;
+ let sound_node;
+ let sound_num_channels;
+ let sound_buffer_address;
+ let sound_max_num_frames;
+
+ let sound_shared_ring;
+ let sound_position;
+
+ canvas = attrs.canvas;
+ context = canvas.getContext("2d");
+
+ sound_init = async () => {
+ if (sound_ready || sound_context !== undefined)
+ return;
+
+ sound_context = new AudioContext({
+ sampleRate : program.instance.exports.js_sample_rate(),
+ });
+
+ let blob = new Blob(
+ [ document.querySelector("script[type=worklet]").innerText ],
+ { type : "application/javascript", }
+ );
+
+ await sound_context.audioWorklet.addModule(URL.createObjectURL(blob));
+
+ sound_num_channels = program.instance.exports.js_num_channels();
+ sound_max_num_frames = program.instance.exports.js_max_num_audio_frames();
+ sound_buffer_address = program.instance.exports.js_sound_buffer();
+
+ sound_shared_ring = new SharedArrayBuffer(sound_max_num_frames * 4);
+ sound_position = 0;
+
+ sound_node = new AudioWorkletNode(
+ sound_context,
+ "Sound_Ring",
+ { numberOfInputs : 0,
+ outputChannelCount : [ sound_num_channels ],
+ processorOptions : { ring : sound_shared_ring, }, }
+ );
+
+ sound_node.connect(sound_context.destination);
+
+ program.instance.exports.js_sound_sync();
+
+ sound_ready = true;
+ };
+
+ program = await WebAssembly.instantiateStreaming(
+ attrs.wasm,
+ {
+ "wasi_snapshot_preview1" : {
+ clock_time_get : () => { return Date.now(); },
+ args_sizes_get : () => { throw new Error("Unexpected args_sizes_get call"); },
+ args_get : () => { throw new Error("Unexpected args_get call"); },
+ proc_exit : () => { throw new Error("Unexpected proc_exit call"); },
+ fd_close : () => { throw new Error("Unexpected fd_close call"); },
+ fd_write : () => { throw new Error("Unexpected fd_write call"); },
+ fd_seek : () => { throw new Error("Unexpected fd_seek call"); },
+ },
+ "env" : {
+ p_init : () => {
+ program.instance.exports.js_init();
+ memory = new Uint8Array(program.instance.exports.memory.buffer);
+ pixels_address = program.instance.exports.js_pixels();
+ document.title = string_from_memory(memory, program.instance.exports.js_title());
+ },
+ p_render_frame_impl : () => {
+ let data = new ImageData(
+ new Uint8ClampedArray(
+ memory.subarray(
+ pixels_address,
+ pixels_address + 4 * canvas.width * canvas.height
+ )
+ ),
+ canvas.width,
+ canvas.height
+ );
+
+ context.putImageData(data, 0, 0);
+ },
+ p_clipboard_write : (size, text) => {
+ navigator.clipboard.writeText(
+ new TextDecoder().decode(memory.subarray(text, text + size))
+ ).catch((e) => { console.error(e); });
+ },
+ p_cleanup : () => {},
+ p_wait_events_impl : () => { wait_for_events = true; },
+ p_sleep_for_impl : (time) => { sleep_duration += time; },
+ p_time_impl : Date.now,
+
+ p_handle_audio_impl : (samples_elapsed) => {
+ if (!sound_ready)
+ return;
+
+ let num_frames = samples_elapsed * sound_num_channels;
+
+ if (num_frames > sound_max_num_frames) {
+ console.error("Sound buffer overflow");
+ return;
+ }
+
+ let dst = new Float32Array(sound_shared_ring);
+ let src = new Float32Array(memory.buffer, sound_buffer_address, sound_max_num_frames);
+
+ if (num_frames <= sound_max_num_frames - sound_position)
+ for (let i = 0; i < num_frames; ++i) {
+ dst[sound_position + i] = src[sound_position + i];
+ src[sound_position + i] = 0.0;
+ }
+ else {
+ let part_one = sound_max_num_frames - sound_position;
+ let part_two = num_frames - part_one;
+
+ for (let i = 0; i < part_one; ++i) {
+ dst[sound_position + i] = src[sound_position + i];
+ src[sound_position + i] = 0.0;
+ }
+ for (let i = 0; i < part_two; ++i) {
+ dst[i] = src[i];
+ src[i] = 0.0;
+ }
+ }
+
+ sound_position = (sound_position + samples_elapsed * sound_num_channels) % sound_max_num_frames;
+ },
+
+ floor : Math.floor,
+ ceil : Math.ceil,
+ sqrt : Math.sqrt,
+ pow : Math.pow,
+ log : Math.log,
+ log2 : Math.log2,
+ log10 : Math.log10,
+ exp : Math.exp,
+ sin : Math.sin,
+ cos : Math.cos,
+ tan : Math.tan,
+ asin : Math.asin,
+ acos : Math.acos,
+ atan : Math.atan,
+ atan2 : Math.atan2,
+ },
+ }
+ );
+
+ program.instance.exports.js_main(document.location.href);
+
+ animation_frame = (time) => {
+ if (attrs.fit_window) {
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+ }
+
+ wait_for_events = false;
+ program.instance.exports.js_frame(canvas.width, canvas.height);
+
+ if (!wait_for_events) {
+ if (sleep_duration > 0) {
+ let timeout = sleep_duration;
+ sleep_duration = 0;
+ setTimeout(() => {
+ window.requestAnimationFrame(animation_frame);
+ }, timeout);
+ } else
+ window.requestAnimationFrame(animation_frame);
+ }
+ };
+
+ window.addEventListener("resize", (ev) => {
+ window.requestAnimationFrame(animation_frame);
+ });
+
+ canvas.addEventListener("mousedown", (ev) => {
+ sound_init();
+ program.instance.exports.js_mousedown(ev.buttons);
+ window.requestAnimationFrame(animation_frame);
+ });
+
+ canvas.addEventListener("mouseup", (ev) => {
+ program.instance.exports.js_mouseup(ev.buttons);
+ window.requestAnimationFrame(animation_frame);
+ });
+
+ canvas.addEventListener("mousemove", (ev) => {
+ program.instance.exports.js_mousemove(ev.clientX, ev.clientY);
+ window.requestAnimationFrame(animation_frame);
+ });
+
+ window.addEventListener("keydown", (ev) => {
+ ev.preventDefault();
+ if (!ev.repeat) {
+ let mod = mod_from_event(ev);
+ let key = key_from_code(ev.code);
+ if (key != 0)
+ program.instance.exports.js_keydown(key, mod);
+ window.requestAnimationFrame(animation_frame);
+ }
+ });
+
+ window.addEventListener("keyup", (ev) => {
+ ev.preventDefault();
+ if (!ev.repeat) {
+ let mod = mod_from_event(ev);
+ let key = key_from_code(ev.code);
+ if (key != 0)
+ program.instance.exports.js_keyup(key, mod);
+ window.requestAnimationFrame(animation_frame);
+ }
+ });
+
+ window.requestAnimationFrame(animation_frame);
+ }
+
+ run({
+ canvas : document.getElementById("frame"),
+ wasm : fetch("index.wasm"),
+ fit_window : true,
+ }).catch((e) => console.error(e));
+ </script>
+ </body>
+</html>