From bfd66ab4d2a6515d2be33e8bd357c03082d77d95 Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 28 Feb 2023 11:24:58 +1000 Subject: [PATCH] Add a very simple Emscripten-specific test. This will be expanded on later to be a lot more complete. --- tests/_build/README.md | 15 ++ tests/test_emscripten/ma_test_emscripten.c | 130 ++++++++++++++++ tests/test_emscripten/ma_test_emscripten.html | 144 ++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 tests/test_emscripten/ma_test_emscripten.c create mode 100644 tests/test_emscripten/ma_test_emscripten.html diff --git a/tests/_build/README.md b/tests/_build/README.md index 6788049c..07dbb519 100644 --- a/tests/_build/README.md +++ b/tests/_build/README.md @@ -6,3 +6,18 @@ Build and run from this directory. Example: ./bin/test_deviceio Output files will be placed in the "res/output" folder. + + +Emscripten +---------- +On Windows, you need to move into the build and run emsdk_env.bat from a command prompt using an absolute +path like "C:\emsdk\emsdk_env.bat". Note that PowerShell doesn't work for me for some reason. Examples: + + emcc ../test_emscripten/ma_test_emscripten.c -o bin/test_emscripten.html-sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY -DMA_ENABLE_AUDIO_WORKLETS -Wall -Wextra + +If you output WASM it may not work when running the web page locally. To test you can run with something +like this: + + emrun ./bin/test_emscripten.html + +If you want to see stdout on the command line when running from emrun, add `--emrun` to your emcc command. \ No newline at end of file diff --git a/tests/test_emscripten/ma_test_emscripten.c b/tests/test_emscripten/ma_test_emscripten.c new file mode 100644 index 00000000..05b744d7 --- /dev/null +++ b/tests/test_emscripten/ma_test_emscripten.c @@ -0,0 +1,130 @@ +#define MA_NO_DECODING +#define MA_NO_ENCODING +#define MINIAUDIO_IMPLEMENTATION +#include "../../miniaudio.h" + +#include + +#define DEVICE_FORMAT ma_format_f32 +#define DEVICE_CHANNELS 2 +#define DEVICE_SAMPLE_RATE 48000 + +ma_bool32 isRunning = MA_FALSE; +ma_device device; +ma_waveform sineWave; /* For playback example. */ + + +void main_loop__em() +{ +} + + + +void data_callback_playback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) +{ + MA_ASSERT(pDevice->playback.channels == DEVICE_CHANNELS); + + ma_waveform_read_pcm_frames(&sineWave, pOutput, frameCount, NULL); + + (void)pInput; /* Unused. */ +} + +static void do_playback() +{ + ma_device_config deviceConfig; + ma_waveform_config sineWaveConfig; + + deviceConfig = ma_device_config_init(ma_device_type_playback); + deviceConfig.playback.format = DEVICE_FORMAT; + deviceConfig.playback.channels = DEVICE_CHANNELS; + deviceConfig.sampleRate = DEVICE_SAMPLE_RATE; + deviceConfig.dataCallback = data_callback_playback; + deviceConfig.pUserData = &sineWave; + + if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) { + printf("Failed to open playback device.\n"); + return; + } + + sineWaveConfig = ma_waveform_config_init(device.playback.format, device.playback.channels, device.sampleRate, ma_waveform_type_sine, 0.2, 220); + ma_waveform_init(&sineWaveConfig, &sineWave); + + if (ma_device_start(&device) != MA_SUCCESS) { + printf("Failed to start device."); + return; + } +} + + + +void data_callback_duplex(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) +{ + MA_ASSERT(pDevice->capture.format == pDevice->playback.format); + MA_ASSERT(pDevice->capture.channels == pDevice->playback.channels); + + /* In this example the format and channel count are the same for both input and output which means we can just memcpy(). */ + MA_COPY_MEMORY(pOutput, pInput, frameCount * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels)); +} + +static void do_duplex() +{ + ma_result result; + ma_device_config deviceConfig; + + deviceConfig = ma_device_config_init(ma_device_type_duplex); + deviceConfig.capture.pDeviceID = NULL; + deviceConfig.capture.format = ma_format_s16; + deviceConfig.capture.channels = 2; + deviceConfig.capture.shareMode = ma_share_mode_shared; + deviceConfig.playback.pDeviceID = NULL; + deviceConfig.playback.format = ma_format_s16; + deviceConfig.playback.channels = 2; + deviceConfig.dataCallback = data_callback_duplex; + result = ma_device_init(NULL, &deviceConfig, &device); + if (result != MA_SUCCESS) { + return; + } + + if (ma_device_start(&device) != MA_SUCCESS) { + printf("Failed to start device."); + return; + } +} + + +static EM_BOOL on_canvas_click(int eventType, const EmscriptenMouseEvent* pMouseEvent, void* pUserData) +{ + if (isRunning == MA_FALSE) { + if (pMouseEvent->button == 0) { /* Left click. */ + do_playback(); + } else if (pMouseEvent->button == 2) { /* Right click. */ + do_duplex(); + } + + isRunning = MA_TRUE; + } + + (void)eventType; + (void)pUserData; + + return EM_FALSE; +} + + + + +int main(int argc, char** argv) +{ + printf("Click inside canvas to start playing:\n"); + printf(" Left click for playback\n"); + printf(" Right click for duplex\n"); + + /* The device must be started in response to an input event. */ + emscripten_set_mouseup_callback("canvas", &device, 0, on_canvas_click); + + emscripten_set_main_loop(main_loop__em, 0, 1); + + (void)argc; + (void)argv; + return 0; +} diff --git a/tests/test_emscripten/ma_test_emscripten.html b/tests/test_emscripten/ma_test_emscripten.html new file mode 100644 index 00000000..19b29d45 --- /dev/null +++ b/tests/test_emscripten/ma_test_emscripten.html @@ -0,0 +1,144 @@ + + + + + + miniaudio - Emscripten Test + + + +
+
emscripten
+
Downloading...
+
+ +
+
+ +
+
+
+ Resize canvas + Lock/hide mouse pointer +     + +
+ +
+ +
+ + {{{ SCRIPT }}} + + \ No newline at end of file