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

emscripten_set_main_loop(main_tick, 25, 1);

in usual case its can be run as

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.

//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.

    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

git clone http://git.main.lv/cgit.cgi/WasmAudio.git/

Build Linux

cd Build
make

Build Macos

Open with XCode

Build Web assembly

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