forked from Sasserisop/MATH201
190 lines
4.9 KiB
JavaScript
190 lines
4.9 KiB
JavaScript
var slider = document.getElementById("sliderHarmonics");
|
|
var textHarmonics = document.getElementById("textHarmonics");
|
|
var sliderFreq = document.getElementById("sliderFreq")
|
|
var textFreq = document.getElementById("textFreq");
|
|
var playing = document.getElementById("playButton");
|
|
textHarmonics.innerHTML = slider.value; // Display the default slider value
|
|
textFreq.innerHTML=sliderFreq.value
|
|
|
|
var isPlaying = false;
|
|
var real = new Float32Array(110);
|
|
var imag = new Float32Array(110);
|
|
|
|
var cspec = document.getElementById('spectrum'),
|
|
ctxspec = cspec.getContext("2d");
|
|
|
|
cspec.height = 200;
|
|
cspec.width = 500;
|
|
|
|
|
|
|
|
|
|
|
|
sliderFreq.oninput = function() {
|
|
textFreq.innerHTML=this.value;
|
|
osc.frequency.value=this.value;
|
|
}
|
|
// Update the current slider value (each time you drag the slider handle)
|
|
slider.oninput = function() {
|
|
textHarmonics.innerHTML = this.value;
|
|
if (isPlaying){
|
|
var numCoeffs = this.value; // The more coefficients you use, the better the approximation
|
|
//var real = new Float32Array(numCoeffs+10);
|
|
//var imag = new Float32Array(numCoeffs+10);
|
|
|
|
//real[0] = 0.5;
|
|
//for (var i = 1; i < numCoeffs; i++) { // note i starts at 1
|
|
// imag[i] = 1 / (i * Math.PI);
|
|
//}
|
|
for (var i = 1; i <= 110; i++) {
|
|
real[i]=0;
|
|
}
|
|
for (var i = 1; i <= numCoeffs; i++) { // note i starts at 1
|
|
real[2*i] = (2/Math.PI) *( 1/(2*i+1)-1/(2*i-1) );
|
|
}
|
|
|
|
osc.frequency.value = textFreq.innerHTML;
|
|
//var imag= new Float32Array([0,0,0,0,0]); // sine
|
|
//var real = new Float32Array(imag.length); // cos
|
|
var customWave = context.createPeriodicWave(real, imag); // cos,sine
|
|
osc.setPeriodicWave(customWave);
|
|
|
|
|
|
|
|
//isPlaying = false;
|
|
// osc.stop();
|
|
//playSound(this.value);}
|
|
}}
|
|
|
|
|
|
//setup audio context
|
|
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
var context = new window.AudioContext();
|
|
|
|
//create nodes
|
|
var osc; //create in event listener so we can press the button more than once
|
|
var masterGain = context.createGain();
|
|
var analyser = context.createAnalyser();
|
|
|
|
//routing
|
|
masterGain.connect(analyser);
|
|
analyser.connect(context.destination);
|
|
|
|
|
|
|
|
//draw function for canvas
|
|
function drawWave(analyser, ctx) {
|
|
|
|
var buffer = new Float32Array(1024),
|
|
w = ctx.canvas.width;
|
|
|
|
ctx.strokeStyle = "#D44"; //reddish color
|
|
ctx.setTransform(1,0,0,-1,0,100.5); // flip y-axis and translate to center
|
|
ctx.lineWidth = 2;
|
|
ctxspec.strokeStyle = "#44D" //blueish color
|
|
ctxspec.setTransform(1,0,0,1,0,100.5);
|
|
ctxspec.lineWidth = 2;
|
|
var wspec=ctxspec.canvas.width;
|
|
(function loop() {
|
|
analyser.getFloatTimeDomainData(buffer);
|
|
var prevValue=999;
|
|
var currentValue=999;
|
|
for (var i=10; i<1024; i++){
|
|
currentValue=buffer[i];
|
|
if (currentValue>prevValue && currentValue>-0.05 && currentValue<0.05){
|
|
break;
|
|
}
|
|
prevValue=currentValue;
|
|
}
|
|
ctx.clearRect(0, -100, w, ctx.canvas.height);
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(0, buffer[i] * 90);
|
|
for (var x = i; x < w+i; x += 2) ctx.lineTo(x-i+2, buffer[x] * 90);
|
|
ctx.stroke();
|
|
|
|
//spectrum stuff:
|
|
//real=getReal();
|
|
//console.log(real);
|
|
ctxspec.clearRect(0, -100, wspec, ctxspec.canvas.height);
|
|
ctxspec.beginPath();
|
|
ctxspec.moveTo(0, 80);
|
|
for (var j=0; j<100; j++){
|
|
ctxspec.lineTo(j*10,real[j]*400+80);
|
|
}
|
|
ctxspec.stroke();
|
|
if (isPlaying) requestAnimationFrame(loop)
|
|
})();
|
|
}
|
|
|
|
//button trigger
|
|
$(function() {
|
|
var c = document.getElementById('scope'),
|
|
ctx = c.getContext("2d");
|
|
|
|
c.height = 200;
|
|
c.width = 600;
|
|
|
|
// make 0-line permanent as background
|
|
ctx.moveTo(0, 100.5);
|
|
ctx.lineTo(c.width, 100.5);
|
|
ctx.stroke();
|
|
c.style.backgroundImage = "url(" + c.toDataURL() + ")";
|
|
|
|
$('button').on('mousedown', function() {
|
|
|
|
if (playing.innerHTML==="Pause sound"){
|
|
playing.innerHTML="Play the sound";
|
|
isPlaying = false;
|
|
osc.stop();
|
|
}else{
|
|
playing.innerHTML="Pause sound";
|
|
playSound(textHarmonics.innerHTML);
|
|
}});
|
|
});
|
|
|
|
function playSound(h){
|
|
var c = document.getElementById('scope'),
|
|
ctx = c.getContext("2d");
|
|
osc = context.createOscillator();
|
|
//osc settings
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var numCoeffs = h; // The more coefficients you use, the better the approximation
|
|
|
|
|
|
//real[0] = 0.5;
|
|
//for (var i = 1; i < numCoeffs; i++) { // note i starts at 1
|
|
// imag[i] = 1 / (i * Math.PI);
|
|
//}
|
|
for (var i = 1; i <= 110; i++) {
|
|
real[i]=0;
|
|
}
|
|
for (var i = 1; i <= numCoeffs; i++) { // note i starts at 1
|
|
real[2*i] = (2/Math.PI) *( 1/(2*i+1)-1/(2*i-1) );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//var imag= new Float32Array([0,0,0,0,0]); // sine
|
|
//var real = new Float32Array(imag.length); // cos
|
|
var customWave = context.createPeriodicWave(real, imag); // cos,sine
|
|
osc.setPeriodicWave(customWave);
|
|
osc.frequency.value = textFreq.innerHTML;
|
|
osc.connect(masterGain);
|
|
osc.start();
|
|
isPlaying = true;
|
|
|
|
drawWave(analyser, ctx);
|
|
} |