summaryrefslogtreecommitdiff
path: root/sensfreq/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'sensfreq/main.js')
-rw-r--r--sensfreq/main.js114
1 files changed, 114 insertions, 0 deletions
diff --git a/sensfreq/main.js b/sensfreq/main.js
new file mode 100644
index 0000000..6dc431e
--- /dev/null
+++ b/sensfreq/main.js
@@ -0,0 +1,114 @@
+const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
+
+e = s => document.getElementById(s);
+
+let ans = false;
+let nq = 0;
+let nc = 0;
+
+function init()
+{
+ e("gench").disabled = false;
+ e("response").style.display="none";
+ reset_stats();
+ loadTheme();
+}
+
+function play_notes(freq, t, arpt)
+{
+ const stop_notes=function(g, o)
+ {
+ o.stop();
+ g.disconnect(audioCtx.destination);
+ o.disconnect(g);
+ }
+ const play_note=function(f)
+ {
+ const gn = audioCtx.createGain();
+ gn.gain.setValueAtTime(.5/freq.length, audioCtx.currentTime);
+ gn.gain.linearRampToValueAtTime(0, audioCtx.currentTime + t / 1000.);
+ gn.connect(audioCtx.destination);
+ const osc = audioCtx.createOscillator();
+ osc.type = "sine";
+ osc.frequency.setValueAtTime(f, audioCtx.currentTime);
+ osc.connect(gn);
+ osc.start();
+ setTimeout(stop_notes.bind(null, gn, osc), t);
+ }
+ let i=0;
+ freq.forEach(function(f){setTimeout(play_note.bind(null, f), arpt * (i++));});
+}
+
+get_freq = n => 440 * Math.pow(Math.pow(2, 1./12), n-69)
+
+function generate_challenge()
+{
+ const nmin=Number(e("minnnotes").value);
+ const nmax=Number(e("maxnnotes").value);
+ const omin=Number(e("minorange").value);
+ const omax=Number(e("maxorange").value);
+ if (omax < omin || nmax < nmin)
+ {
+ alert("?");
+ return;
+ }
+ const nnotes = Math.floor(Math.random() * (nmax - nmin + 1)) + nmin;
+ const minrange = 60 + omin * 12;
+ const maxrange = 71 + omax * 12;
+
+ let f = [];
+ let l = [];
+ ans = false;
+
+ if (Math.random() < 0.3)
+ {
+ const o = Math.floor(Math.random() * (omax - omin + 1)) + omin;
+ let n = 60 + Number(e("note").value) + o * 12;
+ f.push(get_freq(n));
+ l.push(n);
+ ans = true;
+ }
+ while (f.length < nnotes)
+ {
+ let n = Math.floor(Math.random() * (maxrange - minrange + 1)) + minrange;
+ if (l.indexOf(n)!=-1)
+ continue;
+ ans |= ((n % 12) == Number(e("note").value));
+ f.push(get_freq(n));
+ }
+ f.sort((a,b)=>a-b);
+ play_notes(f, 1000, e("arp").checked ? 50 : 0);
+ e("gench").disabled = true;
+ e("response").style.display="";
+}
+
+function update_stats()
+{
+ e("stats").innerHTML=`You got ${nc} of the ${nq} challenges correct.`
+}
+
+function reset_stats()
+{
+ nq = nc = 0;
+ update_stats();
+}
+
+function check_yes()
+{
+ if (ans)
+ ++nc;
+ ++nq;
+ e("gench").disabled = false;
+ e("response").style.display="none";
+ update_stats();
+}
+
+function check_no()
+{
+ if (!ans)
+ ++nc;
+ ++nq;
+ e("gench").disabled = false;
+ e("response").style.display="none";
+ update_stats();
+}