Web Theremin
How do I make an web theremin?
Web Theremin uses the Web Audio API and changes the pitch and volume of an audio signal. You can play with your regular keyboard or using a leapmotion sensor.. What is a web theremin? How do you make a web theremin? This script and codes were developed by Pedro Cacique on 20 November 2022, Sunday.
Web Theremin - Script Codes HTML Codes
<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>Web Theremin</title> <link rel="stylesheet" href="css/style.css">
</head>
<body> <html>
<head> <title>Web Theremin</title> <script src="https://js.leapmotion.com/leap-0.6.4.js"></script>
</head>
<body> <h1>Web Theremin</h1> <h3 id="controlsTitle">Controls</h3> <div> <p> <input type="checkbox" id="allowLeap"/> Allow leapmotion </p> <p>Frequency <br> <label for="minF"> Min:</label> <input type="number" id="minF" value="" onchange="change('f0')" onkeyup="change('f0')" /> <label for="maxF"> Max:</label> <input type="number" id="maxF" value="" onchange="change('f1')" onkeyup="change('f1')"/> </p> <p>Volume <br> <label for="minV"> Min:</label> <input type="number" id="minV" value="" onchange="change('v0')" onkeyup="change('v0')"/> <label for="maxV"> Max:</label> <input type="number" id="maxV" value="" onchange="change('v1')" onkeyup="change('v1')"/> </p> </div> <h3>Console</h3> <div id="console"></div> <h3>Instructions</h3> <div id="instructions"> <div> <h4>Playing with keyboard</h4> <ul> <li>P - Play/Pause</li> <li>R - Reset Console</li> <li>T - Next signal type</li> <li>1 - sine</li> <li>2 - square</li> <li>3 - sawtooth</li> <li>4 - triangle</li> <li>UP - increase pitch</li> <li>DOWN - decrease pitch</li> <li>RIGHT - increase gain</li> <li>LEFT - decrease gain</li> </ul> </div> <di> <h4>Playing with leapmotion</h4> <ul> <li>Close one hand - Play/Pause</li> <li>Move one hand up - increase pitch</li> <li>Move one hand down - decrease pitch</li> <li>Move one hand right - increase volume</li> <li>Move one hand left - decrease volume</li> </ul> </di> </div>
</body>
</html> <script src="js/index.js"></script>
</body>
</html>
Web Theremin - Script Codes CSS Codes
@import url(https://fonts.googleapis.com/css?family=Roboto:400,100); * { font-family: 'Roboto', sans-serif; color:#fff; font-weight: 100; } body,html{ background-color: #1F1F21; } #console { overflow: auto; height: 200px; background-color: #313134; padding: 20px; color: #ffc400; } #instructions { display: flex; justify-content: flex-start; } #instructions>div{ margin-right: 100px; } label{ color: #fa380d; } h1{ background-color: #ffc400; position: absolute; top:0; left:0; width:100%; margin:0; padding:5px; color: #1F1F21; font-weight: 400; padding-left: 20px; } h3{ color: #ffc400; } input{ color: #1F1F21; font-weight: 400; } #controlsTitle{ margin-top: 80px; }
Web Theremin - Script Codes JS Codes
const TYPES = ["sine", "square", "sawtooth", "triangle"];
var context, oscillator, gainNode, f = 100, isPlaying = false, t = 0, step = 5, volume = 1, consoleDiv, minF, maxF, minV, maxV, f0 = 100, f1 = 300, v0 = 0, v1 = 1, checkLeap, consoleDiv, frameString = "", options = { enableGestures: true }, hand_0 = 0, hand_1 = 0;
window.onload = function () { document.body.onkeydown = keyboardHandle; consoleDiv = document.getElementById("console"); context = new AudioContext(); onleapload(); minF = document.getElementById("minF"); maxF = document.getElementById("maxF"); minV = document.getElementById("minV"); maxV = document.getElementById("maxV"); minF.value = f0; maxF.value = f1; minV.value = v0; maxV.value = v1; checkLeap = document.getElementById("allowLeap"); checkLeap.onchange = function () { if (isPlaying && !checkLeap.checked) { pauseTone(); showOnConsole("PAUSE"); isPlaying = false; } }
}
// ----- MAIN CONTROL -----
function change(type) { switch (type) { case "f0": f0 = parseFloat(minF.value); showOnConsole("Min Frequency: " + f0 + "Hz"); break; case "f1": f1 = parseFloat(maxF.value); showOnConsole("Max Frequency: " + f1 + "Hz"); break; case "v0": v0 = parseFloat(minV.value); showOnConsole("Min Volume: " + v0); break; case "v1": v1 = parseFloat(maxV.value); showOnConsole("Max Volume: " + v1); break; }
}
function playTone() { oscillator = context.createOscillator(); gainNode = context.createGain(); oscillator.connect(gainNode); gainNode.connect(context.destination); gainNode.gain.value = volume; // Connect the oscillator to our speakers //oscillator.connect(context.destination); // Type oscillator.type = TYPES[t]; // Frequency oscillator.frequency.value = f; // Start the oscillator now oscillator.start(context.currentTime);
}
function showOnConsole(text) { consoleDiv.innerHTML += text + "<br>"; consoleDiv.scrollTop = consoleDiv.scrollHeight;
}
function pauseTone() { // Stop the oscillator 3 seconds from now oscillator.stop(0);
}
function keyboardHandle(event) { if (event.keyCode == 80) { //P isPlaying = !isPlaying; if (isPlaying) { playTone(); showOnConsole("PLAY"); showOnConsole("Signal type: " + TYPES[t]); showOnConsole("Frequency: " + f + "Hz"); } else { pauseTone(); showOnConsole("PAUSE"); } } else if (event.keyCode == 84) { //T t++; if (t == 4) t = 0; oscillator.type = TYPES[t]; showOnConsole("Signal type: " + TYPES[t]); } else if (event.keyCode == 38) { //T if (f < f1) f += step; oscillator.frequency.value = f; showOnConsole("Frequency: " + f + "Hz"); } else if (event.keyCode == 40) { //T if (f > f0) f -= step; oscillator.frequency.value = f; showOnConsole("Frequency: " + f + "Hz"); } else if (event.keyCode >= 49 && event.keyCode <= 52) { t = event.keyCode - 49; oscillator.type = TYPES[t]; showOnConsole("Signal type: " + TYPES[t]); } else if (event.keyCode == 37) { if (volume > v0) volume -= 0.1; gainNode.gain.value = volume; showOnConsole("Volume: " + volume); } else if (event.keyCode == 39) { if (volume < v1)volume += 0.1; gainNode.gain.value = volume; showOnConsole("Volume: " + volume); } else if (event.keyCode == 82) { consoleDiv.innerHTML = ""; }
}
// ----- LEAPMOTION -----
function onleapload() { consoleDiv = document.getElementById("console"); document.body.onkeydown = keyboardHandle; consoleDiv = document.getElementById("console"); context = new AudioContext();
}
function concatData(id, data) { return id + ": " + data + "<br>";
}
function showOnConsole2(text) { consoleDiv.innerHTML = text + "<br>"; consoleDiv.scrollTop = consoleDiv.scrollHeight;
}
Leap.loop(options, function (frame) { if (checkLeap.checked && frame.valid) { if (frame.hands.length == 1) { var hand = frame.hands[0]; hand_1 = hand.grabStrength; if (hand_1 == 1 && hand_1 != hand_0) { isPlaying = !isPlaying; if (isPlaying) { playTone(); showOnConsole("PLAY"); showOnConsole("Signal type: " + TYPES[t]); showOnConsole("Frequency: " + f + "Hz"); } else { pauseTone(); showOnConsole("PAUSE"); } } hand_0 = hand_1; if (isPlaying && frame.pointables.length > 0) { var pointable = frame.pointables[0]; var interactionBox = frame.interactionBox; var normalizedPosition = interactionBox.normalizePoint(pointable.tipPosition, true); var text = "(" + normalizedPosition[0] + ", " + normalizedPosition[1] + ", " + normalizedPosition[2] + ")"; //calculate frequency changeFrequency(normalizedPosition[1]); //calculate volume changeVolume(normalizedPosition[0]); } } else { if (isPlaying) { pauseTone(); isPlaying = false; showOnConsole("PAUSE"); } } } //showOnConsole2(frameString);
});
function changeFrequency(value) { f = value * (f1 - f0) + f0; oscillator.frequency.value = f; showOnConsole("Frequency: " + f + "Hz");
}
function changeVolume(value) { volume = value * (v1 - v0) + v0; gainNode.gain.value = volume; showOnConsole("Volume: " + volume);
}
Developer | Pedro Cacique |
Username | phcacique |
Uploaded | November 20, 2022 |
Rating | 3 |
Size | 3,970 Kb |
Views | 12,144 |
Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!
Name | Size |
One page scrolling | 2,113 Kb |
Page transition | 2,127 Kb |
Grid Interaction | 3,469 Kb |
Platform game mechanics | 2,799 Kb |
Aside Hover Menu | 1,938 Kb |
Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!
Name | Username | Size |
Growing Root - Scroll control - CANVAS | Cjonasw | 2,342 Kb |
Css or Czz.. | Judag | 4,111 Kb |
DNA Double Helix | Hugo | 5,112 Kb |
Incremental game | Eprouver | 5,868 Kb |
Obligatory CSS3 UI Nav | Romandiaz | 9,017 Kb |
Pure CSS albums gallery | Renaudtertrais | 2,978 Kb |
Freecodecamp - Tribute Page | Samoht513 | 3,583 Kb |
Reading Grid | Tappily | 4,306 Kb |
Long Shadow Button | Uixcrazy | 3,550 Kb |
Cake | Kennyname | 7,220 Kb |
Surf anonymously, prevent hackers from acquiring your IP address, send anonymous email, and encrypt your Internet connection. High speed, ultra secure, and easy to use. Instant setup. Hide Your IP Now!