<!-- AUDIOLET.JS by OAMPO
https://raw.github.com/oampo/Audiolet/master/LICENSE -->
<!-- JQUERY.KNOBBY.JS --->
<div class="keyboard">
<div class="key c zero"><k id="germanY">Y</k></div>
<div class="key c cross zero"><k>S</k></div>
<div class="key d zero"><k>X</k></div>
<div class="key d cross zero"><k>D</k></div>
<div class="key e zero"><k>C</k></div>
<div class="key f zero"><k>V</k></div>
<div class="key f cross zero"><k>G</k></div>
<div class="key g zero"><k>B</k></div>
<div class="key g cross zero"><k>H</k></div>
<div class="key a zero"><k>N</k></div>
<div class="key a cross zero"><k>J</k></div>
<div class="key b zero"><k>M</k></div>
<div class="key c one"><k>Q</k></div>
<div class="key c cross one"><k>2</k></div>
<div class="key d one"><k>W</k></div>
<div class="key d cross one"><k>3</k></div>
<div class="key e one"><k>E</k></div>
<div class="key f one"><k>R</k></div>
<div class="key f cross one"><k>5</k></div>
<div class="key g one"><k>T</k></div>
<div class="key g cross one"><k>6</k></div>
<div class="key a one"><k id="germanZ">Z</k></div>
<div class="key a cross one"><k>7</k></div>
<div class="key b one"><k>U</k></div>
<div class="key c two"><k>I</k></div>
<div class="key c cross two"><k>9</k></div>
<div class="key d two"><k>O</k></div>
<div class="key d cross two"><k>0</k></div>
<div class="key e two"><k>P</k></div>
<div class="key f two"><k>Ü</k></div>
<div class="key f cross two"></div>
<div class="key g two"></div>
<div class="key g cross two"></div>
<div class="key a two"></div>
<div class="key a cross two"></div>
<div class="key b two"></div>
<div class="key c three"></div>
<div class="key c cross three"></div>
<div class="key d three"></div>
<div class="key d cross three"></div>
<div class="key e three"></div>
<div class="key f three"></div>
<div class="key f cross three"></div>
<div class="key g three"></div>
<div class="key g cross three"></div>
<div class="key a three"></div>
<div class="key a cross three"></div>
<div class="key b three"></div>
<div class="key c four"></div>
</div>
<fieldset>
<legend>Keyboard</legend>
<label>Keyboard-Layout:
<select name="keyboardLayout">
<option value="de">German (QWERTZ)</option>
<option value="en">English (QWERTY)</option>
<!--<option value="FRE">French (AZERTY)</option>-->
</select>
</label>
<label>
<input type=checkbox name=showKeyboardKeys checked /> Show keys
</label>
<label>
<input type=checkbox name=transposeUp /> Transpose 1 oct up
</label>
</label>
</fieldset>
<fieldset><legend>Pass</legend>
<label>
LOW
<input class=number type=number name=lowPass value=200 min=1 max=10000 turn=2 step=10>
</label>
<label>
HIGH
<input class=number type=number name=highPass value=300 min=1 max=10000 turn=2 step=10>
</label>
</fieldset>
<fieldset><legend><label><input name=enableDelay type="checkbox" checked> Delay</label></legend>
<label>
Time (sec)
<input class=number type=number name=delayTime step=0.01 value=0.3 max=1 min=0.01>
</label>
<label>
Feedback
<input class=number type=number name=delayFeedback step=0.01 value=0.5 max=1 min=0>
</label>
<label>
Mix
<input class=number type=number name=delayMix step=0.01 max=1 min=0 value=0.5 >
</label>
</fieldset>
.knobby-wrap {
padding: 5px;
display: inline-block;
vertical-align: middle;
text-align: center;
}
.knobby-knob {
display: block;
position: relative;
width: 8em;
height: 8em;
border-radius: 100%;
overflow: hidden;
/* created with http://codeblock.at/base64-noise-generator/ */
background: #212121 url(data:image/png;base64,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);
background-size: 50% 50%;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.knobby-shadow {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
border-radius: 100%;
box-shadow: 0 -1px 6px rgba(0, 0, 0, 0.5) inset, 0 1px 3px rgba(255, 255, 255, 0.85) inset;
}
.knobby-handle {
transform: rotate(0deg) translateY(-3em);
position: absolute;
width: 1em;
height: 1em;
left: 50%;
top: 50%;
margin-top: -0.5em;
margin-left: -0.5em;
background: #525b58;
border-radius: 100%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5) inset, 0 -2px 4px rgba(255, 255, 255, 0.85) inset;
pointer-events: none;
}
.knobby-input {
margin: 4px auto;
text-align: right;
background: #222;
color: #eee;
border: 1px solid #111;
padding: 5px 0;
font-family: monospace;
box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.5), 0 1px 1px rgba(255, 255, 255, 0.85);
}
@keyWidth: 50px;
@keyHeight: 200px;
@crossHeightRatio: 0.75;
@crossWidthRatio: 0.66;
@import url(https://fonts.googleapis.com/css?family=Roboto);
body {
-webkit-backface-visibility: hidden;
font: 0.9em "Roboto", sans-serif;
line-height: 2.0;
background: #333;
color: #aaa;
}
fieldset {
display: block;
border: 1px solid gray;
}
div.keyboard {
-webkit-perspective: 1000px;
-moz-perspective: 1000px;
perspective: 1000px;
margin: 10px auto;
height: 220px;
width:1450px;
}
label { padding: 0 1em }
.key {
position: absolute;
background: white;
height: @keyHeight;
width: @keyWidth;
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.3);
cursor: pointer;
border-radius: 0 0 5px 5px;
-webkit-transform-origin: top center;
-webkit-transform: translate(0, 0) rotateX(0);
-moz-transform-origin: top center;
-moz-transform: translate(0, 0) rotateX(0);
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: all .2s ease;
-moz-transition: all .2s ease;
transition: all .2s ease;
border: 1px solid gray;
z-index: 90;
k {
position: absolute;
bottom: 0;
left: 0;
width: 16px;
height: 16px;
line-height: 16px;
text-align: center;
color: gray;
font-size: 10px;
font-weight: bold;
opacity: 0.8;
}
}
body.hideKeyboardKeys .key k {
display: none;
}
.key.active {
//background: orange!important;
//-webkit-transform-origin:top center;
-webkit-transform: translate3d(0, 0, -5px) rotateX(-1deg) scale(0.95);
//-moz-transform-origin:top center;
-moz-transform: rotateX(-1deg) scale(0.95);
z-index: 80;
k {
//color:white;
}
}
.key.cross.active {
z-index: 100;
-webkit-transform: rotateX(0) scale(0.95);
//-moz-transform-origin:top center;
-moz-transform: rotateX(0) scale(0.95);
}
.key.cross {
height: @keyHeight * @crossHeightRatio;
background: black;
margin-left: @keyWidth - (@keyWidth * @crossWidthRatio/2);
z-index: 100;
width: @keyWidth * @crossWidthRatio;
}
.c {
left: 0;
}
.d {
left: @keyWidth;
}
.e {
left: @keyWidth*2;
}
.f {
left: @keyWidth*3;
}
.g {
left: @keyWidth*4;
}
.a {
left: @keyWidth*5;
}
.b {
left: @keyWidth*6;
}
.one {
margin-left: @keyWidth*7;
}
.one.cross {
margin-left: @keyWidth*7 + @keyWidth - (@keyWidth * @crossWidthRatio/2);
}
.two {
margin-left: @keyWidth*14;
}
.two.cross {
margin-left: @keyWidth*14 + @keyWidth - (@keyWidth * @crossWidthRatio/2);
}
.three {
margin-left: @keyWidth*21;
}
.three.cross {
margin-left: @keyWidth*21 + @keyWidth - (@keyWidth * @crossWidthRatio/2);
}
.four {
margin-left: @keyWidth*28;
}
.four.cross {
margin-left: @keyWidth*28 + @keyWidth - (@keyWidth * @crossWidthRatio/2);
}
View Compiled
var audiolet = new Audiolet();
var lowPass = 200;
var highPass = 300;
var maximumDelayTime = 10.0;
var delayTime = 0.3;
var feedback = 0.5;
var mix = 0.5;
var gate = 1;
var attack = 1;
var decay = .2;
var sustain = .9;
var release = 2;
var sines = [];
var sawes = [];
var lpFilter = new LowPassFilter(audiolet, lowPass);
var hpFilter = new HighPassFilter(audiolet, highPass);
var feedbackDelay = new FeedbackDelay(audiolet, maximumDelayTime, delayTime, feedback, mix);
lpFilter.connect(hpFilter);
hpFilter.connect(feedbackDelay);
feedbackDelay.connect(audiolet.output);
var stoppingKeys = [];
var transposeUp = false;
function makeTone(frequency, stopHandler) {
sines.push(new Sine(audiolet, frequency));
//sawes.push(new Saw(audiolet,frequency));
sines[sines.length - 1].connect(lpFilter);
//sawes[sawes.length-1].connect(lpFilter);
//sawes[sawes.length-1].phase = 0;
stoppingKeys[sines.length - 1] = stopHandler;
return sines.length - 1;
};
function stopMe(index) {
sines[index].remove();
var returnValue = stoppingKeys[index];
stoppingKeys.splice(index);
return returnValue;
}
$(".key").bind("mousedown touchstart", function() {
var className = this.className;
var tone = className.substring(4, 5);
var cross = $(this).hasClass("cross");
var frequency = 0.0;
$(this).addClass("active");
var index = $(this).index() - 21;
frequency = 440 * Math.pow(2, (index / 12));
var index = makeTone(frequency, $(this));
$(this).bind("mouseup touchend mouseleave", function() {
stopMe(index);
$(this).removeClass("active").unbind("mouseup touchend mouseleave");
});
});
var keysPressed = [];
$(window).bind("keydown keyup", function(e) {
var up = (e.type == "keyup");
var key = "";
if (!up && keysPressed[e.which] == true) {
e.preventDefault();
return false;
} else {
var zeroClass = (transposeUp ? "one" : "zero");
var oneClass = (transposeUp ? "two" : "one");
var twoClass = (transposeUp ? "three" : "two");
keysPressed[e.which] = !up;
switch (e.which) {
case keyCZero: // Y
key = ".key." + zeroClass + ".c";
break;
case 83: // S
key = ".key." + zeroClass + ".c.cross";
break;
case 88: // X
key = ".key." + zeroClass + ".d";
break;
case 68: // D
key = ".key." + zeroClass + ".d.cross";
break;
case 67: // C
key = ".key." + zeroClass + ".e";
break;
case 86: // V
key = ".key." + zeroClass + ".f";
break;
case 71: // G
key = ".key." + zeroClass + ".f.cross";
break;
case 66: // B
key = ".key." + zeroClass + ".g";
break;
case 72: // H
key = ".key." + zeroClass + ".g.cross";
break;
case 78: // N
key = ".key." + zeroClass + ".a";
break;
case 74: // J
key = ".key." + zeroClass + ".a.cross";
break;
case 77: // M
key = ".key." + zeroClass + ".b";
break;
case 188: // , ;
case keyCOne: // Q
key = ".key." + oneClass + ".c";
break;
case 76: // L
case 50: // 2
key = ".key." + oneClass + ".c.cross";
break;
case 190: // . :
case 87: // W
key = ".key." + oneClass + ".d";
break;
case 192: // Ö ( GERMAN keyboard )
case 51: // 3
key = ".key." + oneClass + ".d.cross";
break;
case 189: // -_
case 69: // E
key = ".key." + oneClass + ".e";
break;
case 82:
key = ".key." + oneClass + ".f";
break;
case 53:
key = ".key." + oneClass + ".f.cross";
break;
case 84:
key = ".key." + oneClass + ".g";
break;
case 54:
key = ".key." + oneClass + ".g.cross";
break;
case keyAOne: // Z
key = ".key." + oneClass + ".a";
break;
case 55: // 7
key = ".key." + oneClass + ".a.cross";
break;
case 85: // U
key = ".key." + oneClass + ".b";
break;
case 73: // I
key = ".key." + twoClass + ".c";
break;
case 57: // 9
key = ".key." + twoClass + ".c.cross";
break;
case 79: // O (Ooohhhh)
key = ".key." + twoClass + ".d";
break;
case 48: // 0 (NULL)
key = ".key." + twoClass + ".d.cross";
break;
case 80: // P
key = ".key." + twoClass + ".e";
break;
case 186: // Ü (German keyboard)
key = ".key." + twoClass + ".f";
break;
}
if (key) {
if (up) {
$(key).first().mouseup();
} else {
$(key).first().mousedown();
}
e.preventDefault();
return false;
}
}
});
$("input[name=lowPass]").bind("change", function() {
console.log("change detected!");
lowPass = parseInt(this.value);
lpFilter.frequency.setValue(lowPass);
});
$("input[name=highPass]").bind("change", function() {
highPass = parseInt(this.value);
hpFilter.frequency.setValue(highPass);
});
$("input[name=delayTime]").bind("change",function() {
val = parseFloat(this.value);
delayTime = val;
feedbackDelay.delayTime.setValue(delayTime);
});
$("input[name=delayFeedback]").bind("change",function() {
val = parseFloat(this.value);
delayFeedback = val;
feedbackDelay.feedback.setValue(delayFeedback);
});
$("input[name=delayMix]").change(function() {
val = parseFloat(this.value);
delayMix = val;
feedbackDelay.mix.setValue(delayMix);
});
$("input[name=enableDelay]").change(function() {
if (this.checked) {
feedbackDelay.feedback.setValue($("input[name=delayFeedback]").val());
feedbackDelay.mix.setValue($("input[name=delayMix]").val());
feedbackDelay.delayTime.setValue($("input[name=delayTime]").val());
$(this).parents("fieldset").find("input").not(this).removeAttr("disabled");
} else {
feedbackDelay.feedback.setValue(0);
feedbackDelay.mix.setValue(0);
feedbackDelay.delayTime.setValue(0.3);
$(this).parents("fieldset").find("input").not(this).attr("disabled", "disabled");
}
});
$("input[name=showKeyboardKeys]").change(function(e) {
if (this.checked) {
$("body").removeClass("hideKeyboardKeys");
} else {
$("body").addClass("hideKeyboardKeys");
}
});
var keyCZero = 89; // Y (german)
var keyCOne = 81; // Q (german)
var keyAOne = 90; // Z (german)
$("select[name=keyboardLayout]").change(function() {
if (this.value == "de") {
keyCZero = 89;
keyCOne = 81;
keyAOne = 90;
$("#germanY").html("Y");
$("#germanZ").html("Z");
} else {
keyCZero = 90;
keyAOne = 89;
if (this.value == "fr") {
keyCOne = 65; // A
} else {
keyCOne = 81;
}
$("#germanY").html("Z");
$("#germanZ").html("Y");
}
});
var userLang = navigator.language || navigator.userLanguage;
if (userLang.indexOf("de")<0) {
// keys should also be correct at the beginning on an english keyboard
$("select[name=keyboardLayout]").val("en").trigger("change");
}
$("input[name=transposeUp]").change(function() {
transposeUp = this.checked;
$("input[name=showKeyboardKeys]").removeAttr("checked").change();
});
$("input.number").knobby();
This Pen doesn't use any external CSS resources.