forked from gg-1414/music-visualizer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
137 lines (105 loc) · 4.89 KB
/
script.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
window.onload = function() {
const file = document.getElementById("file-input");
const canvas = document.getElementById("canvas");
const h3 = document.getElementById('name')
const audio = document.getElementById("audio");
file.onchange = function() {
const files = this.files; // FileList containing File objects selected by the user (DOM File API)
console.log('FILES[0]: ', files[0])
audio.src = URL.createObjectURL(files[0]); // Creates a DOMString containing the specified File object
const name = files[0].name
h3.innerText = `${name}` // Sets <h3> to the name of the file
///////// <CANVAS> INITIALIZATION //////////
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
///////////////////////////////////////////
const context = new AudioContext(); // (Interface) Audio-processing graph
let src = context.createMediaElementSource(audio); // Give the audio context an audio source,
// to which can then be played and manipulated
const analyser = context.createAnalyser(); // Create an analyser for the audio context
src.connect(analyser); // Connects the audio context source to the analyser
analyser.connect(context.destination); // End destination of an audio graph in a given context
// Sends sound to the speakers or headphones
/////////////// ANALYSER FFTSIZE ////////////////////////
// analyser.fftSize = 32;
// analyser.fftSize = 64;
// analyser.fftSize = 128;
// analyser.fftSize = 256;
// analyser.fftSize = 512;
// analyser.fftSize = 1024;
// analyser.fftSize = 2048;
// analyser.fftSize = 4096;
// analyser.fftSize = 8192;
analyser.fftSize = 16384;
// analyser.fftSize = 32768;
// (FFT) is an algorithm that samples a signal over a period of time
// and divides it into its frequency components (single sinusoidal oscillations).
// It separates the mixed signals and shows what frequency is a violent vibration.
// (FFTSize) represents the window size in samples that is used when performing a FFT
// Lower the size, the less bars (but wider in size)
///////////////////////////////////////////////////////////
const bufferLength = analyser.frequencyBinCount; // (read-only property)
// Unsigned integer, half of fftSize (so in this case, bufferLength = 8192)
// Equates to number of data values you have to play with for the visualization
// The FFT size defines the number of bins used for dividing the window into equal strips, or bins.
// Hence, a bin is a spectrum sample, and defines the frequency resolution of the window.
const dataArray = new Uint8Array(bufferLength); // Converts to 8-bit unsigned integer array
// At this point dataArray is an array with length of bufferLength but no values
console.log('DATA-ARRAY: ', dataArray) // Check out this array of frequency values!
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
console.log('WIDTH: ', WIDTH, 'HEIGHT: ', HEIGHT)
const barWidth = (WIDTH / bufferLength) * 13;
console.log('BARWIDTH: ', barWidth)
console.log('TOTAL WIDTH: ', (117*10)+(118*barWidth)) // (total space between bars)+(total width of all bars)
let barHeight;
let x = 0;
function renderFrame() {
requestAnimationFrame(renderFrame); // Takes callback function to invoke before rendering
x = 0;
analyser.getByteFrequencyData(dataArray); // Copies the frequency data into dataArray
// Results in a normalized array of values between 0 and 255
// Before this step, dataArray's values are all zeros (but with length of 8192)
ctx.fillStyle = "rgba(0,0,0,0.2)"; // Clears canvas before rendering bars (black with opacity 0.2)
ctx.fillRect(0, 0, WIDTH, HEIGHT); // Fade effect, set opacity to 1 for sharper rendering of bars
let r, g, b;
let bars = 118 // Set total number of bars you want per frame
for (let i = 0; i < bars; i++) {
barHeight = (dataArray[i] * 2.5);
if (dataArray[i] > 210){ // pink
r = 250
g = 0
b = 255
} else if (dataArray[i] > 200){ // yellow
r = 250
g = 255
b = 0
} else if (dataArray[i] > 190){ // yellow/green
r = 204
g = 255
b = 0
} else if (dataArray[i] > 180){ // blue/green
r = 0
g = 219
b = 131
} else { // light blue
r = 0
g = 199
b = 255
}
// if (i === 0){
// console.log(dataArray[i])
// }
ctx.fillStyle = `rgb(${r},${g},${b})`;
ctx.fillRect(x, (HEIGHT - barHeight), barWidth, barHeight);
// (x, y, i, j)
// (x, y) Represents start point
// (i, j) Represents end point
x += barWidth + 10 // Gives 10px space between each bar
}
}
audio.play();
renderFrame();
};
};