forked from hvianna/audioMotion-analyzer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmulti.js
175 lines (150 loc) · 5.49 KB
/
multi.js
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
* audioMotion-analyzer multi-instance demo
*
* https://github.com/hvianna/audioMotion-analyzer
*/
import AudioMotionAnalyzer from '../src/audioMotion-analyzer.js';
let audioMotion = [],
selectedAnalyzer = 0;
// Creating three audioMotion-analyzer instances that share the same input:
//
// A media element (<audio> or <video> tag) can only be connected to a single AudioNode, but the node
// itself can be connected to multiple other nodes.
//
// In the loop below, the first instance of audioMotion-analyzer takes the <audio> element as source,
// creating an audio node which is stored in connectedSources[0].
// The 2nd and 3rd instances will then take the created audio node as source.
//
// Only the first instance is connected to the speakers, to avoid unintended output amplification.
try {
for ( let i = 0; i < 3; i++ ) {
const isFirst = ( i == 0 );
audioMotion[ i ] = new AudioMotionAnalyzer( document.getElementById( `container${i}` ), {
source: isFirst ? document.getElementById('audio') : audioMotion[0].connectedSources[0],
connectSpeakers: isFirst,
height: isFirst ? 340 : 160,
onCanvasResize: ( reason, instance ) => {
const instNo = instance.canvas.parentElement.id.slice(-1); // get instance number from container id
console.log( `[#${instNo}] ${reason}: ${instance.canvas.width} x ${instance.canvas.height}` );
if ( reason != 'create' )
updateUI();
}
});
}
}
catch( err ) {
document.getElementById('container0').innerHTML = `<p>audioMotion-analyzer failed with error: ${ err.code ? '<strong>' + err.code + '</strong>' : '' } <em>${ err.code ? err.message : err }</em></p>`;
}
// Display package version at the footer
document.getElementById('version').innerText = AudioMotionAnalyzer.version;
// Set options for each instance
// main analyzer
audioMotion[0].setOptions({
mode: 6,
barSpace: .4,
frequencyScale: 'bark',
ledBars: true,
linearAmplitude: true,
linearBoost: 1.6,
maxFreq: 20000,
minFreq: 30,
reflexRatio: .1,
reflexAlpha: .25,
weightingFilter: 'D'
});
// top right
audioMotion[1].setOptions({
mode: 10,
channelLayout: 'dual-combined',
fillAlpha: .3,
gradientLeft: 'steelblue',
gradientRight: 'orangered',
linearAmplitude: true,
linearBoost: 1.2,
lineWidth: 0,
maxFreq: 16000,
minFreq: 30,
peakLine: true,
showScaleX: false,
showPeaks: true,
weightingFilter: 'D'
});
// bottom right
audioMotion[2].setOptions({
mode: 2,
barSpace: .1,
gradient: 'prism',
lumiBars: true,
minDecibels: -60,
maxDecibels: -30,
maxFreq: 16000,
minFreq: 30,
showBgColor: false,
showPeaks: false,
showScaleX: false,
weightingFilter: 'D'
});
// Analyzer selector
document.querySelectorAll('[name="analyzer"]').forEach( el => {
el.addEventListener( 'click', () => {
selectedAnalyzer = document.querySelector('[name="analyzer"]:checked').value;
updateUI();
});
});
// user can also select an analyzer by clicking on it
document.querySelectorAll('canvas').forEach( el => {
el.addEventListener( 'click', () => {
selectedAnalyzer = el.parentElement.id.slice(-1);
document.querySelector(`[name="analyzer"][value="${selectedAnalyzer}"`).checked = true;
updateUI();
});
});
// Event listeners for UI controls
document.querySelectorAll('button[data-prop]').forEach( el => {
el.addEventListener( 'click', () => {
if ( el.dataset.func )
audioMotion[ selectedAnalyzer ][ el.dataset.func ]();
else
audioMotion[ selectedAnalyzer ][ el.dataset.prop ] = ! audioMotion[ selectedAnalyzer ][ el.dataset.prop ];
el.classList.toggle( 'active', audioMotion[ selectedAnalyzer ][ el.dataset.prop ] );
});
});
document.querySelectorAll('[data-setting]').forEach( el => {
el.addEventListener( 'change', () => audioMotion[ selectedAnalyzer ][ el.dataset.setting ] = el.value );
});
// Display value of ranged input elements
document.querySelectorAll('input[type="range"]').forEach( el => el.addEventListener( 'change', () => updateRangeElement( el ) ) );
// File upload
document.getElementById('uploadFile').addEventListener( 'change', e => loadSong( e.target ) );
// getOptions() button
document.getElementById('btn_getOptions').addEventListener( 'click', () => {
const options = audioMotion[ selectedAnalyzer ].getOptions(['width','height','useCanvas']); // ignore some options
console.log( 'getOptions(): ', options );
navigator.clipboard.writeText( JSON.stringify( options, null, 2 ) )
.then( () => console.log( 'Options object copied to clipboard.' ) );
});
// Initialize UI elements
updateUI();
// Load song from user's computer
function loadSong( el ) {
const fileBlob = el.files[0],
audioEl = document.getElementById('audio');
if ( fileBlob ) {
audioEl.src = URL.createObjectURL( fileBlob );
audioEl.play();
}
}
// Update value div of range input elements
function updateRangeElement( el ) {
const s = el.nextElementSibling;
if ( s && s.className == 'value' )
s.innerText = el.value;
}
// Update UI elements to reflect the selected analyzer's current settings
function updateUI() {
document.querySelectorAll('canvas').forEach( el => el.classList.toggle( 'selected', el.parentElement.id.slice(-1) == selectedAnalyzer ) );
document.querySelectorAll('[data-setting]').forEach( el => el.value = audioMotion[ selectedAnalyzer ][ el.dataset.setting ] );
document.querySelectorAll('input[type="range"]').forEach( el => updateRangeElement( el ) );
document.querySelectorAll('button[data-prop]').forEach( el => el.classList.toggle( 'active', audioMotion[ selectedAnalyzer ][ el.dataset.prop ] ) );
document.querySelector('[data-setting="volume"').disabled = selectedAnalyzer != 0;
}