more GUI stuff

This commit is contained in:
Yotam Mann 2014-03-14 11:28:35 -04:00
parent 1c013c7241
commit ad9e055d3c
15 changed files with 157 additions and 166 deletions

View file

@ -21,6 +21,8 @@
<script type="text/javascript" src="../src/GUI/GUI.Bar.js"></script>
<script type="text/javascript" src="../src/GUI/GUI.Meter.js"></script>
<script type="text/javascript" src="../src/GUI/GUI.Fader.js"></script>
<script type="text/javascript" src="../src/GUI/GUI.ParamFader.js"></script>
<script type="text/javascript" src="../src/GUI/GUI.GainFader.js"></script>
</head>
<body>
<style type="text/css">
@ -39,19 +41,39 @@
right: 100px;
width: auto;
}
#MasterOut {
width: 160px;
height: 200px;
position: absolute;
bottom: 10px;
right: 0px;
}
#Trigger {
width: 100px;
height: 100px;
position: absolute;
top: 20px;
left: 20px;
background-color: blue;
color: white;
}
</style>
<div id='Instructions'>Press 'e'</div>
<div id='meter'></div>
<div id='fader'></div>
<div id='Trigger'>Press</div>
<div id='MasterOut'>
<div id='meter'></div>
<div id='fader'></div>
</div>
<script type="text/javascript">
var player = new AudioUnit.Player("../audio/A3.mp3");
var meter = new AudioUnit.Meter(2);
var env = new AudioUnit.Envelope(.01, .05, 0, 0);
var env = new AudioUnit.Envelope(.05, .01, 0, 0);
var lfo = new AudioUnit.LFO(undefined, 1, .5, 1);
var noise = new AudioUnit.Noise();
var feedbackDelay = new AudioUnit.PingPongDelay(.25);
var meterGui = new AudioUnit.GUI.Meter($("#meter"), meter, "master", 20);
var fader = new AudioUnit.GUI.Fader($("#fader"), 0, 20, "master gain", 20);
var fader = new AudioUnit.GUI.GainFader($("#fader"), AudioUnit.Master.output, "mstr");
noise.connect(env);
env.connect(feedbackDelay);
@ -66,12 +88,20 @@
player.loop();
});
$(document).keydown(function(e){
if (e.which == 69){
env.triggerAttack();
} else if (e.which == 83) {
env.triggerRelease();
}
document.addEventListener('touchstart', function(e){
env.triggerAttack();
});
document.addEventListener('touchend', function(e){
env.triggerRelease();
});
$("#Trigger").bind("mousedown touchstart", function(e){
console.log('hi')
env.triggerAttack();
});
$("#Trigger").bind("mouseup touchend", function(e){
env.triggerRelease();
});
</script>
</body>

View file

@ -13,7 +13,7 @@ AudioUnit.GUI.Bar = function(container, segments){
//vars
this.element = this.createElement();
this.segmentCount = this.defaultArg(segments, 10);
this.segmentCount = this.defaultArg(segments, 20);
this.segments = new Array(this.segmentCount);
this.label = this.createElement();
@ -48,8 +48,3 @@ AudioUnit.GUI.Bar.prototype.setLevel = function(val){
seg.style.opacity = Math.max(Math.min(val - i, 1), 0);
}
}
//@param {string} str
AudioUnit.GUI.Bar.prototype.setLabel = function(str){
this.label.textContent = str;
}

View file

@ -11,16 +11,19 @@ AudioUnit.GUI.Fader = function(container, minOutput, maxOutput, label, segments)
//components
this.element = this.createElement();
this.track = this.createElement();
this.label = this.createElement();
this.slider = this.createElement("input");
this.slider.type = "range";
this.textInput = this.createElement("input");
this.textInput.type = "text";
this.isDragging = false;
this.min = this.defaultArg(minOutput, 0);
this.max = this.defaultArg(maxOutput, 1);
this.scaling = "log";
this.currentLevel = null;
this.scaling = "lin";
this.bars = new AudioUnit.GUI.Bar(this.track, segments);
@ -29,14 +32,19 @@ AudioUnit.GUI.Fader = function(container, minOutput, maxOutput, label, segments)
this.setClass(this.track, "track");
this.setClass(this.slider, "slider");
this.setClass(this.textInput, "label");
this.setClass(this.label, "label");
this.appendChild(container, this.element);
this.appendChild(this.element, this.track);
this.appendChild(this.track, this.slider);
this.appendChild(this.element, this.textInput);
this.appendChild(this.element, this.label);
// this.onAnimationFrame(this.followValue, this);
this._setupEvents();
this.setLevel(this.min);
this.setLevel(this.currentLevel);
this.setLabel(this.defaultArg(label, ""));
//set the slider height based on the segments
this.slider.style.width = this.bars.element.clientHeight;
}
AudioUnit.extend(AudioUnit.GUI.Fader, AudioUnit.GUI);
@ -47,8 +55,12 @@ AudioUnit.GUI.Fader.prototype.onchange = function(){};
//set the level of the
AudioUnit.GUI.Fader.prototype.setLevel = function(level){
this._setText(level);
this._setSlider(level);
if (level !== this.currentLevel){
this.currentLevel = level;
this._setText(level);
this._setSlider(level);
this.onchange(level);
}
};
///////////////////////////////////////////////////////////////////////////////
@ -62,7 +74,7 @@ AudioUnit.GUI.Fader.prototype._onchangeText = function(e){
//called when the value has changed
AudioUnit.GUI.Fader.prototype._onchangeSlider = function(){
var scaledVal = this._scale(this.slider.value / 100)
var scaledVal = this._scale(1 - this.slider.value / 100)
var val = this.interpolate(scaledVal, this.min, this.max);
this.setLevel(val);
};
@ -77,14 +89,13 @@ AudioUnit.GUI.Fader.prototype._setText = function(val){
} else {
this.textInput.value = parseInt(val, 10);
}
this.onchange(val);
}
AudioUnit.GUI.Fader.prototype._setSlider = function(val){
//scale it to the slider range
var normed = this.normalize(val, this.min, this.max);
var scaled = this._inverseScale(normed);
this.slider.value = scaled * 100;
this.slider.value = 100 - scaled * 100;
this.bars.setLevel(scaled);
}

28
src/GUI/GUI.GainFader.js Normal file
View file

@ -0,0 +1,28 @@
///////////////////////////////////////////////////////////////////////////////
//
// GAIN FADER
//
// attach it to an GainNode or an AudioUnit to control the output gain
///////////////////////////////////////////////////////////////////////////////
AudioUnit.GUI.GainFader = function(container, gain, label, segments){
if (!(gain instanceof GainNode) && gain.output instanceof GainNode){
gain = gain.output;
}
//extend Fader
AudioUnit.GUI.ParamFader.call(this, container, gain.gain, 0, 1, label, "log", segments);
}
AudioUnit.extend(AudioUnit.GUI.GainFader, AudioUnit.GUI.ParamFader);
//@override
AudioUnit.GUI.GainFader.prototype._setText = function(val){
this.textInput.value = this.gainToDb(val).toFixed(1) + "db";
}
//@override
AudioUnit.GUI.GainFader.prototype._onchangeText = function(e){
var val = parseFloat(this.textInput.value);
this.setLevel(this.dbToGain(val));
}

View file

@ -1,119 +0,0 @@
AudioUnit.GUI.ParamFader = function(container, connectTo, minOutput, maxOutput, label, scaling, segments){
//extend GUI
AudioUnit.GUI.call(this);
//components
this.element = this.createElement();
this.track = this.createElement();
this.slider = this.createElement("input");
this.slider.type = "range";
this.textInput = this.createElement("input");
this.textInput.type = "text";
this.watch = connectTo;
if (connectTo.output && connectTo.output.gain instanceof AudioParam){
this.watch = connectTo.output.gain;
}
this.isDragging = false;
this.min = this.defaultArg(minOutput, 0);
this.max = this.defaultArg(maxOutput, 1);
this.scaling = this.defaultArg(scaling, "log");
this.bars = new AudioUnit.GUI.Bar(this.track, segments);
//set it
this.setClass(this.element, "fader");
this.setClass(this.track, "track");
this.setClass(this.slider, "slider");
this.setClass(this.textInput, "label");
this.appendChild(container, this.element);
this.appendChild(this.element, this.track);
this.appendChild(this.track, this.slider);
this.appendChild(this.element, this.textInput);
this.onAnimationFrame(this.followValue, this);
this._setupEvents();
this._setInitial();
}
AudioUnit.extend(AudioUnit.GUI.Fader, AudioUnit.GUI);
//called when the value has changed
AudioUnit.GUI.Fader.prototype.onchange = function(){};
//called when the value has changed
AudioUnit.GUI.Fader.prototype._onchange = function(){
var val = this.slider.value / 100;
this.bars.setLevel(val);
var scaled = this.interpolate(this._scale(val), this.min, this.max);
this.textInput.value = scaled.toFixed(3);
this.watch.value = scaled;
this.onchange(scaled);
};
AudioUnit.GUI.Fader.prototype._onchangeText = function(e){
var val = parseFloat(this.textInput.value);
this.slider.value = this._inverseScale(this.normalize(val, this.min, this.max)) * 100;
this._onchange();
}
//called 60fps
AudioUnit.GUI.Fader.prototype.followValue = function(){
if (!this.isDragging){
var normalized = this._inverseScale(this.normalize(this.watch.value, this.min, this.max)) * 100;
if (normalized !== this.slider.value){
this.slider.value = normalized;
}
}
}
//sets the initial values
AudioUnit.GUI.Fader.prototype._setInitial = function(){
var val = this.watch.value;
this.slider.value = this._inverseScale(this.normalize(val, this.min, this.max)) * 100;
this.textInput.value = val.toFixed(3);
this.bars.setLevel(this.slider.value / 100);
}
//input a value between 0-1
AudioUnit.GUI.Fader.prototype._inverseScale = function(x){
switch(this.scaling){
case "lin" :
return parseFloat(x);
case "log" :
return this.gainToLogScale(x);
case "exp" :
return this.gainToPowScale(x);
}
}
//input a value between 0-1
AudioUnit.GUI.Fader.prototype._scale = function(x){
switch(this.scaling){
case "lin" :
return parseFloat(x);
case "log" :
return this.gainToPowScale(x);
case "exp" :
return this.gainToLogScale(x);
}
}
//called when the value has changed
AudioUnit.GUI.Fader.prototype._setupEvents = function(){
this.textInput.onchange = this._onchangeText.bind(this);
this.slider.onchange = this._onchange.bind(this);
this.slider.onmousedown = this._mousedown.bind(this);
this.slider.onmouseup = this._mouseup.bind(this);
};
AudioUnit.GUI.Fader.prototype._mousedown = function(e){
this.isDragging = true;
}
AudioUnit.GUI.Fader.prototype._mouseup = function(e){
this.isDragging = false;
}

View file

@ -34,6 +34,7 @@ AudioUnit.GUI.Meter.prototype.update = function(){
for (var channel = 0, channelCount = this.meter.channels; channel < channelCount; channel++){
var volume = this.meter.getLevel(channel);
this.bars[channel].setLevel(this.gainToLogScale(volume));
//also check if it's clipped
}
}
@ -48,8 +49,3 @@ AudioUnit.GUI.Meter.prototype.labelUpdate = function(){
this.bars[channel].setLabel(db);
}
}
//@param {string} str
AudioUnit.GUI.Meter.prototype.setLabel = function(str){
this.label.textContent = str;
}

