Audio Visualizer
21 |0:00
27 |0:00
28 |H
32 |M
33 |L
34 |L
35 |R
36 |M
37 |├── .gitignore
├── .postcssrc
├── LICENSE
├── README.md
├── old
├── css
│ ├── buttonStyle.css
│ ├── normalize.css
│ ├── rangeStyle.css
│ └── style.css
├── images
│ └── favicon.ico
├── index.html
├── js
│ └── functions.js
└── php
│ ├── getSources.php
│ └── upload.php
├── package-lock.json
├── package.json
└── src
├── demo-songs
├── 0.mp3
├── 1.mp3
├── 2.mp3
├── 3.mp3
├── 4.mp3
└── 5.mp3
├── favicon.png
├── index.html
├── index.js
├── index.styl
├── logo.svg
└── preview.png
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache
3 | dist
4 |
--------------------------------------------------------------------------------
/.postcssrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": {
3 | "autoprefixer": {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Tanasoaia Teodor Andrei
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | # audio-visualizer
8 |
9 | 
10 |
11 | A web audio visualizer experiment
12 |
13 | You can find the working website here: https://teoxoy.github.io/audio-visualizer
14 |
15 | I recommend using the Stereo Mix feature in Windows to route the sound to the visualizer
16 | PS: Stereo Mix doesn't work with digital audio sources
17 |
18 | The `old` folder contains the original project I wrote in highschool
19 |
20 | ## Demo Songs (Free Copyright Music)
21 |
22 | | Nr | Title | Artist | Link |
23 | | --- | ---------------- | ---------------- | ---------------------------------------------------------------- |
24 | | 0 | And So It Begins | Artificial.Music | https://soundcloud.com/artificial-music/and-so-it-begins |
25 | | 1 | Dreams | Joakim Karud | https://soundcloud.com/joakimkarud/dreams-1 |
26 | | 2 | Vibe With Me | Joakim Karud | https://soundcloud.com/joakimkarud/vibe-with-me/ |
27 | | 3 | Rêveur | Peyruis | https://soundcloud.com/peyruis/peyruis-reveur-1/ |
28 | | 4 | Focused | Kontekst | https://soundcloud.com/kontekstmusic/focused |
29 | | 5 | Crying Over You | Chris Morrow 4 | https://soundcloud.com/chris-morrow-3/hip-hop-rap-instrumental-2 |
30 |
31 | # Copyright notice
32 |
33 | All audio assets used in this project belong to their respective artists and
34 | are subject to the Creative Commons License.
35 |
--------------------------------------------------------------------------------
/old/css/buttonStyle.css:
--------------------------------------------------------------------------------
1 | .styledButton {
2 | background-color:#ffffff;
3 | border:1px solid #000000;
4 | display:inline-block;
5 | cursor:pointer;
6 | color:#000000;
7 | font-family:Arial;
8 | font-size:15px;
9 | padding:6px 28px;
10 | text-decoration:none;
11 | }
12 | .styledButton:hover {
13 | background-color: lightgray;
14 | }
15 | .styledButton:active {
16 | position:relative;
17 | top:1px;
18 | }
19 |
20 | input[type=file].styledButton {
21 | box-sizing: border-box;
22 | }
23 |
24 | input[type=file].styledButton::-webkit-file-upload-button {
25 | width: 0;
26 | padding: 0;
27 | margin: 0;
28 | -webkit-appearance: none;
29 | border: none;
30 | }
31 |
32 | .lightGreyBackground {
33 | background-color: lightgrey;
34 | }
--------------------------------------------------------------------------------
/old/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /**
4 | * 1. Change the default font family in all browsers (opinionated).
5 | * 2. Prevent adjustments of font size after orientation changes in IE and iOS.
6 | */
7 |
8 | html {
9 | font-family: sans-serif; /* 1 */
10 | -ms-text-size-adjust: 100%; /* 2 */
11 | -webkit-text-size-adjust: 100%; /* 2 */
12 | }
13 |
14 | /**
15 | * Remove the margin in all browsers (opinionated).
16 | */
17 |
18 | body {
19 | margin: 0;
20 | }
21 |
22 | /* HTML5 display definitions
23 | ========================================================================== */
24 |
25 | /**
26 | * Add the correct display in IE 9-.
27 | * 1. Add the correct display in Edge, IE, and Firefox.
28 | * 2. Add the correct display in IE.
29 | */
30 |
31 | article,
32 | aside,
33 | details, /* 1 */
34 | figcaption,
35 | figure,
36 | footer,
37 | header,
38 | main, /* 2 */
39 | menu,
40 | nav,
41 | section,
42 | summary { /* 1 */
43 | display: block;
44 | }
45 |
46 | /**
47 | * Add the correct display in IE 9-.
48 | */
49 |
50 | audio,
51 | canvas,
52 | progress,
53 | video {
54 | display: inline-block;
55 | }
56 |
57 | /**
58 | * Add the correct display in iOS 4-7.
59 | */
60 |
61 | audio:not([controls]) {
62 | display: none;
63 | height: 0;
64 | }
65 |
66 | /**
67 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
68 | */
69 |
70 | progress {
71 | vertical-align: baseline;
72 | }
73 |
74 | /**
75 | * Add the correct display in IE 10-.
76 | * 1. Add the correct display in IE.
77 | */
78 |
79 | template, /* 1 */
80 | [hidden] {
81 | display: none;
82 | }
83 |
84 | /* Links
85 | ========================================================================== */
86 |
87 | /**
88 | * 1. Remove the gray background on active links in IE 10.
89 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
90 | */
91 |
92 | a {
93 | background-color: transparent; /* 1 */
94 | -webkit-text-decoration-skip: objects; /* 2 */
95 | }
96 |
97 | /**
98 | * Remove the outline on focused links when they are also active or hovered
99 | * in all browsers (opinionated).
100 | */
101 |
102 | a:active,
103 | a:hover {
104 | outline-width: 0;
105 | }
106 |
107 | /* Text-level semantics
108 | ========================================================================== */
109 |
110 | /**
111 | * 1. Remove the bottom border in Firefox 39-.
112 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
113 | */
114 |
115 | abbr[title] {
116 | border-bottom: none; /* 1 */
117 | text-decoration: underline; /* 2 */
118 | text-decoration: underline dotted; /* 2 */
119 | }
120 |
121 | /**
122 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
123 | */
124 |
125 | b,
126 | strong {
127 | font-weight: inherit;
128 | }
129 |
130 | /**
131 | * Add the correct font weight in Chrome, Edge, and Safari.
132 | */
133 |
134 | b,
135 | strong {
136 | font-weight: bolder;
137 | }
138 |
139 | /**
140 | * Add the correct font style in Android 4.3-.
141 | */
142 |
143 | dfn {
144 | font-style: italic;
145 | }
146 |
147 | /**
148 | * Correct the font size and margin on `h1` elements within `section` and
149 | * `article` contexts in Chrome, Firefox, and Safari.
150 | */
151 |
152 | h1 {
153 | font-size: 2em;
154 | margin: 0.67em 0;
155 | }
156 |
157 | /**
158 | * Add the correct background and color in IE 9-.
159 | */
160 |
161 | mark {
162 | background-color: #ff0;
163 | color: #000;
164 | }
165 |
166 | /**
167 | * Add the correct font size in all browsers.
168 | */
169 |
170 | small {
171 | font-size: 80%;
172 | }
173 |
174 | /**
175 | * Prevent `sub` and `sup` elements from affecting the line height in
176 | * all browsers.
177 | */
178 |
179 | sub,
180 | sup {
181 | font-size: 75%;
182 | line-height: 0;
183 | position: relative;
184 | vertical-align: baseline;
185 | }
186 |
187 | sub {
188 | bottom: -0.25em;
189 | }
190 |
191 | sup {
192 | top: -0.5em;
193 | }
194 |
195 | /* Embedded content
196 | ========================================================================== */
197 |
198 | /**
199 | * Remove the border on images inside links in IE 10-.
200 | */
201 |
202 | img {
203 | border-style: none;
204 | }
205 |
206 | /**
207 | * Hide the overflow in IE.
208 | */
209 |
210 | svg:not(:root) {
211 | overflow: hidden;
212 | }
213 |
214 | /* Grouping content
215 | ========================================================================== */
216 |
217 | /**
218 | * 1. Correct the inheritance and scaling of font size in all browsers.
219 | * 2. Correct the odd `em` font sizing in all browsers.
220 | */
221 |
222 | code,
223 | kbd,
224 | pre,
225 | samp {
226 | font-family: monospace, monospace; /* 1 */
227 | font-size: 1em; /* 2 */
228 | }
229 |
230 | /**
231 | * Add the correct margin in IE 8.
232 | */
233 |
234 | figure {
235 | margin: 1em 40px;
236 | }
237 |
238 | /**
239 | * 1. Add the correct box sizing in Firefox.
240 | * 2. Show the overflow in Edge and IE.
241 | */
242 |
243 | hr {
244 | box-sizing: content-box; /* 1 */
245 | height: 0; /* 1 */
246 | overflow: visible; /* 2 */
247 | }
248 |
249 | /* Forms
250 | ========================================================================== */
251 |
252 | /**
253 | * 1. Change font properties to `inherit` in all browsers (opinionated).
254 | * 2. Remove the margin in Firefox and Safari.
255 | */
256 |
257 | button,
258 | input,
259 | select,
260 | textarea {
261 | font: inherit; /* 1 */
262 | margin: 0; /* 2 */
263 | }
264 |
265 | /**
266 | * Restore the font weight unset by the previous rule.
267 | */
268 |
269 | optgroup {
270 | font-weight: bold;
271 | }
272 |
273 | /**
274 | * Show the overflow in IE.
275 | * 1. Show the overflow in Edge.
276 | */
277 |
278 | button,
279 | input { /* 1 */
280 | overflow: visible;
281 | }
282 |
283 | /**
284 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
285 | * 1. Remove the inheritance of text transform in Firefox.
286 | */
287 |
288 | button,
289 | select { /* 1 */
290 | text-transform: none;
291 | }
292 |
293 | /**
294 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
295 | * controls in Android 4.
296 | * 2. Correct the inability to style clickable types in iOS and Safari.
297 | */
298 |
299 | button,
300 | html [type="button"], /* 1 */
301 | [type="reset"],
302 | [type="submit"] {
303 | -webkit-appearance: button; /* 2 */
304 | }
305 |
306 | /**
307 | * Remove the inner border and padding in Firefox.
308 | */
309 |
310 | button::-moz-focus-inner,
311 | [type="button"]::-moz-focus-inner,
312 | [type="reset"]::-moz-focus-inner,
313 | [type="submit"]::-moz-focus-inner {
314 | border-style: none;
315 | padding: 0;
316 | }
317 |
318 | /**
319 | * Restore the focus styles unset by the previous rule.
320 | */
321 |
322 | button:-moz-focusring,
323 | [type="button"]:-moz-focusring,
324 | [type="reset"]:-moz-focusring,
325 | [type="submit"]:-moz-focusring {
326 | outline: 1px dotted ButtonText;
327 | }
328 |
329 | /**
330 | * Change the border, margin, and padding in all browsers (opinionated).
331 | */
332 |
333 | fieldset {
334 | border: 1px solid #c0c0c0;
335 | margin: 0 2px;
336 | padding: 0.35em 0.625em 0.75em;
337 | }
338 |
339 | /**
340 | * 1. Correct the text wrapping in Edge and IE.
341 | * 2. Correct the color inheritance from `fieldset` elements in IE.
342 | * 3. Remove the padding so developers are not caught out when they zero out
343 | * `fieldset` elements in all browsers.
344 | */
345 |
346 | legend {
347 | box-sizing: border-box; /* 1 */
348 | color: inherit; /* 2 */
349 | display: table; /* 1 */
350 | max-width: 100%; /* 1 */
351 | padding: 0; /* 3 */
352 | white-space: normal; /* 1 */
353 | }
354 |
355 | /**
356 | * Remove the default vertical scrollbar in IE.
357 | */
358 |
359 | textarea {
360 | overflow: auto;
361 | }
362 |
363 | /**
364 | * 1. Add the correct box sizing in IE 10-.
365 | * 2. Remove the padding in IE 10-.
366 | */
367 |
368 | [type="checkbox"],
369 | [type="radio"] {
370 | box-sizing: border-box; /* 1 */
371 | padding: 0; /* 2 */
372 | }
373 |
374 | /**
375 | * Correct the cursor style of increment and decrement buttons in Chrome.
376 | */
377 |
378 | [type="number"]::-webkit-inner-spin-button,
379 | [type="number"]::-webkit-outer-spin-button {
380 | height: auto;
381 | }
382 |
383 | /**
384 | * 1. Correct the odd appearance in Chrome and Safari.
385 | * 2. Correct the outline style in Safari.
386 | */
387 |
388 | [type="search"] {
389 | -webkit-appearance: textfield; /* 1 */
390 | outline-offset: -2px; /* 2 */
391 | }
392 |
393 | /**
394 | * Remove the inner padding and cancel buttons in Chrome and Safari on OS X.
395 | */
396 |
397 | [type="search"]::-webkit-search-cancel-button,
398 | [type="search"]::-webkit-search-decoration {
399 | -webkit-appearance: none;
400 | }
401 |
402 | /**
403 | * Correct the text style of placeholders in Chrome, Edge, and Safari.
404 | */
405 |
406 | ::-webkit-input-placeholder {
407 | color: inherit;
408 | opacity: 0.54;
409 | }
410 |
411 | /**
412 | * 1. Correct the inability to style clickable types in iOS and Safari.
413 | * 2. Change font properties to `inherit` in Safari.
414 | */
415 |
416 | ::-webkit-file-upload-button {
417 | -webkit-appearance: button; /* 1 */
418 | font: inherit; /* 2 */
419 | }
--------------------------------------------------------------------------------
/old/css/rangeStyle.css:
--------------------------------------------------------------------------------
1 | input[type=range].styledRange {
2 | -webkit-appearance: none;
3 | width: 100%;
4 | margin: 6.5px 0;
5 | }
6 | input[type=range][orient=vertical].styledRange {
7 | transform:rotate(270deg);
8 | }
9 | input[type=range].styledRange::-webkit-slider-runnable-track {
10 | width: 100%;
11 | height: 9px;
12 | cursor: pointer;
13 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
14 | border-radius: 0px;
15 | border: 1px solid #010101;
16 | }
17 | .fullBackground{
18 | background: linear-gradient(to right, black 100%, white 100%);
19 | }
20 | input[type=range].styledRange::-webkit-slider-thumb {
21 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
22 | border: 1px solid #000000;
23 | height: 22px;
24 | width: 9px;
25 | border-radius: 0px;
26 | background: #ffffff;
27 | cursor: pointer;
28 | -webkit-appearance: none;
29 | margin-top: -7.5px;
30 | }
31 | input[type=range].styledRange::-moz-range-track {
32 | width: 100%;
33 | height: 9px;
34 | cursor: pointer;
35 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
36 | background: #ffffff;
37 | border-radius: 0px;
38 | border: 1px solid #010101;
39 | }
40 | input[type=range].styledRange::-moz-range-thumb {
41 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
42 | border: 1px solid #000000;
43 | height: 22px;
44 | width: 9px;
45 | border-radius: 0px;
46 | background: #ffffff;
47 | cursor: pointer;
48 | }
49 | input[type=range].styledRange::-ms-track {
50 | width: 100%;
51 | height: 9px;
52 | cursor: pointer;
53 | background: transparent;
54 | border-color: transparent;
55 | color: transparent;
56 | }
57 | input[type=range].styledRange::-ms-fill-lower {
58 | background: #e6e6e6;
59 | border: 1px solid #010101;
60 | border-radius: 0px;
61 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
62 | }
63 | input[type=range].styledRange::-ms-fill-upper {
64 | background: #ffffff;
65 | border: 1px solid #010101;
66 | border-radius: 0px;
67 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
68 | }
69 | input[type=range].styledRange::-ms-thumb {
70 | box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0);
71 | border: 1px solid #000000;
72 | height: 22px;
73 | width: 9px;
74 | border-radius: 0px;
75 | background: #ffffff;
76 | cursor: pointer;
77 | height: 9px;
78 | }
79 | input[type=range].styledRange:focus::-ms-fill-lower {
80 | background: #ffffff;
81 | }
82 | input[type=range].styledRange:focus::-ms-fill-upper {
83 | background: #ffffff;
84 | }
--------------------------------------------------------------------------------
/old/css/style.css:
--------------------------------------------------------------------------------
1 | .wrap {
2 | display: block;
3 | width: 1600px;
4 | margin: 0 auto;
5 | }
6 |
7 | html {
8 | font-family: Arial;
9 | }
10 |
11 | * {
12 | user-select: none;
13 | outline: none;
14 | }
15 |
16 | #header{
17 | padding: 10px;
18 | }
19 |
20 | #header p{
21 | font-size: 50px;
22 | text-align: center;
23 | margin: 0px;
24 | }
25 |
26 | #content{
27 | min-width: 1600px;
28 | border-left: 1px solid black;
29 | border-right: 1px solid black;
30 | }
31 |
32 | /*Canvas*/
33 | #canvas{
34 | width: 1600px;
35 | height: 1024px;
36 | display: block;
37 | }
38 |
39 | /*Timeline*/
40 | #timelineDiv{
41 | position: relative;
42 | height: 30px;
43 | margin: 0;
44 | }
45 |
46 | #timeline{
47 | top: 0px;
48 | position: absolute;
49 | display: block;
50 | margin: 0;
51 | }
52 |
53 | #timeline::-webkit-slider-runnable-track{
54 | height: 22px;
55 | border-left: 0px;
56 | border-right: 0px;
57 | }
58 |
59 | #timeline::-webkit-slider-thumb{
60 | margin-top: -1px;
61 | }
62 |
63 | #currentTimeLabel{
64 | display: inline-block;
65 | padding-left: 10px;
66 | left: 0px;
67 | top: 30px;
68 | margin: 0;
69 | position: absolute;
70 | }
71 |
72 | #durationLabel{
73 | right: 0px;
74 | position: absolute;
75 | display: inline-block;
76 | padding-right: 10px;
77 | top: 30px;
78 | margin: 0;
79 | }
80 |
81 | /*EQ*/
82 | #eq{
83 | height: 140px;
84 | width: 600px;
85 | display: block;
86 | position: relative;
87 | margin: 0 auto;
88 | }
89 |
90 | /*Control Buttons*/
91 | #controlButtons{
92 | left: 172.5px;
93 | position: absolute;
94 | width: 255px;
95 | display: inline-block;
96 | top: 0px;
97 | }
98 |
99 | /*Sliders*/
100 | .sliders{
101 | position: absolute;
102 | top: 20px;
103 | width: 100px;
104 | height: 120px;
105 | }
106 |
107 | .sliders input{
108 | position: absolute;
109 | top: 50px;
110 | width: 100px;
111 | }
112 |
113 | /*Slider Labels*/
114 | #labels{
115 | width: 600px;
116 | height: 20px;
117 | }
118 |
119 | #labels p{
120 | text-align: center;
121 | margin-top: 0;
122 | margin-bottom: 0;
123 | font-weight: bold;
124 | font-size: 18px;
125 | width: 20px;
126 | height: 20px;
127 | position: absolute;
128 | }
129 |
130 | #labels p:nth-child(1){
131 | left: 8.5px;
132 | }
133 |
134 | #labels p:nth-child(2){
135 | left: 39px;
136 | }
137 |
138 | #labels p:nth-child(3){
139 | left: 69.5px;
140 | }
141 |
142 | #labels p:nth-child(4){
143 | right: 69.5px;
144 | }
145 |
146 | #labels p:nth-child(5){
147 | right: 39px;
148 | }
149 |
150 | #labels p:nth-child(6){
151 | right: 8.5px;
152 | }
153 |
154 | /*First set of sliders*/
155 | #eqSliders{
156 | left: 0px;
157 | }
158 | #eqHigh{
159 | left: -30px;
160 | }
161 | #eqMid{
162 | left: 0px;
163 | }
164 | #eqLow{
165 | left: 30px;
166 | }
167 |
168 | /*Second set of sliders*/
169 | #gainSliders{
170 | right: 0px;
171 | }
172 | #eqLeft{
173 | left: -30px;
174 | }
175 | #eqRight{
176 | left: 0px;
177 | }
178 | #eqMain{
179 | left: 30px;
180 | }
181 |
182 | /*Form*/
183 | #uploadForm {
184 | height: 35px;
185 | width: 600px;
186 | margin: 0 auto;
187 | display: block;
188 | }
189 |
190 | #uploadForm p{
191 | width: 91px;
192 | display: inline-block;
193 | margin: 0;
194 | }
195 |
196 | #uploadForm input[type=file]{
197 | width: 400px;
198 | display: inline-block;
199 | }
200 |
201 | #uploadForm input[type=submit]{
202 | width: 100px;
203 | display: inline-block;
204 | }
205 |
206 | /*Sources*/
207 | #sourceList {
208 | margin-top: 20px;
209 | display: block;
210 | width: 600px;
211 | margin: 0 auto;
212 | padding: 0;
213 | list-style: none;
214 | }
215 |
216 | #sourceList button{
217 | width: 600px;
218 | border-bottom: 0;
219 | }
--------------------------------------------------------------------------------
/old/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teoxoy/audio-visualizer/e785922dbb71ab3c85f80840f8d0fc522b2118d1/old/images/favicon.ico
--------------------------------------------------------------------------------
/old/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Audio Visualizer
21 |0:00
27 |0:00
28 |H
32 |M
33 |L
34 |L
35 |R
36 |M
37 |Press H to toggle the UI
59 |