-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtuner.js
108 lines (87 loc) · 3.04 KB
/
tuner.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
// tuner.js
// Guitar tuning app
//
// Copyright (c) 2017, Angelo Falchetti. All rights reserved.
(function() {
"use strict";
navigator.getUserMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
/// Generate and insert the tuner GUI to the DOM.
///
/// @param {jQuery} root - DOM element to insert the tuner into.
function create_GUI(root)
{
const time = $("<canvas id='time' class='plot'></canvas>");
const freq = $("<canvas id='freq' class='plot'></canvas>");
root.append(time);
root.append(freq);
}
/// Draw a data array into a canvas as a function of its index, matching the canvas width.
///
/// @param {Array} data - Data to render.
/// @param {CanvasRenderingContext2D} context - Drawing context.
function draw_array(data, context)
{
const width = context.canvas.width;
const height = context.canvas.height;
const dx = width / data.length;
context.clearRect(0, 0, width, height);
context.linewidth = 1;
context.strokeStyle = "rgb(0, 0, 0)";
context.beginPath();
context.moveTo(0.0, data[0] * height / 256.0);
for (let i = 1, x = dx; i < data.length; i++, x += dx) {
const y = (255 - data[i]) * height / 256.0;
context.lineTo(x, y);
}
context.stroke();
}
/// Connect the analyser audio node output to a suitable visualization.
///
/// @param {HTMLElement} time - DOM canvas that will be used to draw the time domain signal.
/// @param {HTMLElement} freq - DOM canvas that will be used to draw the frequency spectrum.
/// @param {AnalyserNode} analyser - WebAudio analyser which acts as a source of microphone data as well
/// as its Fourier transformation (frequency spectrum).
function setup_visualization(time, freq, analyser)
{
analyser.fftSize = 16384; // at 44.1kHz, this gives 5.4Hz resolution
let time_ctx = time.getContext("2d");
let freq_ctx = freq.getContext("2d");
const tdata = new Uint8Array(analyser.frequencyBinCount);
const fdata = new Uint8Array(analyser.frequencyBinCount);
freq_ctx.canvas.width = time_ctx.canvas.width = time.width;
freq_ctx.canvas.height = time_ctx.canvas.height = time.height;
function draw()
{
analyser.getByteTimeDomainData(tdata);
analyser.getByteFrequencyData (fdata);
draw_array(tdata, time_ctx);
draw_array(fdata, freq_ctx);
requestAnimationFrame(draw);
}
draw();
}
/// Create all audio nodes and connect them to each other.
function create_audiograph()
{
const context = new (window.AudioContext || window.webkitAudioContext)();
const analyser = context.createAnalyser();
navigator.getUserMedia({audio: true},
function (stream) {
context.createMediaStreamSource(stream).connect(analyser);
setup_visualization($("#time")[0], $("#freq")[0], analyser);
},
function (error) {
console.log("Error while getting user media: " + error);
});
}
/// Main entry point for the app.
function main()
{
create_GUI($("#tuner"));
create_audiograph();
}
$(document).ready(main);
})();