30
src/GUI/GUI.ParamFader.js Normal file
View file

@ -0,0 +1,30 @@
///////////////////////////////////////////////////////////////////////////////
//
// PARAM FADER
//
// attach it to an AudioParam and let it control/follow it's value
///////////////////////////////////////////////////////////////////////////////
AudioUnit.GUI.ParamFader = function(container, audioParam, minOutput, maxOutput, label, scaling, segments){
//extend Fader
AudioUnit.GUI.Fader.call(this, container, minOutput, maxOutput, label, segments);
//set the scaling
this.scaling = this.defaultArg(scaling, "log");
this.watch = audioParam;
this.onAnimationFrame(this.followValue, this);
}
AudioUnit.extend(AudioUnit.GUI.ParamFader, AudioUnit.GUI.Fader);
//called 60fps
AudioUnit.GUI.ParamFader.prototype.followValue = function(){
if (!this.isDragging){
this.setLevel(this.watch.value);
}
}
AudioUnit.GUI.ParamFader.prototype.onchange = function(val){
this.watch.value = val;
}

View file

@ -155,6 +155,13 @@ window.requestAnimFrame = (function(){
this._getElement(element).className = className;
}
//@param {string} str
AudioUnit.GUI.prototype.setLabel = function(str){
if (this.label && this.label instanceof HTMLElement){
this.label.textContent = str;
}
}
///////////////////////////////////////////////////////////////////////////
// BORROW SOME METHODS

View file

@ -74,6 +74,6 @@ AudioUnit.Meter.prototype.onprocess = function(event){
sum += x * x;
}
var rms = Math.sqrt(sum / bufferSize);
this.volume[channel] = Math.max(rms, this.volume[channel] * .9);
this.volume[channel] = Math.max(rms, this.volume[channel] * .8);
}
}

