Skip to content

Instantly share code, notes, and snippets.

@beseidel
Created July 22, 2019 07:30
Show Gist options
  • Save beseidel/bbbe67a66d37dd95a187890c3aa5bcb4 to your computer and use it in GitHub Desktop.
Save beseidel/bbbe67a66d37dd95a187890c3aa5bcb4 to your computer and use it in GitHub Desktop.
musical mind game
<div id="container">
<div id="main">
<audio id="theSong" controls />
<div id="controls">
<p>
<select id="filtersDropdown">
</select>
</p>
<canvas id="canvas" width="50" height ="20"></canvas>
<p>
<input id="frequencySlider" title="Frequency" type="range" min="0" max="2000" value="1000" />
<input id="qSlider" title="Q" type="range" min="1" max="100" value="10" />
<input id="gainSlider" title="Gain" disabled type="range" min="1" max="100" value="20" />
</p>
</div>
</div>
<div class="circles">
<canvas id="concentric_circles" width="600" height="600"></canvas>
</div>

musical mind game

html5, canvas, and some funky music - kidding! do the math on the object :)

A Pen by Judith on CodePen.

License.

(function() {
var AudioContext = window.AudioContext ||
window.webkitAudioContext;
var audioContext;
var biquadFilter;
var frequencySlider = document.getElementById("frequencySlider");
var qSlider = document.getElementById("qSlider");
var gainSlider = document.getElementById("gainSlider");
var audio;
// All Web Audio API filters
// https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode/type
// q and gain controls if the corresponding slider
// should be enabled
var filters = { "lowpass": {
q: true,
gain: false
}, "highpass": {
q: true,
gain: false
}, "bandpass": {
q: true,
gain: false
}, "lowshelf": {
q: false,
gain: true
}, "highshelf": {
q: false,
gain: true
}, "peaking": {
q: true,
gain: true
}, "notch": {
q: true,
gain: false
}, "allpass": {
q: true,
gain: false
}
};
var canvas = document.getElementById("canvas");
var canvasContext = canvas.getContext("2d");
var frequencyBars = 100;
// Array containing all the frequencies we want to get
// response for when calling getFrequencyResponse()
var myFrequencyArray = new Float32Array(frequencyBars);
for(var i = 0; i < frequencyBars; ++i) {
myFrequencyArray[i] = 2000/frequencyBars*(i+1);
}
// We receive the result in these two when calling
// getFrequencyResponse()
var magResponseOutput = new Float32Array(frequencyBars); // magnitude
var phaseResponseOutput = new Float32Array(frequencyBars);
audioContext = new AudioContext();
window.addEventListener("load", function(e) {
audio = document.getElementById("theSong");
audio.crossOrigin = "anonymous";
var source = audioContext.createMediaElementSource(audio);
biquadFilter = audioContext.createBiquadFilter();
biquadFilter.type = "lowpass";
biquadFilter.frequency.value = 1000;
biquadFilter.Q.value = 10;
biquadFilter.gain.value = 20;
source.connect(biquadFilter);
biquadFilter.connect(audioContext.destination);
updateFrequencyResponse();
}, false);
function drawFrequencyResponse(mag, phase) {
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
var barWidth = 400 / frequencyBars;
// Magnitude
canvasContext.strokeStyle = "white";
canvasContext.beginPath();
for(var frequencyStep = 0; frequencyStep < frequencyBars; ++frequencyStep) {
canvasContext.lineTo(
frequencyStep * barWidth,
canvas.height - mag[frequencyStep]*90);
}
canvasContext.stroke();
// Phase
canvasContext.strokeStyle = "red";
canvasContext.beginPath();
for(var frequencyStep = 0; frequencyStep < frequencyBars; ++frequencyStep) {
canvasContext.lineTo(
frequencyStep * barWidth,
canvas.height - (phase[frequencyStep]*90 + 300)/Math.PI);
}
canvasContext.stroke();
}
function updateFrequencyResponse() {
biquadFilter.getFrequencyResponse(
myFrequencyArray,
magResponseOutput,
phaseResponseOutput);
drawFrequencyResponse(magResponseOutput, phaseResponseOutput);
}
frequencySlider.addEventListener("change", function () {
biquadFilter.frequency.value = this.value;
});
frequencySlider.addEventListener("mousemove", function () {
biquadFilter.frequency.value = this.value;
updateFrequencyResponse();
});
qSlider.addEventListener("mousemove", function () {
biquadFilter.Q.value = this.value;
updateFrequencyResponse();
});
gainSlider.addEventListener("mousemove", function () {
biquadFilter.gain.value = this.value;
updateFrequencyResponse();
});
var filtersDropdown = document.getElementById("filtersDropdown");
for(var item in filters) {
var option = document.createElement("option");
option.innerHTML = item;
// This will cause a re-flow of the page but we don't care
filtersDropdown.appendChild(option);
};
function filterClicked (event) {
event = event || window.event;
var target = event.target || event.srcElement;
var filterName = target.value;
biquadFilter.type = filterName;
updateFrequencyResponse();
qSlider.disabled = !filters[filterName].q;
gainSlider.disabled = !filters[filterName].gain;
};
filtersDropdown.addEventListener("change", filterClicked, false);
////////////////////////////
// Soundcloud stuff below //
////////////////////////////
function get(url, callback) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
callback(request.responseText);
}
}
request.open("GET", url, true);
request.send(null);
}
var clientParameter = "client_id=aae0cd3ce269784234bb78aa6d485394"
var trackPermalinkUrl = "https://soundcloud.com/spinninrecords/project-t-martin-garrix-remix";
//var trackPermalinkUrl =
"https://soundcloud.com/aviciiofficial/avicii-levels-original-mix";
function findTrack() {
get("https://api.soundcloud.com/resolve.json?url=" + trackPermalinkUrl + "&" + clientParameter,
function (response) {
var trackInfo = JSON.parse(response);
audio.src = trackInfo.stream_url + "?" + clientParameter;
}
);
};
findTrack();
})();
var canvas = document.getElementById("concentric_circles");
var ctx = canvas.getContext("2d");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var circles = new Array();
function Circle(angle, radius, rRadius, iX, iY) {
this.angle = angle;
this.radius = radius;
this.rRadius = rRadius;
this.iX = iX;
this.iY = iY;
this.inc = 1;
}
Circle.prototype.add = function () {
this.angle += this.inc;
this.cX = this.iX + this.rRadius * Math.cos(this.angle);
this.cY = this.iY + this.rRadius * Math.sin(this.angle);
if (this.angle >= (Math.PI * 2)) {
this.angle = 0;
this.inc = .01 + Math.random() * .1;
}
var rColor = 'rgba(' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ', .3)';
ctx.beginPath();
ctx.arc(this.cX, this.cY, this.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.fillStyle = rColor;
ctx.fill();
ctx.strokeStyle = rColor;
ctx.stroke();
};
function drawCC() {
for (var i = 0; i < 30 ; i++) {
for (var j = 0; j < 50+Math.random() * 200 ; j++) {
var iX = canvasWidth / 2;
var iY = canvasHeight / 3;
var radius = i;
var rRadius = 30*i;
var angle =100+i;
var circle = new Circle(angle, radius, rRadius, iX, iY);
circles.push(circle);
}
}
requestAnimationFrame(draw);
}
drawCC();
function draw() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
circle.add();
}
requestAnimationFrame(draw);
}
body {
background-color: black;
text-align: center;
margin: 0 auto;
position: relative;
}
.float {
position: absolute;
left: 0;
top: 0;
}
.circles{
width: 85%;
height: auto;
border: 4px solid black;
margin-left: 75px;
}
#main{
width: 100%;
height: 10%;
}
.top-container {
color: #fff;
font-family: sans-serif;
width: 100%;
padding-top: 40px;
padding-bottom: 40px;
margin: 0 auto;
text-align: center;
margin-bottom: 40px;
border-bottom: 2px solid rgba(0, 0, 0, 0);
background-color: #fff;
}
.top-container h1 {
font-size: 28px;
}
.top-container h2 {
font-size: 14px;
font-weight: 100;
opacity: 0.6;
}
#canvas {
border: 4px solid black;
background-color: rgba(128, 128, 128, 0.16);
}
input:disabled {
opacity: 0.1;
}
* { width: 100%;
height: 100%;
margin: 0px;
}
canvas {
width:100%;
display:block;
margin:auto;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment