summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-11-18 01:39:52 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-11-18 01:39:52 +0100
commit96f9236bff9907fc0508f1920ae98bf3076f4755 (patch)
tree7e8d83721ab171b2006799a7ac64b56cc90362a9
parentf8896689131d5218e3bf87c92d188ed7eca31267 (diff)
downloadreduced_system_layer-96f9236bff9907fc0508f1920ae98bf3076f4755.zip
Audio worklet
-rw-r--r--index.htm285
-rwxr-xr-xreduced_system_layer.c38
2 files changed, 206 insertions, 117 deletions
diff --git a/index.htm b/index.htm
index c4c323a..830ebed 100644
--- a/index.htm
+++ b/index.htm
@@ -8,7 +8,133 @@
</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.state = options.processorOptions.state;
+ }
+ process(input, output, parameters) {
+ // TODO
+ return true;
+ }
+ }
+ );
+ </script>
<script type="text/javascript">
+ function key_from_code(code) {
+ switch (code) {
+ case "Backspace": return 8;
+ case "Tab": return 9;
+ case "Enter": return 10;
+ case "ControlLeft": return 11;
+ case "ControlRight": return 12;
+ case "ShiftLeft": return 13;
+ case "ShiftRight": return 14;
+ case "AltLeft": return 15;
+ case "AltRight": return 16;
+ case "ArrowLeft": return 17;
+ case "ArrowRight": return 18;
+ case "ArrowUp": return 19;
+ case "ArrowDown": return 20;
+ case "Pause": return 21;
+ case "Insert": return 22;
+ case "Home": return 23;
+ case "End": return 24;
+ case "PageUp": return 25;
+ case "PageDown": return 26;
+ case "Escape": return 27;
+ case "PrintScreen": return 28;
+ case "Space": return 32;
+ case "MetaLeft": return 33;
+ case "MetaRight": return 34;
+ case "Quote": return 39;
+ case "Comma": return 44;
+ case "Minus": return 45;
+ case "Period": return 46;
+ case "Slash": return 47;
+ case "Digit0": return 48;
+ case "Digit1": return 49;
+ case "Digit2": return 50;
+ case "Digit3": return 51;
+ case "Digit4": return 52;
+ case "Digit5": return 53;
+ case "Digit6": return 54;
+ case "Digit7": return 55;
+ case "Digit8": return 56;
+ case "Digit9": return 57;
+ case "Semicolon": return 59;
+ case "Equal": return 61;
+ case "BracketLeft": return 91;
+ case "Backslash": return 92;
+ case "BracketRight": return 93;
+ case "Backquote": return 96;
+ case "KeyA": return 97;
+ case "KeyB": return 98;
+ case "KeyC": return 99;
+ case "KeyD": return 100;
+ case "KeyE": return 101;
+ case "KeyF": return 102;
+ case "KeyG": return 103;
+ case "KeyH": return 104;
+ case "KeyI": return 105;
+ case "KeyJ": return 106;
+ case "KeyK": return 107;
+ case "KeyL": return 108;
+ case "KeyM": return 109;
+ case "KeyN": return 110;
+ case "KeyO": return 111;
+ case "KeyP": return 112;
+ case "KeyQ": return 113;
+ case "KeyR": return 114;
+ case "KeyS": return 115;
+ case "KeyT": return 116;
+ case "KeyU": return 117;
+ case "KeyV": return 118;
+ case "KeyW": return 119;
+ case "KeyX": return 120;
+ case "KeyY": return 121;
+ case "KeyZ": return 122;
+ case "Delete": return 127;
+ case "F1": return 145;
+ case "F2": return 146;
+ case "F3": return 147;
+ case "F4": return 148;
+ case "F5": return 149;
+ case "F6": return 150;
+ case "F7": return 151;
+ case "F8": return 152;
+ case "F9": return 153;
+ case "F10": return 154;
+ case "F11": return 155;
+ case "F12": return 156;
+ case "F13": return 157;
+ case "F14": return 158;
+ case "F15": return 159;
+ case "F16": return 160;
+ case "F17": return 161;
+ case "F18": return 162;
+ case "F19": return 163;
+ case "F20": return 164;
+ case "F21": return 165;
+ case "F22": return 166;
+ case "F23": return 167;
+ case "F24": return 168;
+ }
+ 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)
@@ -27,11 +153,49 @@
let context;
let animation_frame;
- canvas = document.getElementById(attrs.id);
+ let sound_ready = false;
+ let sound_context;
+ let sound_init;
+ let sound_node;
+
+ let sound_state = {
+ memory : null,
+ buffer_address : 0,
+ };
+
+ 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_node = new AudioWorkletNode(
+ sound_context,
+ "Sound_Ring",
+ { numberOfInputs : 0,
+ outputChannelCount : [ program.instance.exports.js_num_channels() ],
+ processorOptions : { state : sound_state }, }
+ );
+
+ sound_node.connect(sound_context.destination);
+
+ sound_ready = true;
+ };
+
program = await WebAssembly.instantiateStreaming(
- fetch("index.wasm"),
+ attrs.wasm,
{
"wasi_snapshot_preview1" : {
clock_time_get : () => { return Date.now(); },
@@ -68,7 +232,7 @@
new TextDecoder().decode(memory.subarray(text, text + size))
).catch((e) => { console.error(e); });
},
- p_cleanup : () => {},
+ p_cleanup : () => {},
p_wait_events_impl : () => { wait_for_events = true; },
p_sleep_for : (time) => { sleep_duration += time; },
p_time : Date.now,
@@ -123,6 +287,7 @@
});
canvas.addEventListener("mousedown", (ev) => {
+ sound_init();
program.instance.exports.js_mousedown(ev.buttons);
window.requestAnimationFrame(animation_frame);
});
@@ -137,117 +302,6 @@
window.requestAnimationFrame(animation_frame);
});
- let key_from_code = (code) => {
- switch (code) {
- case "Backspace": return 8;
- case "Tab": return 9;
- case "Enter": return 10;
- case "ControlLeft": return 11;
- case "ControlRight": return 12;
- case "ShiftLeft": return 13;
- case "ShiftRight": return 14;
- case "AltLeft": return 15;
- case "AltRight": return 16;
- case "ArrowLeft": return 17;
- case "ArrowRight": return 18;
- case "ArrowUp": return 19;
- case "ArrowDown": return 20;
- case "Pause": return 21;
- case "Insert": return 22;
- case "Home": return 23;
- case "End": return 24;
- case "PageUp": return 25;
- case "PageDown": return 26;
- case "Escape": return 27;
- case "PrintScreen": return 28;
- case "Space": return 32;
- case "MetaLeft": return 33;
- case "MetaRight": return 34;
- case "Quote": return 39;
- case "Comma": return 44;
- case "Minus": return 45;
- case "Period": return 46;
- case "Slash": return 47;
- case "Digit0": return 48;
- case "Digit1": return 49;
- case "Digit2": return 50;
- case "Digit3": return 51;
- case "Digit4": return 52;
- case "Digit5": return 53;
- case "Digit6": return 54;
- case "Digit7": return 55;
- case "Digit8": return 56;
- case "Digit9": return 57;
- case "Semicolon": return 59;
- case "Equal": return 61;
- case "BracketLeft": return 91;
- case "Backslash": return 92;
- case "BracketRight": return 93;
- case "Backquote": return 96;
- case "KeyA": return 97;
- case "KeyB": return 98;
- case "KeyC": return 99;
- case "KeyD": return 100;
- case "KeyE": return 101;
- case "KeyF": return 102;
- case "KeyG": return 103;
- case "KeyH": return 104;
- case "KeyI": return 105;
- case "KeyJ": return 106;
- case "KeyK": return 107;
- case "KeyL": return 108;
- case "KeyM": return 109;
- case "KeyN": return 110;
- case "KeyO": return 111;
- case "KeyP": return 112;
- case "KeyQ": return 113;
- case "KeyR": return 114;
- case "KeyS": return 115;
- case "KeyT": return 116;
- case "KeyU": return 117;
- case "KeyV": return 118;
- case "KeyW": return 119;
- case "KeyX": return 120;
- case "KeyY": return 121;
- case "KeyZ": return 122;
- case "Delete": return 127;
- case "F1": return 145;
- case "F2": return 146;
- case "F3": return 147;
- case "F4": return 148;
- case "F5": return 149;
- case "F6": return 150;
- case "F7": return 151;
- case "F8": return 152;
- case "F9": return 153;
- case "F10": return 154;
- case "F11": return 155;
- case "F12": return 156;
- case "F13": return 157;
- case "F14": return 158;
- case "F15": return 159;
- case "F16": return 160;
- case "F17": return 161;
- case "F18": return 162;
- case "F19": return 163;
- case "F20": return 164;
- case "F21": return 165;
- case "F22": return 166;
- case "F23": return 167;
- case "F24": return 168;
- }
- return 0;
- };
-
- let 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;
- };
-
window.addEventListener("keydown", (ev) => {
ev.preventDefault();
if (!ev.repeat) {
@@ -274,7 +328,8 @@
}
run({
- id : "frame",
+ canvas : document.getElementById("frame"),
+ wasm : fetch("index.wasm"),
fit_window : true,
}).catch((e) => console.error(e));
</script>
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 692d555..dfc8b4f 100755
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -1550,7 +1550,7 @@ void p_clipboard_write(i64 size, c8 *data) {
// ================================================================
//
-// WebAssembly
+// Web canvas
//
// ================================================================
@@ -1592,7 +1592,7 @@ void p_render_frame(void) {
p_render_frame_impl();
}
-__attribute__((export_name("js_memset"))) void js_memset(void *dst, i32 val, u32 num) {
+ __attribute__((export_name("js_memset"))) void js_memset(void *dst, i32 val, u32 num) {
if (dst == NULL) return;
for (u32 i = 0; i < num; ++i)
((u8 *) dst)[i] = (u8) val;
@@ -1678,6 +1678,40 @@ __attribute__((export_name("js_keyup"))) void js_keyup(u32 key, u32 mod) {
#endif // __wasm__
// ================================================================
+//
+// Web audio
+//
+// ================================================================
+
+#ifdef __wasm__
+
+void p_handle_audio(i64 samples_elapsed) {
+ // TODO
+}
+
+void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
+ // TODO
+}
+
+__attribute__((export_name("js_sample_rate"))) f64 js_sample_rate(void) {
+ return (f64) AUDIO_SAMPLE_RATE;
+}
+
+__attribute__((export_name("js_num_channels"))) i32 js_num_channels(void) {
+ return AUDIO_NUM_CHANNELS;
+}
+
+__attribute__((export_name("js_sound_buffer"))) void *js_sound_buffer(void) {
+ return NULL;
+}
+
+__attribute__((export_name("js_sound_playback"))) void js_sound_playback(i64 num_samples) {
+ // TODO
+}
+
+#endif // __wasm__
+
+// ================================================================
#endif // REDUCED_SYSTEM_LAYER_IMPL_GUARD_
#endif // REDUCED_SYSTEM_LAYER_HEADER