View file

@ -80,7 +80,7 @@ AudioUnit.Noise.prototype._brownNoise = (function() {
//modified from http://noisehack.com/generate-noise-web-audio-api/
AudioUnit.Noise.prototype._whiteNoise = function(e){
var bufferSize = this.bufferSize;
var output = event.outputBuffer.getChannelData(0);
var output = e.outputBuffer.getChannelData(0);
for (var i = 0; i < bufferSize; i++) {
output[i] = Math.random() * 2 - 1;
}

View file

@ -217,9 +217,14 @@
///////////////////////////////////////////////////////////////////////////
//A extends B
AudioUnit.extend = function(A, B){
A.prototype = new B();
A.prototype.constructor = A;
//based on closure library 'inherit' function
AudioUnit.extend = function(childCtor, parentCtor){
/** @constructor */
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
/** @override */
childCtor.prototype.constructor = childCtor;
}
//make it global

View file

@ -6,9 +6,6 @@
/*=============================================================================
BAR
=============================================================================*/
.bar {
pointer-events: none; }
.bar .segment {
width: 30px;
height: 6px;
@ -61,12 +58,18 @@
.fader .slider {
position: absolute;
width: 100%;
height: 100%;
margin: 0px;
width: 100px;
height: 40px;
margin-left: 23px;
margin-top: -20px;
top: 0px;
left: 0px;
-webkit-appearance: slider-vertical; }
-webkit-transform: rotate(90deg);
-webkit-transform-origin: left center;
-moz-transform: rotate(90deg);
-moz-transform-origin: left center;
transform: rotate(90deg);
transform-origin: left center; }
.fader input.label {
padding: 0px;

View file

@ -25,7 +25,6 @@ $unitWidth : 30px;
=============================================================================*/
.bar {
pointer-events: none;
}
.bar .segment {
@ -92,12 +91,18 @@ $faderWidth: 40px;
.fader .slider {
position: absolute;
width: 100%;
height: 100%;
margin: 0px;
width: 100px;
height: $faderWidth;
margin-left: 23px;
margin-top: -20px;
top: 0px;
left: 0px;
-webkit-appearance: slider-vertical;
-webkit-transform: rotate(90deg);
-webkit-transform-origin: left center;
-moz-transform: rotate(90deg);
-moz-transform-origin: left center;
transform: rotate(90deg);
transform-origin: left center;
}
.fader input.label {