2015-02-12 03:39:28 +00:00
|
|
|
/* globals Tone, nx */
|
|
|
|
|
|
|
|
//nexusUI setup
|
|
|
|
nx.showLabels = true;
|
|
|
|
nx.colorize("accent", "#D76767");
|
|
|
|
nx.colorize("fill", "#fff");
|
2015-02-13 20:23:30 +00:00
|
|
|
// nx.colorize("border", "#000");
|
2015-02-12 03:39:28 +00:00
|
|
|
|
|
|
|
var Interface = {};
|
|
|
|
|
|
|
|
$(function(){
|
|
|
|
var topbar = $("<div>").attr("id", "TopBar");
|
|
|
|
$("body").prepend(topbar);
|
|
|
|
$("<div>")
|
|
|
|
.attr("id", "Homepage")
|
|
|
|
.attr("title", "github")
|
|
|
|
.html("<a href='http://github.com/TONEnoTONE/Tone.js'>Tone.js</a>")
|
|
|
|
.appendTo(topbar);
|
|
|
|
$("<div>")
|
|
|
|
.attr("id", "Examples")
|
|
|
|
.attr("title", "examples")
|
|
|
|
.html("<a href='./index.html'>examples</a>")
|
|
|
|
.appendTo(topbar);
|
|
|
|
//get the master output
|
|
|
|
if (Tone && Tone.Master){
|
|
|
|
var meter = new Tone.Meter(2);
|
|
|
|
Tone.Master.connect(meter);
|
|
|
|
var meterElement = $("<div>").attr("id", "Meter").appendTo(topbar);
|
|
|
|
var leftLevel = $("<div>").addClass("Level")
|
|
|
|
.attr("id", "Left")
|
|
|
|
.appendTo(meterElement);
|
|
|
|
var rightLevel = $("<div>").addClass("Level")
|
|
|
|
.attr("id", "Right")
|
|
|
|
.appendTo(meterElement);
|
|
|
|
function update(){
|
|
|
|
requestAnimationFrame(update);
|
|
|
|
var leftHeight = 100 - Math.max(Math.min(Math.abs(meter.getDb(0)), 100), 0);
|
|
|
|
var rightHeight = 100 - Math.max(Math.min(Math.abs(meter.getDb(1)), 100), 0);
|
|
|
|
leftLevel.height(leftHeight + "%");
|
|
|
|
rightLevel.height(rightHeight + "%");
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$(window).resize(function(){
|
|
|
|
for (var name in nx.widgets){
|
|
|
|
var widg = nx.widgets[name];
|
|
|
|
widg.init();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2015-02-13 20:23:30 +00:00
|
|
|
Interface._updateList = [];
|
|
|
|
|
|
|
|
Interface.update = function(){
|
|
|
|
requestAnimationFrame(Interface.update);
|
|
|
|
for (var i = 0; i < Interface._updateList.length; i++){
|
|
|
|
Interface._updateList[i]();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Interface.update();
|
|
|
|
|
2015-02-20 05:59:19 +00:00
|
|
|
Interface.getElement = function(el){
|
|
|
|
if (typeof el === "string"){
|
|
|
|
return $("#"+el);
|
|
|
|
} else {
|
|
|
|
return $(el);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-12 03:39:28 +00:00
|
|
|
Interface.Rack = function(id, name, collapsible){
|
2015-02-20 05:59:19 +00:00
|
|
|
var element = Interface.getElement(id);
|
2015-02-12 03:39:28 +00:00
|
|
|
element.addClass("Rack");
|
|
|
|
var title = $("<div>").addClass("Title").text(name);
|
|
|
|
element.prepend(title);
|
|
|
|
title.on("click touch", function(){
|
|
|
|
element.toggleClass("Expanded");
|
|
|
|
});
|
|
|
|
if (collapsible){
|
|
|
|
element.addClass("Collapsible");
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
close : function(){
|
|
|
|
element.removeClass("Expanded");
|
|
|
|
},
|
|
|
|
open : function(){
|
|
|
|
element.addClass("Expanded");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-02-20 05:59:19 +00:00
|
|
|
Interface.Group = function(containerID, name){
|
|
|
|
var container = Interface.getElement(containerID);
|
|
|
|
var element = container.addClass("Group");
|
|
|
|
$("<div>").text(name).appendTo(element).attr("id", "Label");
|
|
|
|
return element;
|
|
|
|
};
|
|
|
|
|
2015-02-12 03:39:28 +00:00
|
|
|
Interface.Toggle = function(container, callback){
|
|
|
|
var toggle = nx.add("toggle", {
|
|
|
|
parent : container
|
|
|
|
});
|
|
|
|
toggle.on("value", function(val){
|
|
|
|
callback(val === 1);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-02-13 20:23:30 +00:00
|
|
|
Interface.DropDown = function(container, node, parameter, options, label){
|
2015-02-20 05:59:19 +00:00
|
|
|
var element = $("<div>").appendTo(Interface.getElement(container))
|
2015-02-13 20:23:30 +00:00
|
|
|
.addClass("DropDown");
|
|
|
|
label = label || parameter;
|
|
|
|
$("<div>").appendTo(element)
|
|
|
|
.text(label)
|
|
|
|
.attr("id", "Label");
|
|
|
|
var selectList = $("<select>").appendTo(element);
|
|
|
|
for (var i = 0; i < options.length; i++){
|
|
|
|
$("<option>").text(options[i]).appendTo(selectList);
|
|
|
|
}
|
|
|
|
//set the initial value
|
|
|
|
selectList.val(node[parameter]);
|
|
|
|
selectList.on("change", function(){
|
|
|
|
node[parameter] = selectList.val();
|
2015-02-12 03:39:28 +00:00
|
|
|
});
|
2015-02-13 20:23:30 +00:00
|
|
|
return {
|
|
|
|
listen : function(){
|
|
|
|
function update(){
|
|
|
|
if (selectList.val() !== node[parameter]){
|
|
|
|
selectList.val(node[parameter]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Interface._updateList.push(update);
|
|
|
|
}
|
|
|
|
};
|
2015-02-12 03:39:28 +00:00
|
|
|
};
|
|
|
|
|
2015-02-24 03:14:51 +00:00
|
|
|
Interface.Presets = function(container, node){
|
|
|
|
var element = $("<div>").appendTo(Interface.getElement(container))
|
|
|
|
.addClass("DropDown");
|
|
|
|
$("<div>").appendTo(element)
|
|
|
|
.text("preset")
|
|
|
|
.attr("id", "Label");
|
|
|
|
var options = Object.keys(node.preset);
|
|
|
|
options.unshift("none");
|
|
|
|
var selectList = $("<select>").appendTo(element);
|
|
|
|
for (var i = 0; i < options.length; i++){
|
|
|
|
$("<option>").text(options[i]).appendTo(selectList);
|
|
|
|
}
|
|
|
|
//set the initial value
|
|
|
|
selectList.on("change", function(){
|
|
|
|
node.setPreset(selectList.val());
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-02-12 03:39:28 +00:00
|
|
|
Interface.ContinuousControl = function(container, type, node, parameter, min, max, exp){
|
2015-02-20 05:59:19 +00:00
|
|
|
container = Interface.getElement(container);
|
2015-02-12 03:39:28 +00:00
|
|
|
min = min || 0;
|
|
|
|
max = max || 1;
|
|
|
|
exp = exp || 1;
|
|
|
|
var isTone = (node[parameter] instanceof Tone || node[parameter] instanceof AudioParam);
|
|
|
|
var currentValue = isTone?node[parameter].value : node[parameter];
|
|
|
|
currentValue = nx.scale(currentValue, min, max, 0, 1);
|
|
|
|
currentValue = Math.pow(currentValue, 1/exp);
|
|
|
|
var slider = nx.add(type, {
|
|
|
|
parent : container,
|
|
|
|
});
|
|
|
|
slider.val.value = currentValue;
|
|
|
|
slider.label = parameter;
|
|
|
|
slider.on("value", function(val){
|
|
|
|
val = Math.pow(val, exp);
|
|
|
|
var scaledVal = nx.scale(val, 0, 1, min, max);
|
|
|
|
if (isTone){
|
|
|
|
node[parameter].value = scaledVal;
|
|
|
|
} else {
|
|
|
|
node[parameter] = scaledVal;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
slider.draw();
|
|
|
|
slider.listen = function(){
|
2015-02-13 20:23:30 +00:00
|
|
|
function update(){
|
|
|
|
var val = node[parameter];
|
|
|
|
if (isTone){
|
|
|
|
val = node[parameter].value;
|
|
|
|
}
|
|
|
|
val = nx.scale(val, min, max, 0, 1);
|
|
|
|
val = Math.pow(val, 1/exp);
|
|
|
|
if (val !== slider.val.value){
|
|
|
|
slider.val.value = val;
|
|
|
|
slider.draw();
|
|
|
|
}
|
2015-02-12 03:39:28 +00:00
|
|
|
}
|
2015-02-13 20:23:30 +00:00
|
|
|
Interface._updateList.push(update);
|
2015-02-13 20:43:20 +00:00
|
|
|
return slider;
|
|
|
|
};
|
|
|
|
slider.name = function(label){
|
|
|
|
slider.label = label;
|
|
|
|
slider.draw();
|
|
|
|
return slider;
|
2015-02-12 03:39:28 +00:00
|
|
|
};
|
|
|
|
return slider;
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.Slider = function(container, node, parameter, min, max, exp){
|
|
|
|
return Interface.ContinuousControl(container, "slider", node, parameter, min, max, exp);
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.HorizontalSlider = function(container, node, parameter, min, max, exp){
|
|
|
|
var slider = Interface.Slider(container, node, parameter, min, max, exp);
|
|
|
|
$(slider.canvas).addClass("HorizontalSlider");
|
|
|
|
return slider;
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.Code = function(container, codeID){
|
|
|
|
Interface.Rack(container, "Code", true);
|
2015-02-20 05:59:19 +00:00
|
|
|
var element = Interface.getElement(container);
|
2015-02-12 03:39:28 +00:00
|
|
|
var codeContainer = $("<code>").addClass("language-javascript Code");
|
|
|
|
element.append(codeContainer);
|
2015-02-20 05:59:19 +00:00
|
|
|
var code = Interface.getElement(codeID);
|
2015-02-12 03:39:28 +00:00
|
|
|
var codeText = code.text();
|
|
|
|
var lines = codeText.split("\n");
|
|
|
|
//remove the same level of indentation for everyone
|
|
|
|
while(lines[1].charAt(0)==="\t"){
|
|
|
|
for (var i = 0; i < lines.length; i++){
|
|
|
|
var line = lines[i];
|
|
|
|
lines[i] = line.substr(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
codeText = lines.join("\n");
|
|
|
|
codeContainer.text(codeText);
|
|
|
|
codeContainer.addClass("Code");
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.Knob = function(container, node, parameter, min, max, exp){
|
|
|
|
return Interface.ContinuousControl(container, "dial", node, parameter, min, max, exp);
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.Momentary = function(container, callback){
|
|
|
|
var button = nx.add("button", {
|
|
|
|
"parent" : container
|
|
|
|
});
|
|
|
|
button.on("press", function(val){
|
|
|
|
callback(val === 1);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.AmplitudeEnvelope = function(container, node){
|
2015-02-20 05:59:19 +00:00
|
|
|
var element = Interface.getElement(container, "Amplitude");
|
2015-02-12 03:39:28 +00:00
|
|
|
var group = $("<div>").addClass("Envelope")
|
|
|
|
.appendTo(element);
|
2015-02-20 05:59:19 +00:00
|
|
|
var attack = Interface.Slider(group, node, "attack", 0.001, 2, 2);
|
|
|
|
var decay = Interface.Slider(group, node, "decay", 0.0, 2, 2);
|
|
|
|
var sustain = Interface.Slider(group, node, "sustain", 0, 1, 2);
|
|
|
|
var release = Interface.Slider(group, node, "release", 0.001, 4, 2);
|
|
|
|
// var labels = $("<div>").attr("id", "Labels")
|
|
|
|
// .appendTo(group);
|
|
|
|
// $("<div>").appendTo(labels).addClass("Label").text("attack");
|
|
|
|
// $("<div>").appendTo(labels).addClass("Label").text("decay");
|
|
|
|
// $("<div>").appendTo(labels).addClass("Label").text("sustain");
|
|
|
|
// $("<div>").appendTo(labels).addClass("Label").text("release");
|
2015-02-12 03:39:28 +00:00
|
|
|
|
|
|
|
return {
|
|
|
|
listen : function(){
|
|
|
|
attack.listen();
|
|
|
|
decay.listen();
|
|
|
|
release.listen();
|
|
|
|
sustain.listen();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-02-20 05:59:19 +00:00
|
|
|
Interface.FilterEnvelope = function(container, node){
|
2015-02-24 03:14:51 +00:00
|
|
|
var element = Interface.getElement(container, "Filter");
|
|
|
|
var group = $("<div>").addClass("Envelope FilterEnvelope")
|
|
|
|
.appendTo(element);
|
|
|
|
var attack = Interface.Slider(group, node, "attack", 0.001, 2, 2);
|
|
|
|
var decay = Interface.Slider(group, node, "decay", 0.0, 2, 2);
|
|
|
|
var sustain = Interface.Slider(group, node, "sustain", 0, 1, 2);
|
|
|
|
var release = Interface.Slider(group, node, "release", 0.001, 4, 2);
|
2015-02-20 05:59:19 +00:00
|
|
|
// var freqGroup = $("<div>").appendTo(element).addClass("FreqGroup");
|
2015-02-24 03:14:51 +00:00
|
|
|
var minSlider = Interface.Slider(group, node, "min", 20, 20000, 2);
|
|
|
|
var maxSlider = Interface.Slider(group, node, "max", 20, 20000, 2);
|
2015-02-20 05:59:19 +00:00
|
|
|
return {
|
|
|
|
listen : function(){
|
2015-02-24 03:14:51 +00:00
|
|
|
attack.listen();
|
|
|
|
decay.listen();
|
|
|
|
release.listen();
|
|
|
|
sustain.listen();
|
2015-02-20 05:59:19 +00:00
|
|
|
maxSlider.listen();
|
|
|
|
minSlider.listen();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.Filter = function(containerID, node){
|
|
|
|
var element = $("<div>").addClass("Filter")
|
|
|
|
.appendTo(Interface.getElement(containerID));
|
|
|
|
|
2015-02-24 03:14:51 +00:00
|
|
|
|
2015-02-20 05:59:19 +00:00
|
|
|
};
|
|
|
|
|
2015-02-12 03:39:28 +00:00
|
|
|
Interface.Loading = function(containerID, callback){
|
2015-02-20 05:59:19 +00:00
|
|
|
var element = Interface.getElement(containerID);
|
2015-02-12 03:39:28 +00:00
|
|
|
element.addClass("LoadingBar");
|
|
|
|
var loader = $("<div>").appendTo(element)
|
|
|
|
.attr("id", "Loader");
|
|
|
|
Tone.Buffer.onprogress = function(percent){
|
|
|
|
loader.width((percent * 100) + "%");
|
|
|
|
};
|
|
|
|
Tone.Buffer.onload = function(){
|
|
|
|
element.css({
|
|
|
|
height: 0,
|
|
|
|
opacity : 0,
|
|
|
|
margin: 0
|
|
|
|
});
|
|
|
|
setTimeout(function(){
|
|
|
|
element.remove();
|
|
|
|
}, 500);
|
|
|
|
if (callback){
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
Interface.Range = function(containerID, callback){
|
|
|
|
var range = nx.add("range", {
|
|
|
|
"parent" : containerID
|
|
|
|
});
|
|
|
|
range.label = "";
|
|
|
|
range.on("*", callback);
|
|
|
|
return range;
|
|
|
|
};
|
2015-02-13 15:52:50 +00:00
|
|
|
|
|
|
|
Interface.Meter = function(container, node, label, units){
|
|
|
|
var meter = new Tone.Meter();
|
|
|
|
node.connect(meter);
|
2015-02-20 05:59:19 +00:00
|
|
|
var element = $("<div>").appendTo(Interface.getElement(container))
|
2015-02-13 15:52:50 +00:00
|
|
|
.addClass("Meter");
|
|
|
|
label = label || "";
|
|
|
|
units = units || "";
|
|
|
|
$("<div>").appendTo(element)
|
|
|
|
.text(label)
|
|
|
|
.attr("id", "Label");
|
|
|
|
var value = $("<div>").appendTo(element)
|
|
|
|
.attr("id", "Value");
|
|
|
|
$("<div>").appendTo(element)
|
|
|
|
.text(units)
|
|
|
|
.attr("id", "Units");
|
|
|
|
function update(){
|
|
|
|
requestAnimationFrame(update);
|
|
|
|
value.text(meter.getValue().toFixed(3));
|
|
|
|
}
|
|
|
|
update();
|
|
|
|
};
|
2015-02-24 17:03:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
Interface.StepSequencer = function(container, width, height){
|
|
|
|
var element = Interface.getElement(container);
|
|
|
|
element.addClass("StepSequencer");
|
|
|
|
var matrix = nx.add("matrix", {
|
|
|
|
"parent" : element,
|
|
|
|
});
|
|
|
|
matrix.row = height;
|
|
|
|
matrix.col = width;
|
|
|
|
matrix.init();
|
|
|
|
matrix.draw();
|
|
|
|
return {
|
|
|
|
randomize : function(){
|
|
|
|
var boxes = [];
|
|
|
|
for (var i = 0; i < width; i++){
|
|
|
|
var row = [];
|
|
|
|
for (var j = 0; j < height; j++){
|
|
|
|
row.push(Math.round(Math.random()));
|
|
|
|
}
|
|
|
|
boxes.push(row);
|
|
|
|
}
|
|
|
|
// console.log(boxes);
|
|
|
|
// debugger;
|
|
|
|
matrix.matrix = boxes;
|
|
|
|
matrix.draw();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|