summaryrefslogtreecommitdiffstats
path: root/md/writeup/web_assembly_audio_with_fir_filter.md
blob: 654f51e961530c5f6e5e19b3ffe19b933eb8dac2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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)