diff options
Diffstat (limited to 'reduced_system_layer.c')
-rwxr-xr-x | reduced_system_layer.c | 189 |
1 files changed, 87 insertions, 102 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c index c272711..30fb48b 100755 --- a/reduced_system_layer.c +++ b/reduced_system_layer.c @@ -77,7 +77,7 @@ #/ #/ ---------------------------------------------------------------- #/ -#/ (C) 2024 Mitya Selivanov <guattari.tech> +#/ (C) 2025 Mitya Selivanov <guattari.tech> #/ #/ ================================================================ #/ @@ -163,7 +163,7 @@ enum { AUDIO_NUM_CHANNELS = 2, AUDIO_SAMPLE_RATE = 44100, - AUDIO_AVAIL_MIN = 256, + AUDIO_AVAIL_MIN = 512, MAX_NUM_AUDIO_FRAMES = 10 * AUDIO_SAMPLE_RATE * AUDIO_NUM_CHANNELS, // 10 seconds @@ -399,6 +399,10 @@ f64 atan2(f64 y, f64 x); #ifndef NULL #define NULL ((void *) 0) #endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif #endif #ifdef __cplusplus @@ -1555,17 +1559,22 @@ void p_clipboard_write(i64 size, c8 *data) { // ================================================================ // -// Web canvas +// WebAssembly // // ================================================================ #ifdef __wasm__ -static u32 _buffer[MAX_NUM_PIXELS] = {0}; -static Input_Key _input[MAX_INPUT_SIZE] = {0}; -static i32 _num_events = 0; -static i32 _input_size = 0; -static b8 _key_pressed[MAX_NUM_KEYS] = {0}; +static u32 _buffer[MAX_NUM_PIXELS] = {0}; +static Input_Key _input[MAX_INPUT_SIZE] = {0}; +static i32 _num_events = 0; +static i32 _input_size = 0; +static b8 _key_pressed[MAX_NUM_KEYS] = {0}; +static b8 _wait_events = 0; +i64 _sound_position = 0; +i64 _sound_read = 0; +f32 _sound_ring[MAX_NUM_AUDIO_FRAMES] = {0}; +f32 _sound_buffer[MAX_NUM_AUDIO_FRAMES] = {0}; i32 p_time_impl(void); @@ -1573,10 +1582,17 @@ i64 p_time(void) { return p_time_impl(); } -void p_sleep_for_impl(i32 duration); - void p_sleep_for(i64 duration) { - p_sleep_for_impl((i32) duration); + // TODO +} + +void p_init(void) { + ++_num_events; + platform.pixels = _buffer; + platform.input = _input; + platform.done = 1; + _sound_position = AUDIO_AVAIL_MIN % MAX_NUM_AUDIO_FRAMES; + _sound_read = 0; } i32 p_handle_events(void) { @@ -1591,46 +1607,58 @@ i32 p_handle_events(void) { return n; } -i32 p_wait_events_impl(void); - i32 p_wait_events(void) { - p_wait_events_impl(); + _wait_events = 1; + return p_handle_events(); } -void p_render_frame_impl(void); +void p_render_frame(void) { } -void p_render_frame(void) { - // Make canvas pixels opaque. - i64 size = platform.frame_width * platform.frame_height; - for (i64 i = 0; i < size; ++i) - platform.pixels[i] |= 0xff000000; +void p_handle_audio(i64 samples_elapsed) { + if (samples_elapsed <= 0) + return; - p_render_frame_impl(); + _sound_position = (_sound_position + samples_elapsed * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES; } - __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; -} +void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { + if (frames == NULL) + return; + + if (delay_in_samples < 0) { + frames += -delay_in_samples * AUDIO_NUM_CHANNELS; + num_samples -= delay_in_samples; + delay_in_samples = 0; + } + + if (num_samples <= 0) + return; + + i64 num_frames = num_samples * AUDIO_NUM_CHANNELS; + if (num_frames > MAX_NUM_AUDIO_FRAMES) + return; + + i64 begin = (_sound_position + delay_in_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES; + + if (num_frames <= MAX_NUM_AUDIO_FRAMES - begin) + for (i64 i = 0; i < num_frames; ++i) + _sound_ring[begin + i] += frames[i]; + else { + i64 part_one = MAX_NUM_AUDIO_FRAMES - begin; + i64 part_two = num_frames - part_one; -__attribute__((export_name("js_memcpy"))) void js_memcpy(void *dst, void const *src, u32 num) { - if (dst == NULL || src == NULL) return; - for (u32 i = 0; i < num; ++i) - ((u8 *) dst)[i] = ((u8 const *) src)[i]; + for (i64 i = 0; i < part_one; ++i) + _sound_ring[begin + i] += frames[i]; + for (i64 i = 0; i < part_two; ++i) + _sound_ring[i] += frames[part_one + i]; + } } __attribute__((export_name("js_main"))) void js_main(c8 *href) { main(1, &href); } -__attribute__((export_name("js_init"))) void js_init(void) { - platform.pixels = _buffer; - platform.input = _input; - platform.done = 1; -} - __attribute__((export_name("js_title"))) void *js_title(void) { return platform.title; } @@ -1639,7 +1667,7 @@ __attribute__((export_name("js_pixels"))) void *js_pixels(void) { return platform.pixels; } -__attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height) { +__attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height, i32 num_samples) { if (platform.frame_width != frame_width || platform.frame_height != frame_height) { ++_num_events; platform.frame_width = frame_width; @@ -1648,7 +1676,25 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram platform.done = 0; - update_and_render_frame(); + if (_num_events > 0 || !_wait_events) { + _wait_events = 0; + update_and_render_frame(); + + // Make canvas pixels opaque. + i64 size = platform.frame_width * platform.frame_height; + for (i64 i = 0; i < size; ++i) + platform.pixels[i] |= 0xff000000; + } + + // Convert interleaved frames to non-interleaved. + for (i64 j = 0; j < AUDIO_NUM_CHANNELS; ++j) + for (i64 i = 0; i < num_samples; ++i) { + i64 n = (_sound_read + i * AUDIO_NUM_CHANNELS + j) % MAX_NUM_AUDIO_FRAMES; + _sound_buffer[j * num_samples + i] = _sound_ring[n]; + _sound_ring [n] = 0.f; + } + + _sound_read = (_sound_read + num_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES; } __attribute__((export_name("js_mousemove"))) void js_mousemove(i32 x, i32 y) { @@ -1677,6 +1723,7 @@ __attribute__((export_name("js_mouseup"))) void js_mouseup(u32 buttons) { } __attribute__((export_name("js_keydown"))) void js_keydown(u32 key, u32 mod) { + // TODO ++_num_events; _key_pressed[key] = 1; platform.key_down[key] = 1; @@ -1688,67 +1735,11 @@ __attribute__((export_name("js_keydown"))) void js_keydown(u32 key, u32 mod) { } __attribute__((export_name("js_keyup"))) void js_keyup(u32 key, u32 mod) { + // TODO ++_num_events; platform.key_down[key] = 0; } -#endif // __wasm__ - -// ================================================================ -// -// Web audio -// -// ================================================================ - -#ifdef __wasm__ - -i64 _sound_position = 0; -f32 _sound_ring[MAX_NUM_AUDIO_FRAMES] = {0}; - -void p_handle_audio_impl(i32 samples_elapsed); - -void p_handle_audio(i64 samples_elapsed) { - if (samples_elapsed <= 0) - return; - - p_handle_audio_impl(samples_elapsed); - - _sound_position = (_sound_position + samples_elapsed * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES; -} - -void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { - if (frames == NULL) - return; - - if (delay_in_samples < 0) { - frames += -delay_in_samples * AUDIO_NUM_CHANNELS; - num_samples -= delay_in_samples; - delay_in_samples = 0; - } - - if (num_samples <= 0) - return; - - i64 num_frames = num_samples * AUDIO_NUM_CHANNELS; - if (num_frames > MAX_NUM_AUDIO_FRAMES) - return; - - i64 begin = (_sound_position + AUDIO_AVAIL_MIN + delay_in_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES; - - if (num_frames <= MAX_NUM_AUDIO_FRAMES - begin) - for (i64 i = 0; i < num_frames; ++i) - _sound_ring[begin + i] += frames[i]; - else { - i64 part_one = MAX_NUM_AUDIO_FRAMES - begin; - i64 part_two = num_frames - part_one; - - for (i64 i = 0; i < part_one; ++i) - _sound_ring[begin + i] += frames[i]; - for (i64 i = 0; i < part_two; ++i) - _sound_ring[i] += frames[part_one + i]; - } -} - __attribute__((export_name("js_sample_rate"))) f64 js_sample_rate(void) { return (f64) AUDIO_SAMPLE_RATE; } @@ -1762,13 +1753,7 @@ __attribute__((export_name("js_max_num_audio_frames"))) i32 js_max_num_audio_fra } __attribute__((export_name("js_sound_buffer"))) void *js_sound_buffer(void) { - return _sound_ring; -} - -__attribute__((export_name("js_sound_sync"))) void js_sound_sync(void) { - _sound_position = 0; - for (i64 i = 0; i < MAX_NUM_AUDIO_FRAMES; ++i) - _sound_ring[i] = 0.f; + return _sound_buffer; } #endif // __wasm__ |