JSFiddle - React, Tailwind, and code Playground
by replicateur
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<h4 class="title">Simple Oscillator</h4>
<div class="commands">
<button id="start" class="btn btn-success">
Start
</button>
<button id="stop" class="btn btn-danger">
Stop
</button>
<button id="add" class="btn btn-primary">
Add oscillator
</button>
<div class="board">
<input class="zoomer" type="range" min="20" max="90" value="75" orient="vertical" />
<canvas id='scope'></canvas>
</div>
</div>
CSS
.slider,
.slider2 {
display: inline-block !important;
float: left;
width: 85% !important;
margin-left: auto;
margin-right: auto;
line-height: normal;
vertical-align: middle;
}
.input-value {
display: inline-block !important;
float: left;
width: 10%;
text-align: center;
line-height: normal;
vertical-align: middle;
}
.wrapper {
padding: 1em;
}
.commands {
text-align: center;
}
.title {
text-align: center;
text-transform: uppercase;
font-weight: bold;
}
input[type=range][orient=vertical] {
writing-mode: bt-lr;
/* IE */
-webkit-appearance: slider-vertical;
/* WebKit */
width: 8px;
height: 175px;
padding: 0 5px;
}
.scope {
display: inline-block;
float: right;
}
.zoomer {
display: inline-block;
float: left;
margin-left: 1em;
}
JavaScript
var context = new(window.AudioContext || window.webkitAudioContext)();
var oscRack = {};
var graphSize = 75;
var lineWidth = 3;
var masterGain = context.createGain();
var analyser = context.createAnalyser();
var isPlaying = false;
//routing
masterGain.connect(analyser);
analyser.connect(context.destination);
//draw function for canvas
function drawWave(analyser) {
var c = document.getElementById('scope');
var ctx = c.getContext("2d");
var buffer = new Float32Array(1024);
var w = $('#scope').width();
var h = $('#scope').height();
ctx.strokeStyle = "darkgrey";
ctx.setTransform(1, 0, 0, -1, 0, h / 2); // flip y-axis and translate to center
ctx.lineWidth = lineWidth;
var coef;
(function loop() {
analyser.getFloatTimeDomainData(buffer);
coef = graphSize - Object.keys(oscRack).length + 1 * 10;
ctx.clearRect(0, -100, w, ctx.canvas.height);
ctx.beginPath();
ctx.moveTo(0, buffer[0] * coef);
for (var x = 2; x < w; x += 2) {
ctx.lineTo(x, buffer[x] * coef);
}
ctx.stroke();
if (isPlaying) requestAnimationFrame(loop)
})();
}
function manageOscillator(command, osc_id) {
if (command === 'create') {
osc_id = "osc-" + Object.keys(oscRack).length + 1;
oscRack[osc_id] = context.createOscillator();
oscRack[osc_id].frequency.value = 300;
oscRack[osc_id].type = 'sawtooth';
//cRack[osc_id].connect(masterGain);
oscRack[osc_id].start();
isPlaying = true;
} else if (command === 'start') {
// Connect sound to speakers
for (var osc in oscRack) {
oscRack[osc].connect(masterGain);
}
drawWave(analyser, context);
} else if (command === 'stop') {
for (var osc in oscRack) {
oscRack[osc].disconnect(masterGain);
}
}
return osc_id;
}
document.addEventListener('input', changeFrequencyValue, false);
function changeFrequencyValue(event) {
if (event !== "undefined" &&
event.target !== "undefined" &&
event.target.value !== "undefined") {
if...