forked from bychen9/vocal-range-detector
-
Notifications
You must be signed in to change notification settings - Fork 0
/
renderer.js
150 lines (136 loc) · 4.3 KB
/
renderer.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
const audioContext = new AudioContext();
let mediaRecorder;
let sourceStream;
let refreshHandle;
let noteArray = [];
let body = document.querySelector("body");
let fileName = location.href.split("/").slice(-1);
let recordbutton = document.getElementById("recordbutton");
recordbutton.onclick = () => {
getMedia();
recordbutton.innerHTML = "Recording";
recordbutton.disabled = true;
if (fileName[0] != "first-step.html") {
play.disabled = true;
}
};
async function getMedia() {
try {
sourceStream = await navigator.mediaDevices.getUserMedia({audio: true});
listen();
let complete = document.getElementById("complete");
if (complete != null) {
complete.parentNode.removeChild(complete);
}
let yousang = document.getElementById("yousang");
if (yousang != null) {
yousang.parentNode.removeChild(yousang);
}
} catch(error) {
console.log(error);
alert("Please enable your microphone.");
recordbutton.innerHTML = "Record";
recordbutton.disabled = false;
if (fileName[0] != "first-step.html") {
play.disabled = false;
}
};
}
/**
* Starts listening for audio.
*/
function listen () {
mediaRecorder = new MediaRecorder(sourceStream);
mediaRecorder.ondataavailable = update;
// Every 500ms, send whatever has been recorded to the audio processor.
// This can't be done with `mediaRecorder.start(ms)` because the
// `AudioContext` may fail to decode the audio data when sent in parts.
refreshHandle = setInterval(() => {
mediaRecorder.start();
setTimeout(() => mediaRecorder.stop(), 500);
}, 1000);
}
/**
* Stops listening for audio.
*/
function stop () {
clearInterval(refreshHandle);
let text = document.createElement("p");
let node = document.createTextNode("Recording Complete.");
text.setAttribute("id", "complete");
text.append(node);
body.append(text);
recordbutton.innerHTML = "Record";
recordbutton.disabled = false;
if (fileName[0] != "first-step.html") {
play.disabled = false;
}
}
/**
* Handles data received from a `MediaRecorder`.
* @param {BlobEvent} e Blob event from the `MediaRecorder`.
*/
async function update (e) {
if (e.data.size !== 0) {
await process(e.data);
}
}
/**
* Sends audio data to the audio processing worker.
* @param {Blob} data The blob containing the recorded audio data.
*/
async function process (data) {
// Load the blob.
const response = await fetch(URL.createObjectURL(data));
const arrayBuffer = await response.arrayBuffer();
// Decode the audio.
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
const audioData = audioBuffer.getChannelData(0);
const sampleRate = audioBuffer.sampleRate;
const pitch = analyseAudioData(sampleRate, audioData, accidentals = 'sharps');
updateNoteArray(pitch);
if (noteArray.length == 2) {
stop();
let note = noteArray[0];
if (fileName[0] == "first-step.html") {
localStorage.setItem("baseNote", note);
let text = document.createElement("p");
let node = document.createTextNode("Your base note is " + note + ".");
text.append(node);
body.append(text);
let button = document.createElement("BUTTON");
button.innerHTML = "Next Step";
button.setAttribute("onclick", "location.href = 'second-step.html'");
body.append(button);
} else {
let text = document.createElement("p");
let noteToSing = document.getElementById("noteToSing");
let goal = noteToSing.innerHTML.substring(17, noteToSing.innerHTML.length - 1);
if (note === goal) {
let node = document.createTextNode("Nice! You correctly sang " + note + ".");
text.setAttribute("id", "yousang");
text.append(node);
body.append(text);
pass();
} else {
let node = document.createTextNode("Oops! You sang " + note + " instead of " + goal + ".");
text.setAttribute("id", "yousang");
text.append(node);
body.append(text);
fail();
}
}
}
}
function updateNoteArray(pitch) {
let previousNote;
if (noteArray.length > 0) {
previousNote = noteArray[noteArray.length-1];
}
if (pitch == null || pitch.octave > 9 || (pitch.key+pitch.octave != previousNote && previousNote != null)) {
noteArray.length = 0;
}
else {
noteArray.push(pitch.key+pitch.octave)
}
}