@logue/reverb 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/index.html DELETED
@@ -1,506 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en" class="h-100">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta
6
- name="viewport"
7
- content="width=device-width, initial-scale=1, shrink-to-fit=no"
8
- />
9
- <meta name="description" content="Reverb effect written in JavaScript." />
10
- <meta name="author" content="Masashi Yoshikawa" />
11
- <!-- ogp -->
12
- <meta property="og:title" content="JavaScript Reverb Effect Test" />
13
- <meta property="og:type" content="article" />
14
- <meta property="og:url" content="https://logue.github.io/Reverb.js/" />
15
- <meta
16
- property="og:image"
17
- content="https://repository-images.githubusercontent.com/194181712/20bdd780-9995-11e9-8811-42e3b44d1cec"
18
- />
19
- <meta property="og:site_name" content="Logue's Lab" />
20
- <meta
21
- property="og:description"
22
- content="Reverb effect written in JavaScript."
23
- />
24
- <meta property="fb:app_id" content="129144050466298" />
25
- <meta
26
- property="article:publisher"
27
- content="https://www.facebook.com/logue256"
28
- />
29
- <meta name="twitter:card" content="Summary" />
30
- <meta name="twitter:site" content="@logue256" />
31
- <meta name="twitter:title" content="JavaScript Reverb Effect Test" />
32
- <meta name="twitter:url" content="https://logue.dev/Reverb.js/" />
33
- <meta
34
- name="twitter:description"
35
- content="Reverb effect written in JavaScript."
36
- />
37
- <meta
38
- name="twitter:image"
39
- content="https://repository-images.githubusercontent.com/194181712/20bdd780-9995-11e9-8811-42e3b44d1cec"
40
- />
41
- <title>Reverb.js Demo</title>
42
- <!-- Global site tag (gtag.js) - Google Analytics -->
43
- <script
44
- async
45
- src="https://www.googletagmanager.com/gtag/js?id=UA-33600926-1"
46
- ></script>
47
- <script>
48
- window.dataLayer = window.dataLayer || [];
49
- function gtag() {
50
- dataLayer.push(arguments);
51
- }
52
- gtag('js', new Date());
53
-
54
- gtag('config', 'UA-33600926-1');
55
- </script>
56
- <link rel="dns-prefetch" href="https://cdn.jsdelivr.net/" />
57
- <!-- Bootstrap core CSS -->
58
- <link
59
- rel="stylesheet"
60
- href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
61
- integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
62
- crossorigin="anonymous"
63
- />
64
- <!-- Web Fonts -->
65
- <link
66
- href="https://fonts.googleapis.com/css?family=M+PLUS+Rounded+1c|Varela+Round&display=swap"
67
- rel="stylesheet"
68
- />
69
- <link
70
- rel="stylesheet"
71
- href="https://use.fontawesome.com/releases/v5.12.0/css/all.css"
72
- />
73
- <style>
74
- body {
75
- font-family: 'Varela Round', 'Rounded Mplus 1c', sans-serif;
76
- }
77
- </style>
78
- </head>
79
-
80
- <body class="d-flex flex-column h-100 pt-5">
81
- <header>
82
- <!-- Fixed navbar -->
83
- <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
84
- <a class="navbar-brand" href="#">Reverb.js</a>
85
- <button
86
- class="navbar-toggler"
87
- type="button"
88
- data-toggle="collapse"
89
- data-target="#navbarCollapse"
90
- aria-controls="navbarCollapse"
91
- aria-expanded="false"
92
- aria-label="Toggle navigation"
93
- >
94
- <span class="navbar-toggler-icon"></span>
95
- </button>
96
- <div class="collapse navbar-collapse" id="navbarCollapse">
97
- <ul class="navbar-nav ml-auto mar-0">
98
- <li class="nav-item active">
99
- <a class="nav-link" href="#"
100
- >Demo <span class="sr-only">(current)</span></a
101
- >
102
- </li>
103
- <li class="nav-item">
104
- <a class="nav-link" href="https://github.com/logue/Reverb.js"
105
- >Github</a
106
- >
107
- </li>
108
- </ul>
109
- </div>
110
- </nav>
111
- </header>
112
-
113
- <!-- Begin page content -->
114
- <main role="main" class="flex-shrink-0 mt-2">
115
- <div class="container">
116
- <h1>Reverb.js Demo</h1>
117
- <p>Refer to the console log for the values.</p>
118
- <button id="play" class="btn btn-primary" disabled>
119
- <i class="fas fa-play"></i> Play
120
- </button>
121
- <button id="stop" class="btn btn-secondary" disabled>
122
- <i class="fas fa-stop"></i> Stop
123
- </button>
124
- <hr />
125
- <h2>Reverb Control</h2>
126
- <div class="custom-control custom-switch">
127
- <input id="reverb" type="checkbox" class="custom-control-input" />
128
- <label class="custom-control-label" for="reverb">Reverb</label>
129
- </div>
130
- <p>
131
- Changing these values will regenerate the impulse response each time,
132
- but due to its nature, it will take some time to see the effect. It
133
- may be helpful to maximize the value of Wet.
134
- </p>
135
- <div class="form-row">
136
- <div class="col-md">
137
- <div class="form-group">
138
- <label for="time">Time <small>(Room size)</small></label>
139
- <input
140
- type="range"
141
- class="custom-range"
142
- value="3"
143
- min="0"
144
- max="50"
145
- id="time"
146
- />
147
- </div>
148
- </div>
149
- <div class="col-md">
150
- <div class="form-group">
151
- <label for="decay"
152
- >Decay <small>(Hardness of room wall)</small></label
153
- >
154
- <input
155
- type="range"
156
- class="custom-range"
157
- value="2"
158
- min="0"
159
- max="100"
160
- id="decay"
161
- />
162
- </div>
163
- </div>
164
- <div class="col-md">
165
- <div class="form-group">
166
- <label for="delay"
167
- >Delay
168
- <small
169
- >(Delays due to obstacles in front of room walls)</small
170
- ></label
171
- >
172
- <input
173
- type="range"
174
- class="custom-range"
175
- value="0"
176
- min="0"
177
- max="100"
178
- id="delay"
179
- />
180
- </div>
181
- </div>
182
- </div>
183
- <div class="form-group">
184
- <div class="custom-control custom-checkbox">
185
- <input type="checkbox" class="custom-control-input" id="reverse" />
186
- <label class="custom-control-label" for="reverse">Reverse</label>
187
- </div>
188
- </div>
189
- <div class="form-group">
190
- <legend>Inpulse Response Noise algorithm</legend>
191
- <div class="custom-control custom-radio custom-control-inline">
192
- <input
193
- class="custom-control-input"
194
- type="radio"
195
- name="noise"
196
- id="white"
197
- value="0"
198
- checked
199
- />
200
- <label class="custom-control-label" for="white">White Noise</label>
201
- </div>
202
- <div class="custom-control custom-radio custom-control-inline">
203
- <input
204
- class="custom-control-input"
205
- type="radio"
206
- name="noise"
207
- id="pink"
208
- value="1"
209
- />
210
- <label class="custom-control-label" for="pink">Pink Noise</label>
211
- </div>
212
- <div class="custom-control custom-radio custom-control-inline">
213
- <input
214
- class="custom-control-input"
215
- type="radio"
216
- name="noise"
217
- id="brown"
218
- value="2"
219
- />
220
- <label class="custom-control-label" for="brown">Brown Noise</label>
221
- </div>
222
- </div>
223
- <div class="form-group">
224
- <label for="mix">Dry / Wet</label>
225
- <div class="input-group mb-3">
226
- <div class="input-group-prepend">
227
- <span class="input-group-text">Dry</span>
228
- </div>
229
- <div class="form-control">
230
- <input
231
- type="range"
232
- id="mix"
233
- class="custom-range"
234
- min="0"
235
- max="1"
236
- step="0.05"
237
- value="0.5"
238
- />
239
- </div>
240
- <div class="input-group-append">
241
- <span class="input-group-text">Wet</span>
242
- </div>
243
- </div>
244
- </div>
245
- <h2>Filter for IR</h2>
246
- <p>
247
- If the value of the filter is allpass, the filtering will be bypassed.
248
- </p>
249
- <div class="form-row">
250
- <div class="col-md">
251
- <div class="form-group">
252
- <label for="filter">Filter Type</label>
253
- <select id="filter" class="form-control">
254
- <option value="lowpass" selected="selected">lowpass</option>
255
- <option value="highpass">highpass</option>
256
- <option value="bandpass">bandpass</option>
257
- <option value="lowshelf">lowshelf</option>
258
- <option value="highshelf">highshelf</option>
259
- <option value="peaking">peaking</option>
260
- <option value="notch">notch</option>
261
- <option value="allpass">allpass (Through)</option>
262
- </select>
263
- </div>
264
- </div>
265
- <div class="col-md">
266
- <div class="form-group">
267
- <label for="freq">Filter frequency</label>
268
- <input
269
- type="range"
270
- class="custom-range"
271
- value="2500"
272
- min="20"
273
- max="5000"
274
- step="5"
275
- id="freq"
276
- />
277
- </div>
278
- </div>
279
- <div class="col-md">
280
- <div class="form-group">
281
- <label for="freq">Quality (Q) value</label>
282
- <input
283
- type="range"
284
- class="custom-range"
285
- value="1"
286
- min=".0001"
287
- max="10"
288
- step=".0005"
289
- id="q"
290
- />
291
- </div>
292
- </div>
293
- </div>
294
- <h2>FFT</h2>
295
- <div class="overflow-auto">
296
- <canvas id="graph" width="512" height="256"></canvas>
297
- </div>
298
- <p class="text-right">
299
- The sound uses the drum part of
300
- <a href="https://soundcloud.com/logue256/autumn-wind" target="_blank"
301
- ><i class="fab fa-soundcloud"></i> Autmun Wind</a
302
- >.
303
- </p>
304
- </div>
305
- </main>
306
-
307
- <footer class="footer mt-auto py-3 bg-light">
308
- <div class="container">
309
- <address class="text-muted">
310
- <i class="far fa-copyright"></i> 2019 by Logue / MIT License.
311
- </address>
312
- </div>
313
- </footer>
314
- <script src="reverb.js"></script>
315
- <script>
316
- // Setup Audio Context
317
- const AudioCtx = new (window.AudioContext || window.webkitAudioContext)();
318
-
319
- // Defreeze AudioContext for iOS.
320
- document.addEventListener('touchstart', initAudioContext);
321
- function initAudioContext() {
322
- document.removeEventListener('touchstart', initAudioContext);
323
- // wake up AudioContext
324
- const emptySource = AudioCtxtx.createBufferSource();
325
- emptySource.start();
326
- emptySource.stop();
327
- }
328
-
329
- // Setup Reverb Class
330
- const reverb = new Reverb.default(AudioCtx);
331
- console.info(
332
- 'Reverb.js loaded. (version:' +
333
- reverb.version +
334
- ' / build: ' +
335
- reverb.build +
336
- ')'
337
- );
338
- const AudioSrc = AudioCtx.createBufferSource();
339
-
340
- // Load audio file and decode asyncly.
341
- const LoadSample = url => {
342
- return new Promise(resolve => {
343
- fetch(url)
344
- .then(response => response.arrayBuffer())
345
- .then(arraybuf =>
346
- AudioCtx.decodeAudioData(
347
- arraybuf,
348
- buffer => {
349
- resolve(buffer);
350
- },
351
- e => alert(e)
352
- )
353
- )
354
- .catch(e => alert(e));
355
- });
356
- };
357
-
358
- // Draw FFT to canvas
359
- // Code taken from https://www.g200kg.com/jp/docs/webaudio/filter.html
360
- const AnalyserNode = AudioCtx.createAnalyser();
361
- const canvas = document.getElementById('graph');
362
- const canvasContext = canvas.getContext('2d');
363
-
364
- const analysedata = new Float32Array(1024);
365
- const DrawGraph = () => {
366
- AnalyserNode.getFloatFrequencyData(analysedata);
367
- // Background
368
- canvasContext.fillStyle = '#343a40';
369
- canvasContext.fillRect(0, 0, canvas.width, canvas.height);
370
- // FFT Graph
371
- canvasContext.fillStyle = document.getElementById('reverb').checked
372
- ? '#17a2b8'
373
- : '#28a745';
374
- for (let i = 0; i < canvas.width; ++i) {
375
- const f = (AudioCtx.sampleRate * i) / (canvas.width * 2);
376
- y = canvas.height / 2 + (analysedata[i] + 48.16) * 2.56;
377
- canvasContext.fillRect(i, canvas.height - y, 1, y);
378
- }
379
-
380
- // y axis (dB)
381
- for (let d = -50; d < 50; d += 10) {
382
- const y = (canvas.height / 2 - (d * canvas.height) / 100) | 0;
383
- // Line
384
- canvasContext.fillStyle = '#6c757d';
385
- canvasContext.fillRect(20, y, canvas.width, 1);
386
- // Label
387
- canvasContext.fillStyle = '#fd7e14';
388
- canvasContext.fillText(d + 'dB', 5, y);
389
- }
390
- canvasContext.fillStyle = '#ffc107';
391
- canvasContext.fillRect(20, canvas.height / 2, canvas.width, 1);
392
-
393
- // x axis (frequency)
394
- for (let f = 2200; f < AudioCtx.sampleRate / 2; f += 2000) {
395
- const x = ((f * (canvas.width * 2)) / AudioCtx.sampleRate) | 0;
396
- // Line
397
- canvasContext.fillStyle = '#6c757d';
398
- canvasContext.fillRect(x, 0, 1, canvas.height - 10);
399
- // Label
400
- if (x % 4 == 0) {
401
- canvasContext.fillStyle = '#e83e8c';
402
- canvasContext.fillText(f / 1000 + 'kHz', x - 10, canvas.height - 1);
403
- }
404
- }
405
- };
406
-
407
- // Reverb switch handler
408
- const setReverb = () => {
409
- AudioSrc.disconnect();
410
-
411
- if (document.getElementById('reverb').checked) {
412
- // Connect Reverb
413
- reverb.connect(AudioSrc).connect(AnalyserNode);
414
- } else {
415
- reverb.disconnect(AudioSrc).connect(AnalyserNode);
416
- }
417
- AnalyserNode.connect(AudioCtx.destination);
418
- };
419
-
420
- window.addEventListener('load', async () => {
421
- const sound = await LoadSample('./demo.wav');
422
-
423
- // Draw FFT
424
- setInterval(DrawGraph, 10);
425
-
426
- // remove disabled
427
- document.getElementById('play').disabled = '';
428
- document.getElementById('stop').disabled = '';
429
-
430
- // Play button
431
- document.getElementById('play').addEventListener('click', () => {
432
- if (AudioCtx.state == 'suspended') AudioCtx.resume();
433
- if (AudioSrc.buffer == null) {
434
- AudioSrc.buffer = sound;
435
- AudioSrc.loop = true;
436
-
437
- setReverb();
438
- AudioSrc.start();
439
- }
440
- });
441
-
442
- // Stop button
443
- document.getElementById('stop').addEventListener('click', () => {
444
- if (AudioSrc.buffer) AudioSrc.stop();
445
- });
446
-
447
- // Reverb switch button
448
- document.getElementById('reverb').addEventListener('click', setReverb);
449
- // Reverse checkbox
450
- document
451
- .getElementById('reverse')
452
- .addEventListener('click', () =>
453
- reverb.reverse(document.getElementById('reverse').checked)
454
- );
455
- // Reverb dualation time
456
- document
457
- .getElementById('time')
458
- .addEventListener('change', () =>
459
- reverb.time(document.getElementById('time').value)
460
- );
461
- // Decay time
462
- document
463
- .getElementById('decay')
464
- .addEventListener('change', () =>
465
- reverb.decay(document.getElementById('decay').value)
466
- );
467
- // Delay time
468
- document
469
- .getElementById('delay')
470
- .addEventListener('change', () =>
471
- reverb.delay(document.getElementById('delay').value)
472
- );
473
- // Filter select box
474
- document
475
- .getElementById('filter')
476
- .addEventListener('change', () =>
477
- reverb.filterType(document.getElementById('filter').value)
478
- );
479
- // Filter frequency
480
- document
481
- .getElementById('freq')
482
- .addEventListener('change', () =>
483
- reverb.filterFreq(document.getElementById('freq').value)
484
- );
485
- // Filter quality
486
- document
487
- .getElementById('q')
488
- .addEventListener('change', () =>
489
- reverb.filterQ(document.getElementById('q').value)
490
- );
491
- // Dry/Wet
492
- document
493
- .getElementById('mix')
494
- .addEventListener('change', () =>
495
- reverb.mix(document.getElementById('mix').value)
496
- );
497
- // Noise Type
498
- document
499
- .querySelectorAll('[name=noise]')
500
- .forEach(dom =>
501
- dom.addEventListener('click', e => reverb.setNoise(e.target.value))
502
- );
503
- });
504
- </script>
505
- </body>
506
- </html>