-
Notifications
You must be signed in to change notification settings - Fork 4
/
client.html
273 lines (216 loc) · 8.08 KB
/
client.html
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head>
<title>Example</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="http://html5-examples.craic.com/js/chroma.js"></script>
<script type="text/javascript" src="js/webkitAudioContextMonkeyPath.js"></script>
<script src="http://192.168.25.10:3030/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://192.168.25.10:3030');
socket.on('sound', function (stream) {
var audio = document.querySelector("audioPlayback");
audio.src = window.URL.createObjectURL(stream);
});
</script>
<style>
body {
font-family: Helvetica, sans-serif;
font-size: 11pt;
padding: 5px;
margin-left: 150px;
margin-right: 150px;
}
h2 {
font-weight: normal;
font-size: 24pt;
text-align: center;
}
#controls {
text-align: center;
}
#start_button {
font-size: 16pt;
}
#stop_button {
font-size: 16pt;
}
#playback_button {
font-size: 16pt;
}
#reset_button {
font-size: 16pt;
}
#canvas {
margin-left: auto;
margin-right: auto;
display: block;
background-color: black ;
}
</style>
</head>
<body>
<h2>Recording Audio from Microphone with Web Audio</h2>
<p> </p>
<p>This demo uses the <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">Web Audio API</a> to capture audio from the
microphone, display a frequency spectrogram and capture the audio in a recording for playback.</p>
<p>Recording is not directly supported in the API, so you need to capture consecutive samples into your own buffer. This can then be
used as an input source during playback.</p>
<p> </p>
<p id="controls">
<button id="start_button">Start Recording</button>
<audio id="audioPlayback" autoplay>
</audio>
<script type="text/javascript">
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000 / 60);
};
})();
// Global Variables for Audio
var audioContext;
var sourceNode;
var analyserNode;
var javascriptNode;
var playbackSourceNode;
var audioStream;
var array = [];
var recording = null; // this is the cumulative buffer for your recording
var audioBufferNode = null;
var audioBuffer = null;
// Global Variables for Drawing
var x = 0;
var canvasWidth = 800;
var canvasHeight = 256;
var ctx;
// Uses the chroma.js library by Gregor Aisch to create a tasteful color gradient
// download from https://github.com/gka/chroma.js
var hot = new chroma.ColorScale({
colors:['#000000', '#ff0000', '#ffff00', '#ffffff'],
positions:[0, .25, .75, 1],
mode:'rgb',
limits:[0, 256]
});
window.craicAudioContext = (function(){
return window.webkitAudioContext || window.AudioContext ;
})();
navigator.getMedia = ( navigator.mozGetUserMedia ||
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.msGetUserMedia);
$(document).ready(function() {
// Check that the browser can handle web audio
try {
// audioContext = new webkitAudioContext();
audioContext = new craicAudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
// get the input audio stream and set up the nodes
try {
// calls the function setupAudioNodes
// navigator.webkitGetUserMedia({audio:true}, setupAudioNodes, onError);
navigator.getMedia({audio:true}, emitToServer, onError);
} catch (e) {
alert('webkitGetUserMedia threw exception :' + e);
}
// Start recording by setting onaudioprocess to the function that manages the recording buffer
$("body").on('click', "#start_button",function(e) {
e.preventDefault();
// execute every time a new sample has been acquired
javascriptNode.onaudioprocess = function (e) {
addSampleToRecording(e.inputBuffer);
// Analyze the frequencies in this sample and add to the spectorgram
analyserNode.getByteFrequencyData(array);
requestAnimFrame(drawSpectrogram);
}
});
// Stop recording by setting onaudioprocess to null
$("body").on('click', "#stop_button",function(e) {
e.preventDefault();
javascriptNode.onaudioprocess = null;
});
// Play the recording
$("body").on('click', "#playback_button",function(e) {
e.preventDefault();
playRecording();
});
// Reset the recording buffer and the graphics, but keep the nodes connected
$("body").on('click', "#reset_button",function(e) {
e.preventDefault();
recording = null;
clearCanvas();
});
// Disable audio completely
$("body").on('click', "#disable_audio",function(e) {
e.preventDefault();
javascriptNode.onaudioprocess = null;
if(audioStream) audioStream.stop();
if(sourceNode) sourceNode.disconnect();
});
});
function onError(e) {
console.log(e);
}
function emitToServer(stream)
{
socket.emit("audio",stream);
}
function setupAudioNodes(stream) {
var sampleSize = 1024; // number of samples to collect before analyzing FFT
// decreasing this gives a faster sonogram, increasing it slows it down
audioStream = stream;
// The nodes are: sourceNode -> analyserNode -> javascriptNode -> destination
// create an audio buffer source node
sourceNode = audioContext.createMediaStreamSource(audioStream);
// Set up the javascript node - this uses only one channel - i.e. a mono microphone
javascriptNode = audioContext.createJavaScriptNode(sampleSize, 1, 1);
// setup the analyser node
analyserNode = audioContext.createAnalyser();
analyserNode.smoothingTimeConstant = 0.0;
analyserNode.fftSize = 1024; // must be power of two
// connect the nodes together
sourceNode.connect(analyserNode);
analyserNode.connect(javascriptNode);
javascriptNode.connect(audioContext.destination);
// optional - connect input to audio output (speaker)
// This will echo your input back to your speakers - Beware of Feedback !!
// sourceNode.connect(audioContext.destination);
// allocate the array for Frequency Data
array = new Uint8Array(analyserNode.frequencyBinCount);
}
// Draw the Spectrogram from the frequency array
// adapted from http://www.smartjava.org/content/exploring-html5-web-audio-visualizing-sound
function drawSpectrogram() {
for (var i = 0; i < array.length; i += 1) {
// Get the color for each pixel from a color map
var value = array[i];
ctx.beginPath();
ctx.strokeStyle = hot.getColor(value).hex();
// draw a 1 pixel wide rectangle on the canvas
var y = canvasHeight - i;
ctx.moveTo(x, y);
ctx.lineTo(x+1, y);
ctx.closePath();
ctx.stroke();
}
// loop around the canvas when we reach the end
x = x + 1;
if(x >= canvasWidth) {
x = 0;
clearCanvas();
}
}
function clearCanvas() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
x = 0;
}
</script>
</body>
</html>