|
| 1 | +const audioContext = new AudioContext() |
| 2 | + |
| 3 | +const NOTE_DETAILS = [ |
| 4 | + { note: "C", key: "Z", frequency: 261.626, active: false }, |
| 5 | + { note: "Db", key: "S", frequency: 277.183, active: false }, |
| 6 | + { note: "D", key: "X", frequency: 293.665, active: false }, |
| 7 | + { note: "Eb", key: "D", frequency: 311.127, active: false }, |
| 8 | + { note: "E", key: "C", frequency: 329.628, active: false }, |
| 9 | + { note: "F", key: "V", frequency: 349.228, active: false }, |
| 10 | + { note: "Gb", key: "G", frequency: 369.994, active: false }, |
| 11 | + { note: "G", key: "B", frequency: 391.995, active: false }, |
| 12 | + { note: "Ab", key: "H", frequency: 415.305, active: false }, |
| 13 | + { note: "A", key: "N", frequency: 440, active: false }, |
| 14 | + { note: "Bb", key: "J", frequency: 466.164, active: false }, |
| 15 | + { note: "B", key: "M", frequency: 493.883, active: false }, |
| 16 | +] |
| 17 | + |
| 18 | +document.addEventListener("keydown", (e) => { |
| 19 | + if (e.repeat) return |
| 20 | + let keyPressed = e.code |
| 21 | + let nodesDetail = getNodeDetails(keyPressed) |
| 22 | + |
| 23 | + if (nodesDetail == null) return |
| 24 | + nodesDetail.active = true |
| 25 | + |
| 26 | + playNode() |
| 27 | +}) |
| 28 | + |
| 29 | +document.addEventListener("keyup", (e) => { |
| 30 | + let keyPressed = e.code |
| 31 | + let nodesDetail = getNodeDetails(keyPressed) |
| 32 | + if (nodesDetail == null) return |
| 33 | + nodesDetail.active = false |
| 34 | + playNode() //we run this function here to remove the class, we added on pressing keydown |
| 35 | +}) |
| 36 | + |
| 37 | +function getNodeDetails(keyboardKey) { |
| 38 | + return NOTE_DETAILS.find((n) => `Key${n.key}` === keyboardKey) |
| 39 | +} |
| 40 | +function playNode() { |
| 41 | + NOTE_DETAILS.forEach((n) => { |
| 42 | + let noteDiv = document.querySelector(`[data-note=${n.note}]`) |
| 43 | + noteDiv.classList.toggle("active", n.active) //if n.active become true then only set the class active --> this is what toggle does |
| 44 | + if (n.oscillator != null) { |
| 45 | + n.oscillator.stop() |
| 46 | + n.oscillator.disconnect() |
| 47 | + } |
| 48 | + }) |
| 49 | + |
| 50 | + const activeNode = NOTE_DETAILS.filter((n) => n.active) |
| 51 | + const gainValue = 1 / activeNode.length |
| 52 | + activeNode.forEach((n) => { |
| 53 | + startNode(n, gainValue) |
| 54 | + }) |
| 55 | +} |
| 56 | +//From here we are going to introduce some function that doesn't mean anything |
| 57 | +//Check your understanding of everything we learn uptill here |
| 58 | +function startNode(activeNoteDetail, gain) { |
| 59 | + const gainNode = audioContext.createGain() |
| 60 | + gainNode.gain.value = gain |
| 61 | + |
| 62 | + const oscillator = audioContext.createOscillator() |
| 63 | + oscillator.frequency.value = activeNoteDetail.frequency |
| 64 | + oscillator.type = "sine" |
| 65 | + oscillator.connect(gainNode).connect(audioContext.destination) |
| 66 | + oscillator.start() |
| 67 | + activeNoteDetail.oscillator = oscillator |
| 68 | +} |
0 commit comments