@logue/reverb 0.4.6 → 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/README.md +85 -64
- package/dist/reverb.es.js +188 -0
- package/dist/reverb.umd.js +10 -0
- package/package.json +59 -45
- package/types/Meta.d.ts +4 -0
- package/types/Meta.d.ts.map +1 -0
- package/types/NoiseType.d.ts +14 -0
- package/types/NoiseType.d.ts.map +1 -0
- package/types/Reverb.d.ts +118 -0
- package/types/Reverb.d.ts.map +1 -0
- package/{src/interfaces/MetaInterface.ts → types/interfaces/MetaInterface.d.ts} +2 -3
- package/{dist → types}/interfaces/MetaInterface.d.ts.map +1 -1
- package/{src/interfaces/OptionInterface.ts → types/interfaces/OptionInterface.d.ts} +3 -5
- package/types/interfaces/OptionInterface.d.ts.map +1 -0
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -21
- package/.gitattributes +0 -1
- package/.prettierrc.js +0 -3
- package/bin/reverb.js +0 -434
- package/bin/reverb.js.map +0 -1
- package/bin/reverb.min.js +0 -2
- package/bin/reverb.min.js.LICENSE.txt +0 -11
- package/dist/Meta.d.ts +0 -4
- package/dist/Meta.d.ts.map +0 -1
- package/dist/Meta.js +0 -9
- package/dist/Meta.js.map +0 -1
- package/dist/NoiseType.d.ts +0 -7
- package/dist/NoiseType.d.ts.map +0 -1
- package/dist/NoiseType.js +0 -12
- package/dist/NoiseType.js.map +0 -1
- package/dist/Reverb.d.ts +0 -114
- package/dist/Reverb.d.ts.map +0 -1
- package/dist/Reverb.js +0 -333
- package/dist/Reverb.js.map +0 -1
- package/dist/interfaces/MetaInterface.d.ts +0 -10
- package/dist/interfaces/MetaInterface.js +0 -3
- package/dist/interfaces/MetaInterface.js.map +0 -1
- package/dist/interfaces/OptionInterface.d.ts +0 -27
- package/dist/interfaces/OptionInterface.d.ts.map +0 -1
- package/dist/interfaces/OptionInterface.js +0 -3
- package/dist/interfaces/OptionInterface.js.map +0 -1
- package/docs/demo.wav +0 -0
- package/docs/index.html +0 -377
- package/docs/localaudio.html +0 -718
- package/docs/reverb.js +0 -434
- package/docs/reverb.js.map +0 -1
- package/src/Meta.ts +0 -8
- package/src/NoiseType.ts +0 -7
- package/src/Reverb.ts +0 -368
- package/tsconfig.json +0 -32
- package/webpack.config.ts +0 -102
package/docs/localaudio.html
DELETED
|
@@ -1,718 +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
|
|
33
|
-
name="twitter:url"
|
|
34
|
-
content="https://logue.github.io/Reverb.js/localaudio.html"
|
|
35
|
-
/>
|
|
36
|
-
<meta
|
|
37
|
-
name="twitter:description"
|
|
38
|
-
content="Reverb effect written in JavaScript."
|
|
39
|
-
/>
|
|
40
|
-
<meta
|
|
41
|
-
name="twitter:image"
|
|
42
|
-
content="https://repository-images.githubusercontent.com/194181712/20bdd780-9995-11e9-8811-42e3b44d1cec"
|
|
43
|
-
/>
|
|
44
|
-
<title>Reverb.js Demo</title>
|
|
45
|
-
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
46
|
-
<script
|
|
47
|
-
async
|
|
48
|
-
src="https://www.googletagmanager.com/gtag/js?id=UA-33600926-1"
|
|
49
|
-
></script>
|
|
50
|
-
<script>
|
|
51
|
-
window.dataLayer = window.dataLayer || [];
|
|
52
|
-
function gtag() {
|
|
53
|
-
dataLayer.push(arguments);
|
|
54
|
-
}
|
|
55
|
-
gtag('js', new Date());
|
|
56
|
-
|
|
57
|
-
gtag('config', 'UA-33600926-1');
|
|
58
|
-
</script>
|
|
59
|
-
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net/" />
|
|
60
|
-
<!-- Bootstrap core CSS -->
|
|
61
|
-
<link
|
|
62
|
-
rel="stylesheet"
|
|
63
|
-
href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
|
|
64
|
-
integrity="sha256-93wNFzm2GO3EoByj9rKZCwGjAJAwr0nujPaOgwUt8ZQ="
|
|
65
|
-
crossorigin="anonymous"
|
|
66
|
-
/>
|
|
67
|
-
<!-- Web Fonts -->
|
|
68
|
-
<link
|
|
69
|
-
href="https://fonts.googleapis.com/css?family=M+PLUS+Rounded+1c|Varela+Round&display=swap"
|
|
70
|
-
rel="stylesheet"
|
|
71
|
-
/>
|
|
72
|
-
<link
|
|
73
|
-
rel="stylesheet"
|
|
74
|
-
href="https://use.fontawesome.com/releases/v5.12.0/css/all.css"
|
|
75
|
-
/>
|
|
76
|
-
<style>
|
|
77
|
-
/*<!CDATA[*/
|
|
78
|
-
body {
|
|
79
|
-
font-family: 'Varela Round', 'Rounded Mplus 1c', sans-serif;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/*]]>*/
|
|
83
|
-
</style>
|
|
84
|
-
</head>
|
|
85
|
-
|
|
86
|
-
<body class="d-flex flex-column h-100 pt-5">
|
|
87
|
-
<header>
|
|
88
|
-
<!-- Fixed navbar -->
|
|
89
|
-
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
|
90
|
-
<a class="navbar-brand" href="#">Reverb.js</a>
|
|
91
|
-
<button
|
|
92
|
-
class="navbar-toggler"
|
|
93
|
-
type="button"
|
|
94
|
-
data-toggle="collapse"
|
|
95
|
-
data-target="#navbarCollapse"
|
|
96
|
-
aria-controls="navbarCollapse"
|
|
97
|
-
aria-expanded="false"
|
|
98
|
-
aria-label="Toggle navigation"
|
|
99
|
-
>
|
|
100
|
-
<span class="navbar-toggler-icon"></span>
|
|
101
|
-
</button>
|
|
102
|
-
<div class="collapse navbar-collapse" id="navbarCollapse">
|
|
103
|
-
<ul class="navbar-nav ml-auto mar-0">
|
|
104
|
-
<li class="nav-item active">
|
|
105
|
-
<a class="nav-link" href="#"
|
|
106
|
-
>Demo <span class="sr-only">(current)</span></a
|
|
107
|
-
>
|
|
108
|
-
</li>
|
|
109
|
-
<li class="nav-item">
|
|
110
|
-
<a class="nav-link" href="https://github.com/logue/Reverb.js"
|
|
111
|
-
>Github</a
|
|
112
|
-
>
|
|
113
|
-
</li>
|
|
114
|
-
</ul>
|
|
115
|
-
</div>
|
|
116
|
-
</nav>
|
|
117
|
-
</header>
|
|
118
|
-
|
|
119
|
-
<!-- Begin page content -->
|
|
120
|
-
<main role="main" class="flex-shrink-0 mt-2">
|
|
121
|
-
<div class="container">
|
|
122
|
-
<h1>Reverb.js Demo</h1>
|
|
123
|
-
<div class="d-flex">
|
|
124
|
-
<div>
|
|
125
|
-
<button id="play" class="btn btn-primary" disabled>
|
|
126
|
-
<i class="fas fa-play"></i> Play
|
|
127
|
-
</button>
|
|
128
|
-
</div>
|
|
129
|
-
<div>
|
|
130
|
-
<button id="stop" class="btn btn-secondary" disabled>
|
|
131
|
-
<i class="fas fa-stop"></i> Stop
|
|
132
|
-
</button>
|
|
133
|
-
</div>
|
|
134
|
-
<div class="custom-file form-control-sm ml-3">
|
|
135
|
-
<input
|
|
136
|
-
type="file"
|
|
137
|
-
class="custom-file-input"
|
|
138
|
-
id="file"
|
|
139
|
-
accept="audio/*"
|
|
140
|
-
/>
|
|
141
|
-
<label class="custom-file-label" for="file"
|
|
142
|
-
>Load Audio file
|
|
143
|
-
<small class="d-none d-sm-inline"
|
|
144
|
-
>(drag and drop file to change audio)</small
|
|
145
|
-
>
|
|
146
|
-
</label>
|
|
147
|
-
</div>
|
|
148
|
-
</div>
|
|
149
|
-
<h2>Reverb Control</h2>
|
|
150
|
-
<div class="custom-control custom-switch">
|
|
151
|
-
<input id="reverb" type="checkbox" class="custom-control-input" />
|
|
152
|
-
<label class="custom-control-label" for="reverb">Reverb</label>
|
|
153
|
-
</div>
|
|
154
|
-
<div class="form-row">
|
|
155
|
-
<div class="col">
|
|
156
|
-
<div class="form-group">
|
|
157
|
-
<label for="time">Time</label>
|
|
158
|
-
<input
|
|
159
|
-
type="range"
|
|
160
|
-
class="custom-range"
|
|
161
|
-
value="3"
|
|
162
|
-
min="0"
|
|
163
|
-
max="50"
|
|
164
|
-
id="time"
|
|
165
|
-
/>
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
<div class="col">
|
|
169
|
-
<div class="form-group">
|
|
170
|
-
<label for="decay">Decay</label>
|
|
171
|
-
<input
|
|
172
|
-
type="range"
|
|
173
|
-
class="custom-range"
|
|
174
|
-
value="2"
|
|
175
|
-
min="0"
|
|
176
|
-
max="100"
|
|
177
|
-
id="decay"
|
|
178
|
-
/>
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
<div class="col">
|
|
182
|
-
<div class="form-group">
|
|
183
|
-
<label for="delay">Delay</label>
|
|
184
|
-
<input
|
|
185
|
-
type="range"
|
|
186
|
-
class="custom-range"
|
|
187
|
-
value="0"
|
|
188
|
-
min="0"
|
|
189
|
-
max="100"
|
|
190
|
-
id="delay"
|
|
191
|
-
/>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
<div class="form-group">
|
|
196
|
-
<div class="custom-control custom-checkbox">
|
|
197
|
-
<input type="checkbox" class="custom-control-input" id="reverse" />
|
|
198
|
-
<label class="custom-control-label" for="reverse">Reverse</label>
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
<div class="form-row">
|
|
202
|
-
<div class="col">
|
|
203
|
-
<div class="form-group">
|
|
204
|
-
<label for="filter">Filter Type</label>
|
|
205
|
-
<select id="filter" class="form-control">
|
|
206
|
-
<option value="lowpass" selected="selected">lowpass</option>
|
|
207
|
-
<option value="highpass">highpass</option>
|
|
208
|
-
<option value="bandpass">bandpass</option>
|
|
209
|
-
<option value="lowshelf">lowshelf</option>
|
|
210
|
-
<option value="highshelf">highshelf</option>
|
|
211
|
-
<option value="peaking">peaking</option>
|
|
212
|
-
<option value="notch">notch</option>
|
|
213
|
-
<option value="allpass">allpass</option>
|
|
214
|
-
</select>
|
|
215
|
-
</div>
|
|
216
|
-
</div>
|
|
217
|
-
<div class="col">
|
|
218
|
-
<div class="form-group">
|
|
219
|
-
<label for="freq">Filter frequency</label>
|
|
220
|
-
<input
|
|
221
|
-
type="range"
|
|
222
|
-
class="custom-range"
|
|
223
|
-
value="2500"
|
|
224
|
-
min="20"
|
|
225
|
-
max="5000"
|
|
226
|
-
step="5"
|
|
227
|
-
id="freq"
|
|
228
|
-
/>
|
|
229
|
-
</div>
|
|
230
|
-
</div>
|
|
231
|
-
<div class="col">
|
|
232
|
-
<div class="form-group">
|
|
233
|
-
<label for="freq">Quality (Q) value</label>
|
|
234
|
-
<input
|
|
235
|
-
type="range"
|
|
236
|
-
class="custom-range"
|
|
237
|
-
value="1"
|
|
238
|
-
min=".0001"
|
|
239
|
-
max="10"
|
|
240
|
-
step=".0005"
|
|
241
|
-
id="q"
|
|
242
|
-
/>
|
|
243
|
-
</div>
|
|
244
|
-
</div>
|
|
245
|
-
</div>
|
|
246
|
-
<div class="form-group">
|
|
247
|
-
<label for="mix">Dry / Wet</label>
|
|
248
|
-
<div class="input-group mb-3">
|
|
249
|
-
<div class="input-group-prepend">
|
|
250
|
-
<span class="input-group-text">Dry</span>
|
|
251
|
-
</div>
|
|
252
|
-
<div class="form-control">
|
|
253
|
-
<input
|
|
254
|
-
type="range"
|
|
255
|
-
id="mix"
|
|
256
|
-
class="custom-range"
|
|
257
|
-
min="0"
|
|
258
|
-
max="1"
|
|
259
|
-
step="0.05"
|
|
260
|
-
value="0.5"
|
|
261
|
-
/>
|
|
262
|
-
</div>
|
|
263
|
-
<div class="input-group-append">
|
|
264
|
-
<span class="input-group-text">Wet</span>
|
|
265
|
-
</div>
|
|
266
|
-
</div>
|
|
267
|
-
</div>
|
|
268
|
-
<h2>Spectrum Analysis</h2>
|
|
269
|
-
<div class="overflow-auto">
|
|
270
|
-
<canvas id="canvas" class="d-none"></canvas>
|
|
271
|
-
<img id="test" class="d-none" />
|
|
272
|
-
<canvas id="graph"></canvas>
|
|
273
|
-
</div>
|
|
274
|
-
</div>
|
|
275
|
-
</main>
|
|
276
|
-
|
|
277
|
-
<footer class="footer mt-auto py-3 bg-light">
|
|
278
|
-
<div class="container">
|
|
279
|
-
<address class="text-muted">
|
|
280
|
-
<i class="far fa-copyright"></i> 2019 by Logue / MIT License.
|
|
281
|
-
</address>
|
|
282
|
-
</div>
|
|
283
|
-
</footer>
|
|
284
|
-
<!--script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.slim.min.js"
|
|
285
|
-
integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
|
|
286
|
-
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.bundle.min.js"
|
|
287
|
-
integrity="sha256-fzFFyH01cBVPYzl16KT40wqjhgPtq6FFUB6ckN2+GGw=" crossorigin="anonymous"></script-->
|
|
288
|
-
<script
|
|
289
|
-
src="https://cdn.jsdelivr.net/npm/three-js@79.0.0/three.js"
|
|
290
|
-
integrity="sha256-A2ofbc4qfSfxXRlxuONE0Bj7ulHxEAIiYk537fvbkJU="
|
|
291
|
-
crossorigin="anonymous"
|
|
292
|
-
></script>
|
|
293
|
-
<script src="reverb.js"></script>
|
|
294
|
-
<script>
|
|
295
|
-
// Setup Audio Context
|
|
296
|
-
const AudioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
|
297
|
-
|
|
298
|
-
// Defreeze AudioContext for iOS.
|
|
299
|
-
document.addEventListener('touchstart', initAudioContext);
|
|
300
|
-
function initAudioContext() {
|
|
301
|
-
document.removeEventListener('touchstart', initAudioContext);
|
|
302
|
-
// wake up AudioContext
|
|
303
|
-
const emptySource = AudioCtx.createBufferSource();
|
|
304
|
-
emptySource.start();
|
|
305
|
-
emptySource.stop();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Audio object
|
|
309
|
-
const audio = new Audio();
|
|
310
|
-
|
|
311
|
-
// Audio Source
|
|
312
|
-
const AudioSrc = AudioCtx.createMediaElementSource(audio);
|
|
313
|
-
|
|
314
|
-
// Analyzer Node
|
|
315
|
-
const AnalyserNode = AudioCtx.createAnalyser();
|
|
316
|
-
|
|
317
|
-
// Setup Reverb Class
|
|
318
|
-
const reverb = new Reverb.default(AudioCtx);
|
|
319
|
-
|
|
320
|
-
// decode audio
|
|
321
|
-
const LoadSample = async input => {
|
|
322
|
-
if (audio) {
|
|
323
|
-
audio.pause();
|
|
324
|
-
audio.src = '';
|
|
325
|
-
}
|
|
326
|
-
audio.src = await loadDataUri(input);
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
// Load array buffer
|
|
330
|
-
const loadDataUri = async input => {
|
|
331
|
-
document.getElementById('play').disabled = 'disabled';
|
|
332
|
-
document.getElementById('stop').disabled = 'disabled';
|
|
333
|
-
return await new Promise(resolve => {
|
|
334
|
-
if (input instanceof File) {
|
|
335
|
-
const reader = new FileReader();
|
|
336
|
-
reader.onload = event => {
|
|
337
|
-
resolve(event.target.result);
|
|
338
|
-
document.getElementById('play').disabled = '';
|
|
339
|
-
document.getElementById('stop').disabled = '';
|
|
340
|
-
};
|
|
341
|
-
reader.readAsDataURL(input);
|
|
342
|
-
} else {
|
|
343
|
-
fetch(input)
|
|
344
|
-
.then(response => {
|
|
345
|
-
return {
|
|
346
|
-
mime: response.headers.get('content-type'),
|
|
347
|
-
buffer: response.arrayBuffer(),
|
|
348
|
-
};
|
|
349
|
-
})
|
|
350
|
-
.then(res => {
|
|
351
|
-
// to base64
|
|
352
|
-
let binary = '';
|
|
353
|
-
let bytes = [].slice.call(new Uint8Array(res.buffer));
|
|
354
|
-
|
|
355
|
-
bytes.forEach(b => (binary += String.fromCharCode(b)));
|
|
356
|
-
const base64 = window.btoa(binary);
|
|
357
|
-
// prepend data scheme
|
|
358
|
-
resolve('data:' + res.mime + ';base64;' + base64);
|
|
359
|
-
|
|
360
|
-
document.getElementById('play').disabled = '';
|
|
361
|
-
document.getElementById('stop').disabled = '';
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}).catch(e => alert(e));
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
const handleFileSelect = async e => {
|
|
368
|
-
const file = e.target.files[0];
|
|
369
|
-
AudioSrc.buffer = await LoadSample(file);
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
// Reverb switch handler
|
|
373
|
-
const setReverb = () => {
|
|
374
|
-
AudioSrc.disconnect();
|
|
375
|
-
|
|
376
|
-
if (document.getElementById('reverb').checked) {
|
|
377
|
-
// Connect Reverb
|
|
378
|
-
reverb.connect(AudioSrc).connect(AnalyserNode);
|
|
379
|
-
} else {
|
|
380
|
-
reverb.disconnect(AudioSrc).connect(AnalyserNode);
|
|
381
|
-
}
|
|
382
|
-
AnalyserNode.connect(AudioCtx.destination);
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* Draw Texture Functions
|
|
387
|
-
**/
|
|
388
|
-
const PIXEL_RATIO = () => {
|
|
389
|
-
const ctx = document.createElement('canvas').getContext('2d'),
|
|
390
|
-
dpr = window.devicePixelRatio || 1,
|
|
391
|
-
bsr =
|
|
392
|
-
ctx.webkitBackingStorePixelRatio ||
|
|
393
|
-
ctx.mozBackingStorePixelRatio ||
|
|
394
|
-
ctx.msBackingStorePixelRatio ||
|
|
395
|
-
ctx.oBackingStorePixelRatio ||
|
|
396
|
-
ctx.backingStorePixelRatio ||
|
|
397
|
-
1;
|
|
398
|
-
return dpr / bsr;
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
// Create retina quality canvas
|
|
402
|
-
const createRetinaCanvas = (w, h, ratio) => {
|
|
403
|
-
if (!ratio) {
|
|
404
|
-
ratio = PIXEL_RATIO;
|
|
405
|
-
}
|
|
406
|
-
const canvas = document.getElementById('canvas');
|
|
407
|
-
//const canvas = document.createElement('canvas');
|
|
408
|
-
canvas.width = w * ratio;
|
|
409
|
-
canvas.height = h * ratio;
|
|
410
|
-
canvas.style.width = w + 'px';
|
|
411
|
-
canvas.style.height = h + 'px';
|
|
412
|
-
canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
|
|
413
|
-
return canvas;
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
// Spectrum Analysis canvas size
|
|
417
|
-
const SPRITE_HEIGHT = 256;
|
|
418
|
-
const SPRITE_WIDTH = 512;
|
|
419
|
-
|
|
420
|
-
// Sprite Canvas
|
|
421
|
-
const spriteCanvas = createRetinaCanvas(SPRITE_WIDTH, SPRITE_HEIGHT);
|
|
422
|
-
|
|
423
|
-
// Draw Graph
|
|
424
|
-
const DrawGraph = () => {
|
|
425
|
-
const AnalyseData = new Float32Array(1024);
|
|
426
|
-
AnalyserNode.getFloatFrequencyData(AnalyseData);
|
|
427
|
-
|
|
428
|
-
const sprite = spriteCanvas.getContext('2d', {antialias: false});
|
|
429
|
-
|
|
430
|
-
// Background
|
|
431
|
-
//sprite.fillStyle = "#343a40";
|
|
432
|
-
//sprite.fillRect(0, 0, SPRITE_WIDTH, SPRITE_HEIGHT);
|
|
433
|
-
|
|
434
|
-
sprite.clearRect(0, 0, spriteCanvas.width, spriteCanvas.height);
|
|
435
|
-
|
|
436
|
-
// Graph
|
|
437
|
-
const grad = sprite.createLinearGradient(0, 0, spriteCanvas.width, 0);
|
|
438
|
-
grad.addColorStop(0, 'rgb(255, 0, 0)');
|
|
439
|
-
grad.addColorStop(0.2, 'rgb(255, 255, 0)');
|
|
440
|
-
grad.addColorStop(0.4, 'rgb(0, 255, 0)');
|
|
441
|
-
grad.addColorStop(0.6, 'rgb(0, 255, 255)');
|
|
442
|
-
grad.addColorStop(0.8, 'rgb(0, 0, 255)');
|
|
443
|
-
grad.addColorStop(1, 'rgb(255, 0, 255)');
|
|
444
|
-
sprite.fillStyle = grad;
|
|
445
|
-
//sprite.fillStyle = document.getElementById('reverb').checked ? "#17a2b8" : "#28a745";
|
|
446
|
-
|
|
447
|
-
for (let i = 0; i < spriteCanvas.width; ++i) {
|
|
448
|
-
const f = (AudioCtx.sampleRate * i) / 1024;
|
|
449
|
-
y = 128 + (AnalyseData[i] + 48.16) * 2.56 + 1;
|
|
450
|
-
sprite.fillRect(i, spriteCanvas.height - y, 1, y);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
return spriteCanvas.toDataURL();
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
// Draw Axis
|
|
457
|
-
const DrawAxis = () => {
|
|
458
|
-
const sprite = spriteCanvas.getContext('2d', {antialias: false});
|
|
459
|
-
// y axis (dB)
|
|
460
|
-
for (let d = -50; d < 50; d += 10) {
|
|
461
|
-
const y = (SPRITE_HEIGHT / 2 - (d * SPRITE_HEIGHT) / 100) | 0;
|
|
462
|
-
// Line
|
|
463
|
-
sprite.fillStyle = '#6c757d';
|
|
464
|
-
sprite.fillRect(20, y, SPRITE_WIDTH, 1);
|
|
465
|
-
// Label
|
|
466
|
-
sprite.fillStyle = '#fd7e14';
|
|
467
|
-
sprite.fillText(d + 'dB', 5, y);
|
|
468
|
-
}
|
|
469
|
-
sprite.fillStyle = '#ffc107';
|
|
470
|
-
sprite.fillRect(20, SPRITE_HEIGHT / 2, SPRITE_WIDTH, 1);
|
|
471
|
-
|
|
472
|
-
// x axis (frequency)
|
|
473
|
-
for (let f = 2000; f < AudioCtx.sampleRate / 2; f += 2000) {
|
|
474
|
-
const x = ((f * 1024) / AudioCtx.sampleRate) | 0;
|
|
475
|
-
// Line
|
|
476
|
-
sprite.fillStyle = '#6c757d';
|
|
477
|
-
sprite.fillRect(x, 0, 1, 245);
|
|
478
|
-
// Label
|
|
479
|
-
sprite.fillStyle = '#e83e8c';
|
|
480
|
-
sprite.fillText(f / 1000 + 'kHz', x - 10, 255);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
return spriteCanvas.toDataURL();
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
// スプライトのデバッグ
|
|
487
|
-
const debug = src => {
|
|
488
|
-
const canvas = document.getElementById('canvas');
|
|
489
|
-
canvas.style.width = SPRITE_WIDTH + 'px';
|
|
490
|
-
canvas.style.height = SPRITE_HEIGHT + 'px';
|
|
491
|
-
canvas.width = SPRITE_WIDTH;
|
|
492
|
-
canvas.height = SPRITE_HEIGHT;
|
|
493
|
-
|
|
494
|
-
const img = document.getElementById('test');
|
|
495
|
-
img.style.width = SPRITE_WIDTH + 'px';
|
|
496
|
-
img.style.height = SPRITE_HEIGHT + 'px';
|
|
497
|
-
img.src = src;
|
|
498
|
-
//ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
499
|
-
|
|
500
|
-
const image = new Image();
|
|
501
|
-
image.addEventListener('load', () => {
|
|
502
|
-
canvas.getContext('2d').drawImage(image, 0, 0); // Or at whatever offset you like
|
|
503
|
-
});
|
|
504
|
-
image.src = src;
|
|
505
|
-
};
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* 3D Spectrum Analyzer Code
|
|
509
|
-
*/
|
|
510
|
-
|
|
511
|
-
// 3D canvas size
|
|
512
|
-
const CANVAS_WIDTH = 960;
|
|
513
|
-
const CANVAS_HEIGHT = 540;
|
|
514
|
-
|
|
515
|
-
// Create renderer
|
|
516
|
-
const renderer = new THREE.WebGLRenderer({
|
|
517
|
-
canvas: document.querySelector('#graph'),
|
|
518
|
-
});
|
|
519
|
-
renderer.setPixelRatio(window.devicePixelRatio);
|
|
520
|
-
renderer.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
|
|
521
|
-
|
|
522
|
-
// Create Scene
|
|
523
|
-
const scene = new THREE.Scene();
|
|
524
|
-
|
|
525
|
-
// Create camera
|
|
526
|
-
const camera = new THREE.PerspectiveCamera(
|
|
527
|
-
30,
|
|
528
|
-
CANVAS_WIDTH / CANVAS_HEIGHT,
|
|
529
|
-
1,
|
|
530
|
-
2000
|
|
531
|
-
);
|
|
532
|
-
// Move Initial camera position (x, y, z)
|
|
533
|
-
camera.position.set(100, 50, 1000);
|
|
534
|
-
//const camera = new THREE.OrthographicCamera(-CANVAS_WIDTH, CANVAS_WIDTH, CANVAS_HEIGHT, -CANVAS_HEIGHT, 1, 100000);
|
|
535
|
-
|
|
536
|
-
// Append Fog
|
|
537
|
-
// new THREE.Fog(color, start distance, end distance);
|
|
538
|
-
scene.fog = new THREE.Fog(0x000000, 1000, 2000);
|
|
539
|
-
|
|
540
|
-
//debug(DrawAxis())
|
|
541
|
-
|
|
542
|
-
const AxisMesh = new THREE.Mesh(
|
|
543
|
-
// Plane
|
|
544
|
-
new THREE.PlaneGeometry(SPRITE_WIDTH, SPRITE_HEIGHT, 5, 5),
|
|
545
|
-
// Texture
|
|
546
|
-
new THREE.MeshBasicMaterial({
|
|
547
|
-
transparent: true,
|
|
548
|
-
needsUpdate: true,
|
|
549
|
-
map: new THREE.TextureLoader().load(DrawAxis()),
|
|
550
|
-
side: THREE.DoubleSide,
|
|
551
|
-
})
|
|
552
|
-
);
|
|
553
|
-
|
|
554
|
-
// Move Mesh object
|
|
555
|
-
AxisMesh.position.set(0, 0, 0);
|
|
556
|
-
|
|
557
|
-
scene.add(AxisMesh);
|
|
558
|
-
|
|
559
|
-
let depth = 0;
|
|
560
|
-
let geometries = [];
|
|
561
|
-
let materials = [];
|
|
562
|
-
let textures = [];
|
|
563
|
-
let meshs = [];
|
|
564
|
-
|
|
565
|
-
const MAX_DEPTH = 1024;
|
|
566
|
-
|
|
567
|
-
// Loop event
|
|
568
|
-
const tick = () => {
|
|
569
|
-
// Draw Texture image
|
|
570
|
-
const sprite = DrawGraph();
|
|
571
|
-
|
|
572
|
-
debug(sprite);
|
|
573
|
-
|
|
574
|
-
textures[depth] = new THREE.TextureLoader().load(sprite);
|
|
575
|
-
|
|
576
|
-
geometries[depth] = new THREE.PlaneGeometry(
|
|
577
|
-
SPRITE_WIDTH,
|
|
578
|
-
SPRITE_HEIGHT,
|
|
579
|
-
5,
|
|
580
|
-
5
|
|
581
|
-
);
|
|
582
|
-
|
|
583
|
-
materials[depth] = new THREE.MeshBasicMaterial({
|
|
584
|
-
color: 0xccddee,
|
|
585
|
-
transparent: true,
|
|
586
|
-
needsUpdate: true,
|
|
587
|
-
map: textures[depth],
|
|
588
|
-
side: THREE.DoubleSide,
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
// Mesh object
|
|
592
|
-
meshs[depth] = new THREE.Mesh(geometries[depth], materials[depth]);
|
|
593
|
-
|
|
594
|
-
// Move Mesh object
|
|
595
|
-
meshs[depth].position.set(0, 0, depth);
|
|
596
|
-
AxisMesh.position.set(0, 0, depth);
|
|
597
|
-
|
|
598
|
-
// Append Mesh object to 3D scene
|
|
599
|
-
scene.add(meshs[depth]);
|
|
600
|
-
|
|
601
|
-
// Render
|
|
602
|
-
renderer.render(scene, camera);
|
|
603
|
-
|
|
604
|
-
// Move Camera
|
|
605
|
-
camera.position.z = depth + 650;
|
|
606
|
-
//camera.zoom = 2;
|
|
607
|
-
camera.updateProjectionMatrix();
|
|
608
|
-
|
|
609
|
-
// Look to origin
|
|
610
|
-
camera.lookAt(new THREE.Vector3(0, 0, depth));
|
|
611
|
-
|
|
612
|
-
// Remove old Mesh
|
|
613
|
-
if (depth > MAX_DEPTH) {
|
|
614
|
-
scene.remove(meshs[depth - MAX_DEPTH]);
|
|
615
|
-
//meshs[depth - MAX_DEPTH].dispose();
|
|
616
|
-
geometries[depth - MAX_DEPTH].dispose();
|
|
617
|
-
materials[depth - MAX_DEPTH].dispose();
|
|
618
|
-
textures[depth - MAX_DEPTH].dispose();
|
|
619
|
-
|
|
620
|
-
// Manual Gabarge Collection
|
|
621
|
-
delete geometries[depth - MAX_DEPTH];
|
|
622
|
-
delete materials[depth - MAX_DEPTH];
|
|
623
|
-
delete textures[depth - MAX_DEPTH];
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// incriment depth
|
|
627
|
-
depth++;
|
|
628
|
-
|
|
629
|
-
// Update Animation
|
|
630
|
-
requestAnimationFrame(tick);
|
|
631
|
-
};
|
|
632
|
-
|
|
633
|
-
// Regist Event
|
|
634
|
-
window.addEventListener('load', async () => {
|
|
635
|
-
audio.src = await LoadSample('./demo.wav');
|
|
636
|
-
// Play button
|
|
637
|
-
document.getElementById('play').addEventListener('click', async () => {
|
|
638
|
-
if (AudioCtx.state == 'suspended') AudioCtx.resume();
|
|
639
|
-
setReverb();
|
|
640
|
-
audio.play();
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
// Stop button
|
|
644
|
-
document.getElementById('stop').addEventListener('click', () => {
|
|
645
|
-
audio.stop();
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
// File form
|
|
649
|
-
document.getElementById('file').addEventListener('dragover', e => {
|
|
650
|
-
e.stopPropagation();
|
|
651
|
-
e.preventDefault();
|
|
652
|
-
e.dataTransfer.dropEffect = 'copy';
|
|
653
|
-
return false;
|
|
654
|
-
});
|
|
655
|
-
document
|
|
656
|
-
.getElementById('file')
|
|
657
|
-
.addEventListener('drag', handleFileSelect, false);
|
|
658
|
-
document
|
|
659
|
-
.getElementById('file')
|
|
660
|
-
.addEventListener('change', handleFileSelect, false);
|
|
661
|
-
|
|
662
|
-
// Reverb switch button
|
|
663
|
-
document.getElementById('reverb').addEventListener('click', setReverb);
|
|
664
|
-
// Reverse checkbox
|
|
665
|
-
document
|
|
666
|
-
.getElementById('reverse')
|
|
667
|
-
.addEventListener('click', () =>
|
|
668
|
-
reverb.reverse(document.getElementById('reverse').checked)
|
|
669
|
-
);
|
|
670
|
-
// Reverb dualation time
|
|
671
|
-
document
|
|
672
|
-
.getElementById('time')
|
|
673
|
-
.addEventListener('change', () =>
|
|
674
|
-
reverb.time(document.getElementById('time').value)
|
|
675
|
-
);
|
|
676
|
-
// Decay time
|
|
677
|
-
document
|
|
678
|
-
.getElementById('decay')
|
|
679
|
-
.addEventListener('change', () =>
|
|
680
|
-
reverb.decay(document.getElementById('decay').value)
|
|
681
|
-
);
|
|
682
|
-
// Delay time
|
|
683
|
-
document
|
|
684
|
-
.getElementById('delay')
|
|
685
|
-
.addEventListener('change', () =>
|
|
686
|
-
reverb.delay(document.getElementById('delay').value)
|
|
687
|
-
);
|
|
688
|
-
// Filter select box
|
|
689
|
-
document
|
|
690
|
-
.getElementById('filter')
|
|
691
|
-
.addEventListener('change', () =>
|
|
692
|
-
reverb.filterType(document.getElementById('filter').value)
|
|
693
|
-
);
|
|
694
|
-
// Filter frequency
|
|
695
|
-
document
|
|
696
|
-
.getElementById('freq')
|
|
697
|
-
.addEventListener('change', () =>
|
|
698
|
-
reverb.filterFreq(document.getElementById('freq').value)
|
|
699
|
-
);
|
|
700
|
-
// Filter quality
|
|
701
|
-
document
|
|
702
|
-
.getElementById('q')
|
|
703
|
-
.addEventListener('change', () =>
|
|
704
|
-
reverb.filterQ(document.getElementById('q').value)
|
|
705
|
-
);
|
|
706
|
-
// Dry/Wet
|
|
707
|
-
document
|
|
708
|
-
.getElementById('mix')
|
|
709
|
-
.addEventListener('change', () =>
|
|
710
|
-
reverb.mix(document.getElementById('mix').value)
|
|
711
|
-
);
|
|
712
|
-
|
|
713
|
-
// Execute Animation Thread
|
|
714
|
-
tick();
|
|
715
|
-
});
|
|
716
|
-
</script>
|
|
717
|
-
</body>
|
|
718
|
-
</html>
|