title: WebAssembly Audio keywords:c,webassembly,js,SDL,FIR,WebAudio,FIR,DSP # Web assembly audio ## Intro After learning how to calculate basic FIR filter, the best demo to play with is compiled to wasm with emcc. It suppose to be compatible with all platforms that have modern browsers. This is combo of two posts [/writeup/calculate_fir_coefficients_with_c.md](/writeup/calculate_fir_coefficients_with_c.md) and [/writeup/web_assembly_sdl_example.md](/writeup/web_assembly_sdl_example.md) joined up filter calculations with SDL_Audio and compiled to wasm make things more interactive. ## Implementation ### FIR filter FIR filter is done as its mentioned in [/writeup/calculate_fir_coefficients_with_c.md](/writeup/calculate_fir_coefficients_with_c.md) Its compiled to web assembly without any modifications. ### Browser main gui loop When write in C and trying to make compatible code for non-wasm platforms there is few things that need to take in considerations. Browser have main gui thread and programs SDL event loop is passed as callback, while running main loop just on pc is no issue. But this does change logic how main loop is invocated to make it compatible between platforms for emscripten main loop is passed as callback ```c emscripten_set_main_loop(main_tick, 25, 1); ``` in usual case its can be run as ```c while (quit = 0) { main_tick(); } ``` ### Event handler Event handler in emscripten part are passing all events to SDL, and if there is text boxes they cannot be filled in, as main loop is handling events. ```c //all events are handled and passed to this routine while (SDL_PollEvent(&event) != 0) { switch (event.type) { case SDL_QUIT: { quit = 1; break; } case SDL_KEYDOWN: { } } ``` ### Audio buffer There is some differences in SDL_Audio for web, browser is playing last part of submitted data to buffer for ever, so before stop playing sound, there is submitted "silence" to buffer to fix this issue. ```c if (audio_buf_position+len <(audio_rec_buffer_size)) { memcpy( outsamples, audio_rec_buffer+audio_buf_position,len); audio_buf_position += len; } else { //silence the playback memset( outsamples, 0, len*sizeof(double)); audio_buf_full = 1; } } ``` ## Demo Here is demo compiled to Web assembly and uploaded http://wasm.main.lv/wasmfir/index.html. Unfortunately as here is no https then better to run it locally and enable chrome://flags/#unsafely-treat-insecure-origin-as-secure So far its not ideal interactive way, but things works. Steps to make thing work are to press buttons r(record) ,then q(apply filter to audio buffer), s(play back buffer) http://wasm.main.lv/wasmfir/index.html ## Source Web interface: http://git.main.lv/cgit.cgi/WasmAudio.git ### Get source ```bash git clone http://git.main.lv/cgit.cgi/WasmAudio.git/ ``` ### Build Linux ```bash cd Build make ``` ### Build Macos Open with XCode ### Build Web assembly ```bash cd Build make emcc ``` ## Testing ## Links [/writeup/calculate_fir_coefficients_with_c.md](/writeup/calculate_fir_coefficients_with_c.md) [/writeup/web_assembly_sdl_example.md](/writeup/web_assembly_sdl_example.md) [/writeup/dsp_lp_filter.md](/writeup/dsp_lp_filter.md) [https://lazyfoo.net/tutorials/SDL/34_audio_recording/index.php](https://lazyfoo.net/tutorials/SDL/34_audio_recording/index.php) [https://gist.github.com/armornick/3447121](https://gist.github.com/armornick/3447121) [https://wiki.libsdl.org/SDL_AudioSpec](https://wiki.libsdl.org/SDL_AudioSpec)