dspjs
Version:
DSP.js is a comprehensive digital signal processing library for javascript
210 lines (182 loc) • 6.15 kB
HTML
<html>
<head>
<!-- Load JQuery and JQuery-UI -->
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<!-- Load Processing.js -->
<script language="javascript" src="js/processing.js"></script>
<script language="javascript" src="js/init.js"></script>
<!-- Load DSP.js -->
<script src="../dsp.js"></script>
<style type="text/css">
body, * {
font-family: Arial, sans-serif;
}
.control {
padding: 5px;
border: 1px outset #CCC;
background-color: #EEE;
float: left;
margin-right: 5px;
}
.control table td {
padding: 10px;
width: 20px;
color: #999;
font-size: 12px;
}
.control h3 {
margin: 0;
padding:0;
font-size: 12px;
margin-bottom: 10px;
}
.control #debug {
border: 1px inset #ccc;
background-color: #FFF;
font-size: 12px;
width: 300px;
padding: 10px;
}
.slider {
margin-bottom: 16px;
width: 8px;
}
.ui-slider .ui-slider-handle {
width: 8px;
margin-left: 3px;
}
</style>
</head>
<body>
<script>
// Setup shared variables
var sampleRate = 44100;
var frameSize = 4096;
var signal = new Float32Array(frameSize/2);
var lp12;
var buffer = [];
// Setup experimental audio out
var output = new Audio();
if ( typeof output.mozSetup === 'function' ) {
output.mozSetup(1, sampleRate);
}
var changeFilter = function() {
lp12.set($('#cutoff').slider('option', 'value'), $('#res').slider('option', 'value'));
}
function loadedMetaData(event) {
var audio = document.getElementById('input');
audio.mozFrameBufferLength = frameSize;
audio.addEventListener("MozAudioAvailable", audioAvailable, false);
}
function audioAvailable(event) {
signal = DSP.getChannel(DSP.MIX, event.frameBuffer);
lp12.process(signal);
output.mozWriteAudio(signal);
}
</script>
<script type="application/processing" target="#signal">
Knob cut;
Knob res;
void setup() {
size(512, 200);
cut = new Knob("", 60, 6000, 2500, 70, 20, 50, 50);
res = new Knob("", 1, 20, 7, 0.3, 20, 100, 50);
lp12 = new IIRFilter(DSP.LOWPASS, 22050, 0, sampleRate);
// mute the input
document.getElementById('input').muted = true;
stroke(255, 0, 0);
}
void draw() {
background(255);
lp12.set(cut.value, res.value);
for (int i = 0; i < width; i+=2) {
line(i, height/2 - signal[4*i]/2 * 200, i, height/2 + signal[4*i]/2 * 200);
}
fill(255, 0, 0);
text("F", 30, 30);
text("Q", 75, 30);
ellipse(52, 52, 40, 40);
ellipse(102, 52, 40, 40);
fill(255);
cut.draw();
res.draw();
}
class Knob {
float radius;
float x;
float y;
boolean active;
float mouseYInit;
float value;
float min;
float max;
float step;
float percent;
float angle;
String label;
Knob(label, min, max, value, step, radius, x, y) {
this.radius = radius;
this.x = x;
this.y = y;
this.active = false;
this.value = value;
this.min = min;
this.max = max;
this.step = step;
this.label = label;
}
void draw() {
textSize(12);
ellipseMode(CENTER);
if (mousePressed) {
if (this.isOver() && !this.active && !Knob.active) {
this.active = true;
this.mouseYInit = mouseY;
Knob.active = true;
} else if (this.active) {
this.value += (this.mouseYInit - mouseY) * this.step;
this.value = constrain(this.value, min, max);
this.mouseYInit = mouseY;
}
} else {
this.active = false;
Knob.active = false;
}
this.percent = (this.value - this.min) / (this.max - this.min);
this.angle = map(this.value, this.min, this.max, radians(-130), radians(130));
pushMatrix();
translate(this.x, this.y);
rotate(this.angle);
ellipse(0, 0, 2*this.radius, 2*this.radius);
line(0, 0, 0, -this.radius);
popMatrix();
/*
text(this.label, this.x - this.radius -5, this.y - this.radius - 5);
text(this.value, this.x+this.radius+5, this.y);
text(round(this.percent * 100) + "%", this.x+this.radius+5, this.y+20);
*/
}
boolean isOver() {
if (mouseX > this.x - this.radius &&
mouseX < this.x + this.radius &&
mouseY > this.y - this.radius &&
mouseY < this.y + this.radius) {
return true;
}
return false;
}
}
</script>
<h1>Audio Filter</h1>
<p>Applies a Low pass filter to an audio stream. Remember to <b>Mute</b> the audio to hear the pure filtered sound.</p>
<p>The low pass filter acts as a gate, only letting frequencies below the cut off value through.</p>
<audio id='input' tabindex="0" src="audio/megaman.ogg" controls="true" onloadedmetadata="loadedMetaData(event);" style="width: 512px;"></audio><br>
<div><canvas id="signal" width="512px" height="200px"></canvas></div>
<p>The <b>F</b> knob controls the cut off frequency, between 0 and 22050 Hz.</p>
<p>The <b>Q</b> knob controls the resonance drive.</p>
<p>A low frequency cutoff and strong resonance can give an acidy or dampened underwater effect.</p>
<p>(Be careful! Adjust your volume! Certain knob combinations can give off loud undesired schreeching noises!)</p>
<p>Music: Delv-X: Megaman theme (cover)</p>
</body>
</html>