gun/lib/wave.js
2020-11-23 13:09:21 +02:00

1749 lines
49 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Create music from text.
* examples/wave.html
*
* Music Makers is an application using the same libraries as Wave:
* https://github.com/jussiry/musicmakers
* http://edide.xyz/musicmakers.app
* https://edide.io/musicmakers.app
*/
"use strict";
(function(){
var MODSELF, edide = {};
edide.global = (function (edide, mod_global) {
return typeof global !== 'undefined' ? global : window;
}).call(MODSELF={}, edide, MODSELF);
edide.set = (function (edide, set) {Object.defineProperty(this, 'module_name', {value:'set'});
set = (...args) => new Set(args)
set.addArr = (s, arr) => {
var i, len
for (i = 0, len = arr.length; i < len; i++) {
s.add(arr[i])
}
}
set.map = (s, func) => Array.from(s).map(func)
return set;
}).call(MODSELF={}, edide, MODSELF);
edide.membrameSynth = (function (edide, membrameSynth) {Object.defineProperty(this, 'module_name', {value:'membrameSynth'});
this.startNote = 'A0';
this.init = () => {
var bd, compressor, distortion, gain, reverb;
distortion = new Tone.Distortion({
distortion: 0.1,
oversample: "4x" // none, 2x, 4x
});
reverb = new Tone.Freeverb(0.75, 1000);
gain = new Tone.Gain(0.5);
compressor = new Tone.Compressor({
ratio: 12,
threshold: -24,
release: 0.05,
attack: 0.003,
knee: 1
});
bd = new Tone.MembraneSynth({
pitchDecay: 0.05,
octaves: 4,
envelope: {
attack: 0.01,
decay: 0.74,
sustain: 0.71,
release: 0.05,
attackCurve: "exponential"
}
});
bd.chain(gain, distortion, reverb, compressor);
return [bd, compressor];
};
return membrameSynth;
}).call(MODSELF={}, edide, MODSELF);
edide.toneSynth = (function (edide, toneSynth) {Object.defineProperty(this, 'module_name', {value:'toneSynth'});
this.startNote = 'C3';
this.init = () => {
var ss;
return ss = new Tone.PolySynth(12, Tone.Synth, {
oscillator: {
type: 'sine'
},
envelope: {
attack: 0.005,
decay: 0.1,
sustain: 0.3,
release: 1
}
});
};
return toneSynth;
}).call(MODSELF={}, edide, MODSELF);
edide.instrumentConfigs = (function (edide, instrumentConfigs) {
var configs = {
'bass-electric': {
startNote: 'C#2',
notes: 8, // 16
step: 3
},
'cello': {
startNote: 'C2',
notes: 11,
step: 2,
skipNotes: edide.set('F#2', 'C4')
},
'drum-electric': edide.membrameSynth,
'guitar-acoustic': {
startNote: 'D1',
notes: 26, // 36
step: 2,
skipNotes: edide.set('E4', 'F#4', 'G#4', 'A#4', 'C5', 'D5', 'E5')
},
'guitar-electric': {
startNote: 'F#2',
notes: 15, // 15
step: 3,
},
'piano': {
startNote: 'A1',
notes: 30, // 29
step: 2,
baseUrl: "https://tonejs.github.io/examples/audio/salamander/"
},
'synth-simple': edide.toneSynth,
'xylophone': {
startNote: 'G3',
notes: ['G3', 'C4', 'G4', 'C5', 'G5', 'C6', 'G6', 'C7']
}
}
for (let inst in configs) {
configs[inst].name = inst
}
return configs
}).call(MODSELF={}, edide, MODSELF);
edide.objectFromArray = (function (edide, objectFromArray) {
var identity;
identity = function(el) {
return el;
};
return (array, valFromEl, keyFromEl) => {
var el, i, ind, len, obj;
if (valFromEl == null) {
valFromEl = identity;
}
if (keyFromEl == null) {
keyFromEl = identity;
}
obj = {};
for (ind = i = 0, len = array.length; i < len; ind = ++i) {
el = array[ind];
obj[keyFromEl(el, ind)] = valFromEl(el, ind);
}
return obj;
};
}).call(MODSELF={}, edide, MODSELF);
edide.noteFreq = (function (edide, noteFreq) {Object.defineProperty(this, 'module_name', {value:'noteFreq'});
var a4, noteMap, notesObj;
this.notes = [['C0', 16.35, 2109.89], ['C#0', 17.32, 1991.47], ['D0', 18.35, 1879.69], ['D#0', 19.45, 1774.20], ['E0', 20.60, 1674.62], ['F0', 21.83, 1580.63], ['F#0', 23.12, 1491.91], ['G0', 24.50, 1408.18], ['G#0', 25.96, 1329.14], ['A0', 27.50, 1254.55], ['A#0', 29.14, 1184.13], ['B0', 30.87, 1117.67], ['C1', 32.70, 1054.94], ['C#1', 34.65, 995.73], ['D1', 36.71, 939.85], ['D#1', 38.89, 887.10], ['E1', 41.20, 837.31], ['F1', 43.65, 790.31], ['F#1', 46.25, 745.96], ['G1', 49.00, 704.09], ['G#1', 51.91, 664.57], ['A1', 55.00, 627.27], ['A#1', 58.27, 592.07], ['B1', 61.74, 558.84], ['C2', 65.41, 527.47], ['C#2', 69.30, 497.87], ['D2', 73.42, 469.92], ['D#2', 77.78, 443.55], ['E2', 82.41, 418.65], ['F2', 87.31, 395.16], ['F#2', 92.50, 372.98], ['G2', 98.00, 352.04], ['G#2', 103.83, 332.29], ['A2', 110.00, 313.64], ['A#2', 116.54, 296.03], ['B2', 123.47, 279.42], ['C3', 130.81, 263.74], ['C#3', 138.59, 248.93], ['D3', 146.83, 234.96], ['D#3', 155.56, 221.77], ['E3', 164.81, 209.33], ['F3', 174.61, 197.58], ['F#3', 185.00, 186.49], ['G3', 196.00, 176.02], ['G#3', 207.65, 166.14], ['A3', 220.00, 156.82], ['A#3', 233.08, 148.02], ['B3', 246.94, 139.71], ['C4', 261.63, 131.87], ['C#4', 277.18, 124.47], ['D4', 293.66, 117.48], ['D#4', 311.13, 110.89], ['E4', 329.63, 104.66], ['F4', 349.23, 98.79], ['F#4', 369.99, 93.24], ['G4', 392.00, 88.01], ['G#4', 415.30, 83.07], ['A4', 440.00, 78.41], ['A#4', 466.16, 74.01], ['B4', 493.88, 69.85], ['C5', 523.25, 65.93], ['C#5', 554.37, 62.23], ['D5', 587.33, 58.74], ['D#5', 622.25, 55.44], ['E5', 659.25, 52.33], ['F5', 698.46, 49.39], ['F#5', 739.99, 46.62], ['G5', 783.99, 44.01], ['G#5', 830.61, 41.54], ['A5', 880.00, 39.20], ['A#5', 932.33, 37.00], ['B5', 987.77, 34.93], ['C6', 1046.50, 32.97], ['C#6', 1108.73, 31.12], ['D6', 1174.66, 29.37], ['D#6', 1244.51, 27.72], ['E6', 1318.51, 26.17], ['F6', 1396.91, 24.70], ['F#6', 1479.98, 23.31], ['G6', 1567.98, 22.00], ['G#6', 1661.22, 20.77], ['A6', 1760.00, 19.60], ['A#6', 1864.66, 18.50], ['B6', 1975.53, 17.46], ['C7', 2093.00, 16.48], ['C#7', 2217.46, 15.56], ['D7', 2349.32, 14.69], ['D#7', 2489.02, 13.86], ['E7', 2637.02, 13.08], ['F7', 2793.83, 12.35], ['F#7', 2959.96, 11.66], ['G7', 3135.96, 11.00], ['G#7', 3322.44, 10.38], ['A7', 3520.00, 9.80], ['A#7', 3729.31, 9.25], ['B7', 3951.07, 8.73], ['C8', 4186.01, 8.24], ['C#8', 4434.92, 7.78], ['D8', 4698.63, 7.34], ['D#8', 4978.03, 6.93], ['E8', 5274.04, 6.54], ['F8', 5587.65, 6.17], ['F#8', 5919.91, 5.83], ['G8', 6271.93, 5.50], ['G#8', 6644.88, 5.19], ['A8', 7040.00, 4.90], ['A#8', 7458.62, 4.63], ['B8', 7902.13, 4.37]];
notesObj = null;
noteMap = () => {
if (notesObj) {
return notesObj;
}
return notesObj = edide.objectFromArray(this.notes, (val, ind) => {
return [ind, ...val];
}, (key) => {
return key[0];
});
};
this.findNote = (name) => {
return noteMap()[name];
};
a4 = this.findNote('A4');
this.diffToA4 = (name) => {
var note;
note = this.findNote(name);
return note[0] - a4[0];
};
this.diff = (n1, n2) => {
return this.findNote(n2)[0] - this.findNote(n1)[0];
};
return noteFreq;
}).call(MODSELF={}, edide, MODSELF);
edide.strRandom = (function (edide, strRandom) {
return (limit = 20) => {
return (Math.random() + '').slice(2, +(limit + 1) + 1 || 9e9);
};
}).call(MODSELF={}, edide, MODSELF);
edide.inEditor = (function (edide, inEditor) {Object.defineProperty(this, 'module_name', {value:'inEditor'});
inEditor = (inEditor === true) || false
return inEditor;
}).call(MODSELF={}, edide, MODSELF);
edide.edideNamespace = (function (edide, edideNamespace) {
return 'edide'
}).call(MODSELF={}, edide, MODSELF);
edide.edideNs = (function (edide, edideNs) {
var base, name;
return (base = edide.global)[name = edide.edideNamespace] != null ? base[name] : base[name] = {};
}).call(MODSELF={}, edide, MODSELF);
edide.editorModule = (function (edide, editorModule) {
var editorModule;
editorModule = edide.inEditor ? edide.edideNs : null;
return editorModule;
}).call(MODSELF={}, edide, MODSELF);
edide.keep = (function (edide, keep) {Object.defineProperty(this, 'module_name', {value:'keep'});
var keep;
keep = (prop) => {
return prop;
};
return keep;
}).call(MODSELF={}, edide, MODSELF);
edide.logProd = (function (edide, logProd) {
return (...args) => {
var console, ref, ref1;
console = (ref = (ref1 = edide.editorModule) != null ? ref1.console : void 0) != null ? ref : edide.global.console;
return console.log(...args);
};
}).call(MODSELF={}, edide, MODSELF);
edide.onUnload = (function (edide, onUnload) {
var ref, ref1;
return (ref = (ref1 = edide.editorModule) != null ? ref1.unload.add : void 0) != null ? ref : () => {};
}).call(MODSELF={}, edide, MODSELF);
edide.var = (function (edide, mod_var) {
var clearVar, currentReact, debugging, dependees, dependsOn, depsRequired, inInitCall, infinityCheck, initSetter, loopLimit, newVar, parent, setLinks, setters, updateVar, values;
values = edide.keep(new Map); // #edide.keep if clearVar added again..
setters = edide.keep(new Map); // varName => setter:func
dependees = edide.keep(new Map); // varName => deps:
setLinks = edide.keep(new Map); // for reactiveGraph, show setters inside reactive/setter:s
debugging = false; //edide.editorModule?
depsRequired = new Map; // varName : dependsOn
inInitCall = false; // TODO use dependsOn? instead
dependsOn = new Set(); // remove
initSetter = (name, setter) => {
var debugName, err, parent, ref, val;
debugName = (ref = setter.type) != null ? ref : name;
if ((setters.get(name)) != null) {
throw Error(`Reactive for '${debugName}' already exists`);
}
setters.set(name, setter);
if (inInitCall) {
throw Error(`can't create reactive setter (for '${debugName}') inside reactive context`);
}
inInitCall = name;
dependsOn.clear(); // TODO clear => new Set
try {
val = setter(); // TODO: some day add revar and unvar as params; helps with multiple reactives to keep the separated
} catch (error) {
err = error;
inInitCall = false;
err.message = `Reactive initialization of '${debugName}' failed: ${err.message}`;
throw err;
}
parent = null;
dependsOn.forEach((depName) => {
var deps;
if ((deps = dependees.get(depName)) == null) {
dependees.set(depName, deps = new Set);
}
return deps.add(name);
});
inInitCall = false;
return val;
};
loopLimit = 0;
infinityCheck = new Map; //edide.keep
parent = null;
updateVar = function(name, val) {
var ref, ref1, type;
if (arguments.length === 1) { //unless val?
val = setters.get(name)();
if (debugging && (type = setters.get(name).type)) {
edide.logProd(`running ${(setters.get(name).type)}`);
}
}
if (typeof name !== 'string') { // symbol ~ react function
return;
}
if (values.get(name) === val && typeof val !== 'object') {
return;
}
if (infinityCheck.get(name) > loopLimit) {
infinityCheck.forEach((k) => {
return edide.logProd(k);
});
edide.logProd(name);
if ((ref = edide.editorModule) != null) {
if (typeof ref.reactiveGraph === "function") {
ref.reactiveGraph();
}
}
throw Error("Inifinite loop in \:var dependencies");
}
if (debugging) {
edide.logProd(`updating ${name}`);
}
values.set(name, val);
if (!inInitCall) {
infinityCheck.set(name, (infinityCheck.get(name) || 0) + 1);
if ((ref1 = dependees.get(name)) != null) {
ref1.forEach((depName) => {
return updateVar(depName);
});
}
infinityCheck.delete(name);
}
return val;
};
currentReact = [];
newVar = function(name, setter) {
var context, contextSet, err;
if (arguments.length === 1) {
if (typeof name === 'string') {
if (inInitCall) {
dependsOn.add(name);
edide.onUnload(() => {
return clearVar(name); // TODO make specific clear?
});
}
return values.get(name);
} else {
setter = name;
name = Symbol();
values.set(name, name); // for debugging (showing react/dom funcs in graph)
edide.onUnload(() => {
return clearVar(name); // TODO make specific clear?
});
}
}
if (currentReact.length) { // and debugging
context = currentReact[currentReact.length - 1];
if (!(contextSet = setLinks.get(context))) {
setLinks.set(context, contextSet = new Set);
}
contextSet.add(name);
}
currentReact.push(name);
if (values.get(name) == null) {
edide.onUnload(() => {
return clearVar(name);
});
}
if (typeof setter === 'function') {
setter = initSetter(name, setter); // setter becomes value
}
if (typeof name === 'string') {
try {
updateVar(name, setter);
} catch (error) {
err = error;
infinityCheck.clear();
throw err;
}
}
currentReact.pop();
return setter;
};
clearVar = (name) => {
var i, len, map, ref;
ref = [values, setters, dependees, setLinks];
for (i = 0, len = ref.length; i < len; i++) {
map = ref[i];
map.delete(name);
}
};
Object.assign(newVar, {dependees, values, setters, setLinks});
return newVar;
}).call(MODSELF={}, edide, MODSELF);
edide.reactiveWithFilters = (function (edide, reactiveWithFilters) {
return (initialVars = {}, filters = {}) => {
var handler, id, key, react, revar, todoMap, unvar, val;
id = edide.strRandom();
handler = {
get: (map, prop) => {
var ref;
if ((ref = edide.editorModule) != null ? ref.editor_inspector.inspectingNow : void 0) {
console.log('IN inspector? Find out is it possible to end up here form inside setter');
return edide.var.values.get(`${id}.${prop}`);
}
return edide.var(`${id}.${prop}`);
},
set: (map, prop, value) => {
if ((filters[prop] != null) && !filters[prop](value)) {
throw Error(`Illegal reactive (${prop}: ${value})`);
}
edide.var(`${id}.${prop}`, value);
return true; // Proxy set must return true if set is successfull; In the future use Reflect.set, which returns true automatically?
}
};
revar = new Proxy((todoMap = new Map), handler); // NOTE: map is not used yet
unvar = new Proxy(todoMap, {
get: (map, prop) => {
return edide.var.values.get(`${id}.${prop}`);
},
set: (map, prop, value) => {
return edide.var.values.set(`${id}.${prop}`, value);
}
});
for (key in initialVars) {
val = initialVars[key];
revar[key] = val;
}
react = (nameOrFunc, func) => {
if (func != null) {
func.type = nameOrFunc;
} else {
func = nameOrFunc;
func.type = 'react'; // for debugging
}
return edide.var(func);
};
return {
react,
revar,
unvar,
un: unvar,
re: revar // , dom
};
};
}).call(MODSELF={}, edide, MODSELF);
edide.mmState = (function (edide, mmState) {Object.defineProperty(this, 'module_name', {value:'mmState'});
var filters, instruments;
this.defaults = {
playing: false,
recorderOn: false,
fullSheet: '',
sheet: '', // selected/play part of fullSheet
diffText: '',
note: null, // currently playing note
// state properties
pace: 400, // -> bpm -> beatDelay
bpm: 400, // deprecate
beatDelay: (1 / 400) * 60 * 1000, // silly! unify with pace as one statestate variable
balance: 0,
volume: 0,
detune: 0,
blur: 0,
itch: 0,
instrumentsLoading: 0,
// dropdowns
instrument: 'guitar-electric',
scale: 'pentatonic',
root: 'C3',
highlight: null,
keyboardInd: 0 // TODO --> keyboard
};
instruments = Object.keys(edide.instrumentConfigs);
filters = {
scale: (val) => {
return ['pentatonic', 'minor', 'major'].includes(val);
},
instrument: (val) => {
return instruments.includes(val);
},
root: (val) => {
return edide.noteFreq.findNote(val);
}
};
this.react = null;
this.init = (startingProps = {}) => {
var props;
if (this.react != null) {
return this;
}
props = Object.assign({}, this.defaults, startingProps);
({react: this.react, revar: this.revar, unvar: this.unvar} = edide.reactiveWithFilters(props, filters));
return this;
};
return mmState;
}).call(MODSELF={}, edide, MODSELF);
edide.mmEffects = (function (edide, mmEffects) {Object.defineProperty(this, 'module_name', {value:'mmEffects'});
({revar: this.revar} = edide.mmState.init());
this.maxLowpass = 10000;
this.maxDistortion = 3;
this.revar.lowpass = () => {
var blur;
({blur} = this.revar);
return this.maxLowpass - blur * (this.maxLowpass - 200);
};
this.revar.distortion = () => {
var itch;
({itch} = this.revar);
return this.maxDistortion * itch;
};
return mmEffects;
}).call(MODSELF={}, edide, MODSELF);
edide.clone = (function (edide, clone) {
return (...objects) => {
if (Array.isArray(objects[0])) {
return Object.assign([], ...objects);
} else {
return Object.assign({}, ...objects);
}
};
}).call(MODSELF={}, edide, MODSELF);
edide.strParsesToNumber = (function (edide, strParsesToNumber) {Object.defineProperty(this, 'module_name', {value:'strParsesToNumber'});
var strParsesToNumber;
strParsesToNumber = (str) => {
return !Number.isNaN(parseInt(str));
};
return strParsesToNumber;
}).call(MODSELF={}, edide, MODSELF);
edide.mmConfigs = (function (edide, mmConfigs) {Object.defineProperty(this, 'module_name', {value:'mmConfigs'});
var defaultVars, mutatingProp, mutatingVars, stateVars, vars;
vars = {}; // varName: config object
mutatingVars = {};
stateVars = edide.set('itch', 'blur', 'instrument', 'bpm', 'pace', 'beatDelay', 'scale', 'root', 'balance', 'detune', 'volume');
this.hasVar = (varName) => {
var ref, ref1;
return !!((ref = (ref1 = vars[varName]) != null ? ref1 : mutatingVars[varName]) != null ? ref : stateVars.has(varName));
};
this.activateVar = (name, value) => {
var configs;
if (value != null) {
configs = stateVars.has(name) ? {
[`${name}`]: value
} : mutatingVars[name] != null ? edide.clone(mutatingVars[name]) : void 0;
if (edide.strParsesToNumber(value)) {
value = parseFloat(value);
}
configs[mutatingProp(configs)] = value;
return this.activate(configs);
} else {
return this.activate(vars[name]);
}
};
mutatingProp = (configs) => {
var name, val;
for (name in configs) {
val = configs[name];
if (val === '*') {
return name;
}
}
return false;
};
this.activate = (conf) => {
if (conf.name != null) {
return; // throw warning?
}
return Object.assign(edide.mmState.revar, conf);
};
this.reset = () => {
stateVars.forEach((name) => {
return edide.mmState.revar[name] = edide.mmState.defaults[name];
});
};
this.addVar = (varName, config) => { // , activate=true
if (mutatingProp(config)) {
return mutatingVars[varName] = config;
} else {
return vars[varName] = config;
}
};
defaultVars = {
bass: {
"instrument": "bass-electric"
},
cello: {
"instrument": "cello"
},
guitar: {
"instrument": "guitar-acoustic"
},
eguitar: {
"instrument": "guitar-electric"
},
piano: {
"instrument": "piano"
},
synth: {
"instrument": "synth-simple"
},
xylophone: {
"instrument": "xylophone"
},
pentatonic: {
"scale": "pentatonic"
},
major: {
"scale": "major"
},
minor: {
"scale": "minor"
}
};
this.init = () => {
var conf, name;
vars = {};
for (name in defaultVars) {
conf = defaultVars[name];
this.addVar(name, conf, false);
}
};
this.init();
return mmConfigs;
}).call(MODSELF={}, edide, MODSELF);
edide.setTimeout = (function (edide, mod_setTimeout) {
var nativeSetTimeout, ref;
nativeSetTimeout = edide.global.nativeSetTimeout = (ref = edide.global.nativeSetTimeout) != null ? ref : edide.global.setTimeout;
return function(arg1, arg2) {
var fun, id, num;
[fun, num] = typeof arg2 === 'function' ? [arg2, arg1] : [arg1, arg2];
id = nativeSetTimeout(fun, num);
edide.onUnload(() => {
return clearTimeout(id);
});
return id;
};
}).call(MODSELF={}, edide, MODSELF);
edide.musicScales = (function (edide, musicScales) {Object.defineProperty(this, 'module_name', {value:'musicScales'});
this.full = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
this.scaleSteps = {
// rock
// 0, 3, 2, 2, 3, (2)
pentatonic: [
0,
3,
2,
2,
3 // hidden 2 # "pentatonicMinor"
],
//pentatonicMajor: ['C, D, E, G, A']
// blues: minor penta +
// whole whole half whole whole whole half
major: [
0,
2,
2,
1,
2,
2,
2 // hidden to beginning: 1 # "naturalMajor"
],
// whole half whole whole half whole whole
minor: [
0,
2,
1,
2,
2,
1,
2 // hidden to beginning: 2 # "naturalMinor"
]
};
// http://whatmusicreallyis.com/papers/sacred_sounds_scale.html
this.triadSteps = {
major: [
0,
4,
3 // positive valence
],
minor: [0, 3, 4]
};
// M = major triad
// m = minor triar
// i = number of (half) steps from first triad to second
// (source: https://www.youtube.com/watch?v=YSKAt3pmYBs)
this.triadCombinations = {
protagonism: 'M2M',
outerSpace: 'M6M',
fantastical: 'M8M',
sadness: 'M4m',
romantic: 'M5m', // and middle eastern
wonder: 'm5M', // and trancendence
mystery: 'm2M', // and dark comedy
dramatic: 'm11M',
antagonismDanger: 'm6m', // less character based
antagonismEvil: 'm8m' // cahracter based
};
return musicScales;
}).call(MODSELF={}, edide, MODSELF);
edide.mathOp = (function (edide, mathOp) {Object.defineProperty(this, 'module_name', {value:'mathOp'});
this.sum = function(a, b) {
return a + b;
};
this.multiply = function(a, b) {
return a * b;
};
return mathOp;
}).call(MODSELF={}, edide, MODSELF);
edide.mmKeyboard = (function (edide, mmKeyboard) {Object.defineProperty(this, 'module_name', {value:'mmKeyboard'});
var A, a, char, chari, i, j, len, len1, noncaps, qwertyChar, qwertyRows, revar, row, rowi, space, unvar;
({revar, unvar} = edide.mmState.init());
revar.scaleSteps = () => {
return edide.musicScales.scaleSteps[revar.scale];
};
this.special = {
rest: '.',
long: '=',
comment: '#',
var: ':',
confStart: '{',
confEnd: '}'
};
this.specialKeyCodes = new Set(Object.values(this.special).map((s) => {
return s.charCodeAt(0);
}));
this.specialChars = new Set(Object.values(this.special));
this.isPauseKey = (keyCode) => {
return this.specialKeyCodes.has(keyCode);
};
this.isSpecialChar = (char) => {
return this.specialChars.has(char);
};
this.isPauseChar = this.isSpecialChar; // not really...
this.keyboards = ['qwerty', 'abc'];
a = 'a'.charCodeAt(0);
A = 'A'.charCodeAt(0);
space = ' '.charCodeAt(0);
this.isCaps = (key) => {
return A <= key && key < a;
};
this.capsDiff = a - A;
noncaps = (key) => {
if (this.isCaps(key)) {
return key + this.capsDiff;
} else {
return key;
}
};
this.getNoteInd = (key) => {
var maxInstrumentNoteInd, noteBaseInd, noteInd, notes, startNote, step;
({startNote, notes, step} = unvar.instrumentConf);
startNote = unvar.root;
noteBaseInd = edide.noteFreq.findNote(startNote)[0];
noteInd = this[this.keyboards[unvar.keyboardInd]](noncaps(key), noteBaseInd);
maxInstrumentNoteInd = noteBaseInd + notes * step;
while (noteInd > maxInstrumentNoteInd) {
noteInd -= 2 * 12;
}
return noteInd;
};
this.abc = (key, baseInd) => {
var fromLowest, noteInd, stepsFromClosestOctave;
fromLowest = key - a;
stepsFromClosestOctave = fromLowest % revar.scaleSteps.length;
noteInd = 0;
noteInd += revar.scaleSteps.slice(0, +stepsFromClosestOctave + 1 || 9e9).reduce(edide.mathOp.sum);
noteInd += 12 * Math.floor(fromLowest / revar.scaleSteps.length);
return baseInd + noteInd;
};
qwertyRows = ['qwertyuiop', 'asdfghjkl', 'zxcvbnm'];
qwertyChar = {};
for (rowi = i = 0, len = qwertyRows.length; i < len; rowi = ++i) {
row = qwertyRows[rowi];
for (chari = j = 0, len1 = row.length; j < len1; chari = ++j) {
char = row[chari];
qwertyChar[char.charCodeAt(0)] = [rowi, chari];
}
}
this.qwerty = (key, baseInd) => {
var charSteps, halfSteps, noteInd, octave, rowchar;
if (!(rowchar = qwertyChar[key])) {
return;
}
[row, char] = rowchar;
octave = qwertyRows.length - 1 - row + Math.floor(char / unvar.scaleSteps.length);
char = char % revar.scaleSteps.length;
charSteps = revar.scaleSteps.slice(0, +char + 1 || 9e9).reduce((a, b) => {
return a + b;
});
halfSteps = 12 * octave + charSteps;
return noteInd = baseInd + halfSteps;
};
return mmKeyboard;
}).call(MODSELF={}, edide, MODSELF);
edide.chars = (function (edide, chars) {Object.defineProperty(this, 'module_name', {value:'chars'});
this.space = ' ';
this.nonBreakingSpace = ' ';
this.enter = "\n";
return chars;
}).call(MODSELF={}, edide, MODSELF);
edide.showError = (function (edide, showError) {
var error;
error = (err) => {
if (edide.inEditor) {
return edide.editorModule.editor_error.show(err);
} else if (typeof edide.global.require === 'object' && (edide.global[edide.edideNamespace].prodErrorPrinter != null)) {
return edide.global[edide.edideNamespace].prodErrorPrinter.showError(err);
} else {
return console.error(err);
}
};
return (err) => {
var err2;
if (err != null ? err.stack : void 0) {
return error(err); // create error to capture stack trace
} else {
try {
throw Error(err);
} catch (error1) {
err2 = error1;
return error(err2);
}
}
};
}).call(MODSELF={}, edide, MODSELF);
edide.mmParserSpecial = (function (edide, mmParserSpecial) {Object.defineProperty(this, 'module_name', {value:'mmParserSpecial'});
// parse config { .. } and variable : .. : syntaxes
this.config = (trackStr, ts = {}) => {
var endInd, err, name;
endInd = trackStr.search('}') || trackStr.length;
try {
ts.conf = JSON.parse(trackStr.slice(0, +endInd + 1 || 9e9));
if (ts.conf.name != null) {
({name} = ts.conf);
delete ts.conf.name;
edide.mmConfigs.addVar(name, ts.conf);
} else {
edide.mmConfigs.activate(ts.conf); // add variable if exists
}
} catch (error) {
err = error;
ts.skip = true; // could be used to show error highlighting in editor
edide.showError(err); // remove this if error highlighting implemented
}
return endInd;
};
// parse variable from curren track row
// returns false if parsing fails
this.var = (track, trackState) => {
var err, i, value, varLength, varName, varStr;
({i} = trackState);
varLength = track.slice(i + 1).indexOf(edide.mmKeyboard.special.var);
if (varLength === -1) {
return false;
}
varStr = track.slice(i + 1, +(i + varLength) + 1 || 9e9);
[varName, value] = varStr.split(' ');
if (!edide.mmConfigs.hasVar(varName)) {
// TODO: with errors shown in UI the following check could be removed:
return false;
}
try {
edide.mmConfigs.activateVar(varName, value);
trackState.i += varLength + 2;
return true;
} catch (error) {
err = error;
//throw err if edide.inEditor
return false;
}
};
return mmParserSpecial;
}).call(MODSELF={}, edide, MODSELF);
edide.mmNote = (function (edide, mmNote) {Object.defineProperty(this, 'module_name', {value:'mmNote'});
this.fromChar = (char) => {
return this.fromKeyCode(char.charCodeAt(0));
};
this.fromKeyCode = (key) => {
var noteInd, ref;
if (typeof (noteInd = edide.mmKeyboard.getNoteInd(key)) === 'number') {
return (ref = edide.noteFreq.notes[noteInd]) != null ? ref[0] : void 0;
}
};
return mmNote;
}).call(MODSELF={}, edide, MODSELF);
edide.mmParser = (function (edide, mmParser) {Object.defineProperty(this, 'module_name', {value:'mmParser'});
var getNoteLength, nonBreakingSpace, processTrack, revar, space, unvar;
({revar, unvar} = edide.mmState);
getNoteLength = (row, noteInd) => {
var char, length;
length = 1;
while (char = row[++noteInd]) {
if (char === edide.mmKeyboard.special.long) {
length++;
} else {
break;
}
}
return length;
};
({space, nonBreakingSpace} = edide.chars);
// Processes one char in a track, and iteratively calls itself if needed.
// ccs - "current column state" - inline chord + played?
// ts - track state: char index, configs
processTrack = (track, ccs, ts) => {
var bef, chord, groupingChars, keyCode, lastSpace, note, repeat, repeatStart;
if (!track[ts.i]) {
return;
}
if (ts.skip) { // comment or erroneous chars
return;
}
// bracket chords
switch (track[ts.i]) {
case '{':
return ts.i += edide.mmParserSpecial.config(track.slice(ts.i), ts); // parseConfigs
case '*':
if (ts.repeat != null) {
// inside a repeating pattern
ts.repeat--;
if (ts.repeat > 0) {
// still repeats left to do, start from the beginning
ts.i = ts.iStart = ts.repeatStart; // repeats done
} else {
ts.repeat = ts.repeatStart = null;
ts.i++; // step over '*' so won't end up starting repeats again
}
} else {
if (isNaN(repeat = parseInt(track.slice(ts.i + 1)))) {
ts.i++; // unable to parse number of repeats, skip them
} else {
// initialize new repeating patter (-1 because repeat pattern already played once)
ts.repeat = repeat - 1;
// search for beginning of repeat group
bef = track.slice(0, ts.i);
groupingChars = ['(', space, nonBreakingSpace, '*'];
lastSpace = Math.max(...groupingChars.map((c) => {
return bef.lastIndexOf(c);
}));
repeatStart = lastSpace !== -1 ? lastSpace + 1 : 0; // beginning of row if no grouping char found
// set track state at the beginning of repeats
ts.i = ts.iStart = ts.repeatStart = repeatStart;
}
}
return processTrack(track, ccs, ts);
case '[':
ccs.chord = [];
ts.i++;
return processTrack(track, ccs, ts);
case ']':
ts.i++;
({chord} = ccs);
if (!chord) { // illegal - missing beginning [
return processTrack(track, ccs, ts);
}
ccs.chord = null;
if (chord.length) {
if (!unvar.preprocessing) {
revar.playNote = [chord, getNoteLength(track, ts.i)];
}
//edide.mmInstrument.playNote chord, getNoteLength track, ts.i
ccs.played = true;
} else {
processTrack(track, ccs, ts);
}
return;
case edide.mmKeyboard.special.var:
if (edide.mmParserSpecial.var(track, ts)) {
processTrack(track, ccs, ts); // recursive, since next char could be another var, e.g. \:bass::minor:
} else {
ts.skip = true; // parse error
}
return;
case edide.mmKeyboard.special.comment:
return ts.skip = true;
}
// TODO: merge switch and bottom code OR put them in a different functions
if (!(keyCode = track.charCodeAt(ts.i))) {
return;
}
ts.i++;
if (note = edide.mmNote.fromKeyCode(keyCode)) {
if (ccs.chord) {
ccs.chord.push(note);
processTrack(track, ccs, ts);
} else {
if (!unvar.preprocessing) {
revar.playNote = [note, getNoteLength(track, ts.i)];
}
//edide.mmInstrument.playNote note, getNoteLength track, ts.i
ccs.played = true;
}
} else if (edide.mmKeyboard.isPauseKey(keyCode)) {
ccs.played = true; // "play silence"
// meaningless char
} else {
processTrack(track, ccs, ts);
}
};
// TODO figure sheetStart != 0 -- maybe makes more sense to remove textarea first
this.splitSections = (str) => {
var i, j, prevInd, ref, row, section, sections;
str = str.replace('&\n', ''); // TODO fix row tracking with &\n
sections = [];
section = null;
row = 0;
prevInd = 0;
for (i = j = 0, ref = str.length; (0 <= ref ? j <= ref : j >= ref); i = 0 <= ref ? ++j : --j) {
if (!(str[i] === '\n' || i === str.length)) {
continue;
}
if (str[i - 1] === '\n') {
if (section != null) {
sections.push(section);
}
section = null;
}
if (i > prevInd) {
if (section == null) {
section = {
row: row,
tracks: []
};
}
section.tracks.push(str.slice(prevInd, i));
}
row++;
prevInd = i + 1;
}
if (section != null) {
sections.push(section);
}
sections.row = 0;
return sections;
};
this.play = (song, sectionInd, trackStates) => {
var ccs, section;
if (!unvar.playing) {
return;
}
revar.highlight = null;
sectionInd = sectionInd || 0;
if (typeof song === 'string') {
song = this.splitSections(song);
}
section = song[sectionInd];
if (!section) { // song finished
if (!unvar.preprocessing) {
revar.playing = false;
}
return;
}
if (!Array.isArray(trackStates)) {
trackStates = section.tracks.map(() => {
return {
i: 0 // initi track indices on first call to section
};
});
}
// init @play ccs
ccs = {}; // chord, played # TODO change back to chord: [C3, D3] and [].played = true
// OR: why not just ts.chord?
section.tracks.forEach((track, tInd) => {
var conf, i, iStart;
if (conf = trackStates[tInd].conf) {
// config row and already parsed (NOTE: config row can only have one config object and nothing else)
return edide.mmConfigs.activate(conf);
} else {
trackStates[tInd].iStart = trackStates[tInd].i;
processTrack(track, ccs, trackStates[tInd]);
({iStart, i} = trackStates[tInd]);
if (i > iStart) {
return revar.highlight = [section.row + tInd, iStart, i - 1];
}
}
});
if (ccs.played) {
if (unvar.preprocessing) {
this.play(song, sectionInd, trackStates);
} else {
edide.setTimeout(() => {
return this.play(song, sectionInd, trackStates);
}, unvar.beatDelay);
}
} else {
// using timeout fixes bug where revar.playing is set false in same exec where it's set true (infinite loop)
this.play(song, sectionInd + 1);
}
};
return mmParser;
}).call(MODSELF={}, edide, MODSELF);
edide.moduleGate = (function (edide, moduleGate) {Object.defineProperty(this, 'module_name', {value:'moduleGate'});
if (!edide.inEditor) {
return this;
}
this.root; // module that is edited in root
this.rootName;
this.active; // module that is currently being edited (can be root or in window)
this.activeName;
this.executing;
this.executingName;
return moduleGate;
}).call(MODSELF={}, edide, MODSELF);
edide.rejectIfRecompiled = (function (edide, rejectIfRecompiled) {
if (!edide.inEditor) {
return () => {};
}
return (promise) => {
var recompiled, rootName;
({rootName} = edide.moduleGate);
recompiled = false;
edide.editorModule.editor_events.on('before_recompile', () => {
return recompiled = true;
});
return promise.then(function(arg) {
if (recompiled || rootName !== edide.moduleGate.rootName) { // root module changed
return Promise.reject(); // quiet rejection; no need to show error
} else {
return arg; // arg get wrapped in promise
}
});
};
}).call(MODSELF={}, edide, MODSELF);
edide.promise = (function (edide, promise) {Object.defineProperty(this, 'module_name', {value:'promise'});
var localPromise, ref;
localPromise = edide.global.origPromise = (ref = edide.global.origPromise) != null ? ref : edide.global.Promise;
this.new = function(cb) {
if (edide.inEditor) {
return edide.rejectIfRecompiled(new Promise(cb)); // don't fire cb if code has been re-executed in the meantime
} else {
return new Promise(cb);
}
};
this.all = function(cbArray) {
if (edide.inEditor) { // check that after resolved, still editing same module
return edide.rejectIfRecompiled(Promise.all(cbArray));
} else {
return Promise.all(cbArray);
}
};
this.resolve = Promise.resolve.bind(Promise);
this.reject = Promise.reject.bind(Promise);
return promise;
}).call(MODSELF={}, edide, MODSELF);
edide.qs = (function (edide, qs) {
return (selector, el = document) => {
return el.querySelector(selector);
};
}).call(MODSELF={}, edide, MODSELF);
edide.scriptContainer = (function (edide, scriptContainer) {
var createContainer, ref;
createContainer = () => {
var s;
s = document.createElement('div');
s.id = 'scripts';
return s;
};
return (ref = edide.qs('#scripts')) != null ? ref : document.body.appendChild(createContainer());
}).call(MODSELF={}, edide, MODSELF);
edide.scriptAdd = (function (edide, scriptAdd) {
return (src, cb) => {
var el;
el = document.createElement('script');
edide.scriptContainer.appendChild(el);
if (cb) {
el.onload = cb;
}
el.type = 'application/javascript';
el.src = src;
};
}).call(MODSELF={}, edide, MODSELF);
edide.requireScript = (function (edide, requireScript) {
var base;
if ((base = edide.global).requireScriptPromises == null) {
base.requireScriptPromises = new Map;
}
return (scriptSrc) => {
var promise;
if (promise = requireScriptPromises.get(scriptSrc)) {
return promise;
} else {
requireScriptPromises.set(scriptSrc, promise = edide.promise.new((resolve) => {
return edide.scriptAdd(scriptSrc, resolve);
}));
return promise.catch((err) => {
edide.showError(err);
return requireScriptPromises.delete(scriptSrc);
});
}
};
}).call(MODSELF={}, edide, MODSELF);
edide.mmPipe = (function (edide, mmPipe) {Object.defineProperty(this, 'module_name', {value:'mmPipe'});
var dist, lowpass, panner, react, revar, reverber, unvar;
({revar, unvar, react} = edide.mmState.init());
dist = lowpass = reverber = panner = null;
this.initPipe = () => {
lowpass = new Tone.Filter(unvar.lowpass, 'lowpass', -12);
dist = new Tone.Distortion(unvar.distortion);
panner = new Tone.Panner();
panner.connect(dist);
dist.connect(lowpass);
lowpass.toMaster();
this.output = lowpass;
revar.pipeReady = true;
return edide.onUnload(() => {
if (dist != null) {
if (typeof dist.dipose === "function") {
dist.dipose();
}
}
if (lowpass != null) {
if (typeof lowpass.dispose === "function") {
lowpass.dispose();
}
}
return panner != null ? typeof panner.dispose === "function" ? panner.dispose() : void 0 : void 0;
});
};
this.initInstrument = (instrument) => {
instrument.connect(panner);
edide.onUnload(() => {
return instrument != null ? instrument.disconnect() : void 0;
});
return instrument;
};
revar.panner = () => {
return revar.balance;
};
react('panner', () => {
revar.panner;
return panner != null ? panner.pan.value = revar.panner : void 0;
});
react('pipe distortion', () => {
var ref;
revar.distortion;
revar.lowpass;
if (dist != null) {
dist.distortion = revar.distortion;
}
return lowpass != null ? (ref = lowpass.frequency) != null ? ref.linearRampTo(revar.lowpass, 0) : void 0 : void 0;
});
return mmPipe;
}).call(MODSELF={}, edide, MODSELF);
edide.mmInstruments = (function (edide, mmInstruments) {Object.defineProperty(this, 'module_name', {value:'mmInstruments'});
var defaultUrl = 'https://nbrosowsky.github.io/tonejs-instruments/samples/'
var { revar, unvar, react } = edide.mmState
var defaultInstrument = 'electric-guitar'
this.initInstrument = async (resolve) => {
await edide.requireScript('https://cdnjs.cloudflare.com/ajax/libs/tone/13.8.9/Tone.js')
edide.mmPipe.initPipe()
}
var instrumentCache = edide.keep({})
this.createNew = () => {
var {name} = unvar.instrumentConf
var instrument, endOfPipe
var instrumentConf = this.instruments[name]
if (instrumentConf.module_name) {
var res = instrumentConf.init()
if (Array.isArray(res)) {
instrument = res[0]
endOfPipe = res[1]
} else {
instrument = endOfPipe = res
}
} else if (instrumentCache[name]) {
instrument = endOfPipe = instrumentCache[name]
} else {
var noteFiles = buildNotes(instrumentConf)
revar.instrumentsLoading++
var inst = new Tone.Sampler(noteFiles, { //edide.mmInstrumentssAll[name]
"release" : 1,
"baseUrl" : instrumentConf.url || defaultUrl + name + '/',
"onload" : () => revar.instrumentsLoading--
})
inst.soundFontInstrument = true
instrument = endOfPipe = instrumentCache[name] = inst //[inst, inst]
}
edide.mmPipe.initInstrument(endOfPipe)
return instrument
}
this.isReady = () => {
var { current } = this
return current && (typeof current.loaded == 'undefined' || current.loaded === true)
}
function buildNotes({startNote, notes, step, skipNotes}) {
var [startInd] = edide.noteFreq.findNote(startNote)
var noteFiles = {}
if (Array.isArray(notes)) {
notes.forEach(note => {
noteFiles[note] = note.replace('#','s') + '.[mp3|ogg]'
})
} else {
for (let i=0; i < notes*step; i+=step) {
let note = edide.noteFreq.notes[startInd + i][0];
if (skipNotes && skipNotes.has(note))
continue
noteFiles[note] = note.replace('#','s') + '.[mp3|ogg]'
}
}
return noteFiles
}
this.instruments = edide.instrumentConfigs
this.instrumentList = Object.values(this.instruments)
react('active instrument config', () => {
revar.instrumentConf = this.instruments[revar.instrument] // conf
})
return mmInstruments;
}).call(MODSELF={}, edide, MODSELF);
edide.cloneSibling = (function (edide, cloneSibling) {
return (srcObj) => {
var o;
o = Object.create(Object.getPrototypeOf(srcObj));
Object.assign(o, srcObj);
return o;
};
}).call(MODSELF={}, edide, MODSELF);
edide.times = (function (edide, times) {
return (timesNum, action) => {
while (timesNum-- > 0) {
action(timesNum + 1);
}
};
}).call(MODSELF={}, edide, MODSELF);
edide.sleep = (function (edide, sleep) {
var sleep;
sleep = (ms) => {
var resolve, timeout;
timeout = resolve = null;
return edide.promise.new((res) => {
resolve = res;
return timeout = edide.setTimeout(ms, res);
});
};
return sleep;
}).call(MODSELF={}, edide, MODSELF);
edide.mmInstrument = (function (edide, mmInstrument) {Object.defineProperty(this, 'module_name', {value:'mmInstrument'});
var cloneOrCreateInstrument, getInstruments, instruments, play, react, revar, unvar, updateVolAndTune;
instruments = {}; // name: [instrument instances...]
({unvar, revar, react} = edide.mmState);
revar.bpm = () => {
return revar.pace;
};
revar.beatDelay = () => {
return (1 / revar.bpm) * 60 * 1000;
};
react(() => {});
updateVolAndTune = (inst) => {
var detune, volume;
({volume, detune} = unvar);
if ((detune != null) && (inst.detune != null)) {
inst.set("detune", detune);
}
if ((volume != null) && (inst.volume != null)) {
return inst.set("volume", volume);
}
};
react(() => {
var inst, insts, j, len, name;
revar.volume;
revar.detune;
for (name in instruments) {
insts = instruments[name];
for (j = 0, len = insts.length; j < len; j++) {
inst = insts[j];
updateVolAndTune(inst);
}
}
});
react('create first instrument', () => {
var name, ref;
if (!(name = (ref = revar.instrumentConf) != null ? ref.name : void 0)) { // e.g. illegal instrument name
return edide.showError(`Unknown instrument: ${unvar.instrument}`);
}
if (revar.pipeReady && !instruments[name]) {
return instruments[name] = [edide.mmInstruments.createNew()];
}
});
cloneOrCreateInstrument = (name) => {
var inst;
inst = instruments[name][0].soundFontInstrument ? (inst = edide.cloneSibling(instruments[name][0]), inst.isPlaying = false, inst) : edide.mmInstruments.createNew();
updateVolAndTune(inst);
return inst;
};
getInstruments = (n) => {
var all, free, name;
({name} = unvar.instrumentConf);
all = instruments[name];
free = all.filter((i) => {
return !i.isPlaying;
});
edide.times(n - free.length, () => {
var inst;
free.push(inst = cloneOrCreateInstrument(name));
return all.push(inst);
});
return free.slice(0, n);
};
this.playChord = (chord, noteLength = 1) => {};
this.playNote = (chord, noteLength = 1) => {
var ind, inst, insts, j, len, ref;
if (!Array.isArray(chord)) {
chord = [chord];
}
ref = insts = getInstruments(chord.length);
for (ind = j = 0, len = ref.length; j < len; ind = ++j) {
inst = ref[ind];
play(inst, chord[ind], noteLength);
}
};
play = async(instrument, note, length) => {
var err;
instrument.isPlaying = note; // true
try {
instrument.triggerAttackRelease(note, (length * unvar.beatDelay) / 1000);
} catch (error) {
err = error;
err.message = `Error in playing note ${note}, '${unvar.instrumentConf.name}' probably not loaded yet`;
edide.showError(err);
}
revar.note = note;
await edide.sleep(unvar.nextDelay);
return instrument.isPlaying = false;
};
return mmInstrument;
}).call(MODSELF={}, edide, MODSELF);
edide.mmPlayer = (function (edide, mmPlayer) {Object.defineProperty(this, 'module_name', {value:'mmPlayer'});
var react, revar, unvar;
({revar, unvar, react} = edide.mmState.init());
this.play = (str) => {
revar.sheet = str;
return revar.playing = true;
};
react('play from sheet', () => {
if (!revar.playing) {
return;
}
edide.mmConfigs.init();
revar.preprocessing = true;
return edide.setTimeout(() => { // infinite revar.playing loop
edide.mmParser.play(unvar.sheet);
return revar.preprocessing = 'done';
});
});
react('play notes/chords', () => {
var chord, playNote, playing, preprocessing, time;
({playNote, playing, preprocessing} = revar);
if (!(playNote && playing && preprocessing === false)) {
return;
}
[chord, time] = revar.playNote;
return edide.mmInstrument.playNote(chord, time);
});
this.toggle = () => {
return revar.playing = !unvar.playing;
};
revar.instrumentsLoading;
react('play after preprocess', () => {
var instrumentsLoading, preprocessing;
({instrumentsLoading, preprocessing} = revar);
if (!(preprocessing === 'done' && instrumentsLoading === 0)) {
return;
}
unvar.preprocessing = false;
edide.mmConfigs.reset();
return edide.mmParser.play(unvar.sheet);
});
return mmPlayer;
}).call(MODSELF={}, edide, MODSELF);
edide.waves = (function (edide, waves) {Object.defineProperty(this, 'module_name', {value:'waves'});
edide.global.music = this
edide.mmEffects
var { revar, unvar, react } = edide.mmState
var playQueue = []
this.play = (str) => {
if (!unvar.pipeReady) return playQueue.push(str)
revar.playing = true
edide.mmPlayer.play(str)
}
this.stop = () => revar.playing = false
edide.mmInstruments.initInstrument()
react(() => {
if(!revar.pipeReady) return
edide.mmConfigs.reset()
this.play(playQueue.join("\n\n")) // JSON.stringify(initialSettings)
})
return waves;
}).call(MODSELF={}, edide, MODSELF);
edide.wave = (function (edide, wave) {
var parent = {
play: function(){
edide.waves.play(this.sheet)
return this
},
stop: function(){
edide.waves.stop(this.sheet)
return this
},
blur: function(val){
this.sheet = `:blur ${val}:` + this.sheet
return this
},
itch: function(val){
this.sheet = `:itch ${val}:` + this.sheet
return this
},
long: function(val){ // note delay in seconds
this.sheet = `:beatDelay ${val*1000}:` + this.sheet
return this
},
pace: function(val) { // note delay in beats per minute
this.sheet = `:pace ${val}:` + this.sheet
return this
},
vary: function(val){
this.sheet = `:detune ${val}:` + this.sheet
return this
},
loud: function(val){ // increase (>0) or decrease (<0) amplitude in decibels
this.sheet = `:volume ${val}:` + this.sheet
return this
},
balance: function(val){
this.sheet = `:balance ${val}:` + this.sheet
return this
}
}
return edide.global.wave = (str) => {
edide.mmConfigs.reset()
var obj = Object.create(parent)
obj.sheet = str
return obj
}
}).call(MODSELF={}, edide, MODSELF);
edide.global.wave = edide.wave;
})()