");
var tb = $("").appendTo(t);
var ksmps = 64;
var tr = $("
").appendTo(tb);
$("
").text("FFT size").appendTo(tr);
var fftSize = $("").change(function(){
updateDecimation();
});
$("
").appendTo(tr).append(fftSize);
for (let o of [256, 512, 1024, 2048]) {
$("").val(o).text(o).appendTo(fftSize);
}
tr = $("
").appendTo(tb);
$("
").text("FFT decimation").appendTo(tr);
var fftDecim = $("");
$("
").appendTo(tr).append(fftDecim);
function updateDecimation() {
fftDecim.empty();
var max = fftSize.val() / 64;
var min = max / 2;
for (let o of [min, max]) {
$("").val(o).text(o).appendTo(fftDecim);
}
}
twirl.prompt.show(t, function() {
onComplete(fftSize.val(), fftDecim.val());
});
fftSize.val(512);
updateDecimation();
};
function addActionMenu(menu, item) {
for (let i in twigsTopMenuData) {
if (twigsTopMenuData[i].name.toLowerCase() == menu.toLowerCase()) {
twigsTopMenuData[i].contents.push(item);
}
}
}
var zoomIcons = [
{
label: "Zoom in frequency",
icon: "zoomIn",
size: 20,
click: function() {
twigs.vzoomIn();
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_vzoom"
},
{
label: "Zoom out frequency",
icon: "zoomOut",
size: 20,
click: function() {
twigs.vzoomOut();
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_vzoom"
},
{
label: "Show all frequency",
icon: "showAll",
size: 20,
click: function() {
twigs.setFrequencyRegion(0, 1);
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_vzoom"
},
{
label: "Zoom in time",
icon: "zoomIn",
size: 20,
click: function() {
twigs.hzoomIn();
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_hzoom"
},
{
label: "Zoom out time",
icon: "zoomOut",
size: 20,
click: function() {
twigs.hzoomOut();
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_hzoom"
},
{
label: "Show all time",
icon: "showAll",
size: 20,
click: function() {
twigs.setTimeRegion(0, 1);
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_hzoom"
},
{
label: "Show all",
icon: "showAll",
size: 20,
click: function() {
twigs.setFrequencyRegion(0, 1, true);
twigs.setTimeRegion(0, 1);
},
shortcut: {name: "W", key: "w"},
menuAdd: "view",
target: "#twigs_editor_hzoom"
}
];
this.showAbout = function() {
var el = $("");
var x = $("").appendTo(el);
var string = "twigs";
var intervals = [];
function addChar(c) {
var elC = $("").text(c).css("display", "inline-block").appendTo(x);
var rate = (Math.random() * 0.005) + 0.001;
var scale = 1;
var scaleDirection = false;
return setInterval(function(){
if (scaleDirection) {
if (scale < 1) {
scale += rate;
} else {
scaleDirection = false;
}
} else {
if (scale > 0.05) {
scale -= rate;
} else {
scaleDirection = true;
}
}
elC.css("transform", "scaleX(" + scale + ")");
}, (Math.random() * 10) + 8);
}
for (let c of string) {
intervals.push(addChar(c));
}
$("").text("Version " + twigs.version.toFixed(1)).appendTo(el);
$("").css("font-size", "12px").text("By Richard Knight 2024").appendTo(el);
twirl.prompt.show(el, function(){
for (let i of intervals) clearInterval(i);
});
};
this.showSettings = function() {
var settings = [
{
name: "Undo levels",
description: "Number of undo levels stored. Large numbers may affect memory usage",
min: 0, max: 32, step: 1, dfault: 2, storageKey: "maxundo",
onChange: function(val) {
app.setControlChannel("twgs_maxundo", val);
}
},
{
name: "Resynthesis type",
description: "Type of resynthesis to be used",
options: ["Overlap-add", "Additive"],
dfault: 0,
storageKey: "resynthType"
},
{
name: "Colour type",
description: "Type of colouration to use in graphing",
options: ["Monochrome", "Colour"],
dfault: 0,
storageKey: "colourType",
onChange: function() {
twigs.redraw();
}
},
{
name: "Graph type",
description: "Approach to graphing partials used",
options: ["Joined line", "Separate lines"],
dfault: 0,
storageKey: "graphType",
onChange: function() {
twigs.redraw();
}
},
{
name: "Basic lines",
description: "Show thin, basic lines in graphing",
bool: true,
dfault: 0,
storageKey: "basicLines",
onChange: function() {
twigs.redraw();
}
},
{
name: "Frequency gridlines",
description: "Draw the vertical frequency grid",
bool: true,
dfault: 1,
storageKey: "drawFrequencyGrid",
onChange: function() {
twigs.redraw();
}
},
{
name: "Time gridlines",
description: "Draw the horizontal time grid",
bool: true,
dfault: 1,
storageKey: "drawTimeGrid",
onChange: function() {
twigs.redraw();
}
},
{
name: "Zoom to start on load",
description: "Zoom to the start portion of time and frequency when loading a new file",
bool: true,
dfault: 1,
storageKey: "zoomOnLoad"
}
];
twirl.showSettings(twigs, settings);
};
var icon_groups = {};
ui.setSelectionMode = function(mode, iconObj) {
for (let s of icon_groups.selection) s.setActive(false);
iconObj.setActive(true);
elEditor.css("cursor", iconObj.definition.cursor);
twigs.setSelectionMode(mode);
}
function setOptionsArea(el) {
var o = $("#twigs_options").empty();
if (el) o.append(el);
}
ui.icons = {};
var icons = [
[{
label: "Select single bin",
icon: "pointer",
shortcut: {name: "Q", key: "q"},
menuAdd: "action",
group: "selection",
cursor: "default",
bgColor: 1,
clickOnInactive: true,
click: function(obj) {
ui.setSelectionMode(twigs.SELECTIONMODE.singleBin, obj);
}
},
{
label: "Select area",
icon: "areaSelect",
shortcut: {name: "W", key: "w"},
menuAdd: "action",
group: "selection",
cursor: "crosshair",
bgColor: 1,
clickOnInactive: true,
click: function(obj) {
ui.setSelectionMode(twigs.SELECTIONMODE.dragArea, obj);
}
}],
[{
label: "Select bins",
icon: "verticalArrows",
shortcut: {name: "A", key: "a"},
menuAdd: "action",
group: "selection",
cursor: "vertical-text",
bgColor: 1,
clickOnInactive: true,
click: function(obj) {
ui.setSelectionMode(twigs.SELECTIONMODE.dragBins, obj);
}
},
{
label: "Free select",
icon: "lasso",
shortcut: {name: "S", key: "s"},
menuAdd: "action",
group: "selection",
cursor: "crosshair",
bgColor: 1,
clickOnInactive: true,
click: function(obj) {
ui.setSelectionMode(twigs.SELECTIONMODE.lasso, obj);
}
}],
[{
label: "Bin append select",
icon: "waves",
shortcut: {name: "Z", key: "z"},
menuAdd: "action",
group: "selection",
cursor: "copy",
bgColor: 1,
clickOnInactive: true,
click: function(obj) {
ui.setSelectionMode(twigs.SELECTIONMODE.binAppend, obj);
}
},
{
label: "Play selection",
icon: "ear",
shortcut: {name: "X", key: "x"},
menuAdd: "action",
bgColor: 2,
click: function(obj) {
twigs.play(true);
}
}],
[{
label: "Move",
icon: "move",
shortcut: {name: "E", key: "e"},
menuAdd: "action",
group: "selection",
cursor: "grab",
bgColor: 3,
clickOnInactive: true,
click: function(obj) {
ui.setSelectionMode(twigs.SELECTIONMODE.move, obj);
},
optionsArea: function() {
if (!twigs.storage.movementType) twigs.storage.movementType = 2;
if (!twigs.storage.interpolateVoid) twigs.storage.interpolateVoid = 1;
if (!twigs.storage.interpolateRatio) twigs.storage.interpolateRatio = 0;
var el = $("");
var typeOptions = new twirl.transform.Transform({host: twigs, element: el, definition: {
name: "Movement",
instr: "twgs_movement",
parameters: [
{name: "Movement type", description: "Type of movement to apply", channel: "twgs_movementtype", absolutechannel: true, options: ["Copy", "Leave void", "Retain amp/freq in void", "Retain amp in void", "Retain freq in void"], automatable: false, dfault: twigs.storage.movementType, onChange: function(val){
twigs.storage.movementType = val;
twigs.saveStorage();
}},
{name: "Interpolate void", description: "Interpolate values in the void created by the movement", channel: "twgs_interpolatevoid", absolutechannel: true, min: 0, max: 1, step: 1, automatable: false, dfault: twigs.storage.interpolateVoid, onChange: function(val){
twigs.storage.interpolateVoid = val;
twigs.saveStorage();
}, conditions: [{channel: "twgs_movementtype", absolutechannel: true, operator: "ge", value: 2}]},
{name: "Interpolation ratio", description: "Ratio of interpolation to integrate with target position", channel: "twgs_interpolateratio", absolutechannel: true, min: 0, max: 0.45, automatable: false, dfault: twigs.storage.interpolateRatio, onChange: function(val){
twigs.storage.interpolateRatio = val;
twigs.saveStorage();
}}
]
}});
return el;
}
},
{
label: "Transpose",
icon: "arrowsUpDown",
shortcut: {name: "R", key: "r"},
menuAdd: "action",
group: "selection",
cursor: "row-resize",
bgColor: 3,
clickOnInactive: true,
click: function(obj) {
setSelectionMode(twigs.SELECTIONMODE.transpose, obj);
}
}],
[{
label: "Amplify",
icon: "fileVolume",
shortcut: {name: "D", key: "d"},
menuAdd: "action",
bgColor: 3,
click: function(obj) {
if (!twigs.hasSelection) return;
var el = $("");
$("").text("Amplitude scale").appendTo(el);
var amp = $("").attr("type", "range").attr("max", 10).attr("min", 0).attr("step", 0.000001).val(1).appendTo(el);
twirl.prompt.show(el, function(){
twigs.selectionOperation.amplify(amp.val());
});
}
},
{
label: "Draw",
icon: "pencil",
shortcut: {name: "F", key: "f"},
menuAdd: "action",
group: "selection",
cursor: "row-resize",
bgColor: 3,
clickOnInactive: true,
click: function(obj) {
setSelectionMode(twigs.SELECTIONMODE.draw, obj);
}
}],
[{
label: "Play",
icon: "play",
shortcut: {name: "Space", key: "space"},
menuAdd: "action",
bgColor: 2,
click: function(obj) {
twigs.play();
}
},
{
label: "Stop",
icon: "stop",
bgColor: 2,
click: function(obj) {
twigs.stop();
}
}],
[{
label: "Zoom in amplitude",
icon: "brightnessIncrease",
shortcut: {name: "C", key: "c"},
menuAdd: "action",
bgColor: 1,
click: function(obj) {
twigs.increaseAmpScaling();
}
},
{
label: "Zoom out amplitude",
icon: "brightnessDecrease",
shortcut: {name: "V", key: "v"},
menuAdd: "action",
bgColor: 1,
click: function(obj) {
twigs.decreaseAmpScaling();
}
}]
];
function addIcon(def) {
let ops = {};
Object.assign(ops, def);
if (ops.shortcut) {
ops.label += " (" + ops.shortcut.name + ")";
}
ops.click = function(obj) {
def.click(obj);
if (def.optionsArea) {
setOptionsArea(def.optionsArea())
} else {
setOptionsArea();
}
}
let icon = twirl.createIcon(ops);
if (ops.menuAdd) {
let menuData = {
name: ops.label,
click: function() {
icon.el.click();
}
};
if (ops.shortcut) {
menuData.shortcut = ops.shortcut;
}
addActionMenu(ops.menuAdd, menuData);
}
return icon;
}
function create() {
for (let z of zoomIcons) {
var icon = addIcon(z);
$(z.target).append(icon.el);
}
var tb = $("").appendTo($("
").appendTo(el));
var icol = 0;
var first;
for (let row of icons) {
var tr = $("
").appendTo(tb);
for (let col of row) {
let icon = addIcon(col);
if (!first) first = icon;
if (col.group) {
if (!icon_groups[col.group]) icon_groups[col.group] = [];
icon_groups[col.group].push(icon);
}
var td = $("
").append(icon.el).appendTo(tr);
if (col.bgColor) {
td.css("background-color", "var(--bgColor" + col.bgColor + ")");
}
icons[col.key] = icon;
}
}
first.click();
}
create();
var topMenu = new twirl.TopMenu(twigs, twigsTopMenuData, $("#twigs_menubar"));
};