forked from cs4241-20a/a4-creative-coding
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmusic.html
More file actions
169 lines (154 loc) · 6.61 KB
/
Copy pathmusic.html
File metadata and controls
169 lines (154 loc) · 6.61 KB
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>createMediaStreamSource example</title>
<style>
#canvas {
margin-left: auto;
margin-right: auto;
display: block;
background-color: black;
}
#controls {
text-align: center;
}
#start_button, #stop_button {
font-size: 16pt;
}
#msg {
text-align: center;
}
</style>
</head>
<body>
<canvas id="canvas" width="512" height="256" ></canvas>
<p id="controls">
<input type="button" id="start_button" value="Start">
<input type="button" id="stop_button" value="Stop">
<p id="msg"></p>
</p>
<script>
// Hacks to deal with different function names in different browsers
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000 / 60);
};
})();
window.AudioContext = (function(){
return window.webkitAudioContext || window.AudioContext || window.mozAudioContext;
})();
// Global Variables for Audio
let audioContext;
let audioBuffer;
let sourceNode;
let analyserNode;
let javascriptNode;
let audioData = null;
let audioPlaying = false;
let sampleSize = 1024; // number of samples to collect before analyzing data
let amplitudeArray; // array to hold time domain data
// This must be hosted on the same server as this page - otherwise you get a Cross Site Scripting error
let audioUrl = "viper.mp3";
// Global variables for the Graphics
let canvasWidth = 512;
let canvasHeight = 256;
let ctx;
ctx = document.querySelector('#canvas').getContext('2d');
// When the Start button is clicked, finish setting up the audio nodes, play the sound,
// gather samples for the analysis, update the canvas
document.querySelector('#start_button').addEventListener('click', function(e) {
// the AudioContext is the primary 'container' for all your audio node objects
if(!audioContext) {
try {
audioContext = new AudioContext();
} catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
e.preventDefault();
// Set up the audio Analyser, the Source Buffer and javascriptNode
setupAudioNodes();
// setup the event handler that is triggered every time enough samples have been collected
// trigger the audio analysis and draw the results
javascriptNode.onaudioprocess = function () {
// get the Time Domain data for this sample
analyserNode.getByteTimeDomainData(amplitudeArray);
// draw the display if the audio is playing
if (audioPlaying == true) {
requestAnimFrame(drawTimeDomain);
}
}
// Load the Audio the first time through, otherwise play it from the buffer
if(audioData == null) {
loadSound(audioUrl);
} else {
playSound(audioData);
}
});
// Stop the audio playing
document.querySelector('#stop_button').addEventListener('click', function(e) {
e.preventDefault();
sourceNode.stop(0);
audioPlaying = false;
});
function setupAudioNodes() {
sourceNode = audioContext.createBufferSource();
analyserNode = audioContext.createAnalyser();
javascriptNode = audioContext.createScriptProcessor(sampleSize, 1, 1);
// Create the array for the data values
amplitudeArray = new Uint8Array(analyserNode.frequencyBinCount);
// Now connect the nodes together
sourceNode.connect(audioContext.destination);
sourceNode.connect(analyserNode);
analyserNode.connect(javascriptNode);
javascriptNode.connect(audioContext.destination);
}
// Load the audio from the URL via Ajax and store it in global variable audioData
// Note that the audio load is asynchronous
function loadSound(url) {
document.getElementById('msg').textContent = "Loading audio...";
let request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// When loaded, decode the data and play the sound
request.onload = function () {
audioContext.decodeAudioData(request.response, function (buffer) {
document.getElementById('msg').textContent = "Audio sample download finished";
audioData = buffer;
playSound(audioData);
}, onError);
}
request.send();
}
// Play the audio and loop until stopped
function playSound(buffer) {
sourceNode.buffer = buffer;
sourceNode.start(0); // Play the sound now
sourceNode.loop = true;
audioPlaying = true;
}
function onError(e) {
console.log(e);
}
function drawTimeDomain() {
clearCanvas();
for (let i = 0; i < amplitudeArray.length; i++) {
let value = amplitudeArray[i] / 256;
let y = canvasHeight - (canvasHeight * value) - 1;
ctx.fillStyle = '#ffffff';
ctx.fillRect(i, y, 1, 1);
}
}
function clearCanvas() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
}
</script>
</body>
</html>