UNPKG

crossbrowdy

Version:

A Multimedia JavaScript framework to create real cross-platform and hybrid game engines, games, emulators, multimedia libraries and apps.

1,484 lines (1,367 loc) 377 kB
/** * T("timbre.js") - A JavaScript library for objective sound programming */ var _timbreJSInitializer = function() //CrossBrowdy modification to be able to initialize the library after an user-driven event (as onClick, etc.). { (function(undefined) { "use strict"; var timbre = function() { return T.apply(null, arguments); }; var slice = Array.prototype.slice; var FINISHED_STATE = 0; var PLAYING_STATE = 1; var UNSCHEDULED_STATE = 2; // (not use) var SCHEDULED_STATE = 3; // (not use) var ACCEPT_SAMPLERATES = [8000,11025,12000,16000,22050,24000,32000,44100,48000]; var ACCEPT_CELLSIZES = [32,64,128,256]; var _ver = "14.10.12"; var _sys = null; var _constructors = {}; var _factories = {}; var _envtype = (typeof window !== "undefined") ? "browser" : (typeof module !== "undefined" && module.exports) ? "node" : "unknown"; var _envmobile = _envtype === "browser" && /(iPhone|iPad|iPod|Android)/i.test(navigator.userAgent); var _f64mode = false; var _bpm = 120; var T = function() { var args = slice.call(arguments), key = args[0], t, m; switch (typeof key) { case "string": if (_constructors[key]) { t = new _constructors[key](args.slice(1)); } else if (_factories[key]) { t = _factories[key](args.slice(1)); } else { m = /^(.+?)(?:\.(ar|kr))?$/.exec(key); if (m) { key = m[1]; if (_constructors[key]) { t = new _constructors[key](args.slice(1)); } else if (_factories[key]) { t = _factories[key](args.slice(1)); } if (t && m[2]) { t[m[2]](); } } } break; case "number": t = new NumberWrapper(args); break; case "boolean": t = new BooleanWrapper(args); break; case "function": t = new FunctionWrapper(args); break; case "object": if (key !== null) { if (key instanceof TimbreObject) { return key; } else if (key.context instanceof TimbreObject) { return key.context; } else if (isDictionary(key)) { t = new ObjectWrapper(args); } else if (isArray(key)) { t = new ArrayWrapper(args); } } break; } if (t === undefined) { t = new AddNode(args.slice(1)); console.warn("T(\"" + key + "\") is not defined."); } var _ = t._; _.originkey = key; _.meta = __buildMetaData(t); _.emit("init"); return t; }; var __buildMetaData = function(instance) { var meta = instance._.meta; var names, desc; var p = instance; while (p !== null && p.constructor !== Object) { names = Object.getOwnPropertyNames(p); for (var i = 0, imax = names.length; i < imax; ++i) { if (meta[names[i]]) { continue; } if (/^(constructor$|process$|_)/.test(names[i])) { meta[names[i]] = "ignore"; } else { desc = Object.getOwnPropertyDescriptor(p, names[i]); if (typeof desc.value === "function") { meta[names[i]] = "function"; } else if (desc.get || desc.set) { meta[names[i]] = "property"; } } } p = Object.getPrototypeOf(p); } return meta; }; // properties Object.defineProperties(timbre, { version : { value: _ver }, envtype : { value: _envtype }, envmobile: { value: _envmobile }, env: { get: function() { return _sys.impl.env; } }, samplerate: { get: function() { return _sys.samplerate; } }, channels: { get: function() { return _sys.channels; } }, cellsize: { get: function() { return _sys.cellsize; } }, currentTime: { get: function() { return _sys.currentTime; } }, isPlaying: { get: function() { return _sys.status === PLAYING_STATE; } }, isRecording: { get: function() { return _sys.status === SCHEDULED_STATE; } }, amp: { set: function(value) { if (typeof value === "number") { _sys.amp = value; } }, get: function() { return _sys.amp; } }, bpm: { set: function(value) { if (typeof value === "number") { if (5 <= value && value <= 300) { _bpm = value; } } }, get: function() { return _bpm; } } }); timbre.bind = function(Klass, opts) { _sys.bind(Klass, opts); return timbre; }; timbre.setup = function(opts) { _sys.setup(opts); return timbre; }; timbre.play = function() { _sys.play(); return timbre; }; timbre.pause = function() { _sys.pause(); return timbre; }; timbre.reset = function() { _sys.reset(); _sys.events.emit("reset"); return timbre; }; timbre.on = timbre.addListener = function(type, listener) { _sys.on(type, listener); return timbre; }; timbre.once = function(type, listener) { _sys.once(type, listener); return timbre; }; timbre.off = timbre.removeListener = function(type, listener) { _sys.off(type, listener); return timbre; }; timbre.removeAllListeners = function(type) { _sys.removeAllListeners(type); return timbre; }; timbre.listeners = function(type) { return _sys.listeners(type); }; timbre.rec = function() { return _sys.rec.apply(_sys, arguments); }; timbre.timevalue = (function() { var getbpm = function(str) { var m, bpm = _bpm; if ((m = /^bpm(\d+(?:\.\d+)?)/i.exec(str))) { bpm = Math.max(5, Math.min(300, +(m[1]||0))); } return bpm; }; return function(str) { var m, ms, x; if ((m = /^(\d+(?:\.\d+)?)Hz$/i.exec(str))) { return +m[1] === 0 ? 0 : 1000 / +m[1]; } if ((m = /L(\d+)?(\.*)$/i.exec(str))) { ms = 60 / getbpm(str) * (4 / (m[1]||4)) * 1000; ms *= [1, 1.5, 1.75, 1.875][(m[2]||"").length] || 1; return ms; } if ((m = /^(\d+(?:\.\d+)?|\.(?:\d+))(min|sec|m)s?$/i.exec(str))) { switch (m[2]) { case "min": return +(m[1]||0) * 60 * 1000; case "sec": return +(m[1]||0) * 1000; case "m" : return +(m[1]||0); } } if ((m = /^(?:([0-5]?[0-9]):)?(?:([0-5]?[0-9]):)(?:([0-5]?[0-9]))(?:\.([0-9]{1,3}))?$/.exec(str))) { x = (m[1]||0) * 3600 + (m[2]||0) * 60 + (m[3]||0); x = x * 1000 + ((((m[4]||"")+"00").substr(0, 3))|0); return x; } if ((m = /(\d+)\.(\d+)\.(\d+)$/i.exec(str))) { x = (m[1] * 4 + (+m[2])) * 480 + (+m[3]); return 60 / getbpm(str) * (x / 480) * 1000; } if ((m = /(\d+)ticks$/i.exec(str))) { return 60 / getbpm(str) * (m[1] / 480) * 1000; } if ((m = /^(\d+)samples(?:\/(\d+)Hz)?$/i.exec(str))) { return m[1] * 1000 / (m[2] || timbre.samplerate); } return 0; }; })(); var fn = timbre.fn = { SignalArray: Float32Array, currentTimeIncr: 0, emptycell: null, FINISHED_STATE: FINISHED_STATE, PLAYING_STATE: PLAYING_STATE, UNSCHEDULED_STATE: UNSCHEDULED_STATE, SCHEDULED_STATE: SCHEDULED_STATE }; var isArray = fn.isArray = Array.isArray; var isDictionary = fn.isDictionary = function(object) { return typeof object === "object" && object.constructor === Object; }; fn.nop = function() { return this; }; fn.isSignalArray = function(obj) { if (obj instanceof fn.SignalArray) { return true; } if (Array.isArray(obj) && obj.__klass && obj.__klass.type === 2) { return true; } return false; }; // borrowed from coffee-script fn.extend = function(child, parent) { parent = parent || TimbreObject; for (var key in parent) { if (parent.hasOwnProperty(key)) { child[key] = parent[key]; } } /*jshint validthis:true */ function ctor() { this.constructor = child; } /*jshint validthis:false */ ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; fn.constructorof = function(ctor, Klass) { var f = ctor && ctor.prototype; while (f) { if (f === Klass.prototype) { return true; } f = Object.getPrototypeOf(f); } return false; }; fn.register = function(key, ctor) { if (fn.constructorof(ctor, TimbreObject)) { _constructors[key] = ctor; } else { _factories[key] = ctor; } }; fn.alias = function(key, alias) { if (_constructors[alias]) { _constructors[key] = _constructors[alias]; } else if (_factories[alias]) { _factories[key] = _factories[alias]; } }; fn.getClass = function(key) { return _constructors[key]; }; fn.pointer = function(src, offset, length) { offset = src.byteOffset + offset * src.constructor.BYTES_PER_ELEMENT; if (typeof length === "number") { return new src.constructor(src.buffer, offset, length); } else { return new src.constructor(src.buffer, offset); } }; fn.nextTick = function(func) { _sys.nextTick(func); return timbre; }; fn.fixAR = function(self) { self._.ar = true; self._.aronly = true; }; fn.fixKR = function(self) { self._.ar = false; self._.kronly = true; }; fn.changeWithValue = function() { var _ = this._; var x = _.value * _.mul + _.add; if (isNaN(x)) { x = 0; } var cell = this.cells[0]; for (var i = 0, imax = cell.length; i < imax; ++i) { cell[i] = x; } }; fn.changeWithValue.unremovable = true; fn.clone = function(src) { var new_instance = new src.constructor([]); new_instance._.ar = src._.ar; new_instance._.mul = src._.mul; new_instance._.add = src._.add; new_instance._.bypassed = src._.bypassed; return new_instance; }; fn.timer = (function() { var make_onstart = function(self) { return function() { if (_sys.timers.indexOf(self) === -1) { _sys.timers.push(self); _sys.events.emit("addObject"); self._.emit("start"); fn.buddies_start(self); } }; }; var make_onstop = function(self) { return function() { var i = _sys.timers.indexOf(self); if (i !== -1) { _sys.timers.splice(i, 1); self._.emit("stop"); _sys.events.emit("removeObject"); fn.buddies_stop(self); } }; }; return function(self) { var onstart = make_onstart(self); var onstop = make_onstop(self); self.nodeType = TimbreObject.TIMER; self.start = function() { _sys.nextTick(onstart); return self; }; self.stop = function() { _sys.nextTick(onstop); return self; }; return self; }; })(); fn.listener = (function() { var make_onlisten = function(self) { return function() { if (_sys.listeners.indexOf(self) === -1) { _sys.listeners.push(self); _sys.events.emit("addObject"); self._.emit("listen"); fn.buddies_start(self); } }; }; var make_onunlisten = function(self) { return function() { var i = _sys.listeners.indexOf(self); if (i !== -1) { _sys.listeners.splice(i, 1); self._.emit("unlisten"); _sys.events.emit("removeObject"); fn.buddies_stop(self); } }; }; return function(self) { var onlisten = make_onlisten(self); var onunlisten = make_onunlisten(self); self.nodeType = TimbreObject.LISTENER; self.listen = function(buddies) { if (arguments.length) { self.append.apply(self, arguments); } if (self.nodes.length) { _sys.nextTick(onlisten); } return self; }; self.unlisten = function() { if (arguments.length) { self.remove.apply(self, arguments); } if (!self.nodes.length) { _sys.nextTick(onunlisten); } return self; }; return self; }; })(); fn.make_onended = function(self, lastValue) { return function() { self.playbackState = FINISHED_STATE; if (typeof lastValue === "number") { var cell = self.cells[0]; var cellL = self.cells[1]; var cellR = self.cells[2]; for (var i = 0, imax = cellL.length; i < imax; ++i) { cell[0] = cellL[i] = cellR[i] = lastValue; } } self._.emit("ended"); }; }; fn.inputSignalAR = function(self) { var cell = self.cells[0]; var cellL = self.cells[1]; var cellR = self.cells[2]; var nodes = self.nodes; var i, imax = nodes.length; var j, jmax = cell.length; var tickID = self.tickID; var not_clear, tmp, tmpL, tmpR; if (self.numChannels === 2) { not_clear = true; if (imax !== 0) { for (i = 0; i < imax; ++i) { if (nodes[i].playbackState === PLAYING_STATE) { nodes[i].process(tickID); cellL.set(nodes[i].cells[1]); cellR.set(nodes[i].cells[2]); not_clear = false; ++i; break; } } for (; i < imax; ++i) { if (nodes[i].playbackState === PLAYING_STATE) { nodes[i].process(tickID); tmpL = nodes[i].cells[1]; tmpR = nodes[i].cells[2]; for (j = jmax; j; ) { j -= 8; cellL[j ] += tmpL[j ]; cellR[j ] += tmpR[j ]; cellL[j+1] += tmpL[j+1]; cellR[j+1] += tmpR[j+1]; cellL[j+2] += tmpL[j+2]; cellR[j+2] += tmpR[j+2]; cellL[j+3] += tmpL[j+3]; cellR[j+3] += tmpR[j+3]; cellL[j+4] += tmpL[j+4]; cellR[j+4] += tmpR[j+4]; cellL[j+5] += tmpL[j+5]; cellR[j+5] += tmpR[j+5]; cellL[j+6] += tmpL[j+6]; cellR[j+6] += tmpR[j+6]; cellL[j+7] += tmpL[j+7]; cellR[j+7] += tmpR[j+7]; } } } } if (not_clear) { cellL.set(fn.emptycell); cellR.set(fn.emptycell); } } else { not_clear = true; if (imax !== 0) { for (i = 0; i < imax; ++i) { if (nodes[i].playbackState === PLAYING_STATE) { nodes[i].process(tickID); cell.set(nodes[i].cells[0]); not_clear = false; ++i; break; } } for (; i < imax; ++i) { if (nodes[i].playbackState === PLAYING_STATE) { tmp = nodes[i].process(tickID).cells[0]; for (j = jmax; j; ) { j -= 8; cell[j ] += tmp[j ]; cell[j+1] += tmp[j+1]; cell[j+2] += tmp[j+2]; cell[j+3] += tmp[j+3]; cell[j+4] += tmp[j+4]; cell[j+5] += tmp[j+5]; cell[j+6] += tmp[j+6]; cell[j+7] += tmp[j+7]; } } } } if (not_clear) { cell.set(fn.emptycell); } } }; fn.inputSignalKR = function(self) { var nodes = self.nodes; var i, imax = nodes.length; var tickID = self.tickID; var tmp = 0; for (i = 0; i < imax; ++i) { if (nodes[i].playbackState === PLAYING_STATE) { tmp += nodes[i].process(tickID).cells[0][0]; } } return tmp; }; fn.outputSignalAR = function(self) { var cell = self.cells[0]; var cellL = self.cells[1]; var cellR = self.cells[2]; var mul = self._.mul, add = self._.add; var i; if (self.numChannels === 2) { for (i = cell.length; i; ) { i -= 8; cellL[i ] = cellL[i ] * mul + add; cellR[i ] = cellR[i ] * mul + add; cellL[i+1] = cellL[i+1] * mul + add; cellR[i+1] = cellR[i+1] * mul + add; cellL[i+2] = cellL[i+2] * mul + add; cellR[i+2] = cellR[i+2] * mul + add; cellL[i+3] = cellL[i+3] * mul + add; cellR[i+3] = cellR[i+3] * mul + add; cellL[i+4] = cellL[i+4] * mul + add; cellR[i+4] = cellR[i+4] * mul + add; cellL[i+5] = cellL[i+5] * mul + add; cellR[i+5] = cellR[i+5] * mul + add; cellL[i+6] = cellL[i+6] * mul + add; cellR[i+6] = cellR[i+6] * mul + add; cellL[i+7] = cellL[i+7] * mul + add; cellR[i+7] = cellR[i+7] * mul + add; cell[i ] = (cellL[i ] + cellR[i ]) * 0.5; cell[i+1] = (cellL[i+1] + cellR[i+1]) * 0.5; cell[i+2] = (cellL[i+2] + cellR[i+2]) * 0.5; cell[i+3] = (cellL[i+3] + cellR[i+3]) * 0.5; cell[i+4] = (cellL[i+4] + cellR[i+4]) * 0.5; cell[i+5] = (cellL[i+5] + cellR[i+5]) * 0.5; cell[i+6] = (cellL[i+6] + cellR[i+6]) * 0.5; cell[i+7] = (cellL[i+7] + cellR[i+7]) * 0.5; } } else { if (mul !== 1 || add !== 0) { for (i = cell.length; i; ) { i -= 8; cell[i ] = cell[i ] * mul + add; cell[i+1] = cell[i+1] * mul + add; cell[i+2] = cell[i+2] * mul + add; cell[i+3] = cell[i+3] * mul + add; cell[i+4] = cell[i+4] * mul + add; cell[i+5] = cell[i+5] * mul + add; cell[i+6] = cell[i+6] * mul + add; cell[i+7] = cell[i+7] * mul + add; } } } }; fn.outputSignalKR = function(self) { var cell = self.cells[0]; var cellL = self.cells[1]; var cellR = self.cells[2]; var mul = self._.mul, add = self._.add; var value = cell[0] * mul + add; var i; if (self.numChannels === 2) { for (i = cell.length; i; ) { i -= 8; cell[i] = cell[i+1] = cell[i+2] = cell[i+3] = cell[i+4] = cell[i+5] = cell[i+6] = cell[i+7] = cellL[i] = cellL[i+1] = cellL[i+2] = cellL[i+3] = cellL[i+4] = cellL[i+5] = cellL[i+6] = cellL[i+7] = cellR[i] = cellR[i+1] = cellR[i+2] = cellR[i+3] = cellR[i+4] = cellR[i+5] = cellR[i+6] = cellR[i+7] = value; } } else { for (i = cell.length; i; ) { i -= 8; cell[i] = cell[i+1] = cell[i+2] = cell[i+3] = cell[i+4] = cell[i+5] = cell[i+6] = cell[i+7] = value; } } }; fn.buddies_start = function(self) { var buddies = self._.buddies; var node, i, imax; for (i = 0, imax = buddies.length; i < imax; ++i) { node = buddies[i]; switch (node.nodeType) { case TimbreObject.DSP: node.play(); break; case TimbreObject.TIMER: node.start(); break; case TimbreObject.LISTENER: node.listen(); break; } } }; fn.buddies_stop = function(self) { var buddies = self._.buddies; var node, i, imax; for (i = 0, imax = buddies.length; i < imax; ++i) { node = buddies[i]; switch (node.nodeType) { case TimbreObject.DSP: node.pause(); break; case TimbreObject.TIMER: node.stop(); break; case TimbreObject.LISTENER: node.unlisten(); break; } } }; fn.fix_iOS6_1_problem = function(flag) { _sys.fix_iOS6_1_problem(flag); }; var modules = timbre.modules = {}; // EventEmitter var EventEmitter = modules.EventEmitter = (function() { function EventEmitter(context) { this.context = context; this.events = {}; } var $ = EventEmitter.prototype; $.emit = function(type) { var handler = this.events[type]; if (!handler) { return false; } var args; if (typeof handler === "function") { switch (arguments.length) { case 1: handler.call(this.context); break; case 2: handler.call(this.context, arguments[1]); break; case 3: handler.call(this.context, arguments[1], arguments[2]); break; default: args = slice.call(arguments, 1); handler.apply(this.context, args); } return true; } else if (isArray(handler)) { args = slice.call(arguments, 1); var listeners = handler.slice(); for (var i = 0, imax = listeners.length; i < imax; ++i) { if (listeners[i] instanceof TimbreObject) { listeners[i].bang.apply(listeners[i], args); } else { listeners[i].apply(this.context, args); } } return true; } else if (handler instanceof TimbreObject) { args = slice.call(arguments, 1); handler.bang.apply(handler, args); } else { return false; } }; $.on = function(type, listener) { if (typeof listener !== "function" && !(listener instanceof TimbreObject)) { throw new Error("addListener takes instances of Function or timbre.Object"); } var e = this.events; if (!e[type]) { e[type] = listener; } else if (isArray(e[type])) { e[type].push(listener); } else { e[type] = [e[type], listener]; } return this; }; $.once = function(type, listener) { var self = this; var g; if (typeof listener === "function") { g = function () { self.off(type, g); listener.apply(self.context, arguments); }; } else if (listener instanceof TimbreObject) { g = function () { self.off(type, g); listener.bang.apply(listener, arguments); }; } else { throw new Error("once takes instances of Function or timbre.Object"); } g.listener = listener; self.on(type, g); return this; }; $.off = function(type, listener) { if (typeof listener !== "function" && !(listener instanceof TimbreObject)) { throw new Error("removeListener takes instances of Function or timbre.Object"); } var e = this.events; if (!e[type]) { return this; } var list = e[type]; if (isArray(list)) { var position = -1; for (var i = 0, imax = list.length; i < imax; ++i) { if (list[i] === listener || // once listener (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) { return this; } list.splice(position, 1); if (list.length === 0) { e[type] = null; } } else if (list === listener || // once listener (list.listener && list.listener === listener)) { e[type] = null; } return this; }; $.removeAllListeners = function(type) { var e = this.events; var remain = false; var listeners = e[type]; if (isArray(listeners)) { for (var i = listeners.length; i--; ) { var listener = listeners[i]; if (listener.unremovable) { remain = true; continue; } this.off(type, listener); } } else if (listeners) { if (!listeners.unremovable) { this.off(type, listeners); } else { remain = true; } } if (!remain) { e[type] = null; } return this; }; $.listeners = function(type) { var a, e = this.events; if (!e[type]) { return []; } e = e[type]; if (!isArray(e)) { return e.unremovable ? [] : [e]; } e = e.slice(); a = []; for (var i = 0, imax = e.length; i < imax; ++i) { if (!e[i].unremovable) { a.push(e[i]); } } return a; }; return EventEmitter; })(); var Deferred = modules.Deferred = (function() { function Deferred(context) { this.context = context || this; this._state = "pending"; this._doneList = []; this._failList = []; this._promise = new Promise(this); } var $ = Deferred.prototype; var exec = function(statue, list, context, args) { if (this._state === "pending") { this._state = statue; for (var i = 0, imax = list.length; i < imax; ++i) { list[i].apply(context, args); } this._doneList = this._failList = null; } }; var isDeferred = function(x) { return x && typeof x.promise === "function"; }; $.resolve = function() { var args = slice.call(arguments, 0); exec.call(this, "resolved", this._doneList, this.context || this, args); return this; }; $.resolveWith = function(context) { var args = slice.call(arguments, 1); exec.call(this, "resolved", this._doneList, context, args); return this; }; $.reject = function() { var args = slice.call(arguments, 0); exec.call(this, "rejected", this._failList, this.context || this, args); return this; }; $.rejectWith = function(context) { var args = slice.call(arguments, 1); exec.call(this, "rejected", this._failList, context, args); return this; }; $.promise = function() { return this._promise; }; $.done = function() { var args = slice.call(arguments); var isResolved = (this._state === "resolved"); var isPending = (this._state === "pending"); var list = this._doneList; for (var i = 0, imax = args.length; i < imax; ++i) { if (typeof args[i] === "function") { if (isResolved) { args[i](); } else if (isPending) { list.push(args[i]); } } } return this; }; $.fail = function() { var args = slice.call(arguments); var isRejected = (this._state === "rejected"); var isPending = (this._state === "pending"); var list = this._failList; for (var i = 0, imax = args.length; i < imax; ++i) { if (typeof args[i] === "function") { if (isRejected) { args[i](); } else if (isPending) { list.push(args[i]); } } } return this; }; $.always = function() { this.done.apply(this, arguments); this.fail.apply(this, arguments); return this; }; $.then = function then(done, fail) { return this.done(done).fail(fail); }; $.pipe = function(done, fail) { var self = this; var dfd = new Deferred(this.context); this.done(function() { var res = done.apply(self.context, arguments); if (isDeferred(res)) { res.then(function() { var args = slice.call(arguments); dfd.resolveWith.apply(dfd, [res].concat(args)); }); } else { dfd.resolveWith(self, res); } }); this.fail(function() { if (typeof fail === "function") { var res = fail.apply(self.context, arguments); if (isDeferred(res)) { res.fail(function() { var args = slice.call(arguments); dfd.rejectWith.apply(dfd, [res].concat(args)); }); } } else { dfd.reject.apply(dfd, arguments); } }); return dfd.promise(); }; // $.then = $.pipe; $.isResolved = function() { return this._state === "resolved"; }; $.isRejected = function() { return this._state === "rejected"; }; $.state = function() { return this._state; }; // TODO: test Deferred.when = function(subordinate) { var i = 0; var resolveValues = slice.call(arguments); var length = resolveValues.length; var remaining = length; if (length === 1 && !isDeferred(subordinate)) { remaining = 0; } var deferred = (remaining === 1) ? subordinate : new Deferred(); var updateFunc = function(i, results) { return function(value) { results[i] = arguments.length > 1 ? slice.call(arguments) : value; if (!(--remaining)) { deferred.resolve.apply(deferred, results); } }; }; if (length > 1) { var resolveResults = new Array(length); var onfailed = function() { deferred.reject(); }; for (; i < length; ++i) { if (resolveValues[i] && isDeferred(resolveValues[i])) { resolveValues[i].promise().done( updateFunc(i, resolveResults) ).fail(onfailed); } else { resolveResults[i] = resolveValues[i]; --remaining; } } } if (!remaining) { deferred.resolve.apply(deferred, resolveValues); } return deferred.promise(); }; function Promise(object) { this.context = object.context; this.then = object.then; this.done = function() { object.done.apply(object, arguments); return this; }; this.fail = function() { object.fail.apply(object, arguments); return this; }; this.pipe = function() { return object.pipe.apply(object, arguments); }; this.always = function() { object.always.apply(object, arguments); return this; }; this.promise = function() { return this; }; this.isResolved = function() { return object.isResolved(); }; this.isRejected = function() { return object.isRejected(); }; } return Deferred; })(); // root object var TimbreObject = timbre.Object = (function() { function TimbreObject(numChannels, _args) { this._ = {}; // private members var e = this._.events = new EventEmitter(this); this._.emit = function() { return e.emit.apply(e, arguments); }; if (isDictionary(_args[0])) { var params = _args.shift(); var _in = params["in"]; this.once("init", function() { this.set(params); if (_in) { if (isArray(_in)) { this.append.apply(this, _in); } else if (_in instanceof TimbreObject) { this.append(_in); } } }); } this.tickID = -1; this.nodes = _args.map(timbre); this.cells = []; this.numChannels = numChannels; switch (numChannels) { case 0: this.L = this.R = new ChannelObject(null); this.cells[0] = this.cells[1] = this.cells[2] = this.L.cell; break; case 1: this.L = this.R = new ChannelObject(this); this.cells[0] = this.cells[1] = this.cells[2] = this.L.cell; break; case 2: this.L = new ChannelObject(this); this.R = new ChannelObject(this); this.cells[0] = new fn.SignalArray(_sys.cellsize); this.cells[1] = this.L.cell; this.cells[2] = this.R.cell; break; } this.playbackState = PLAYING_STATE; this.nodeType = TimbreObject.DSP; this._.ar = true; this._.mul = 1; this._.add = 0; this._.dac = null; this._.bypassed = false; this._.meta = {}; this._.samplerate = _sys.samplerate; this._.cellsize = _sys.cellsize; this._.buddies = []; } TimbreObject.DSP = 1; TimbreObject.TIMER = 2; TimbreObject.LISTENER = 3; var $ = TimbreObject.prototype; Object.defineProperties($, { isAr: { get: function() { return this._.ar; } }, isKr: { get: function() { return !this._.ar; } }, isBypassed: { get: function() { return this._.bypassed; } }, isEnded: { get: function() { return !(this.playbackState & 1); } }, mul: { set: function(value) { if (typeof value === "number") { this._.mul = value; this._.emit("setMul", value); } }, get: function() { return this._.mul; } }, add: { set: function(value) { if (typeof value === "number") { this._.add = value; this._.emit("setAdd", value); } }, get: function() { return this._.add; } }, buddies: { set: function(value) { if (!isArray(value)) { value = [value]; } this._.buddies = value.filter(function(node) { return node instanceof TimbreObject; }); }, get: function() { return this._.buddies; } } }); $.toString = function() { return this.constructor.name; }; $.valueOf = function() { if (_sys.tickID !== this.tickID) { this.process(_sys.tickID); } return this.cells[0][0]; }; $.append = function() { if (arguments.length > 0) { var list = slice.call(arguments).map(timbre); this.nodes = this.nodes.concat(list); this._.emit("append", list); } return this; }; $.appendTo = function(object) { object.append(this); return this; }; $.remove = function() { if (arguments.length > 0) { var j, nodes = this.nodes, list = []; for (var i = 0, imax = arguments.length; i < imax; ++i) { if ((j = nodes.indexOf(arguments[i])) !== -1) { list.push(nodes[j]); nodes.splice(j, 1); } } if (list.length > 0) { this._.emit("remove", list); } } return this; }; $.removeFrom = function(object) { object.remove(this); return this; }; $.removeAll = function() { var list = this.nodes.slice(); this.nodes = []; if (list.length > 0) { this._.emit("remove", list); } return this; }; $.removeAtIndex = function(index) { var item = this.nodes[index]; if (item) { this.nodes.splice(index, 1); this._.emit("remove", [item]); } return this; }; $.postMessage = function(message) { this._.emit("message", message); return this; }; $.to = function(object) { if (object instanceof TimbreObject) { object.append(this); } else { var args = slice.call(arguments); if (isDictionary(args[1])) { args.splice(2, 0, this); } else { args.splice(1, 0, this); } object = T.apply(null, args); } return object; }; $.splice = function(ins, obj, rem) { var i; if (!obj) { if (this._.dac) { if (ins instanceof TimbreObject) { if (rem instanceof TimbreObject) { if (rem._.dac) { rem._.dac._.node = ins; ins._.dac = rem._.dac; rem._.dac = null; ins.nodes.push(this); } } else { if (this._.dac) { this._.dac._.node = ins; ins._.dac = this._.dac; this._.dac = null; ins.nodes.push(this); } } } else if (rem instanceof TimbreObject) { if (rem._.dac) { rem._.dac._.node = this; this._.dac = rem._.dac; rem._.dac = null; } } } } else { if (obj instanceof TimbreObject) { i = obj.nodes.indexOf(rem); if (i !== -1) { obj.nodes.splice(i, 1); } if (ins instanceof TimbreObject) { ins.nodes.push(this); obj.nodes.push(ins); } else { obj.nodes.push(this); } } } return this; }; // EventEmitter $.on = $.addListener = function(type, listener) { this._.events.on(type, listener); return this; }; $.once = function(type, listener) { this._.events.once(type, listener); return this; }; $.off = $.removeListener = function(type, listener) { this._.events.off(type, listener); return this; }; $.removeAllListeners = function(type) { this._.events.removeAllListeners(type); return this; }; $.listeners = function(type) { return this._.events.listeners(type); }; $.set = function(key, value) { var x, desc, meta = this._.meta; switch (typeof key) { case "string": switch (meta[key]) { case "property": this[key] = value; break; case "function": this[key](value); break; default: x = this; while (x !== null) { desc = Object.getOwnPropertyDescriptor(x, key); if (desc) { if (typeof desc.value === "function") { meta[key] = "function"; this[key](value); } else if (desc.get || desc.set) { meta[key] = "property"; this[key] = value; } } x = Object.getPrototypeOf(x); } } break; case "object": for (x in key) { this.set(x, key[x]); } break; } return this; }; $.get = function(key) { if (this._.meta[key] === "property") { return this[key]; } }; $.bang = function() { this._.emit.apply(this, ["bang"].concat(slice.call(arguments))); return this; }; $.process = fn.nop; $.bypass = function() { this._.bypassed = (arguments.length === 0) ? true : !!arguments[0]; return this; }; $.play = function() { var dac = this._.dac; if (dac === null) { dac = this._.dac = new SystemInlet(this); } if (dac.play()) { this._.emit.apply(this, ["play"].concat(slice.call(arguments))); } fn.buddies_start(this); return this; }; $.pause = function() { var dac = this._.dac; if (dac && dac.playbackState === PLAYING_STATE) { dac.pause(); this._.dac = null; this._.emit("pause"); } fn.buddies_stop(this); return this; }; $.start = $.stop = $.listen = $.unlisten = function() { return this; }; $.ar = function() { if ((arguments.length === 0) ? true : !!arguments[0]) { if (!this._.kronly) { this._.ar = true; this._.emit("ar", true); } } else { this.kr(true); } return this; }; $.kr = function() { if ((arguments.length === 0) ? true : !!arguments[0]) { if (!this._.aronly) { this._.ar = false; this._.emit("ar", false); } } else { this.ar(true); } return this; }; if (_envtype === "browser") { $.plot = function(opts) { var _ = this._; var canvas = opts.target; if (!canvas) { return this; } var width = opts.width || canvas.width || 320; var height = opts.height || canvas.height || 240; var offset_x = (opts.x || 0) + 0.5;