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
and
/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
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
1 | emscripten_set_main_loop(main_tick, 25, 1);
|
in usual case its can be run as
1 2 3 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //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.
1 2 3 4 5 6 7 8 9 10 | 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
1 | git clone http://git.main.lv/cgit.cgi/WasmAudio.git/
|
Build Linux
1 2 | cd Build
make
|
Build Macos
Open with XCode
Build Web assembly
1 2 | cd Build
make emcc
|
Testing
Links
/writeup/calculate_fir_coefficients_with_c.md
/writeup/web_assembly_sdl_example.md
/writeup/dsp_lp_filter.md
https://lazyfoo.net/tutorials/SDL/34_audio_recording/index.php
https://gist.github.com/armornick/3447121
https://wiki.libsdl.org/SDL_AudioSpec