From c370c357865d32e7e284fe53ea28556f667ca172 Mon Sep 17 00:00:00 2001 From: azeem Date: Tue, 22 Oct 2013 12:11:25 +0530 Subject: [PATCH] fixes. adding build into master --- .gitignore | 1 - build/libs.js | 2666 ++++++++++++++++ build/pegs_expr_parser.js | 2152 +++++++++++++ build/webvs.js | 6135 +++++++++++++++++++++++++++++++++++++ dist/webvs.full.min.js | 4 +- dist/webvs.min.js | 4 +- 6 files changed, 10957 insertions(+), 5 deletions(-) create mode 100644 build/libs.js create mode 100644 build/pegs_expr_parser.js create mode 100644 build/webvs.js diff --git a/.gitignore b/.gitignore index e549e11..7a6cd2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules .idea -build bower_components diff --git a/build/libs.js b/build/libs.js new file mode 100644 index 0000000..7f826da --- /dev/null +++ b/build/libs.js @@ -0,0 +1,2666 @@ +// Underscore.js 1.5.1 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.5.1'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? void 0 : []; + return _[first ? 'find' : 'filter'](obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed > result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + index : index, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value == null ? _.identity : value); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + }; + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var length = _.max(_.pluck(arguments, "length").concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, l = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error("bindAll must be passed function names"); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var result; + var timeout = null; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + +}).call(this); + +/* + * DSP.js - a comprehensive digital signal processing library for javascript + * + * Created by Corban Brook on 2010-01-01. + * Copyright 2010 Corban Brook. All rights reserved. + * + */ + +// Fourier Transform Module used by DFT, FFT, RFFT +function FourierTransform(bufferSize, sampleRate) { + this.bufferSize = bufferSize; + this.sampleRate = sampleRate; + this.bandwidth = 2 / bufferSize * sampleRate / 2; + + this.spectrum = new Float32Array(bufferSize/2); + this.real = new Float32Array(bufferSize); + this.imag = new Float32Array(bufferSize); + + this.peakBand = 0; + this.peak = 0; + + /** + * Calculates the *middle* frequency of an FFT band. + * + * @param {Number} index The index of the FFT band. + * + * @returns The middle frequency in Hz. + */ + this.getBandFrequency = function(index) { + return this.bandwidth * index + this.bandwidth / 2; + }; + + this.calculateSpectrum = function() { + var spectrum = this.spectrum, + real = this.real, + imag = this.imag, + bSi = 2 / this.bufferSize, + sqrt = Math.sqrt, + rval, + ival, + mag; + + for (var i = 0, N = bufferSize/2; i < N; i++) { + rval = real[i]; + ival = imag[i]; + mag = bSi * sqrt(rval * rval + ival * ival); + + if (mag > this.peak) { + this.peakBand = i; + this.peak = mag; + } + + spectrum[i] = mag; + } + }; +} + +/** + * FFT is a class for calculating the Discrete Fourier Transform of a signal + * with the Fast Fourier Transform algorithm. + * + * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 + * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) + * + * @constructor + */ +function FFT(bufferSize, sampleRate) { + FourierTransform.call(this, bufferSize, sampleRate); + + this.reverseTable = new Uint32Array(bufferSize); + + var limit = 1; + var bit = bufferSize >> 1; + + var i; + + while (limit < bufferSize) { + for (i = 0; i < limit; i++) { + this.reverseTable[i + limit] = this.reverseTable[i] + bit; + } + + limit = limit << 1; + bit = bit >> 1; + } + + this.sinTable = new Float32Array(bufferSize); + this.cosTable = new Float32Array(bufferSize); + + for (i = 0; i < bufferSize; i++) { + this.sinTable[i] = Math.sin(-Math.PI/i); + this.cosTable[i] = Math.cos(-Math.PI/i); + } +} + +/** + * Performs a forward transform on the sample buffer. + * Converts a time domain signal to frequency domain spectra. + * + * @param {Array} buffer The sample buffer. Buffer Length must be power of 2 + * + * @returns The frequency spectrum array + */ +FFT.prototype.forward = function(buffer) { + // Locally scope variables for speed up + var bufferSize = this.bufferSize, + cosTable = this.cosTable, + sinTable = this.sinTable, + reverseTable = this.reverseTable, + real = this.real, + imag = this.imag, + spectrum = this.spectrum; + + var k = Math.floor(Math.log(bufferSize) / Math.LN2); + + if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; } + if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; } + + var halfSize = 1, + phaseShiftStepReal, + phaseShiftStepImag, + currentPhaseShiftReal, + currentPhaseShiftImag, + off, + tr, + ti, + tmpReal, + i; + + for (i = 0; i < bufferSize; i++) { + real[i] = buffer[reverseTable[i]]; + imag[i] = 0; + } + + while (halfSize < bufferSize) { + //phaseShiftStepReal = Math.cos(-Math.PI/halfSize); + //phaseShiftStepImag = Math.sin(-Math.PI/halfSize); + phaseShiftStepReal = cosTable[halfSize]; + phaseShiftStepImag = sinTable[halfSize]; + + currentPhaseShiftReal = 1; + currentPhaseShiftImag = 0; + + for (var fftStep = 0; fftStep < halfSize; fftStep++) { + i = fftStep; + + while (i < bufferSize) { + off = i + halfSize; + tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); + ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); + + real[off] = real[i] - tr; + imag[off] = imag[i] - ti; + real[i] += tr; + imag[i] += ti; + + i += halfSize << 1; + } + + tmpReal = currentPhaseShiftReal; + currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); + currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); + } + + halfSize = halfSize << 1; + } + + return this.calculateSpectrum(); +}; + +/* + * Dancer.js (c) 2012 Jordan Santell + * MIT License + * http://github.com/jsantell/dancer.js + * + * v0.3.1 + */ + +(function() { + + var Dancer = function () { + this.audioAdapter = Dancer._getAdapter( this ); + this.events = {}; + this.sections = []; + this.bind( 'update', update ); + }; + + Dancer.adapters = {}; + + Dancer.prototype = { + + load : function ( source ) { + var path; + + // Loading an Audio element + if ( source instanceof HTMLElement ) { + this.source = source; + if ( Dancer.isSupported() === 'flash' ) { + this.source = { src: Dancer._getMP3SrcFromAudio( source ) }; + } + + // Loading an object with src, [codecs] + } else { + this.source = window.Audio ? new Audio() : {}; + this.source.src = Dancer._makeSupportedPath( source.src, source.codecs ); + } + + this.audio = this.audioAdapter.load( this.source ); + return this; + }, + + /* Controls */ + + play : function () { + this.audioAdapter.play(); + return this; + }, + + pause : function () { + this.audioAdapter.pause(); + return this; + }, + + setVolume : function ( volume ) { + this.audioAdapter.setVolume( volume ); + return this; + }, + + + /* Actions */ + + createKick : function ( options ) { + return new Dancer.Kick( this, options ); + }, + + bind : function ( name, callback ) { + if ( !this.events[ name ] ) { + this.events[ name ] = []; + } + this.events[ name ].push( callback ); + return this; + }, + + unbind : function ( name ) { + if ( this.events[ name ] ) { + delete this.events[ name ]; + } + return this; + }, + + trigger : function ( name ) { + var _this = this; + if ( this.events[ name ] ) { + this.events[ name ].forEach(function( callback ) { + callback.call( _this ); + }); + } + return this; + }, + + + /* Getters */ + + getVolume : function () { + return this.audioAdapter.getVolume(); + }, + + getProgress : function () { + return this.audioAdapter.getProgress(); + }, + + getTime : function () { + return this.audioAdapter.getTime(); + }, + + // Returns the magnitude of a frequency or average over a range of frequencies + getFrequency : function ( freq, endFreq ) { + var sum = 0; + if ( endFreq !== undefined ) { + for ( var i = freq; i <= endFreq; i++ ) { + sum += this.getSpectrum()[ i ]; + } + return sum / ( endFreq - freq + 1 ); + } else { + return this.getSpectrum()[ freq ]; + } + }, + + getWaveform : function () { + return this.audioAdapter.getWaveform(); + }, + + getSpectrum : function () { + return this.audioAdapter.getSpectrum(); + }, + + isLoaded : function () { + return this.audioAdapter.isLoaded; + }, + + isPlaying : function () { + return this.audioAdapter.isPlaying; + }, + + + /* Sections */ + + after : function ( time, callback ) { + var _this = this; + this.sections.push({ + condition : function () { + return _this.getTime() > time; + }, + callback : callback + }); + return this; + }, + + before : function ( time, callback ) { + var _this = this; + this.sections.push({ + condition : function () { + return _this.getTime() < time; + }, + callback : callback + }); + return this; + }, + + between : function ( startTime, endTime, callback ) { + var _this = this; + this.sections.push({ + condition : function () { + return _this.getTime() > startTime && _this.getTime() < endTime; + }, + callback : callback + }); + return this; + }, + + onceAt : function ( time, callback ) { + var + _this = this, + thisSection = null; + this.sections.push({ + condition : function () { + return _this.getTime() > time && !this.called; + }, + callback : function () { + callback.call( this ); + thisSection.called = true; + }, + called : false + }); + // Baking the section in the closure due to callback's this being the dancer instance + thisSection = this.sections[ this.sections.length - 1 ]; + return this; + } + }; + + function update () { + for ( var i in this.sections ) { + if ( this.sections[ i ].condition() ) + this.sections[ i ].callback.call( this ); + } + } + + window.Dancer = Dancer; +})(); + +(function ( Dancer ) { + + var CODECS = { + 'mp3' : 'audio/mpeg;', + 'ogg' : 'audio/ogg; codecs="vorbis"', + 'wav' : 'audio/wav; codecs="1"', + 'aac' : 'audio/mp4; codecs="mp4a.40.2"' + }, + audioEl = document.createElement( 'audio' ); + + Dancer.options = {}; + + Dancer.setOptions = function ( o ) { + for ( var option in o ) { + if ( o.hasOwnProperty( option ) ) { + Dancer.options[ option ] = o[ option ]; + } + } + }; + + Dancer.isSupported = function () { + if ( !window.Float32Array || !window.Uint32Array ) { + return null; + } else if ( !isUnsupportedSafari() && ( window.AudioContext || window.webkitAudioContext )) { + return 'webaudio'; + } else if ( audioEl && audioEl.mozSetup ) { + return 'audiodata'; + } else if ( FlashDetect.versionAtLeast( 9 ) ) { + return 'flash'; + } else { + return ''; + } + }; + + Dancer.canPlay = function ( type ) { + var canPlay = audioEl.canPlayType; + return !!( + Dancer.isSupported() === 'flash' ? + type.toLowerCase() === 'mp3' : + audioEl.canPlayType && + audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, '')); + }; + + Dancer.addPlugin = function ( name, fn ) { + if ( Dancer.prototype[ name ] === undefined ) { + Dancer.prototype[ name ] = fn; + } + }; + + Dancer._makeSupportedPath = function ( source, codecs ) { + if ( !codecs ) { return source; } + + for ( var i = 0; i < codecs.length; i++ ) { + if ( Dancer.canPlay( codecs[ i ] ) ) { + return source + '.' + codecs[ i ]; + } + } + return source; + }; + + Dancer._getAdapter = function ( instance ) { + switch ( Dancer.isSupported() ) { + case 'webaudio': + return new Dancer.adapters.webkit( instance ); + case 'audiodata': + return new Dancer.adapters.moz( instance ); + case 'flash': + return new Dancer.adapters.flash( instance ); + default: + return null; + } + }; + + Dancer._getMP3SrcFromAudio = function ( audioEl ) { + var sources = audioEl.children; + if ( audioEl.src ) { return audioEl.src; } + for ( var i = sources.length; i--; ) { + if (( sources[ i ].type || '' ).match( /audio\/mpeg/ )) return sources[ i ].src; + } + return null; + }; + + // Browser detection is lame, but Safari 6 has Web Audio API, + // but does not support processing audio from a Media Element Source + // https://gist.github.com/3265344 + function isUnsupportedSafari () { + var + isApple = !!( navigator.vendor || '' ).match( /Apple/ ), + version = navigator.userAgent.match( /Version\/([^ ]*)/ ); + version = version ? parseFloat( version[ 1 ] ) : 0; + return isApple && version <= 6; + } + +})( window.Dancer ); + +(function ( undefined ) { + var Kick = function ( dancer, o ) { + o = o || {}; + this.dancer = dancer; + this.frequency = o.frequency !== undefined ? o.frequency : [ 0, 10 ]; + this.threshold = o.threshold !== undefined ? o.threshold : 0.3; + this.decay = o.decay !== undefined ? o.decay : 0.02; + this.onKick = o.onKick; + this.offKick = o.offKick; + this.isOn = false; + this.currentThreshold = this.threshold; + + var _this = this; + this.dancer.bind( 'update', function () { + _this.onUpdate(); + }); + }; + + Kick.prototype = { + on : function () { + this.isOn = true; + return this; + }, + off : function () { + this.isOn = false; + return this; + }, + + set : function ( o ) { + o = o || {}; + this.frequency = o.frequency !== undefined ? o.frequency : this.frequency; + this.threshold = o.threshold !== undefined ? o.threshold : this.threshold; + this.decay = o.decay !== undefined ? o.decay : this.decay; + this.onKick = o.onKick || this.onKick; + this.offKick = o.offKick || this.offKick; + }, + + onUpdate : function () { + if ( !this.isOn ) { return; } + var magnitude = this.maxAmplitude( this.frequency ); + if ( magnitude >= this.currentThreshold && + magnitude >= this.threshold ) { + this.currentThreshold = magnitude; + this.onKick && this.onKick.call( this.dancer, magnitude ); + } else { + this.offKick && this.offKick.call( this.dancer, magnitude ); + this.currentThreshold -= this.decay; + } + }, + maxAmplitude : function ( frequency ) { + var + max = 0, + fft = this.dancer.getSpectrum(); + + // Sloppy array check + if ( !frequency.length ) { + return frequency < fft.length ? + fft[ ~~frequency ] : + null; + } + + for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) { + if ( fft[ i ] > max ) { max = fft[ i ]; } + } + return max; + } + }; + + window.Dancer.Kick = Kick; +})(); + +(function() { + var + SAMPLE_SIZE = 2048, + SAMPLE_RATE = 44100; + + var adapter = function ( dancer ) { + this.dancer = dancer; + this.audio = new Audio(); + this.context = window.AudioContext ? + new window.AudioContext() : + new window.webkitAudioContext(); + }; + + adapter.prototype = { + + load : function ( _source ) { + var _this = this; + this.audio = _source; + + this.isLoaded = false; + this.progress = 0; + + this.proc = this.context.createJavaScriptNode( SAMPLE_SIZE / 2, 1, 1 ); + this.proc.onaudioprocess = function ( e ) { + _this.update.call( _this, e ); + }; + this.gain = this.context.createGainNode(); + + this.fft = new FFT( SAMPLE_SIZE / 2, SAMPLE_RATE ); + this.signal = new Float32Array( SAMPLE_SIZE / 2 ); + + if ( this.audio.readyState < 3 ) { + this.audio.addEventListener( 'canplay', function () { + connectContext.call( _this ); + }); + } else { + connectContext.call( _this ); + } + + this.audio.addEventListener( 'progress', function ( e ) { + if ( e.currentTarget.duration ) { + _this.progress = e.currentTarget.seekable.end( 0 ) / e.currentTarget.duration; + } + }); + + return this.audio; + }, + + play : function () { + this.audio.play(); + this.isPlaying = true; + }, + + pause : function () { + this.audio.pause(); + this.isPlaying = false; + }, + + setVolume : function ( volume ) { + this.gain.gain.value = volume; + }, + + getVolume : function () { + return this.gain.gain.value; + }, + + getProgress : function() { + return this.progress; + }, + + getWaveform : function () { + return this.signal; + }, + + getSpectrum : function () { + return this.fft.spectrum; + }, + + getTime : function () { + return this.audio.currentTime; + }, + + update : function ( e ) { + if ( !this.isPlaying || !this.isLoaded ) return; + + var + buffers = [], + channels = e.inputBuffer.numberOfChannels, + resolution = SAMPLE_SIZE / channels, + i, + sum = function ( prev, curr ) { + return prev[ i ] + curr[ i ]; + }; + + for ( i = channels; i--; ) { + buffers.push( e.inputBuffer.getChannelData( i ) ); + } + + for ( i = 0; i < resolution; i++ ) { + this.signal[ i ] = channels > 1 ? + buffers.reduce( sum( prev, curr ) ) / channels : + buffers[ 0 ][ i ]; + } + + this.fft.forward( this.signal ); + this.dancer.trigger( 'update' ); + } + }; + + function connectContext () { + this.source = this.context.createMediaElementSource( this.audio ); + this.source.connect( this.proc ); + this.source.connect( this.gain ); + this.gain.connect( this.context.destination ); + this.proc.connect( this.context.destination ); + + this.isLoaded = true; + this.progress = 1; + this.dancer.trigger( 'loaded' ); + } + + Dancer.adapters.webkit = adapter; + +})(); + +(function() { + + var adapter = function ( dancer ) { + this.dancer = dancer; + this.audio = new Audio(); + }; + + adapter.prototype = { + + load : function ( _source ) { + var _this = this; + this.audio = _source; + + this.isLoaded = false; + this.progress = 0; + + if ( this.audio.readyState < 3 ) { + this.audio.addEventListener( 'loadedmetadata', function () { + getMetadata.call( _this ); + }, false); + } else { + getMetadata.call( _this ); + } + + this.audio.addEventListener( 'MozAudioAvailable', function ( e ) { + _this.update( e ); + }, false); + + this.audio.addEventListener( 'progress', function ( e ) { + if ( e.currentTarget.duration ) { + _this.progress = e.currentTarget.seekable.end( 0 ) / e.currentTarget.duration; + } + }, false); + + return this.audio; + }, + + play : function () { + this.audio.play(); + this.isPlaying = true; + }, + + pause : function () { + this.audio.pause(); + this.isPlaying = false; + }, + + setVolume : function ( volume ) { + this.audio.volume = volume; + }, + + getVolume : function () { + return this.audio.volume; + }, + + getProgress : function () { + return this.progress; + }, + + getWaveform : function () { + return this.signal; + }, + + getSpectrum : function () { + return this.fft.spectrum; + }, + + getTime : function () { + return this.audio.currentTime; + }, + + update : function ( e ) { + if ( !this.isPlaying || !this.isLoaded ) return; + + for ( var i = 0, j = this.fbLength / 2; i < j; i++ ) { + this.signal[ i ] = ( e.frameBuffer[ 2 * i ] + e.frameBuffer[ 2 * i + 1 ] ) / 2; + } + + this.fft.forward( this.signal ); + this.dancer.trigger( 'update' ); + } + }; + + function getMetadata () { + this.fbLength = this.audio.mozFrameBufferLength; + this.channels = this.audio.mozChannels; + this.rate = this.audio.mozSampleRate; + this.fft = new FFT( this.fbLength / this.channels, this.rate ); + this.signal = new Float32Array( this.fbLength / this.channels ); + this.isLoaded = true; + this.progress = 1; + this.dancer.trigger( 'loaded' ); + } + + Dancer.adapters.moz = adapter; + +})(); + +(function() { + var + SAMPLE_SIZE = 1024, + SAMPLE_RATE = 44100, + smLoaded = false, + smLoading = false, + CONVERSION_COEFFICIENT = 0.93; + + var adapter = function ( dancer ) { + this.dancer = dancer; + this.wave_L = []; + this.wave_R = []; + this.spectrum = []; + window.SM2_DEFER = true; + }; + + adapter.prototype = { + // `source` can be either an Audio element, if supported, or an object + // either way, the path is stored in the `src` property + load : function ( source ) { + var _this = this; + this.path = source ? source.src : this.path; + + this.isLoaded = false; + this.progress = 0; + + !window.soundManager && !smLoading && loadSM.call( this ); + + if ( window.soundManager ) { + this.audio = soundManager.createSound({ + id : 'dancer' + Math.random() + '', + url : this.path, + stream : true, + autoPlay : false, + autoLoad : true, + whileplaying : function () { + _this.update(); + }, + whileloading : function () { + _this.progress = this.bytesLoaded / this.bytesTotal; + }, + onload : function () { + _this.fft = new FFT( SAMPLE_SIZE, SAMPLE_RATE ); + _this.signal = new Float32Array( SAMPLE_SIZE ); + _this.waveform = new Float32Array( SAMPLE_SIZE ); + _this.isLoaded = true; + _this.progress = 1; + _this.dancer.trigger( 'loaded' ); + } + }); + this.dancer.audio = this.audio; + } + + // Returns audio if SM already loaded -- otherwise, + // sets dancer instance's audio property after load + return this.audio; + }, + + play : function () { + this.audio.play(); + this.isPlaying = true; + }, + + pause : function () { + this.audio.pause(); + this.isPlaying = false; + }, + + setVolume : function ( volume ) { + this.audio.setVolume( volume * 100 ); + }, + + getVolume : function () { + return this.audio.volume / 100; + }, + + getProgress : function () { + return this.progress; + }, + + getWaveform : function () { + return this.waveform; + }, + + getSpectrum : function () { + return this.fft.spectrum; + }, + + getTime : function () { + return this.audio.position / 1000; + }, + + update : function () { + if ( !this.isPlaying && !this.isLoaded ) return; + this.wave_L = this.audio.waveformData.left; + this.wave_R = this.audio.waveformData.right; + var avg; + for ( var i = 0, j = this.wave_L.length; i < j; i++ ) { + avg = parseFloat(this.wave_L[ i ]) + parseFloat(this.wave_R[ i ]); + this.waveform[ 2 * i ] = avg / 2; + this.waveform[ i * 2 + 1 ] = avg / 2; + this.signal[ 2 * i ] = avg * CONVERSION_COEFFICIENT; + this.signal[ i * 2 + 1 ] = avg * CONVERSION_COEFFICIENT; + } + + this.fft.forward( this.signal ); + this.dancer.trigger( 'update' ); + } + }; + + function loadSM () { + var adapter = this; + smLoading = true; + loadScript( Dancer.options.flashJS, function () { + soundManager = new SoundManager(); + soundManager.flashVersion = 9; + soundManager.flash9Options.useWaveformData = true; + soundManager.useWaveformData = true; + soundManager.useHighPerformance = true; + soundManager.useFastPolling = true; + soundManager.multiShot = false; + soundManager.debugMode = false; + soundManager.debugFlash = false; + soundManager.url = Dancer.options.flashSWF; + soundManager.onready(function () { + smLoaded = true; + adapter.load(); + }); + soundManager.ontimeout(function(){ + console.error( 'Error loading SoundManager2.swf' ); + }); + soundManager.beginDelayedInit(); + }); + } + + function loadScript ( url, callback ) { + var + script = document.createElement( 'script' ), + appender = document.getElementsByTagName( 'script' )[0]; + script.type = 'text/javascript'; + script.src = url; + script.onload = callback; + appender.parentNode.insertBefore( script, appender ); + } + + Dancer.adapters.flash = adapter; + +})(); + +/* + * DSP.js - a comprehensive digital signal processing library for javascript + * + * Created by Corban Brook on 2010-01-01. + * Copyright 2010 Corban Brook. All rights reserved. + * + */ + +// Fourier Transform Module used by DFT, FFT, RFFT +function FourierTransform(bufferSize, sampleRate) { + this.bufferSize = bufferSize; + this.sampleRate = sampleRate; + this.bandwidth = 2 / bufferSize * sampleRate / 2; + + this.spectrum = new Float32Array(bufferSize/2); + this.real = new Float32Array(bufferSize); + this.imag = new Float32Array(bufferSize); + + this.peakBand = 0; + this.peak = 0; + + /** + * Calculates the *middle* frequency of an FFT band. + * + * @param {Number} index The index of the FFT band. + * + * @returns The middle frequency in Hz. + */ + this.getBandFrequency = function(index) { + return this.bandwidth * index + this.bandwidth / 2; + }; + + this.calculateSpectrum = function() { + var spectrum = this.spectrum, + real = this.real, + imag = this.imag, + bSi = 2 / this.bufferSize, + sqrt = Math.sqrt, + rval, + ival, + mag; + + for (var i = 0, N = bufferSize/2; i < N; i++) { + rval = real[i]; + ival = imag[i]; + mag = bSi * sqrt(rval * rval + ival * ival); + + if (mag > this.peak) { + this.peakBand = i; + this.peak = mag; + } + + spectrum[i] = mag; + } + }; +} + +/** + * FFT is a class for calculating the Discrete Fourier Transform of a signal + * with the Fast Fourier Transform algorithm. + * + * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2 + * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100) + * + * @constructor + */ +function FFT(bufferSize, sampleRate) { + FourierTransform.call(this, bufferSize, sampleRate); + + this.reverseTable = new Uint32Array(bufferSize); + + var limit = 1; + var bit = bufferSize >> 1; + + var i; + + while (limit < bufferSize) { + for (i = 0; i < limit; i++) { + this.reverseTable[i + limit] = this.reverseTable[i] + bit; + } + + limit = limit << 1; + bit = bit >> 1; + } + + this.sinTable = new Float32Array(bufferSize); + this.cosTable = new Float32Array(bufferSize); + + for (i = 0; i < bufferSize; i++) { + this.sinTable[i] = Math.sin(-Math.PI/i); + this.cosTable[i] = Math.cos(-Math.PI/i); + } +} + +/** + * Performs a forward transform on the sample buffer. + * Converts a time domain signal to frequency domain spectra. + * + * @param {Array} buffer The sample buffer. Buffer Length must be power of 2 + * + * @returns The frequency spectrum array + */ +FFT.prototype.forward = function(buffer) { + // Locally scope variables for speed up + var bufferSize = this.bufferSize, + cosTable = this.cosTable, + sinTable = this.sinTable, + reverseTable = this.reverseTable, + real = this.real, + imag = this.imag, + spectrum = this.spectrum; + + var k = Math.floor(Math.log(bufferSize) / Math.LN2); + + if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; } + if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; } + + var halfSize = 1, + phaseShiftStepReal, + phaseShiftStepImag, + currentPhaseShiftReal, + currentPhaseShiftImag, + off, + tr, + ti, + tmpReal, + i; + + for (i = 0; i < bufferSize; i++) { + real[i] = buffer[reverseTable[i]]; + imag[i] = 0; + } + + while (halfSize < bufferSize) { + //phaseShiftStepReal = Math.cos(-Math.PI/halfSize); + //phaseShiftStepImag = Math.sin(-Math.PI/halfSize); + phaseShiftStepReal = cosTable[halfSize]; + phaseShiftStepImag = sinTable[halfSize]; + + currentPhaseShiftReal = 1; + currentPhaseShiftImag = 0; + + for (var fftStep = 0; fftStep < halfSize; fftStep++) { + i = fftStep; + + while (i < bufferSize) { + off = i + halfSize; + tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); + ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); + + real[off] = real[i] - tr; + imag[off] = imag[i] - ti; + real[i] += tr; + imag[i] += ti; + + i += halfSize << 1; + } + + tmpReal = currentPhaseShiftReal; + currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); + currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); + } + + halfSize = halfSize << 1; + } + + return this.calculateSpectrum(); +}; + +/* +Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved. +Code licensed under the BSD License: http://www.featureblend.com/license.txt +Version: 1.0.4 +*/ +var FlashDetect = new function(){ + var self = this; + self.installed = false; + self.raw = ""; + self.major = -1; + self.minor = -1; + self.revision = -1; + self.revisionStr = ""; + var activeXDetectRules = [ + { + "name":"ShockwaveFlash.ShockwaveFlash.7", + "version":function(obj){ + return getActiveXVersion(obj); + } + }, + { + "name":"ShockwaveFlash.ShockwaveFlash.6", + "version":function(obj){ + var version = "6,0,21"; + try{ + obj.AllowScriptAccess = "always"; + version = getActiveXVersion(obj); + }catch(err){} + return version; + } + }, + { + "name":"ShockwaveFlash.ShockwaveFlash", + "version":function(obj){ + return getActiveXVersion(obj); + } + } + ]; + /** + * Extract the ActiveX version of the plugin. + * + * @param {Object} The flash ActiveX object. + * @type String + */ + var getActiveXVersion = function(activeXObj){ + var version = -1; + try{ + version = activeXObj.GetVariable("$version"); + }catch(err){} + return version; + }; + /** + * Try and retrieve an ActiveX object having a specified name. + * + * @param {String} name The ActiveX object name lookup. + * @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true. + * @type Object + */ + var getActiveXObject = function(name){ + var obj = -1; + try{ + obj = new ActiveXObject(name); + }catch(err){ + obj = {activeXError:true}; + } + return obj; + }; + /** + * Parse an ActiveX $version string into an object. + * + * @param {String} str The ActiveX Object GetVariable($version) return value. + * @return An object having raw, major, minor, revision and revisionStr attributes. + * @type Object + */ + var parseActiveXVersion = function(str){ + var versionArray = str.split(",");//replace with regex + return { + "raw":str, + "major":parseInt(versionArray[0].split(" ")[1], 10), + "minor":parseInt(versionArray[1], 10), + "revision":parseInt(versionArray[2], 10), + "revisionStr":versionArray[2] + }; + }; + /** + * Parse a standard enabledPlugin.description into an object. + * + * @param {String} str The enabledPlugin.description value. + * @return An object having raw, major, minor, revision and revisionStr attributes. + * @type Object + */ + var parseStandardVersion = function(str){ + var descParts = str.split(/ +/); + var majorMinor = descParts[2].split(/\./); + var revisionStr = descParts[3]; + return { + "raw":str, + "major":parseInt(majorMinor[0], 10), + "minor":parseInt(majorMinor[1], 10), + "revisionStr":revisionStr, + "revision":parseRevisionStrToInt(revisionStr) + }; + }; + /** + * Parse the plugin revision string into an integer. + * + * @param {String} The revision in string format. + * @type Number + */ + var parseRevisionStrToInt = function(str){ + return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision; + }; + /** + * Is the major version greater than or equal to a specified version. + * + * @param {Number} version The minimum required major version. + * @type Boolean + */ + self.majorAtLeast = function(version){ + return self.major >= version; + }; + /** + * Is the minor version greater than or equal to a specified version. + * + * @param {Number} version The minimum required minor version. + * @type Boolean + */ + self.minorAtLeast = function(version){ + return self.minor >= version; + }; + /** + * Is the revision version greater than or equal to a specified version. + * + * @param {Number} version The minimum required revision version. + * @type Boolean + */ + self.revisionAtLeast = function(version){ + return self.revision >= version; + }; + /** + * Is the version greater than or equal to a specified major, minor and revision. + * + * @param {Number} major The minimum required major version. + * @param {Number} (Optional) minor The minimum required minor version. + * @param {Number} (Optional) revision The minimum required revision version. + * @type Boolean + */ + self.versionAtLeast = function(major){ + var properties = [self.major, self.minor, self.revision]; + var len = Math.min(properties.length, arguments.length); + for(i=0; i=arguments[i]){ + if(i+10){ + var type = 'application/x-shockwave-flash'; + var mimeTypes = navigator.mimeTypes; + if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){ + var version = mimeTypes[type].enabledPlugin.description; + var versionObj = parseStandardVersion(version); + self.raw = versionObj.raw; + self.major = versionObj.major; + self.minor = versionObj.minor; + self.revisionStr = versionObj.revisionStr; + self.revision = versionObj.revision; + self.installed = true; + } + }else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){ + var version = -1; + for(var i=0; i prevTime + 1000 ) { + + fps = Math.round( ( frames * 1000 ) / ( time - prevTime ) ); + fpsMin = Math.min( fpsMin, fps ); + fpsMax = Math.max( fpsMax, fps ); + + fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')'; + updateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) ); + + prevTime = time; + frames = 0; + + } + + return time; + + }, + + update: function () { + + startTime = this.end(); + + } + + } + +}; diff --git a/build/pegs_expr_parser.js b/build/pegs_expr_parser.js new file mode 100644 index 0000000..750b768 --- /dev/null +++ b/build/pegs_expr_parser.js @@ -0,0 +1,2152 @@ +Webvs.PegExprParser = (function(){ + /* + * Generated by PEG.js 0.7.0. + * + * http://pegjs.majda.cz/ + */ + + function quote(s) { + /* + * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a + * string literal except for the closing quote character, backslash, + * carriage return, line separator, paragraph separator, and line feed. + * Any character may appear in the form of an escape sequence. + * + * For portability, we also escape escape all control and non-ASCII + * characters. Note that "\0" and "\v" escape sequences are not used + * because JSHint does not like the first and IE the second. + */ + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\x08/g, '\\b') // backspace + .replace(/\t/g, '\\t') // horizontal tab + .replace(/\n/g, '\\n') // line feed + .replace(/\f/g, '\\f') // form feed + .replace(/\r/g, '\\r') // carriage return + .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) + + '"'; + } + + var result = { + /* + * Parses the input with a generated parser. If the parsing is successfull, + * returns a value explicitly or implicitly specified by the grammar from + * which the parser was generated (see |PEG.buildParser|). If the parsing is + * unsuccessful, throws |PEG.parser.SyntaxError| describing the error. + */ + parse: function(input, startRule) { + var parseFunctions = { + "program": parse_program, + "statement": parse_statement, + "unary_ops": parse_unary_ops, + "additive_ops": parse_additive_ops, + "multiplicative_ops": parse_multiplicative_ops, + "boolean_ops": parse_boolean_ops, + "boolean_expr": parse_boolean_expr, + "additive_expr": parse_additive_expr, + "multiplicative_expr": parse_multiplicative_expr, + "unary": parse_unary, + "func_call": parse_func_call, + "primary_expr": parse_primary_expr, + "assignable": parse_assignable, + "identifier": parse_identifier, + "constant": parse_constant, + "register": parse_register, + "value": parse_value, + "__": parse___, + "whiteSpace": parse_whiteSpace, + "lineEnd": parse_lineEnd, + "comment": parse_comment + }; + + if (startRule !== undefined) { + if (parseFunctions[startRule] === undefined) { + throw new Error("Invalid rule name: " + quote(startRule) + "."); + } + } else { + startRule = "program"; + } + + var pos = { offset: 0, line: 1, column: 1, seenCR: false }; + var reportFailures = 0; + var rightmostFailuresPos = { offset: 0, line: 1, column: 1, seenCR: false }; + var rightmostFailuresExpected = []; + var cache = {}; + + function padLeft(input, padding, length) { + var result = input; + + var padLength = length - input.length; + for (var i = 0; i < padLength; i++) { + result = padding + result; + } + + return result; + } + + function escape(ch) { + var charCode = ch.charCodeAt(0); + var escapeChar; + var length; + + if (charCode <= 0xFF) { + escapeChar = 'x'; + length = 2; + } else { + escapeChar = 'u'; + length = 4; + } + + return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); + } + + function clone(object) { + var result = {}; + for (var key in object) { + result[key] = object[key]; + } + return result; + } + + function advance(pos, n) { + var endOffset = pos.offset + n; + + for (var offset = pos.offset; offset < endOffset; offset++) { + var ch = input.charAt(offset); + if (ch === "\n") { + if (!pos.seenCR) { pos.line++; } + pos.column = 1; + pos.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + pos.line++; + pos.column = 1; + pos.seenCR = true; + } else { + pos.column++; + pos.seenCR = false; + } + } + + pos.offset += n; + } + + function matchFailed(failure) { + if (pos.offset < rightmostFailuresPos.offset) { + return; + } + + if (pos.offset > rightmostFailuresPos.offset) { + rightmostFailuresPos = clone(pos); + rightmostFailuresExpected = []; + } + + rightmostFailuresExpected.push(failure); + } + + function parse_program() { + var cacheKey = "program@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5, result6; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_statement(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + result2 = []; + pos2 = clone(pos); + if (input.charCodeAt(pos.offset) === 59) { + result3 = ";"; + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_statement(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + result3 = [result3, result4, result5, result6]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + while (result3 !== null) { + result2.push(result3); + pos2 = clone(pos); + if (input.charCodeAt(pos.offset) === 59) { + result3 = ";"; + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_statement(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + result3 = [result3, result4, result5, result6]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } + if (result2 !== null) { + if (input.charCodeAt(pos.offset) === 59) { + result3 = ";"; + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, p) { + var stmts = [p[0]]; + stmts = stmts.concat(_.map(p[2], function(pp) { + return pp[2]; + })); + return new Webvs.AstProgram(stmts); + })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_statement() { + var cacheKey = "statement@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_assignable(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + if (input.charCodeAt(pos.offset) === 61) { + result2 = "="; + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"=\""); + } + } + if (result2 !== null) { + result3 = parse___(); + if (result3 !== null) { + result4 = parse_boolean_expr(); + if (result4 !== null) { + result0 = [result0, result1, result2, result3, result4]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, lhs, e) { return new Webvs.AstAssignment(lhs, e); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[4]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + result0 = parse_boolean_expr(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_unary_ops() { + var cacheKey = "unary_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 43) { + result0 = "+"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 45) { + result0 = "-"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_additive_ops() { + var cacheKey = "additive_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 43) { + result0 = "+"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 45) { + result0 = "-"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_multiplicative_ops() { + var cacheKey = "multiplicative_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 42) { + result0 = "*"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"*\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 47) { + result0 = "/"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 37) { + result0 = "%"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"%\""); + } + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_boolean_ops() { + var cacheKey = "boolean_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 38) { + result0 = "&"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"&\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 124) { + result0 = "|"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"|\""); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_boolean_expr() { + var cacheKey = "boolean_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_additive_expr(); + if (result0 !== null) { + result1 = []; + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_boolean_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_additive_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_boolean_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_additive_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, head, tail) { return makeBinaryExpr(head, tail); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_additive_expr() { + var cacheKey = "additive_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_multiplicative_expr(); + if (result0 !== null) { + result1 = []; + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_additive_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_multiplicative_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_additive_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_multiplicative_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, head, tail) { return makeBinaryExpr(head, tail); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_multiplicative_expr() { + var cacheKey = "multiplicative_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_unary(); + if (result0 !== null) { + result1 = []; + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_multiplicative_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_unary(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_multiplicative_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_unary(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, head, tail) { return makeBinaryExpr(head, tail); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_unary() { + var cacheKey = "unary@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_unary_ops(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + result2 = parse_func_call(); + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, op, oper) { return new Webvs.AstUnaryExpr(op, oper); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[2]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + result0 = parse_func_call(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_func_call() { + var cacheKey = "func_call@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5, result6, result7; + var pos0, pos1, pos2, pos3; + + pos0 = clone(pos); + pos1 = clone(pos); + pos2 = clone(pos); + if (/^[a-zA-Z_]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_]"); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos2); + } + } else { + result0 = null; + pos = clone(pos2); + } + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + if (input.charCodeAt(pos.offset) === 40) { + result2 = "("; + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"(\""); + } + } + if (result2 !== null) { + pos2 = clone(pos); + result3 = []; + pos3 = clone(pos); + result4 = parse___(); + if (result4 !== null) { + result5 = parse_boolean_expr(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + if (input.charCodeAt(pos.offset) === 44) { + result7 = ","; + advance(pos, 1); + } else { + result7 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result7 !== null) { + result4 = [result4, result5, result6, result7]; + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + while (result4 !== null) { + result3.push(result4); + pos3 = clone(pos); + result4 = parse___(); + if (result4 !== null) { + result5 = parse_boolean_expr(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + if (input.charCodeAt(pos.offset) === 44) { + result7 = ","; + advance(pos, 1); + } else { + result7 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result7 !== null) { + result4 = [result4, result5, result6, result7]; + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_boolean_expr(); + if (result5 !== null) { + result3 = [result3, result4, result5]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + if (input.charCodeAt(pos.offset) === 41) { + result5 = ")"; + advance(pos, 1); + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("\")\""); + } + } + if (result5 !== null) { + result0 = [result0, result1, result2, result3, result4, result5]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, funcName, args) { + var argsList = []; + _.each(args[0], function(toks) { + argsList.push(toks[1]); + }); + argsList.push(args[2]); + return new Webvs.AstFuncCall(flattenChars(funcName), argsList); + })(pos0.offset, pos0.line, pos0.column, result0[0], result0[3]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + result0 = parse_primary_expr(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_primary_expr() { + var cacheKey = "primary_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + result0 = parse_value(); + if (result0 === null) { + result0 = parse_constant(); + if (result0 === null) { + result0 = parse_register(); + if (result0 === null) { + result0 = parse_identifier(); + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (input.charCodeAt(pos.offset) === 40) { + result0 = "("; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"(\""); + } + } + if (result0 !== null) { + result1 = parse_boolean_expr(); + if (result1 !== null) { + if (input.charCodeAt(pos.offset) === 41) { + result2 = ")"; + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\")\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, e) { return e; })(pos0.offset, pos0.line, pos0.column, result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + } + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_assignable() { + var cacheKey = "assignable@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + result0 = parse_register(); + if (result0 === null) { + result0 = parse_identifier(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_identifier() { + var cacheKey = "identifier@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[a-zA-Z_]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_]"); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(flattenChars(val).toLowerCase(), "ID"); })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_constant() { + var cacheKey = "constant@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + if (input.charCodeAt(pos.offset) === 36) { + result0 = "$"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"$\""); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(flattenChars(val).toLowerCase(), "CONST"); })(pos0.offset, pos0.line, pos0.column, result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_register() { + var cacheKey = "register@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + if (input.charCodeAt(pos.offset) === 64) { + result0 = "@"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"@\""); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr("__REG_AT_" + flattenChars(val).toLowerCase(), "REG"); })(pos0.offset, pos0.line, pos0.column, result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[rR]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[rR]"); + } + } + if (result0 !== null) { + if (/^[eE]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[eE]"); + } + } + if (result1 !== null) { + if (/^[gG]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[gG]"); + } + } + if (result2 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result3 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result4 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result4 !== null) { + result0 = [result0, result1, result2, result3, result4]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr("__REG_" + flattenChars(val).toLowerCase(), "REG"); })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_value() { + var cacheKey = "value@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = []; + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + if (result0 !== null) { + if (input.charCodeAt(pos.offset) === 46) { + result1 = "."; + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\".\""); + } + } + if (result1 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result3 !== null) { + result2 = []; + while (result3 !== null) { + result2.push(result3); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result2 = null; + } + if (result2 !== null) { + pos2 = clone(pos); + if (/^[Ee]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[Ee]"); + } + } + if (result3 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result5 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result5 !== null) { + result4 = []; + while (result5 !== null) { + result4.push(result5); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result5 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result4 = null; + } + if (result4 !== null) { + result3 = [result3, result4]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(parseFloat(flattenChars(val)), "VALUE"); })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[a-fA-F0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[a-fA-F0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[a-fA-F0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[a-fA-F0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + if (/^[hH]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[hH]"); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(parseInt(flattenChars(val), 16), "VALUE"); })(pos0.offset, pos0.line, pos0.column, result0[0]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + if (/^[dD]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[dD]"); + } + } + result1 = result1 !== null ? result1 : ""; + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(parseInt(flattenChars(val), 10), "VALUE"); })(pos0.offset, pos0.line, pos0.column, result0[0]); + } + if (result0 === null) { + pos = clone(pos0); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse___() { + var cacheKey = "__@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1; + + result0 = []; + result1 = parse_whiteSpace(); + if (result1 === null) { + result1 = parse_lineEnd(); + if (result1 === null) { + result1 = parse_comment(); + } + } + while (result1 !== null) { + result0.push(result1); + result1 = parse_whiteSpace(); + if (result1 === null) { + result1 = parse_lineEnd(); + if (result1 === null) { + result1 = parse_comment(); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_whiteSpace() { + var cacheKey = "whiteSpace@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (/^[\t\x0B\f \xA0\uFEFF]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\t\\x0B\\f \\xA0\\uFEFF]"); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_lineEnd() { + var cacheKey = "lineEnd@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (/^[\n\r\u2028\u2029]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\n\\r\\u2028\\u2029]"); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_comment() { + var cacheKey = "comment@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3; + var pos0, pos1, pos2; + + pos0 = clone(pos); + if (input.substr(pos.offset, 2) === "/*") { + result0 = "/*"; + advance(pos, 2); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/*\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + if (input.substr(pos.offset, 2) === "*/") { + result2 = "*/"; + advance(pos, 2); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + while (result2 !== null) { + result1.push(result2); + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + if (input.substr(pos.offset, 2) === "*/") { + result2 = "*/"; + advance(pos, 2); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + } + if (result1 !== null) { + if (input.substr(pos.offset, 2) === "*/") { + result2 = "*/"; + advance(pos, 2); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = clone(pos0); + } + } else { + result0 = null; + pos = clone(pos0); + } + } else { + result0 = null; + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + if (input.substr(pos.offset, 2) === "//") { + result0 = "//"; + advance(pos, 2); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"//\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + result2 = parse_lineEnd(); + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + while (result2 !== null) { + result1.push(result2); + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + result2 = parse_lineEnd(); + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos0); + } + } else { + result0 = null; + pos = clone(pos0); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + + function cleanupExpected(expected) { + expected.sort(); + + var lastExpected = null; + var cleanExpected = []; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== lastExpected) { + cleanExpected.push(expected[i]); + lastExpected = expected[i]; + } + } + return cleanExpected; + } + + + + function makeBinaryExpr(head, tail) { + var result = head; + _.each(tail, function(tailItem) { + result = new Webvs.AstBinaryExpr(tailItem[1], result, tailItem[3]); + }); + return result; + } + + function flattenChars(val) { + return _.flatten(val).join(""); + } + + + var result = parseFunctions[startRule](); + + /* + * The parser is now in one of the following three states: + * + * 1. The parser successfully parsed the whole input. + * + * - |result !== null| + * - |pos.offset === input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 2. The parser successfully parsed only a part of the input. + * + * - |result !== null| + * - |pos.offset < input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 3. The parser did not successfully parse any part of the input. + * + * - |result === null| + * - |pos.offset === 0| + * - |rightmostFailuresExpected| contains at least one failure + * + * All code following this comment (including called functions) must + * handle these states. + */ + if (result === null || pos.offset !== input.length) { + var offset = Math.max(pos.offset, rightmostFailuresPos.offset); + var found = offset < input.length ? input.charAt(offset) : null; + var errorPosition = pos.offset > rightmostFailuresPos.offset ? pos : rightmostFailuresPos; + + throw new this.SyntaxError( + cleanupExpected(rightmostFailuresExpected), + found, + offset, + errorPosition.line, + errorPosition.column + ); + } + + return result; + }, + + /* Returns the parser source code. */ + toSource: function() { return this._source; } + }; + + /* Thrown when a parser encounters a syntax error. */ + + result.SyntaxError = function(expected, found, offset, line, column) { + function buildMessage(expected, found) { + var expectedHumanized, foundHumanized; + + switch (expected.length) { + case 0: + expectedHumanized = "end of input"; + break; + case 1: + expectedHumanized = expected[0]; + break; + default: + expectedHumanized = expected.slice(0, expected.length - 1).join(", ") + + " or " + + expected[expected.length - 1]; + } + + foundHumanized = found ? quote(found) : "end of input"; + + return "Expected " + expectedHumanized + " but " + foundHumanized + " found."; + } + + this.name = "SyntaxError"; + this.expected = expected; + this.found = found; + this.message = buildMessage(expected, found); + this.offset = offset; + this.line = line; + this.column = column; + }; + + result.SyntaxError.prototype = Error.prototype; + + return result; +})(); \ No newline at end of file diff --git a/build/webvs.js b/build/webvs.js new file mode 100644 index 0000000..58e64dc --- /dev/null +++ b/build/webvs.js @@ -0,0 +1,6135 @@ +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(window) { + +/** + * Webvs namespace that contains all classes + * @alias Webvs + * @namespace + */ +var Webvs = {}; + +window.Webvs = Webvs; + +/** + * A wrapper around Object.create to help with class definition + * @param {function} constructor - constructor function for which the prototype is to be defined + * @param {function} baseConstructor - base constructor whose prototype will be extended + * @param {...object} [properties] - additional properties to be added to the prototype + * @returns {function} the constructor + */ +Webvs.defineClass = function(constructor, baseConstructor) { + constructor.prototype = Object.create(baseConstructor.prototype); + constructor.prototype.constructor = constructor; // fix the constructor reference + constructor.super = baseConstructor.prototype; // add a superclass reference + + // extend mixins and properties + _.chain(arguments).drop(2).each(function(properties) { + _.extend(constructor.prototype, properties); + }); + + return constructor; +}; + +/** + * An empty function + */ +Webvs.noop = function() {}; + +/** + * Checks if an object contains the required properties + * @param {object} options - object to be checked + * @param {Array.} - properties to be checked + */ +Webvs.checkRequiredOptions = function(options, requiredOptions) { + for(var i in requiredOptions) { + var key = requiredOptions[i]; + if(!(key in options)) { + throw new Error("Required option " + key + "not found"); + } + } +}; + +/** + * Returns a floating point value representation of a number + * embeddable in glsl shader code + * @param {number} val - value to be converted + * @returns {string} float represntation + */ +Webvs.glslFloatRepr = function(val) { + return val + (val%1 === 0?".0":""); +}; + +/** + * Parse css color string #RRGGBB or rgb(r, g, b) + * @param {string} color - color to be parsed + * @returns {Array.} triple of color values in 0-255 range + */ +Webvs.parseColor = function(color) { + if(_.isArray(color) && color.length == 3) { + return color; + } + if(_.isString(color)) { + var match; + color = color.toLowerCase(); + match = color.match(/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/); + if(match) { + return _.chain(match).last(3).map(function(channel) { + return parseInt(channel, 16); + }).value(); + } + + match = color.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/); + if(match) { + return _.chain(match).last(3).map(function(channel) { + return Math.min(parseInt(channel, 10), 255); + }).value(); + } + } + throw new Error("Invalid Color Format"); +}; + +/** + * 0-1 normalized version of {@link Webvs.parseColor} + */ +Webvs.parseColorNorm = function(color) { + return _.map(Webvs.parseColor(color), function(value) { return value/255; }); +}; + +/** + * Pretty prints a shader compilation error + * @param {string} - shader source code + * @param {string} - error message from gl.getShaderInfoLog + */ +Webvs.logShaderError = function(src, error) { + var lines = src.split("\n"); + var ndigits = lines.length.toString().length; + + var errorPos = error.match(/(\d+):(\d+)/); + if(errorPos) { + errorPos = [parseInt(errorPos[1], 10), parseInt(errorPos[2], 10)]; + } + + var numberedLines = _.map(lines, function(line, index) { + var i; + var number = (index+1) + ""; + for(i = 0;i < (ndigits-number.length);i++) { + number = "0" + number; + } + + var errorIndicator = ""; + if(errorPos && errorPos[1] == index+1) { + var indent = ""; + for(i = 0;i < errorPos[0]+ndigits+2;i++) { + indent += " "; + } + errorIndicator = "\n" + indent + "^\n" + indent + error; + } + return number + ": " + line + errorIndicator; + }).join("\n"); + + console.log("Shader Error : \n" + numberedLines); +}; + + +/** + * @class + * A simple promise object to notify async init of + * components + * @memberof Webvs + * @constructor + */ +var Promise = function() { + this.resolved = false; + this.listeners = []; +}; +Webvs.Promise = Webvs.defineClass(Promise, Object, { + /** + * resolves the promise object and runs all + * the callbacks + * @memberof Webvs.Promise + */ + resolve: function() { + if(!this.resolved) { + this.resolved = true; + _.each(this.listeners, function(cb) { + cb(); + }); + } + }, + + /** + * register a callback which should be called + * when the promise resolves + * @param {function} cb - callback + * @memberof Webvs.Promise + */ + onResolve : function(cb) { + if(this.resolved) { + cb(); + } else { + this.listeners.push(cb); + } + } +}); + +/** + * Combines several promises into one promise + * @param {Array.} promises - promises to be combined + * @returns {Webvs.Promise} + */ +Webvs.joinPromises = function(promises) { + var joinedPromise = new Promise(); + + if(promises.length === 0) { + joinedPromise.resolve(); + } else { + var counter = promises.length; + var onResolveCb = function() { + counter--; + if(counter === 0) { + joinedPromise.resolve(); + } + }; + _.each(promises, function(promise) { + if(promise.resolved) { + onResolveCb(); + } else { + promise.onResolve(onResolveCb); + } + }); + } + + return joinedPromise; +}; + +_.flatMap = _.compose(_.flatten, _.map); + +/** + * Blend mode constants + */ +Webvs.blendModes = { + REPLACE: 1, + MAXIMUM: 2, + AVERAGE: 3, + ADDITIVE: 4, + SUBTRACTIVE1: 5, + SUBTRACTIVE2: 6 +}; +_.extend(Webvs, Webvs.blendModes); + +})(window); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * AnalyserAdapter adapts music data analysers so that it can be plugged into Webvs. + * Adapters extend this class and define the required methods. + * @memberof Webvs + * @constructor + */ +function AnalyserAdapter() {} +Webvs.AnalyserAdapter = Webvs.defineClass(AnalyserAdapter, Object, { + /** + * boolean value indicating whether a beat + * is in progress or not + * @type boolean + * @memberof Webvs.AnalyserAdapter + */ + beat: false, + + /** + * returns whether song is being played or not. + * @abstract + * @returns {boolean} + * @memberof Webvs.AnalyserAdapter + */ + isPlaying: function() {return false;}, + + /** + * Returns array of waveform values + * @abstract + * @returns {Float32Array} + * @memberof Webvs.AnalyserAdapter + */ + getWaveForm: function() {return new Float32Array(0);}, + + /** + * Returns array of spectrum values + * @abstract + * @returns {Float32Array} + * @memberof Webvs.AnalyserAdapter + */ + getSpectrum: function() {return new Float32Array(0);} +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * Analyser adapter that adapts the Dancer library. + * @param dancer + * @augments Webvs.AnalyserAdapter + * @constructor + * @memberof Webvs + */ +function DancerAdapter(dancer) { + this.dancer = dancer; + this.beat = false; + + var _this = this; + this.kick = dancer.createKick({ + onKick: function(mag) { + _this.beat = true; + }, + + offKick: function() { + _this.beat = false; + } + }); + this.kick.on(); +} +Webvs.DancerAdapter = Webvs.defineClass(DancerAdapter, Webvs.AnalyserAdapter, { + /** + * returns whether song is being played or not. + * @returns {boolean} + * @memberof Webvs.DancerAdapter + */ + isPlaying: function() { + return this.dancer.isPlaying(); + }, + + /** + * returns array of waveform values + * @returns {Float32Array} + * @memberof Webvs.DancerAdapter + */ + getWaveform: function() { + return this.dancer.getWaveform(); + }, + + /** + * Returns array of spectrum values + * @returns {Float32Array} + * @memberof Webvs.DancerAdapter + */ + getSpectrum: function() { + return this.dancer.getSpectrum(); + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * Main Webvs object, that represents a running webvs instance. + * + * @example + * var dancer = new Dancer(); + * var webvs = new Webvs.Main({ + * canvas: document.getElementById("canvas"), + * analyser: new Webvs.DancerAdapter(dancer), + * showStat: true + * }); + * webvs.loadPreset(samplePreset); + * webvs.start(); + * dancer.load({src: "music.ogg"}); // start playing musc + * dancer.play(); + * + * @param {object} options - options object + * @param {HTMLCanvasElement} options.canvas - canvas element on which the visualization will be rendered + * @param {Webvs.AnalyserAdapter} options.analyser - a music analyser instance + * @param {boolean} [options.showStat=false] - if set, then a framerate status indicator is inserted into the page + * @memberof Webvs + * @constructor + */ +function Main(options) { + Webvs.checkRequiredOptions(options, ["canvas", "analyser"]); + options = _.defaults(options, { + showStat: false + }); + this.canvas = options.canvas; + this.analyser = options.analyser; + if(options.showStat) { + var stats = new Stats(); + stats.setMode(0); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.right = '5px'; + stats.domElement.style.bottom = '5px'; + document.body.appendChild(stats.domElement); + this.stats = stats; + } + this._initGl(); +} +Webvs.Main = Webvs.defineClass(Main, Object, { + _initGl: function() { + try { + this.gl = this.canvas.getContext("experimental-webgl", {alpha: false}); + + this.copier = new Webvs.CopyProgram({dynamicBlend: true}); + this.copier.init(this.gl); + + this.resolution = { + width: this.canvas.width, + height: this.canvas.height + }; + } catch(e) { + throw new Error("Couldnt get webgl context" + e); + } + }, + + /** + * Loads a preset JSON. If a preset is already loaded and running, then + * the animation is stopped, and the new preset is loaded. + * @param {object} preset - JSON representation of the preset + * @memberof Webvs.Main + */ + loadPreset: function(preset) { + var newRoot = new Webvs.EffectList(preset); + this.stop(); + this.preset = preset; + if(this.rootComponent) { + this.rootComponent.destroy(); + } + this.rootComponent = newRoot; + }, + + /** + * Reset all the components. Call this when canvas dimensions changes + * @memberof Webvs.Main + */ + resetCanvas: function() { + this.stop(); + if(this.rootComponent) { + this.rootComponent.destroy(); + this.rootComponent = null; + } + this._initGl(); + if(this.preset) { + this.rootComponent = new EffectList(this.preset); + } + }, + + /** + * Starts the animation + * @memberof Webvs.Main + */ + start: function() { + if(!this.rootComponent) { + return; // no preset loaded yet. cannot start! + } + + this.registerBank = {}; + this.bootTime = (new Date()).getTime(); + var rootComponent = this.rootComponent; + var promise = rootComponent.init(this.gl, this); + + var that = this; + var drawFrame = function() { + if(that.analyser.isPlaying()) { + rootComponent.update(); + } + that.animReqId = requestAnimationFrame(drawFrame); + }; + + // wrap drawframe in stats collection if required + if(this.stats) { + var oldDrawFrame = drawFrame; + drawFrame = function() { + that.stats.begin(); + oldDrawFrame.call(this, arguments); + that.stats.end(); + }; + } + + // start rendering when the promise is done + promise.onResolve(function() { + that.animReqId = requestAnimationFrame(drawFrame); + }); + }, + + /** + * Stops the animation + * @memberof Webvs.Main + */ + stop: function() { + if(typeof this.animReqId !== "undefined") { + cancelAnimationFrame(this.animReqId); + } + } +}); + +Main.ui = { + leaf: false, + disp: "Main", + schema: { + name: { + type: "string", + title: "Name" + }, + author: { + type: "string", + title: "Author" + }, + description: { + type: "string", + title: "Description" + }, + clearFrame: { + type: "boolean", + title: "Clear every frame", + default: false, + required: true + } + }, +}; + +})(Webvs); + + + + + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A base class that all Webvs effects extend from. + * @memberof Webvs + * @constructor + */ +function Component() {} +Webvs.Component = Webvs.defineClass(Component, Object, { + /** + * String name of the component class. Used to generate + * id strings. + * @memberof Webgl.Component + */ + componentName: "Component", + + /** + * Initialize component. Called once before animation starts. + * Override and implement initialization code + * @abstract + * @param {webglcontext} gl - webgl context + * @param {Webvs.Main} main - container main object for this component + * @param {Webvs.Component} - parent component + * @memberof Webvs.Component + */ + init: function(gl, main, parent) { + this.gl = gl; + this.main = main; + this.parent = parent; + }, + + /** + * Render a frame. Called once for every frame, + * Override and implement rendering code + * @abstract + * @memberof Webvs.Component + */ + update: function() {}, + + /** + * Release any Webgl resources. Called during + * reinitialization. Override and implement cleanup code + * @abstract + * @memberof Webvs.Component + */ + destroy: function() {}, + + /** + * Generates a printable id for this component + * @returns {string} printable name generated from the parent hierarchy + * @memberof Webvs.Component + */ + getIdString: function() { + if(!_.isUndefined(this.parent) && !_.isUndefined(this.id)) { + return this.parent.getIdString() + "/" + this.componentName + "#" + this.id; + } else { + return this.componentName + "#Main"; + } + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * Effectlist is a component that can contain other components. Its also used as the root + * component in Webvs.Main + * + * @param {object} options - options object + * @param {Array.} options.components - the constructor options object for each subcomponent + * in this effectlist. + * @param {string} options.components[i].type - the component class name + * @param {number} [options.components[i].clone] - the number of times this component should be cloned + * @param {string} [options.output="REPLACE"] - the output blend mode + * @param {string} [options.input="IGNORE"] - the input blend mode + * @param {boolean} [options.clearFrame=false] - if set then the buffer is cleared for each frame + * @param {boolean} [options.enableOnBeat=false] - if set then the subcomponents are rendered only + * for a fixed number of frames on beat + * @param {number} [options.enableOnBeatFor=1] - the number frames for enableOnBeat setting + * + * @augments Webvs.Component + * @memberof Webvs + * @constructor + */ +function EffectList(options) { + Webvs.checkRequiredOptions(options, ["components"]); + options = _.defaults(options, { + output: "REPLACE", + input: "IGNORE", + clearFrame: false, + enableOnBeat: false, + enableOnBeatFor: 1 + }); + + this._constructComponent(options.components); + this.output = options.output=="IGNORE"?-1:Webvs.blendModes[options.output]; + this.input = options.input=="IGNORE"?-1:Webvs.blendModes[options.input]; + this.clearFrame = options.clearFrame; + this.enableOnBeat = options.enableOnBeat; + this.enableOnBeatFor = options.enableOnBeatFor; + this.first = true; + this._frameCounter = 0; + + EffectList.super.constructor.call(this); +} +Webvs.EffectList = Webvs.defineClass(EffectList, Webvs.Component, { + componentName: "EffectList", + + _constructComponent: function(optList) { + var components = []; + var that = this; + // construct components from JSON + _.each(optList, function(componentOptions, i) { + if(typeof componentOptions.enabled === "boolean" && !componentOptions.enabled) { + return; + } + var type = componentOptions.type; + var cloneCount = typeof componentOptions.clone === "undefined"?1:componentOptions.clone; + _.times(cloneCount, function(cloneId) { + var component = new Webvs[type](componentOptions); + component.id = i; + component.cloneId = cloneId; + components.push(component); + }); + }); + this.components = components; + }, + + /** + * Initializes the effect list + * @memberof Webvs.EffectList + */ + init: function(gl, main, parent) { + EffectList.super.init.call(this, gl, main, parent); + + // create a framebuffer manager for this effect list + this.fm = new Webvs.FrameBufferManager(main.canvas.width, main.canvas.height, gl, main.copier); + + // initialize all the sub components + var components = this.components; + var initPromises = []; + for(var i = 0;i < components.length;i++) { + var res = components[i].init(gl, main, this); + if(res) { + initPromises.push(res); + } + } + + return Webvs.joinPromises(initPromises); + }, + + /** + * Renders a frame of the effect list, by running + * all the subcomponents. + * @memberof Webvs.EffectList + */ + update: function() { + EffectList.super.update.call(this); + var gl = this.gl; + + if(this.enableOnBeat) { + if(this.main.analyser.beat) { + this._frameCounter = this.enableOnBeatFor; + } else if(this._frameCounter > 0) { + this._frameCounter--; + } + + // only enable for enableOnBeatFor # of frames + if(this._frameCounter === 0) { + return; + } + } + + // set rendertarget to internal framebuffer + this.fm.setRenderTarget(); + + // clear frame + if(this.clearFrame || this.first) { + gl.clearColor(0,0,0,1); + gl.clear(gl.COLOR_BUFFER_BIT); + this.first = false; + } + + // blend input texture onto internal texture + if(this.input !== -1) { + var inputTexture = this.parent.fm.getCurrentTexture(); + this.main.copier.run(this.fm, this.input, inputTexture); + } + + // render all the components + var components = this.components; + for(var i = 0;i < components.length;i++) { + components[i].update(); + } + + // switch to old framebuffer + this.fm.restoreRenderTarget(); + + // blend current texture to the output framebuffer + if(this.output != -1) { + if(this.parent) { + this.main.copier.run(this.parent.fm, this.output, this.fm.getCurrentTexture()); + } else { + this.main.copier.run(null, null, this.fm.getCurrentTexture()); + } + } + }, + + /** + * Releases resources. + * @memberof Webgl.EffectList + */ + destroy: function() { + EffectList.super.destroy.call(this); + + // destory all the sub-components + for(i = 0;i < this.components.length;i++) { + this.components[i].destroy(); + } + + // destroy the framebuffer manager + this.fm.destroy(); + } +}); + +EffectList.ui = { + disp: "Effect List", + type: "EffectList", + leaf: false, + schema: { + clearFrame: { + type: "boolean", + title: "Clear Frame", + default: false, + required: true + }, + enableOnBeat: { + type: "boolean", + title: "Enable on beat", + default: false, + }, + enableOnBeatFor: { + type: "number", + title: "Enable on beat for frames", + default: 1 + }, + output: { + type: "string", + title: "Output", + default: "REPLACE", + enum: _.keys(Webvs.blendModes) + }, + input: { + type: "string", + title: "Input", + default: "IGNORE", + enum: _.union(_.keys(Webvs.blendModes), ["IGNORE"]) + } + } +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * Base class for Webgl Shaders. This provides an abstraction + * with support for blended output, easier variable bindings + * etc. + * + * For outputblending, we try to use GL blendEq and blendFunc + * if possible, otherwise we fallback to shader based blending, + * where we swap the frame, sample the previous texture, and blend + * the colors in the shader itself. To do this seamlessly, shader code in subclasses + * should use a set of macros. eg: setFragColor instead of + * setting gl_FragColor directly. The proper macro implementation + * is inserted based on the blending modes. + * + * #### glsl utilities + * + * The following utilities are usable inside the shader code in subclasses + * + * + `setPosition(vec2 pos)` - sets gl_Position + * + `getSrcColorAtPos(vec2 pos)` - pixel value at pos in u_srcTexture + * + `getSrcColor(vec2 pos)` - same as above, but uses v_position + * + `setFragColor(vec4 color)` - sets the correctly blended fragment color + * + `sampler2D u_srcTexture` - the source texture from previous frame. enabled + * when swapFrame is set to true + * + `vec2 u_resolution` - the screen resolution. enabled only if fm is + * passed to {@link Webvs.ShaderProgram.run} call + * + `vec2 v_position` - a 0-1, 0-1 normalized varying of the vertex. enabled + * when varyingPos option is used + * + * @param {object} options - refer class description + * @param {string} options.vertexShader - the source for the vertex shader + * @param {string} options.fragmentShader - the source for the fragment shader + * @param {boolean} [options.forceShaderBlend=false] - force the use of shader based blending mode + * @param {string} [options.oututBlendMode="REPLACE"] - the output blending mode. + * @param {boolean} [options.dynamicBlend=false] - when set to true, blending mode can be changed + * at runtime even after shader compilation + * @param {boolean} [options.swapFrame=false] - if set then a render target swap is done on the + * framebuffermanager, before rendering. This is used + * by programs where the previous rendering need to be + * sampled + * @param {boolean} [options.copyOnSwap=false] - if set to true then on swap, a copyOver is done on + * the framebuffermanager. This is used to maintain + * consistency during shader based blending in shaders + * that do not touch all the pixels + * @param {boolean} [options.varyingPos=false] - if true then a varying called v_position is added + * automatically + * @param {function} [options.draw ] - override the draw function + * @memberof Webvs + * @constructor + */ +function ShaderProgram(options) { + options = _.defaults(options, { + forceShaderBlend: false, + outputBlendMode: Webvs.REPLACE, + varyingPos: false, + dynamicBlend: false, + swapFrame: false, + copyOnSwap: false + }); + var fsrc = [ + "precision mediump float;", + "uniform vec2 u_resolution;", + "#define PI "+Math.PI + ]; + var vsrc = _.clone(fsrc); + + if(_.isFunction(options.draw)) { + this.draw = options.draw; + } + this.copyOnSwap = options.copyOnSwap; + this.varyingPos = options.varyingPos; + this.dynamicBlend = options.dynamicBlend; + + // select the blend equation + this.outputBlendMode = options.outputBlendMode; + if(options.swapFrame || this.dynamicBlend || options.forceShaderBlend || !_.contains(this.glBlendModes, this.outputBlendMode)) { + this.swapFrame = true; + this.glBlendMode = false; + this.varyingPos = true; + } else { + this.swapFrame = false; + this.glBlendMode = true; + } + + // varying position and macros + if(this.varyingPos) { + fsrc.push("varying vec2 v_position;"); + vsrc.push( + "varying vec2 v_position;", + "#define setPosition(pos) (v_position = (((pos)+1.0)/2.0),gl_Position = vec4((pos), 0, 1))" + ); + } else { + vsrc.push("#define setPosition(pos) (gl_Position = vec4((pos), 0, 1))"); + } + + // source teture uniform variable and macors + if(this.swapFrame) { + vsrc.push( + "uniform sampler2D u_srcTexture;", + "#define getSrcColorAtPos(pos) (texture2D(u_srcTexture, pos))" + ); + + fsrc.push( + "uniform sampler2D u_srcTexture;", + "#define getSrcColor() (texture2D(u_srcTexture, v_position))", + "#define getSrcColorAtPos(pos) (texture2D(u_srcTexture, pos))" + ); + } + + // color blend macro/function + if(this.dynamicBlend) { + fsrc.push( + "uniform int u_blendMode;", + "void setFragColor(vec4 color) {" + ); + _.each(this.blendEqs, function(eq, mode) { + fsrc.push( + " if(u_blendMode == "+mode+") {", + " gl_FragColor = ("+eq+");", + " }" + ); + }); + fsrc.push( + "}" + ); + } else { + var blendEq = this.blendEqs[this.glBlendMode?Webvs.REPLACE:this.outputBlendMode]; + if(_.isUndefined(blendEq)) { + throw new Error("Blend Mode " + this.outputBlendMode + " not supported"); + } + fsrc.push("#define setFragColor(color) (gl_FragColor = ("+blendEq+"))"); + } + + this.fragmentSrc = fsrc.join("\n") + "\n" + options.fragmentShader.join("\n"); + this.vertexSrc = vsrc.join("\n") + "\n" + options.vertexShader.join("\n"); + this._locations = {}; + this._textureVars = []; + this._arrBuffers = {}; +} + +Webvs.ShaderProgram = Webvs.defineClass(ShaderProgram, Object, { + // these are blend modes supported with gl.BLEND + // all other modes have to implemented with shaders + glBlendModes: [ + Webvs.REPLACE, + Webvs.AVERAGE, + Webvs.ADDITIVE, + Webvs.SUBTRACTIVE1, + Webvs.SUBTRACTIVE2 + ], + + // the blending formulas to be used inside shaders + blendEqs: _.object([ + [Webvs.REPLACE, "color"], + [Webvs.MAXIMUM, "max(color, texture2D(u_srcTexture, v_position))"], + [Webvs.AVERAGE, "(color+texture2D(u_srcTexture, v_position))/2.0"], + [Webvs.ADDITIVE, "color+texture2D(u_srcTexture, v_position)"], + [Webvs.SUBTRACTIVE1, "texture2D(u_srcTexture, v_position)-color"], + [Webvs.SUBTRACTIVE2, "color-texture2D(u_srcTexture, v_position)"] + ]), + + /** + * initializes and compiles the shaders + * @memberof Webvs.ShaderProgram + */ + init: function(gl) { + this.gl = gl; + try { + this._compileProgram(this.vertexSrc, this.fragmentSrc); + } catch(e) { + throw e; + } + }, + + /** + * Sets the output blend mode for this shader + * @param {Webvs.blendModes} mode - the blending mode + * @memberof Webvs.ShaderProgram + */ + setOutputBlendMode: function(mode) { + this.outputBlendMode = mode; + }, + + /** + * Runs this shader program + * @param {Webvs.FrameBufferManager} fm - frame manager. pass null, if no fm is required + * @param {Webvs.blendModes} outputBlendMode - overrides the blendmode. pass null to use default + * @param {...any} extraParams - remaining parameters are passed to the draw function + * @memberof Webvs.ShaderProgram + */ + run: function(fm, outputBlendMode) { + var gl = this.gl; + var oldProgram = gl.getParameter(gl.CURRENT_PROGRAM); + gl.useProgram(this.program); + + if(fm) { + this.setUniform("u_resolution", "2f", fm.width, fm.height); + if(this.swapFrame) { + this.setUniform("u_srcTexture", "texture2D", fm.getCurrentTexture()); + fm.swapAttachment(); + if(this.copyOnSwap) { + fm.copyOver(); + } + } + } + + outputBlendMode = outputBlendMode || this.outputBlendMode; + if(this.dynamicBlend) { + this.setUniform("u_blendMode", "1i", outputBlendMode); + } + + if(this.glBlendMode && outputBlendMode != Webvs.REPLACE) { + gl.enable(gl.BLEND); + this._setGlBlendMode(gl, outputBlendMode); + } else { + gl.disable(gl.BLEND); + } + + this.draw.apply(this, _.drop(arguments, 2)); + + gl.disable(gl.BLEND); + gl.useProgram(oldProgram); + }, + + /** + * Performs the actual drawing and any further bindings and calculations if required. + * @param {...any} extraParams - the extra parameters passed to {@link Webvs.ShaderProgram.run} + * @abstract + * @memberof Webvs.ShaderProgram + */ + draw: function() {}, + + _compileProgram: function(vertexSrc, fragmentSrc) { + var gl = this.gl; + var vertex = this._compileShader(vertexSrc, gl.VERTEX_SHADER); + var fragment = this._compileShader(fragmentSrc, gl.FRAGMENT_SHADER); + var program = gl.createProgram(); + gl.attachShader(program, vertex); + gl.attachShader(program, fragment); + gl.linkProgram(program); + + if(!gl.getProgramParameter(program, gl.LINK_STATUS)) { + throw new Error("Program link Error: " + gl.getProgramInfoLog(program)); + } + + this.vertex = vertex; + this.fragment = fragment; + this.program = program; + }, + + _compileShader: function(shaderSrc, type) { + var gl = this.gl; + var shader = gl.createShader(type); + gl.shaderSource(shader, shaderSrc); + gl.compileShader(shader); + if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + Webvs.logShaderError(this.fragmentSrc, gl.getShaderInfoLog(shader)); + throw new Error("Shader compilation Error: " + gl.getShaderInfoLog(shader)); + } + return shader; + }, + + _setGlBlendMode: function(gl, mode) { + switch(mode) { + case Webvs.ADDITIVE: + gl.blendFunc(gl.ONE, gl.ONE); + gl.blendEquation(gl.FUNC_ADD); + break; + case Webvs.SUBTRACTIVE1: + gl.blendFunc(gl.ONE, gl.ONE); + gl.blendEquation(gl.FUNC_REVERSE_SUBTRACT); + break; + case Webvs.SUBTRACTIVE2: + gl.blendFunc(gl.ONE, gl.ONE); + gl.blendEquation(gl.FUNC_SUBTRACT); + break; + case Webvs.AVERAGE: + gl.blendColor(0.5, 0.5, 0.5, 1); + gl.blendFunc(gl.CONSTANT_COLOR, gl.CONSTANT_COLOR); + gl.blendEquation(gl.FUNC_ADD); + break; + default: throw new Error("Invalid blend mode"); + } + }, + + /** + * returns the location of a uniform or attribute. locations are cached. + * @param {string} name - name of the variable + * @param {boolean} [attrib] - pass true if variable is attribute + * @returns {location} + * @memberof Webvs.ShaderProgram + */ + getLocation: function(name, attrib) { + var location = this._locations[name]; + if(_.isUndefined(location)) { + if(attrib) { + location = this.gl.getAttribLocation(this.program, name); + } else { + location = this.gl.getUniformLocation(this.program, name); + } + this._locations[name] = location; + } + return location; + }, + + /** + * returns the index of a texture. assigns id if not already assigned. + * @param {string} name - name of the varaible + * @returns {number} index of the texture + * @memberof Webvs.ShaderProgram + */ + getTextureId: function(name) { + var id = _.indexOf(this._textureVars, name); + if(id === -1) { + this._textureVars.push(name); + id = this._textureVars.length-1; + } + return id; + }, + + /** + * binds value of a uniform variable in this program + * @param {string} name - name of the variable + * @param {string} type - type of the variable (texture2D, [1234]f, [1234]i, [1234]fv, [1234]iv) + * @param {...any} values - values to be assigned + * @memberof Webvs.ShaderProgram + */ + setUniform: function(name, type, value) { + var location = this.getLocation(name); + var gl = this.gl; + switch(type) { + case "texture2D": + var id = this.getTextureId(name); + gl.activeTexture(gl["TEXTURE"+id]); + gl.bindTexture(gl.TEXTURE_2D, value); + gl.uniform1i(location, id); + break; + case "1f": case "2f": case "3f": case "4f": + case "1i": case "2i": case "3i": case "4i": + var args = [location].concat(_.drop(arguments, 2)); + gl["uniform" + type].apply(gl, args); + break; + case "1fv": case "2fv": case "3fv": case "4fv": + case "1iv": case "2iv": case "3iv": case "4iv": + gl["uniform" + type].apply(gl, location, value); + break; + } + }, + + /** + * binds the vertex attribute array + * @param {string} name - name of the variable + * @param {Array} array - array of vertex data + * @param {number} [size=2] - size of each item + * @param [type=gl.FLOAT] + * @param [normalized=false] + * @param [stride=0] + * @param [offset=0] + * @memberof Webvs.ShaderProgram + */ + setVertexAttribArray: function(name, array, size, type, normalized, stride, offset) { + var gl = this.gl; + size = size || 2; + type = type || gl.FLOAT; + normalized = normalized || false; + stride = stride || 0; + offset = offset || 0; + + var buffer = this._arrBuffers[name]; + if(_.isUndefined(buffer)) { + buffer = gl.createBuffer(); + this._arrBuffers[name] = buffer; + } + var location = this.getLocation(name, true); + + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW); + gl.enableVertexAttribArray(location); + gl.vertexAttribPointer(location, size, type, normalized, stride, offset); + }, + + /** + * destroys webgl resources consumed by this program. + * call in component destroy + * @memberof Webvs.ShaderProgram + */ + cleanup: function() { + var gl = this.gl; + _.each(this._buffers, function(buffer) { + gl.deleteBuffer(buffer); + }, this); + gl.deleteProgram(this.program); + gl.deleteShader(this.vertexShader); + gl.deleteShader(this.fragmentShader); + }, + +}); + + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +function QuadBoxProgram(options) { + options = _.defaults(options, { + vertexShader: [ + "attribute vec2 a_position;", + "void main() {", + " setPosition(a_position);", + "}" + ], + varyingPos: true + }); + QuadBoxProgram.super.constructor.call(this, options); +} +Webvs.QuadBoxProgram = Webvs.defineClass(QuadBoxProgram, Webvs.ShaderProgram, { + draw: function() { + this.setVertexAttribArray( + "a_position", + new Float32Array([ + -1, -1, + 1, -1, + -1, 1, + -1, 1, + 1, -1, + 1, 1 + ]) + ); + this.gl.drawArrays(this.gl.TRIANGLES, 0, 6); + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +function CopyProgram(options) { + options = _.defaults(options||{}, { + fragmentShader: [ + "uniform sampler2D u_copySource;", + "void main() {", + " setFragColor(texture2D(u_copySource, v_position));", + "}" + ] + }); + CopyProgram.super.constructor.call(this, options); +} +Webvs.CopyProgram = Webvs.defineClass(CopyProgram, Webvs.QuadBoxProgram, { + draw: function(srcTexture) { + this.setUniform("u_copySource", "texture2D", srcTexture); + CopyProgram.super.draw.call(this); + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * FrameBufferManager maintains a set of render targets + * and switches between them, when requested by different + * shader programs. Its used in EffectLists to compose rendering + * of the different {@link Webvs.Component} + * + * @param {number} width - the width of the textures to be initialized + * @param {number} height - the height of the textures to be initialized + * @param {WebGLRenderingContext} gl - the webgl context to be used + * @param {Webvs.CopyProgram} copier - an instance of a CopyProgram that should be used + * when a frame copyOver is required + * @constructor + * @memberof Webvs + */ +function FrameBufferManager(width, height, gl, copier, texCount) { + this.gl = gl; + this.width = width; + this.height = height; + this.copier = copier; + this.texCount = texCount || 2; + this._initFrameBuffers(); +} +Webvs.FrameBufferManager = Webvs.defineClass(FrameBufferManager, Object, { + _initFrameBuffers: function() { + var gl = this.gl; + + var framebuffer = gl.createFramebuffer(); + var attachments = []; + for(var i = 0;i < this.texCount;i++) { + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, + 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + var renderbuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.width, this.height); + + attachments[i] = { + texture: texture, + renderbuffer: renderbuffer + }; + } + + this.framebuffer = framebuffer; + this.frameAttachments = attachments; + this.currAttachment = 0; + }, + + /** + * Saves the current render target and sets this + * as the render target + * @memberof Webvs.FrameBufferManager + */ + setRenderTarget: function() { + var gl = this.gl; + this.inputFrameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + gl.viewport(0, 0, this.width, this.height); + this._setFBAttachment(); + }, + + /** + * Restores the render target previously saved with + * a {@link Webvs.FrameBufferManager.setRenderTarget} call + * @memberof Webvs.FrameBufferManager + */ + restoreRenderTarget: function() { + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, this.inputFrameBuffer); + gl.viewport(0, 0, this.width, this.height); + }, + + /** + * Returns the texture that is currently being used + * @returns {WebGLTexture} + * @memberof Webvs.FrameBufferManager + */ + getCurrentTexture: function() { + return this.frameAttachments[this.currAttachment].texture; + }, + + /** + * Copies the previous texture into the current texture + * @memberof Webvs.FrameBufferManager + */ + copyOver: function() { + var prevTexture = this.frameAttachments[Math.abs(this.currAttachment-1)%this.texCount].texture; + this.copier.run(null, null, prevTexture); + }, + + /** + * Swaps the current texture + * @memberof Webvs.FrameBufferManager + */ + swapAttachment : function() { + this.currAttachment = (this.currAttachment + 1) % this.texCount; + this._setFBAttachment(); + }, + + /** + * cleans up all webgl resources + * @memberof Webvs.FrameBufferManager + */ + destroy: function() { + var gl = this.gl; + for(var i = 0;i < this.texCount;i++) { + gl.deleteRenderbuffer(this.frameAttachments[i].renderbuffer); + gl.deleteTexture(this.frameAttachments[i].texture); + } + gl.deleteFramebuffer(this.framebuffer); + }, + + + _setFBAttachment: function() { + var attachment = this.frameAttachments[this.currAttachment]; + var gl = this.gl; + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, attachment.texture, 0); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, attachment.renderbuffer); + }, +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +function ClearScreenProgram(blendMode) { + ClearScreenProgram.super.constructor.call(this, { + fragmentShader: [ + "uniform vec3 u_color;", + "void main() {", + " setFragColor(vec4(u_color, 1));", + "}" + ], + outputBlendMode: blendMode + }); +} +Webvs.ClearScreenProgram = Webvs.defineClass(ClearScreenProgram, Webvs.QuadBoxProgram, { + draw: function(color) { + this.setUniform.apply(this, ["u_color", "3f"].concat(color)); + ClearScreenProgram.super.draw.call(this); + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * Base class for AVS expression Syntax Tree + * @memberof Webvs + */ +function AstBase() {} +Webvs.AstBase = Webvs.defineClass(AstBase, Object); + +/** + * @class + * Binary Expression + * @augments Webvs.AstBase + * @param {string} operator + * @param {string} leftOperand + * @param {string} rightOperand + * @memberof Webvs + */ +function AstBinaryExpr(operator, leftOperand, rightOperand) { + this.operator = operator; + this.leftOperand = leftOperand; + this.rightOperand = rightOperand; +} +Webvs.AstBinaryExpr = Webvs.defineClass(AstBinaryExpr, AstBase); + +/** + * @class + * Unary Expression + * @augments Webvs.AstBase + * @param {string} operator + * @param {string} operand + * @memberof Webvs + */ +function AstUnaryExpr(operator, operand) { + this.operator = operator; + this.operand = operand; +} +Webvs.AstUnaryExpr = Webvs.defineClass(AstUnaryExpr, AstBase); + +/** + * @class + * Function call + * @augments Webvs.AstBase + * @param {string} funcName - function identifier + * @param {Array.} args - argument expressions + * @memberof Webvs + */ +function AstFuncCall(funcName, args) { + this.funcName = funcName; + this.args = args; +} +Webvs.AstFuncCall = Webvs.defineClass(AstFuncCall, AstBase); + +/** + * @class + * Variable assignment + * @augments Webvs.AstBase + * @param {string} lhs - identifier + * @param {Array.} expr - expression being assigned + * @memberof Webvs + */ +function AstAssignment(lhs, expr) { + this.lhs = lhs; + this.expr = expr; +} +Webvs.AstAssignment = Webvs.defineClass(AstAssignment, AstBase); + +/** + * @class + * Code start symbol + * @augments Webvs.AstBase + * @param {Array.} statements - statements in the program + * @memberof Webvs + */ +function AstProgram(statements) { + this.statements = statements; +} +Webvs.AstProgram = Webvs.defineClass(AstProgram, AstBase); + +/** + * @class + * Atomic expression + * @augments Webvs.AstBase + * @param value + * @param {String} type - type of the atom viz. "ID", "CONST", "REG", "VALUE" + * @memberof Webvs + */ +function AstPrimaryExpr(value, type) { + this.value = value; + this.type = type; +} +Webvs.AstPrimaryExpr = Webvs.defineClass(AstPrimaryExpr, AstBase); + +})(Webvs); + +Webvs.PegExprParser = (function(){ + /* + * Generated by PEG.js 0.7.0. + * + * http://pegjs.majda.cz/ + */ + + function quote(s) { + /* + * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a + * string literal except for the closing quote character, backslash, + * carriage return, line separator, paragraph separator, and line feed. + * Any character may appear in the form of an escape sequence. + * + * For portability, we also escape escape all control and non-ASCII + * characters. Note that "\0" and "\v" escape sequences are not used + * because JSHint does not like the first and IE the second. + */ + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\x08/g, '\\b') // backspace + .replace(/\t/g, '\\t') // horizontal tab + .replace(/\n/g, '\\n') // line feed + .replace(/\f/g, '\\f') // form feed + .replace(/\r/g, '\\r') // carriage return + .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) + + '"'; + } + + var result = { + /* + * Parses the input with a generated parser. If the parsing is successfull, + * returns a value explicitly or implicitly specified by the grammar from + * which the parser was generated (see |PEG.buildParser|). If the parsing is + * unsuccessful, throws |PEG.parser.SyntaxError| describing the error. + */ + parse: function(input, startRule) { + var parseFunctions = { + "program": parse_program, + "statement": parse_statement, + "unary_ops": parse_unary_ops, + "additive_ops": parse_additive_ops, + "multiplicative_ops": parse_multiplicative_ops, + "boolean_ops": parse_boolean_ops, + "boolean_expr": parse_boolean_expr, + "additive_expr": parse_additive_expr, + "multiplicative_expr": parse_multiplicative_expr, + "unary": parse_unary, + "func_call": parse_func_call, + "primary_expr": parse_primary_expr, + "assignable": parse_assignable, + "identifier": parse_identifier, + "constant": parse_constant, + "register": parse_register, + "value": parse_value, + "__": parse___, + "whiteSpace": parse_whiteSpace, + "lineEnd": parse_lineEnd, + "comment": parse_comment + }; + + if (startRule !== undefined) { + if (parseFunctions[startRule] === undefined) { + throw new Error("Invalid rule name: " + quote(startRule) + "."); + } + } else { + startRule = "program"; + } + + var pos = { offset: 0, line: 1, column: 1, seenCR: false }; + var reportFailures = 0; + var rightmostFailuresPos = { offset: 0, line: 1, column: 1, seenCR: false }; + var rightmostFailuresExpected = []; + var cache = {}; + + function padLeft(input, padding, length) { + var result = input; + + var padLength = length - input.length; + for (var i = 0; i < padLength; i++) { + result = padding + result; + } + + return result; + } + + function escape(ch) { + var charCode = ch.charCodeAt(0); + var escapeChar; + var length; + + if (charCode <= 0xFF) { + escapeChar = 'x'; + length = 2; + } else { + escapeChar = 'u'; + length = 4; + } + + return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); + } + + function clone(object) { + var result = {}; + for (var key in object) { + result[key] = object[key]; + } + return result; + } + + function advance(pos, n) { + var endOffset = pos.offset + n; + + for (var offset = pos.offset; offset < endOffset; offset++) { + var ch = input.charAt(offset); + if (ch === "\n") { + if (!pos.seenCR) { pos.line++; } + pos.column = 1; + pos.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + pos.line++; + pos.column = 1; + pos.seenCR = true; + } else { + pos.column++; + pos.seenCR = false; + } + } + + pos.offset += n; + } + + function matchFailed(failure) { + if (pos.offset < rightmostFailuresPos.offset) { + return; + } + + if (pos.offset > rightmostFailuresPos.offset) { + rightmostFailuresPos = clone(pos); + rightmostFailuresExpected = []; + } + + rightmostFailuresExpected.push(failure); + } + + function parse_program() { + var cacheKey = "program@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5, result6; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_statement(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + result2 = []; + pos2 = clone(pos); + if (input.charCodeAt(pos.offset) === 59) { + result3 = ";"; + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_statement(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + result3 = [result3, result4, result5, result6]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + while (result3 !== null) { + result2.push(result3); + pos2 = clone(pos); + if (input.charCodeAt(pos.offset) === 59) { + result3 = ";"; + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_statement(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + result3 = [result3, result4, result5, result6]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } + if (result2 !== null) { + if (input.charCodeAt(pos.offset) === 59) { + result3 = ";"; + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\";\""); + } + } + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, p) { + var stmts = [p[0]]; + stmts = stmts.concat(_.map(p[2], function(pp) { + return pp[2]; + })); + return new Webvs.AstProgram(stmts); + })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_statement() { + var cacheKey = "statement@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_assignable(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + if (input.charCodeAt(pos.offset) === 61) { + result2 = "="; + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"=\""); + } + } + if (result2 !== null) { + result3 = parse___(); + if (result3 !== null) { + result4 = parse_boolean_expr(); + if (result4 !== null) { + result0 = [result0, result1, result2, result3, result4]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, lhs, e) { return new Webvs.AstAssignment(lhs, e); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[4]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + result0 = parse_boolean_expr(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_unary_ops() { + var cacheKey = "unary_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 43) { + result0 = "+"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 45) { + result0 = "-"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_additive_ops() { + var cacheKey = "additive_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 43) { + result0 = "+"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 45) { + result0 = "-"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_multiplicative_ops() { + var cacheKey = "multiplicative_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 42) { + result0 = "*"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"*\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 47) { + result0 = "/"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 37) { + result0 = "%"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"%\""); + } + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_boolean_ops() { + var cacheKey = "boolean_ops@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (input.charCodeAt(pos.offset) === 38) { + result0 = "&"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"&\""); + } + } + if (result0 === null) { + if (input.charCodeAt(pos.offset) === 124) { + result0 = "|"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"|\""); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_boolean_expr() { + var cacheKey = "boolean_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_additive_expr(); + if (result0 !== null) { + result1 = []; + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_boolean_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_additive_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_boolean_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_additive_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, head, tail) { return makeBinaryExpr(head, tail); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_additive_expr() { + var cacheKey = "additive_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_multiplicative_expr(); + if (result0 !== null) { + result1 = []; + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_additive_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_multiplicative_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_additive_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_multiplicative_expr(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, head, tail) { return makeBinaryExpr(head, tail); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_multiplicative_expr() { + var cacheKey = "multiplicative_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_unary(); + if (result0 !== null) { + result1 = []; + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_multiplicative_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_unary(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = clone(pos); + result2 = parse___(); + if (result2 !== null) { + result3 = parse_multiplicative_ops(); + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_unary(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } else { + result2 = null; + pos = clone(pos2); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, head, tail) { return makeBinaryExpr(head, tail); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_unary() { + var cacheKey = "unary@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = parse_unary_ops(); + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + result2 = parse_func_call(); + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, op, oper) { return new Webvs.AstUnaryExpr(op, oper); })(pos0.offset, pos0.line, pos0.column, result0[0], result0[2]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + result0 = parse_func_call(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_func_call() { + var cacheKey = "func_call@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5, result6, result7; + var pos0, pos1, pos2, pos3; + + pos0 = clone(pos); + pos1 = clone(pos); + pos2 = clone(pos); + if (/^[a-zA-Z_]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_]"); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos2); + } + } else { + result0 = null; + pos = clone(pos2); + } + if (result0 !== null) { + result1 = parse___(); + if (result1 !== null) { + if (input.charCodeAt(pos.offset) === 40) { + result2 = "("; + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"(\""); + } + } + if (result2 !== null) { + pos2 = clone(pos); + result3 = []; + pos3 = clone(pos); + result4 = parse___(); + if (result4 !== null) { + result5 = parse_boolean_expr(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + if (input.charCodeAt(pos.offset) === 44) { + result7 = ","; + advance(pos, 1); + } else { + result7 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result7 !== null) { + result4 = [result4, result5, result6, result7]; + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + while (result4 !== null) { + result3.push(result4); + pos3 = clone(pos); + result4 = parse___(); + if (result4 !== null) { + result5 = parse_boolean_expr(); + if (result5 !== null) { + result6 = parse___(); + if (result6 !== null) { + if (input.charCodeAt(pos.offset) === 44) { + result7 = ","; + advance(pos, 1); + } else { + result7 = null; + if (reportFailures === 0) { + matchFailed("\",\""); + } + } + if (result7 !== null) { + result4 = [result4, result5, result6, result7]; + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } else { + result4 = null; + pos = clone(pos3); + } + } + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + result5 = parse_boolean_expr(); + if (result5 !== null) { + result3 = [result3, result4, result5]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result4 = parse___(); + if (result4 !== null) { + if (input.charCodeAt(pos.offset) === 41) { + result5 = ")"; + advance(pos, 1); + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("\")\""); + } + } + if (result5 !== null) { + result0 = [result0, result1, result2, result3, result4, result5]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, funcName, args) { + var argsList = []; + _.each(args[0], function(toks) { + argsList.push(toks[1]); + }); + argsList.push(args[2]); + return new Webvs.AstFuncCall(flattenChars(funcName), argsList); + })(pos0.offset, pos0.line, pos0.column, result0[0], result0[3]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + result0 = parse_primary_expr(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_primary_expr() { + var cacheKey = "primary_expr@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + result0 = parse_value(); + if (result0 === null) { + result0 = parse_constant(); + if (result0 === null) { + result0 = parse_register(); + if (result0 === null) { + result0 = parse_identifier(); + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (input.charCodeAt(pos.offset) === 40) { + result0 = "("; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"(\""); + } + } + if (result0 !== null) { + result1 = parse_boolean_expr(); + if (result1 !== null) { + if (input.charCodeAt(pos.offset) === 41) { + result2 = ")"; + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\")\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, e) { return e; })(pos0.offset, pos0.line, pos0.column, result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + } + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_assignable() { + var cacheKey = "assignable@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + result0 = parse_register(); + if (result0 === null) { + result0 = parse_identifier(); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_identifier() { + var cacheKey = "identifier@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[a-zA-Z_]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_]"); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(flattenChars(val).toLowerCase(), "ID"); })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_constant() { + var cacheKey = "constant@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + if (input.charCodeAt(pos.offset) === 36) { + result0 = "$"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"$\""); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(flattenChars(val).toLowerCase(), "CONST"); })(pos0.offset, pos0.line, pos0.column, result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_register() { + var cacheKey = "register@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4; + var pos0, pos1; + + pos0 = clone(pos); + pos1 = clone(pos); + if (input.charCodeAt(pos.offset) === 64) { + result0 = "@"; + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"@\""); + } + } + if (result0 !== null) { + result1 = []; + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z_0-9]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z_0-9]"); + } + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr("__REG_AT_" + flattenChars(val).toLowerCase(), "REG"); })(pos0.offset, pos0.line, pos0.column, result0[1]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[rR]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[rR]"); + } + } + if (result0 !== null) { + if (/^[eE]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[eE]"); + } + } + if (result1 !== null) { + if (/^[gG]/.test(input.charAt(pos.offset))) { + result2 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[gG]"); + } + } + if (result2 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result3 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result4 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result4 !== null) { + result0 = [result0, result1, result2, result3, result4]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr("__REG_" + flattenChars(val).toLowerCase(), "REG"); })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_value() { + var cacheKey = "value@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + pos0 = clone(pos); + pos1 = clone(pos); + result0 = []; + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + if (result0 !== null) { + if (input.charCodeAt(pos.offset) === 46) { + result1 = "."; + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\".\""); + } + } + if (result1 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result3 !== null) { + result2 = []; + while (result3 !== null) { + result2.push(result3); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result2 = null; + } + if (result2 !== null) { + pos2 = clone(pos); + if (/^[Ee]/.test(input.charAt(pos.offset))) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[Ee]"); + } + } + if (result3 !== null) { + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result5 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result5 !== null) { + result4 = []; + while (result5 !== null) { + result4.push(result5); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result5 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result4 = null; + } + if (result4 !== null) { + result3 = [result3, result4]; + } else { + result3 = null; + pos = clone(pos2); + } + } else { + result3 = null; + pos = clone(pos2); + } + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(parseFloat(flattenChars(val)), "VALUE"); })(pos0.offset, pos0.line, pos0.column, result0); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[a-fA-F0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[a-fA-F0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[a-fA-F0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[a-fA-F0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + if (/^[hH]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[hH]"); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(parseInt(flattenChars(val), 16), "VALUE"); })(pos0.offset, pos0.line, pos0.column, result0[0]); + } + if (result0 === null) { + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + pos1 = clone(pos); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + if (/^[dD]/.test(input.charAt(pos.offset))) { + result1 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[dD]"); + } + } + result1 = result1 !== null ? result1 : ""; + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos1); + } + } else { + result0 = null; + pos = clone(pos1); + } + if (result0 !== null) { + result0 = (function(offset, line, column, val) { return new Webvs.AstPrimaryExpr(parseInt(flattenChars(val), 10), "VALUE"); })(pos0.offset, pos0.line, pos0.column, result0[0]); + } + if (result0 === null) { + pos = clone(pos0); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse___() { + var cacheKey = "__@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1; + + result0 = []; + result1 = parse_whiteSpace(); + if (result1 === null) { + result1 = parse_lineEnd(); + if (result1 === null) { + result1 = parse_comment(); + } + } + while (result1 !== null) { + result0.push(result1); + result1 = parse_whiteSpace(); + if (result1 === null) { + result1 = parse_lineEnd(); + if (result1 === null) { + result1 = parse_comment(); + } + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_whiteSpace() { + var cacheKey = "whiteSpace@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (/^[\t\x0B\f \xA0\uFEFF]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\t\\x0B\\f \\xA0\\uFEFF]"); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_lineEnd() { + var cacheKey = "lineEnd@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0; + + if (/^[\n\r\u2028\u2029]/.test(input.charAt(pos.offset))) { + result0 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[\\n\\r\\u2028\\u2029]"); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + function parse_comment() { + var cacheKey = "comment@" + pos.offset; + var cachedResult = cache[cacheKey]; + if (cachedResult) { + pos = clone(cachedResult.nextPos); + return cachedResult.result; + } + + var result0, result1, result2, result3; + var pos0, pos1, pos2; + + pos0 = clone(pos); + if (input.substr(pos.offset, 2) === "/*") { + result0 = "/*"; + advance(pos, 2); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"/*\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + if (input.substr(pos.offset, 2) === "*/") { + result2 = "*/"; + advance(pos, 2); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + while (result2 !== null) { + result1.push(result2); + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + if (input.substr(pos.offset, 2) === "*/") { + result2 = "*/"; + advance(pos, 2); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + } + if (result1 !== null) { + if (input.substr(pos.offset, 2) === "*/") { + result2 = "*/"; + advance(pos, 2); + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"*/\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = clone(pos0); + } + } else { + result0 = null; + pos = clone(pos0); + } + } else { + result0 = null; + pos = clone(pos0); + } + if (result0 === null) { + pos0 = clone(pos); + if (input.substr(pos.offset, 2) === "//") { + result0 = "//"; + advance(pos, 2); + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"//\""); + } + } + if (result0 !== null) { + result1 = []; + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + result2 = parse_lineEnd(); + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + while (result2 !== null) { + result1.push(result2); + pos1 = clone(pos); + pos2 = clone(pos); + reportFailures++; + result2 = parse_lineEnd(); + reportFailures--; + if (result2 === null) { + result2 = ""; + } else { + result2 = null; + pos = clone(pos2); + } + if (result2 !== null) { + if (input.length > pos.offset) { + result3 = input.charAt(pos.offset); + advance(pos, 1); + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("any character"); + } + } + if (result3 !== null) { + result2 = [result2, result3]; + } else { + result2 = null; + pos = clone(pos1); + } + } else { + result2 = null; + pos = clone(pos1); + } + } + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = clone(pos0); + } + } else { + result0 = null; + pos = clone(pos0); + } + } + + cache[cacheKey] = { + nextPos: clone(pos), + result: result0 + }; + return result0; + } + + + function cleanupExpected(expected) { + expected.sort(); + + var lastExpected = null; + var cleanExpected = []; + for (var i = 0; i < expected.length; i++) { + if (expected[i] !== lastExpected) { + cleanExpected.push(expected[i]); + lastExpected = expected[i]; + } + } + return cleanExpected; + } + + + + function makeBinaryExpr(head, tail) { + var result = head; + _.each(tail, function(tailItem) { + result = new Webvs.AstBinaryExpr(tailItem[1], result, tailItem[3]); + }); + return result; + } + + function flattenChars(val) { + return _.flatten(val).join(""); + } + + + var result = parseFunctions[startRule](); + + /* + * The parser is now in one of the following three states: + * + * 1. The parser successfully parsed the whole input. + * + * - |result !== null| + * - |pos.offset === input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 2. The parser successfully parsed only a part of the input. + * + * - |result !== null| + * - |pos.offset < input.length| + * - |rightmostFailuresExpected| may or may not contain something + * + * 3. The parser did not successfully parse any part of the input. + * + * - |result === null| + * - |pos.offset === 0| + * - |rightmostFailuresExpected| contains at least one failure + * + * All code following this comment (including called functions) must + * handle these states. + */ + if (result === null || pos.offset !== input.length) { + var offset = Math.max(pos.offset, rightmostFailuresPos.offset); + var found = offset < input.length ? input.charAt(offset) : null; + var errorPosition = pos.offset > rightmostFailuresPos.offset ? pos : rightmostFailuresPos; + + throw new this.SyntaxError( + cleanupExpected(rightmostFailuresExpected), + found, + offset, + errorPosition.line, + errorPosition.column + ); + } + + return result; + }, + + /* Returns the parser source code. */ + toSource: function() { return this._source; } + }; + + /* Thrown when a parser encounters a syntax error. */ + + result.SyntaxError = function(expected, found, offset, line, column) { + function buildMessage(expected, found) { + var expectedHumanized, foundHumanized; + + switch (expected.length) { + case 0: + expectedHumanized = "end of input"; + break; + case 1: + expectedHumanized = expected[0]; + break; + default: + expectedHumanized = expected.slice(0, expected.length - 1).join(", ") + + " or " + + expected[expected.length - 1]; + } + + foundHumanized = found ? quote(found) : "end of input"; + + return "Expected " + expectedHumanized + " but " + foundHumanized + " found."; + } + + this.name = "SyntaxError"; + this.expected = expected; + this.found = found; + this.message = buildMessage(expected, found); + this.offset = offset; + this.line = line; + this.column = column; + }; + + result.SyntaxError.prototype = Error.prototype; + + return result; +})(); +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * An object that encapsulates the generated executable code + * and its state values. Also contains implementations of + * functions callable from expressions + * @constructor + * @memberof Webvs + */ +function CodeInstance() {} +Webvs.CodeInstance = Webvs.defineClass(CodeInstance, Object, { + /** + * avs expression rand function + * @memberof Webvs.CodeInstance + */ + rand: function(max) { + return Math.floor(Math.random() * max) + 1; + }, + + /** + * avs expression gettime function + * @memberof Webvs.CodeInstance + */ + gettime: function(startTime) { + switch(startTime) { + case 0: + var currentTime = (new Date()).getTime(); + return (currentTime-this._bootTime)/1000; + default: throw new Error("Invalid startTime mode for gettime call"); + } + }, + + /** + * avs expression getosc function + * @memberof Webvs.CodeInstance + */ + getosc: function(band, width, channel) { + var osc = this._analyser.getWaveform(); + var pos = Math.floor((band - width/2)*(osc.length-1)); + var end = Math.floor((band + width/2)*(osc.length-1)); + + var sum = 0; + for(var i = pos;i <= end;i++) { + sum += osc[i]; + } + return sum/(end-pos+1); + }, + + /** + * bind state values to uniforms + * @param {Webvs.ShaderProgram} program - program to which the state values + * should be bound + * @memberof Webvs.CodeInstance + */ + bindUniforms: function(program) { + var that = this; + // bind all values + var toBeBound = _.difference(_.keys(this), this._treatAsNonUniform); + _.each(toBeBound, function(name) { + var value = that[name]; + if(typeof value !== "number") { return; } + program.setUniform(name, "1f", value); + }); + + // bind registers + _.each(this._registerUsages, function(name) { + program.setUniform(name, "1f", this._registerBank[name]); + }); + + // bind random step value if there are usages of random + if(this.hasRandom) { + var step = [Math.random()/100, Math.random()/100]; + program.setUniform("__randStep", "2fv", step); + } + + // bind time values for gettime calls + if(this.hasGettime) { + var time0 = ((new Date()).getTime()-this._bootTime)/1000; + program.setUniform("__gettime0", "1f", time0); + } + + // bind precomputed values + _.each(this._preCompute, function(item, index) { + var args = _.map(_.last(item, item.length-2), function(arg) { + if(_.isString(arg)) { + if(arg.substring(0, 5) == "__REG") { + return this._registerBank[arg]; + } else { + return this[arg]; + } + } else { + return arg; + } + }); + var result = this[item[0]].apply(this, args); + program.setUniform(item[1], "1f", result); + }); + }, + + /** + * initializes this codeinstance + * @param {Webvs.Main} main - webvs main instance + * @param {Webvs.Component} parent - the component thats using this codeinstance + * @memberof Webvs.CodeInstance + */ + setup: function(main, parent) { + this._registerBank = main.registerBank; + this._bootTime = main.bootTime; + this._analyser = main.analyser; + + this.w = main.canvas.width; + this.h = main.canvas.height; + this.cid = parent.cloneId; + + // clear all used registers + _.each(this._registerUsages, function(name) { + if(!_.has(main.registerBank, name)) { + main.registerBank[name] = 0; + } + }); + } +}); + + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * AVS expression parser and code generator. + * Generates JS and GLSL code from avs expressions + * @param {object.} codeSrc - object containing avs expression code string + * @param {Array.} externalVars - list of variables that will be supplied externally. + * @memberof Webvs + * @constructor + */ +function ExprCodeGenerator(codeSrc, externalVars) { + this.codeSrc = codeSrc; + this.externalVars = externalVars?externalVars:[]; + this._parseSrc(); +} +Webvs.ExprCodeGenerator = Webvs.defineClass(ExprCodeGenerator, Object, { + _parseSrc: function() { + // Generate AST and find variables usages in all the expressions + var codeAst = {}; + var variables = []; + var funcUsages = {}; + var registerUsages = []; + for(var name in this.codeSrc) { + try { + var codeSrc = this.codeSrc[name]; + if(_.isArray(codeSrc)) { + codeSrc = codeSrc.join("\n"); + } + codeAst[name] = Webvs.PegExprParser.parse(codeSrc); + var vars = []; + var fu = []; + this._getVars(codeAst[name], variables, fu, registerUsages); + funcUsages[name] = fu; + } catch(e) { + throw new Error("Error parsing " + name + "(" + e.line + ":" + e.column + ")" + " : " + e); + } + } + this.codeAst = codeAst; + this.funcUsages = funcUsages; + + // find instance variables + this.instanceVars = _.uniq(this.externalVars.concat(variables)); + + // find register variable usages + this.registerUsages = _.uniq(registerUsages); + }, + + /** + * Generates js and glsl executable code for each expression code string + * @param {Array.} jsFuncs - functions to be generated as javascript + * @param {Array.} jsFuncs - functions to be generated as glsl + * @param {Array.} treatAsNonUniform - variables to be treated as + * uniform variables in the glsl code + * @returns {Array} pair containing {@link Webvs.CodeInstance} and a glsl code + * @memberof Webvs.ExprCodeGenerator + */ + generateCode: function(jsFuncs, glslFuncs, treatAsNonUniform) { + var inst = new Webvs.CodeInstance(); + var that = this; + var glsl = []; + + _.each(this.instanceVars, function(ivar) { + // clear instance variables in code instance + inst[ivar] = 0; + + // create declarations for instance variables in glsl + var prefix = ""; + if(!_.contains(treatAsNonUniform, ivar)) { + prefix = "uniform "; + } + glsl.push(prefix + "float " + ivar + ";"); + }); + + var jsFuncList = _.intersection(_.keys(this.codeAst), jsFuncs); + var missingJsFuncList = _.difference(jsFuncs, jsFuncList); + + // generate javascript functions and assign to code instance + _.each(jsFuncList, function(name) { + var ast = that.codeAst[name]; + var codeString = that._generateJs(ast); + inst[name] = new Function(codeString); + }); + // add noops for missing expressions + _.each(missingJsFuncList, function(name) { + inst[name] = Webvs.noop; + }); + + var glslFuncList = _.intersection(_.keys(this.codeAst), glslFuncs); + var missingGlslFuncList = _.difference(glslFuncs, glslFuncList); + var glsFuncUsages = _.uniq( + _.flatMap(glslFuncList, function(name) { return that.funcUsages[name]; }) + ); + + // include required functions in glsl + _.each(glsFuncUsages, function(usage) { + var code = that.glslFuncCode[usage]; + if(!code) { + return; + } + glsl.push(code); + }); + var preCompute = []; // list of precomputed bindings + var generatedGlslFuncs = []; + // generate glsl functions + _.each(glslFuncList, function(name) { + var ast = that.codeAst[name]; + var codeString = that._generateGlsl(ast, preCompute); + generatedGlslFuncs.push("void " + name + "() {"); + generatedGlslFuncs.push(codeString); + generatedGlslFuncs.push("}"); + }); + // add the uniform declarations for precomputed functions + glsl = glsl.concat(_.map(preCompute, function(item) { + return "uniform float " + item[1] + ";"; + })); + glsl = glsl.concat(generatedGlslFuncs); + inst._preCompute = preCompute; + + // generate noops for missing functions + _.each(missingGlslFuncList, function(name) { + glsl.push("void " + name + "() {}"); + }); + + if(_.contains(glslFuncList, "rand")) { + inst.hasRandom = true; + } + if(_.contains(glslFuncList, "gettime")) { + inst.hasGettime = true; + } + inst._treatAsNonUniform = treatAsNonUniform; + inst._registerUsages = this.registerUsages; + + return [inst, glsl.join("")]; + }, + + funcArgLengths: { + "above": 2, + "below": 2, + "equal": 2, + "pow": 2, + "sqr": 1, + "sqrt": 1, + "invsqrt": 1, + "floor" : 1, + "ceil" : 1, + "abs": 1, + "if": 3, + "sin": 1, + "cos": 1, + "tan": 1, + "asin": 1, + "acos": 1, + "atan": 1, + "atan2": 2, + "log": 1, + "band": 2, + "bor": 2, + "bnot": 1, + "rand": 1, + "gettime": 1, + "getosc": 3, + "select": {min: 2} + }, + + jsMathFuncs: ["sin", "cos", "abs", "tan", "asin", "acos", "atan", "log", "pow", "sqrt", "floor", "ceil"], + + glslFuncCode: { + "rand": [ + "uniform vec2 __randStep;", + "vec2 __randSeed;", + "float rand(float max) {", + " __randCur += __randStep;", + " float val = fract(sin(dot(__randSeed.xy ,vec2(12.9898,78.233))) * 43758.5453);", + " return (floor(val*max)+1);", + "}" + ].join("\n"), + "gettime": [ + "uniform float __gettime0;", + "int gettime(int startTime) {", + " int time = 0;", + " if(startTime == 0) {", + " time = __gettime0;", + " }", + " return time;", + "}" + ].join("\n") + }, + + _checkFunc: function(ast) { + var requiredArgLength = this.funcArgLengths[ast.funcName]; + if(requiredArgLength === undefined) { + throw Error("Unknown function " + ast.funcName); + } + if(_.isNumber(requiredArgLength)) { + if(ast.args.length != requiredArgLength) { + throw Error(ast.funcName + " accepts " + requiredArgLength + " arguments"); + } + } else if(requiredArgLength.min) { + if(ast.args.length < requiredArgLength.min) { + throw Error(ast.funcName + " accepts atleast " + requiredArgLength.min + " arguments"); + } + } + }, + + _generateGlsl: function(ast, preCompute) { + var that = this; + + if(ast instanceof Webvs.AstBinaryExpr) { + return "(" + this._generateGlsl(ast.leftOperand, preCompute) + ast.operator + this._generateGlsl(ast.rightOperand, preCompute) + ")"; + } + if(ast instanceof Webvs.AstUnaryExpr) { + return "(" + ast.operator + this._generateGlsl(ast.operand, preCompute) + ")"; + } + if(ast instanceof Webvs.AstFuncCall) { + this._checkFunc(ast); + switch(ast.funcName) { + case "above": + return [ + "(", + this._generateGlsl(ast.args[0], preCompute), + ">", + this._generateGlsl(ast.args[1], preCompute), + "?1.0:0.0)" + ].join(""); + case "below": + return [ + "(", + this._generateGlsl(ast.args[0], preCompute), + "<", + this._generateGlsl(ast.args[1], preCompute), + "?1.0:0.0)" + ].join(""); + case "equal": + return [ + "(", + this._generateGlsl(ast.args[0], preCompute), + "==", + this._generateGlsl(ast.args[1], preCompute), + "?1.0:0.0)" + ].join(""); + case "if": + return [ + "(", + this._generateGlsl(ast.args[0], preCompute), + "!=0.0?", + this._generateGlsl(ast.args[1], preCompute), + ":", + this._generateGlsl(ast.args[2], preCompute), + ")" + ].join(""); + case "select": + var selectExpr = this._generateGlsl(ast.args[0], preCompute); + var generateSelect = function(args, i) { + if(args.length == 1) { + return that._generateGlsl(args[0], preCompute); + } + else { + return [ + "(("+selectExpr+" === "+i+")?", + "("+that._generateGlsl(args[0], preCompute)+"):", + "("+generateSelect(_.last(args, args.length-1), i+1)+"))" + ].join(""); + } + }; + return generateSelect(_.last(ast.args, ast.args.length-1), 0); + case "sqr": + return "(pow((" + this._generateGlsl(ast.args[0], preCompute) + "), 2))"; + case "band": + return "(float(("+this._generateGlsl(ast.args[0], preCompute)+")&&("+this._generateGlsl(ast.args[1], preCompute)+")))"; + case "bor": + return "(float(("+this._generateGlsl(ast.args[0], preCompute)+")||("+this._generateGlsl(ast.args[1], preCompute)+")))"; + case "bnot": + return "(float(!("+this._generateGlsl(ast.args[0], preCompute)+")))"; + case "invsqrt": + return "(1/sqrt("+this._generateGlsl(ast.args[0], preCompute)+"))"; + case "atan2": + return "(atan(("+this._generateGlsl(ast.args[0], preCompute)+"),("+this._generateGlsl(ast.args[1], preCompute)+"))"; + case "getosc": + var allStatic = _.every(ast.args, function(arg) { + return arg instanceof Webvs.AstPrimaryExpr; + }); + if(!allStatic) { + throw new Error("Non Pre-Computable arguments for getosc in shader code, use variables or constants"); + } + var uniformName = "__PC_" + ast.funcName + "_" + pos; + var item = [ast.funcName, uniformName].concat(_.map(ast.args, function(arg) {return arg.value;})); + var pos = _.indexOf(preCompute, item); + if(pos == -1) { + preCompute.push(item); + pos = preCompute.length-1; + } + return uniformName; + default: + var args = _.map(ast.args, function(arg) {return that._generateGlsl(arg, preCompute);}).join(","); + var funcName = ast.funcName; + if(_.contains(this.varArgFuncs, ast.funcName)) { + funcName += ast.args.length; + } + return "(" + funcName + "(" + args + "))"; + } + } + if(ast instanceof Webvs.AstAssignment) { + return this._generateGlsl(ast.lhs, preCompute) + "=" + this._generateGlsl(ast.expr, preCompute); + } + if(ast instanceof Webvs.AstProgram) { + var stmts = _.map(ast.statements, function(stmt) {return that._generateGlsl(stmt, preCompute);}); + return stmts.join(";\n")+";"; + } + if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "VALUE") { + return Webvs.glslFloatRepr(ast.value); + } + if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "CONST") { + return this._translateConstants(ast.value).toString(); + } + if(ast instanceof Webvs.AstPrimaryExpr && (ast.type === "ID" || ast.type === "REG")) { + return ast.value; + } + }, + + _generateJs: function(ast) { + var prefix; + var that = this; + + if(ast instanceof Webvs.AstBinaryExpr) { + return "(" + this._generateJs(ast.leftOperand) + ast.operator + this._generateJs(ast.rightOperand) + ")"; + } + if(ast instanceof Webvs.AstUnaryExpr) { + return "(" + ast.operator + this._generateJs(ast.operand) + ")"; + } + if(ast instanceof Webvs.AstFuncCall) { + this._checkFunc(ast); + switch(ast.funcName) { + case "above": + return [ + "(", + this._generateJs(ast.args[0]), + ">", + this._generateJs(ast.args[1]), + "?1:0)" + ].join(""); + case "below": + return [ + "(", + this._generateJs(ast.args[0]), + "<", + this._generateJs(ast.args[1]), + "?1:0)" + ].join(""); + case "equal": + return [ + "(", + this._generateJs(ast.args[0]), + "==", + this._generateJs(ast.args[1]), + "?1:0)" + ].join(""); + case "if": + return [ + "(", + this._generateJs(ast.args[0]), + "!==0?", + this._generateJs(ast.args[1]), + ":", + this._generateJs(ast.args[2]), + ")" + ].join(""); + case "select": + var code = ["((function() {"]; + code.push("switch("+this._generateJs(ast.args[0])+") {"); + _.each(_.last(ast.args, ast.args.length-1), function(arg, i) { + code.push("case "+i+": return "+this._generateJs(arg)+";"); + }, this); + code.push("default : throw new Error('Unknown selector value in select');"); + code.push("}}).call(this))"); + return code.join(""); + case "sqr": + return "(Math.pow((" + this._generateJs(ast.args[0]) + "),2))"; + case "band": + return "((("+this._generateJs(ast.args[0])+")&&("+this._generateJs(ast.args[1])+"))?1:0)"; + case "bor": + return "((("+this._generateJs(ast.args[0])+")||("+this._generateJs(ast.args[1])+"))?1:0)"; + case "bnot": + return "((!("+this._generateJs(ast.args[0])+"))?1:0)"; + case "invsqrt": + return "(1/Math.sqrt("+this._generateJs(ast.args[0])+"))"; + case "atan2": + return "(Math.atan(("+this._generateJs(ast.args[0])+")/("+this._generateJs(ast.args[1])+")))"; + default: + var args = _.map(ast.args, function(arg) {return that._generateJs(arg);}).join(","); + if(_.contains(this.jsMathFuncs, ast.funcName)) { + prefix = "Math."; + } else { + prefix = "this."; + } + return "(" + prefix + ast.funcName + "(" + args + "))"; + } + } + if(ast instanceof Webvs.AstAssignment) { + return this._generateJs(ast.lhs) + "=" + this._generateJs(ast.expr); + } + if(ast instanceof Webvs.AstProgram) { + var stmts = _.map(ast.statements, function(stmt) {return that._generateJs(stmt);}); + return stmts.join(";\n"); + } + if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "VALUE") { + return ast.value.toString(); + } + if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "CONST") { + return this._translateConstants(ast.value).toString(); + } + if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "ID") { + return "this." + ast.value; + } + if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "REG") { + return "this._registerBank[\"" + ast.value + "\"]"; + } + }, + + _getVars: function(ast, vars, funcUsages, regUsages) { + var that = this; + + if(ast instanceof Webvs.AstBinaryExpr) { + this._getVars(ast.leftOperand, vars, funcUsages, regUsages); + this._getVars(ast.rightOperand, vars, funcUsages, regUsages); + } + + else if(ast instanceof Webvs.AstUnaryExpr) { + this._getVars(ast.operand, vars, funcUsages, regUsages); + } + else if(ast instanceof Webvs.AstFuncCall) { + funcUsages.push(ast.funcName); + _.each(ast.args, function(arg) { + that._getVars(arg, vars, funcUsages, regUsages); + }); + } + else if(ast instanceof Webvs.AstAssignment) { + this._getVars(ast.lhs, vars, funcUsages, regUsages); + this._getVars(ast.expr, vars, funcUsages, regUsages); + } + else if(ast instanceof Webvs.AstProgram) { + _.each(ast.statements, function(stmt) { + that._getVars(stmt, vars, funcUsages, regUsages); + }); + } + else if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "ID") { + vars.push(ast.value); + } + else if(ast instanceof Webvs.AstPrimaryExpr && ast.type === "REG") { + regUsages.push(ast.value); + } + }, + + _translateConstants: function(value) { + switch(value) { + case "pi": return Math.PI; + case "e": return Math.E; + case "phi": return 1.6180339887; + default: throw new Error("Unknown constant " + value); + } + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that simply runs some avs expressions. + * Useful to maintain global state + * + * @param {object} options - options object + * @param {string} [options.code.init] - code to be run at startup + * @param {string} [options.code.onBeat] - code to be run when a beat occurs + * @param {string} [ptions.code.perFrame]- code to be run on every frame + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function GlobalVar(options) { + Webvs.checkRequiredOptions(options, ["code"]); + var codeGen = new Webvs.ExprCodeGenerator(options.code, ["b", "w", "h"]); + var genResult = codeGen.generateCode(["init", "onBeat", "perFrame"], [], []); + this.code = genResult[0]; + this.inited = false; + + GlobalVar.super.constructor.call(this); +} +Webvs.GlobalVar = Webvs.defineClass(GlobalVar, Webvs.Component, { + /** + * initializes the globalvar component + * @memberof Webvs.GlobalVar + */ + init: function(gl, main, parent) { + GlobalVar.super.init.call(this, gl, main, parent); + + this.code.setup(main, this); + }, + + /** + * Runs the code + * @memberof Webvs.GlobalVar + */ + update: function() { + var code = this.code; + code.b = this.main.analyser.beat?1:0; + + if(!this.inited) { + code.init(); + this.inited = true; + } + + if(this.main.analyser.beat) { + code.onBeat(); + } + + code.perFrame(); + } +}); + +GlobalVar.ui = { + disp: "Global Var", + type: "GlobalVar", + schema: { + code: { + type: "object", + title: "Code", + default: {}, + properties: { + init: { + type: "string", + title: "Init", + }, + onBeat: { + type: "string", + title: "On Beat", + }, + perFrame: { + type: "string", + title: "Per Frame", + } + }, + } + } +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A components that saves or restores a copy of the current + * frame buffer. + * + * @param {object} options - options object + * @param {string} [options.action="SAVE"] - the action to be performed. viz. "SAVE", + * "RESTORE", "RESTORESAVE", "SAVERESTORE" + * @param {number} [options.bufferId=1] - an identifying number for the buffer. This number + * is used to share buffer between different instances of BufferSave + * @param {string} [options.blendMode="REPLACE"] - blending mode when restoring buffers + * @constructor + * @augments Webvs.Component + * @memberof Webvs + */ +function BufferSave(options) { + options = _.defaults(options, { + action: "SAVE", + bufferId: 1, + blendMode: "REPLACE" + }); + this.blendMode = Webvs.blendModes[options.blendMode]; + this.action = this.actions[options.action]; + if(!this.action) { + throw new Error("Unknown BufferSave action " + options.action); + } + + if(this.action == this.actions.SAVERESTORE) { + this._nextAction = this.actions.SAVE; + } else if(this.action == this.actions.RESTORESAVE) { + this._nextAction = this.actions.RESTORE; + } + this._bufferId = "__BUFFERSAVE_" + options.bufferId; + BufferSave.super.constructor.call(this); +} +Webvs.BufferSave = Webvs.defineClass(BufferSave, Webvs.Component, { + actions: { + SAVE: 1, + RESTORE: 2, + SAVERESTORE: 3, + RESTORESAVE: 4 + }, + + /** + * Initializes the BufferSave component + * @memberof Webvs.BufferSave + */ + init: function(gl, main, parent) { + BufferSave.super.init.call(this, gl, main, parent); + + // create frame buffer manager + if(!main.registerBank[this._bufferId]) { + var fm = new Webvs.FrameBufferManager(main.canvas.width, main.canvas.height, gl, main.copier, 1); + main.registerBank[this._bufferId] = fm; + } + }, + + /** + * Saves or Renders the current frame + * @memberof Webvs.BufferSave + */ + update: function() { + var gl = this.gl; + var fm = this.main.registerBank[this._bufferId]; + + // find the current action + var currentAction; + if(this.action == this.actions.SAVERESTORE || this.action == this.RESTORESAVE) { + currentAction = this._nextAction; + // set the next action + if(this._nextAction == this.actions.SAVE) { + this._nextAction = this.actions.RESTORE; + } else { + this._nextAction = this.actions.SAVE; + } + } else { + currentAction = this.action; + } + + switch(currentAction) { + case this.actions.SAVE: + fm.setRenderTarget(); + this.main.copier.run(null, null, this.parent.fm.getCurrentTexture()); + fm.restoreRenderTarget(); + break; + case this.actions.RESTORE: + this.main.copier.run(this.parent.fm, this.blendMode, fm.getCurrentTexture()); + break; + } + }, + + /** + * Releases resources. + * @memberof Webgl.BufferSave + */ + destroy: function() { + BufferSave.super.destroy.call(this); + // destroy the framebuffermanager + this.main.registerBank[this._bufferId].destroy(); + } +}); + +BufferSave.ui = { + disp: "Buffer Save", + type: "BufferSave", + schema: { + action: { + type: "string", + title: "Buffer save action", + enum: ["SAVE", "RESTORE", "SAVERESTORE", "RESTORESAVE"] + }, + bufferId: { + type: "number", + title: "Buffer Id", + enum: [1,2,3,4,5,6,7,8] + }, + blendMode: { + type: "string", + title: "Blend mode", + enum: _.keys(Webvs.blendModes) + } + } +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that slowly fades the screen to a specified color + * + * @param {object} options - options object + * @param {number} [speed=1] - speed at which the screen is faded 0 (never) - 1 (fastest) + * @param {string} [color="#000000"] - fade color + * @augments Webvs.Component + * @constructor + * @memberof Webvs + * @constructor + */ +function FadeOut(options) { + options = _.defaults(options, { + speed: 1, + color: "#000000" + }); + this.color = Webvs.parseColorNorm(options.color); + + this.frameCount = 0; + this.maxFrameCount = Math.floor(1/options.speed); + this.program = new Webvs.ClearScreenProgram(Webvs.AVERAGE); + + FadeOut.super.constructor.call(this); +} +Webvs.FadeOut = Webvs.defineClass(FadeOut, Webvs.Component, { + componentName: "FadeOut", + + /** + * initializes the FadeOut component + * @memberof Webvs.FadeOut + */ + init: function(gl, main, parent) { + FadeOut.super.init.call(this, gl, main, parent); + this.program.init(gl); + }, + + /** + * fades the screen + * @memberof Webvs.FadeOut + */ + update: function() { + var gl = this.gl; + this.frameCount++; + if(this.frameCount == this.maxFrameCount) { + this.frameCount = 0; + this.program.run(this.parent.fm, null, this.color); + } + }, + + /** + * releases resources + * @memberof Webvs.FadeOut + */ + destroy: function() { + FadeOut.super.destroy.call(this); + this.program.cleanup(); + } +}); + +FadeOut.ui = { + type: "FadeOut", + disp: "Fade Out", + schema: { + speed: { + type: "number", + title: "Speed", + maximum: 0, + minimum: 1, + default: 1 + }, + color: { + type: "string", + title: "Fadeout color", + format: "color", + default: "#FFFFFF" + } + }, + form: [ + {key: "speed", type: "range", step: "0.05"}, + "color" + ] +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that applies a convolution kernel + * + * @param {object} options - options object + * @param {Array.>} options.kernel - an NxN array of numbers + * @param {number} [options.bias=0] - bias value to be added + * @param {number} [options.scale] - scale for the kernel. default is sum of kernel values + * @param {object} [options.edgeMode="EXTEND"] - how the frame edge cases should be handled viz. `WRAP`, `EXTEND` + * + * @constructor + * @augments Webvs.Component + * @memberof Webvs + */ +function Convolution(options) { + Webvs.checkRequiredOptions(options, ["kernel"]); + options = _.defaults(options, { + edgeMode: "EXTEND", + bias: 0 + }); + + var kernel; + if(options.kernel in Convolution.kernels) { + kernel = Convolution.kernels[options.kernel]; + } else if(_.isArray(options.kernel) && options.kernel.length%2 === 1) { + kernel = options.kernel; + } else { + throw new Error("Invalid convolution kernel"); + } + + var kernelSize = Math.floor(Math.sqrt(kernel.length)); + if(kernelSize*kernelSize != kernel.length) { + throw new Error("Invalid convolution kernel"); + } + + this.program = new Webvs.ConvolutionProgram(kernel, kernelSize, + options.edgeMode, options.scale, + options.bias); + + Convolution.super.constructor.call(this); +} +Webvs.Convolution = Webvs.defineClass(Convolution, Webvs.Component, { + componentName: "Convolution", + + /** + * initializes the Convolution component + * @method + * @memberof Webvs.Convolution + */ + init: function(gl, main, parent) { + Convolution.super.init.call(this, gl, main, parent); + this.program.init(gl); + }, + + /** + * applies the Convolution matrix + * @method + * @memberof Webvs.Convolution + */ + update: function() { + this.program.run(this.parent.fm, null); + }, + + /** + * releases resources + * @memberof Webvs.Convolution + */ + destroy: function() { + Convolution.super.destroy.call(this); + this.program.cleanup(); + } +}); + +Convolution.kernels = { + normal: [ + 0, 0, 0, + 0, 1, 0, + 0, 0, 0 + ], + gaussianBlur: [ + 0.045, 0.122, 0.045, + 0.122, 0.332, 0.122, + 0.045, 0.122, 0.045 + ], + unsharpen: [ + -1, -1, -1, + -1, 9, -1, + -1, -1, -1 + ], + emboss: [ + -2, -1, 0, + -1, 1, 1, + 0, 1, 2 + ], + blur: [ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1 + ] +}; + +function ConvolutionProgram(kernel, kernelSize, edgeMode, scale, bias) { + // generate edge correction function + var edgeFunc = ""; + switch(edgeMode) { + case "WRAP": + edgeFunc = "pos = vec2(pos.x<0?pos.x+1.0:pos.x%1, pos.y<0?pos.y+1.0:pos.y%1);"; + break; + case "EXTEND": + edgeFunc = "pos = clamp(pos, vec2(0,0), vec2(1,1));"; + break; + default: + throw new Error("Invalid edge mode"); + } + + var i,j; + + // generate kernel multiplication code + var colorSumEq = []; + var mid = Math.floor(kernelSize/2); + for(i = 0;i < kernelSize;i++) { + for(j = 0;j < kernelSize;j++) { + var value = kernel[(i*kernelSize+j)]; + if(value === 0) { + continue; + } + colorSumEq.push("pos = v_position + onePixel * vec2("+(i-mid)+","+(j-mid)+");"); + colorSumEq.push(edgeFunc); + colorSumEq.push("colorSum += texture2D(u_srcTexture, pos) * "+Webvs.glslFloatRepr(value)+";"); + } + } + + // compute kernel scaling factor + if(_.isUndefined(scale)) { + scale = _.reduce(kernel, function(memo, num){ return memo + num; }, 0); + } + + ConvolutionProgram.super.constructor.call(this, { + swapFrame: true, + fragmentShader: [ + "void main() {", + " vec2 onePixel = vec2(1.0, 1.0)/u_resolution;", + " vec2 pos;", + " vec4 colorSum = vec4(0,0,0,0);", + colorSumEq.join("\n"), + " setFragColor(vec4(((colorSum+"+Webvs.glslFloatRepr(bias)+") / "+Webvs.glslFloatRepr(scale)+").rgb, 1.0));", + "}" + ] + }); +} +Webvs.ConvolutionProgram = Webvs.defineClass(ConvolutionProgram, Webvs.QuadBoxProgram); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * a component that changes colors according to a gradient map using + * a key generated from the source colors + * + * @param {object} options - options object + * @param {Array.>} options.maps - a set of color maps. each colormap consists of + * a set of keystones. The map is generated by interpolating colors between the keystones. + * @param {string} options.maps[i][j].color - keystone color + * @param {number} options.maps[i][j].index - position of keystone (0-255) + * @param {object} options.maps - a set of color map + * @param {string} [options.key="RED"] - the key function viz. `RED`, `GREEN`, `BLUE`, `(R+G+B)/2`, `(R+G+B)/3`, `MAX` + * @param {string} [options.output="REPLACE"] - output blending mode + * @param {string} [options.mapCycleMode="SINGLE"] - how to cycle between maps + * + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function ColorMap(options) { + Webvs.checkRequiredOptions(options, ["maps"]); + options = _.defaults(options, { + key: "RED", + output: "REPLACE", + mapCycleMode: "SINGLE", + }); + + var that = this; + this.maps = options.maps; + this.currentMap = 0; + + this.mapCycleMode = this.mapCycleModes[options.mapCycleMode]; + if(!this.mapCycleMode) { + throw new Error("Unknown mapCycleMode " + options.mapCycleMode); + } + + this.program = new Webvs.ColorMapProgram(options.key, Webvs.blendModes[options.output]); + + ColorMap.super.constructor.call(this); +} +Webvs.ColorMap = Webvs.defineClass(ColorMap, Webvs.Component, { + mapCycleModes: { + SINGLE: 1, + ONBEATRANDOM: 2, + ONBEATSEQUENTIAL: 3 + }, + + /** + * initializes the ColorMap component + * @memberof Webvs.ColorMap + */ + init: function(gl, main, parent) { + ColorMap.super.init.call(this, gl, main, parent); + + this.colorMaps = _.map(this.maps, function(map) { + return this._buildColorMap(map); + }, this); + this.currentMap = 0; + + this.program.init(gl); + }, + + /** + * maps the colors + * @memberof Webvs.ColorMap + */ + update: function() { + if(this.main.analyser.beat) { + switch(this.mapCycleMode) { + case this.mapCycleModes.ONBEATRANDOM: + this.currentMap = Math.floor(Math.random()*this.colorMaps.length); + break; + case this.mapCycleModes.ONBEATSEQUENTIAL: + this.currentMap = (this.currentMap+1)%this.colorMaps.length; + break; + } + } + + this.program.run(this.parent.fm, null, this.colorMaps[this.currentMap]); + }, + + /** + * releases resources + * @memberof Webvs.ColorMap + */ + destroy: function() { + ColorMap.super.destroy.call(this); + this.program.cleanup(); + }, + + _buildColorMap: function(map) { + var gl = this.gl; + map = _.sortBy(map, function(mapItem) {return mapItem.index;}); + + // check for repeated indices + var indices = _.map(map, function(mapItem) {return mapItem.index;}); + if(_.uniq(indices).length != indices.length) { + throw new Error("map cannot have repeated indices"); + } + + // add a cap entries at the ends + var first = _.first(map); + if(first.index !== 0) { + map.splice(0, 0, {color:first.color, index:0}); + } + var last = _.last(map); + if(last.index !== 255) { + map.push({color:last.color, index:255}); + } + + map = _.map(map, function(mapItem) { + var color = Webvs.parseColor(mapItem.color); + return {color:color, index:mapItem.index}; + }); + + // lerp intermediate values + var colorMap = new Uint8Array(256*4); + var cmi = 0; + var pairs = _.zip(_.first(map, map.length-1), _.last(map, map.length-1)); + _.each(pairs, function(pair, i) { + var first = pair[0]; + var second = pair[1]; + var steps = second.index - first.index; + var colorStep = [ + (second.color[0] - first.color[0])/steps, + (second.color[1] - first.color[1])/steps, + (second.color[2] - first.color[2])/steps + ]; + _.times(steps, function(i) { + colorMap[cmi++] = (first.color[0] + colorStep[0]*i); + colorMap[cmi++] = (first.color[1] + colorStep[1]*i); + colorMap[cmi++] = (first.color[2] + colorStep[2]*i); + colorMap[cmi++] = 255; + }); + }); + colorMap[cmi++] = last.color[0]; + colorMap[cmi++] = last.color[1]; + colorMap[cmi++] = last.color[2]; + colorMap[cmi++] = 255; + + // put the color values into a 256x1 texture + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, colorMap); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + return texture; + } +}); + +function ColorMapProgram(key, blendMode) { + var keyEq = ""; + switch(key) { + case "RED": keyEq = "srcColor.r"; break; + case "GREEN": keyEq = "srcColor.g"; break; + case "BLUE": keyEq = "srcColor.b"; break; + case "(R+G+B)/2": keyEq = "mod((srcColor.r+srcColor.g+srcColor.b)/2.0, 1.0)"; break; + case "(R+G+B)/3": keyEq = "(srcColor.r+srcColor.g+srcColor.b)/3.0"; break; + case "MAX": keyEq = "max(srcColor.r, max(srcColor.g, srcColor.b))"; break; + default: throw new Error("Unknown colormap key function " + options.key); + } + + ColorMapProgram.super.constructor.call(this, { + outputBlendMode: blendMode, + swapFrame: true, + fragmentShader: [ + "uniform sampler2D u_colorMap;", + "void main() {", + " vec4 srcColor = getSrcColor();", + " setFragColor(texture2D(u_colorMap, vec2(("+keyEq+"), 0)));", + "}" + ] + }); +} +Webvs.ColorMapProgram = Webvs.defineClass(ColorMapProgram, Webvs.QuadBoxProgram, { + draw: function(colorMap) { + this.setUniform("u_colorMap", "texture2D", colorMap); + ColorMapProgram.super.draw.call(this); + } +}); + +ColorMap.ui = { + disp: "Color Map", + type: "ColorMap", + schema: { + maps: { + type: "array", + items: { + type: "array", + title: "Map", + items: { + type: "object", + properties: { + color: { + type: "string", + title: "Color", + format: "color", + default: "#FFFFFF" + }, + index: { + type: "number", + title: "Index", + minimum: 0, + maximum: 255, + } + } + } + } + }, + key: { + type: "string", + title: "Map key", + enum: ["RED", "GREEN", "BLUE", "(R+G+B)/2", "(R+G+B)/3", "MAX"], + default: "RED" + }, + mapCycleMode: { + type: "string", + title: "Map Cycle Mode", + enum: ["SINGLE", "ONBEATRANDOM", "ONBEATSEQUENTIAL"], + default: "SINGLE" + }, + output: { + type: "string", + title: "Output blend mode", + enum: _.keys(Webvs.blendModes), + default: "REPLACE" + } + } +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that clips colors to a different color depending + * on whether the source colors are above or below a reference color. + * + * @see r_contrast.cpp + * @param {object} options - options object + * @param {string} [options.mode="BELOW"] - comparison mode viz. `BELOW`, `ABOVE`, `NEAR` + * @param {string} [options.color="#202020"] - reference color against which the + * the screen colors are compared + * @param {string} [options.outColor="#202020"] - output color for clipped pixels + * @param {number} [options.level=0] - when mode is `NEAR`, this value decides the distance + * between source and reference colors below which pixels would be clipped. 0-1 normalized + * + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function ColorClip(options) { + Webvs.checkRequiredOptions(options, ["mode", "color", "outColor"]); + options = _.defaults(options, { + mode: "BELOW", + color: "#202020", + outColor: "#202020", + level: 0 + }); + + this.mode = _.indexOf(this.modes, options.mode); + if(this.mode == -1) { + throw new Error("ColorClip: invalid mode"); + } + this.color = Webvs.parseColorNorm(options.color); + this.outColor = Webvs.parseColorNorm(options.outColor); + this.level = options.level; + + this.program = new Webvs.ColorClipProgram(); +} +Webvs.ColorClip = Webvs.defineClass(ColorClip, Webvs.Component, { + modes: ["BELOW", "ABOVE", "NEAR"], + componentName: "ChannelShift", + + /** + * initializes the ColorClip component + * @memberof Webvs.ColorClip + */ + init: function(gl, main, parent) { + ColorClip.super.init.call(this, gl, main, parent); + + this.program.init(gl); + }, + + /** + * clips the colors + * @memberof Webvs.ColorClip + */ + update: function() { + this.program.run(this.parent.fm, null, this.mode, this.color, this.outColor, this.level); + }, + + /** + * releases resources + * @memberof Webvs.ColorClip + */ + destroy: function() { + ColorClip.super.destroy.call(this); + this.program.cleanup(); + } +}); + +function ColorClipProgram() { + ColorClipProgram.super.constructor({ + swapFrame: true, + fragmentShader: [ + "uniform int u_mode;", + "uniform vec3 u_color;", + "uniform vec3 u_outColor;", + "uniform float u_level;", + + "void main() {", + " vec4 inColor4 = getSrcColor();", + " vec3 inColor = inColor4.rgb;", + " bool clip = false;", + " if(u_mode == 0) {", + " clip = all(lessThanEqual(inColor, u_color));", + " }", + " if(u_mode == 1) {", + " clip = all(greaterThanEqual(inColor, u_color));", + " }", + " if(u_mode == 2) {", + " clip = (distance(inColor, u_color) <= u_level*0.5);", + " }", + " if(clip) {", + " setFragColor(vec4(u_outColor, inColor4.a));", + " } else {", + " setFragColor(inColor4);", + " }", + "}", + ] + }); +} +Webvs.ColorClipProgram = Webvs.defineClass(ColorClipProgram, Webvs.QuadBoxProgram, { + draw: function(mode, color, outColor, level) { + this.setUniform("u_mode", "1i", mode); + this.setUniform.apply(this, ["u_color", "3f"].concat(color)); + this.setUniform.apply(this, ["u_outColor", "3f"].concat(outColor)); + this.setUniform("u_level", "1f", level); + ColorClipProgram.super.draw.call(this); + } +}); + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that moves pixels according to user code. + * + * #### Code variables + * + * The following variables are available in the code + * + * + x - x position of the pixel (-1 to +1) + * + y - y position of the pixel (-1 to +1) + * + d - length of pixel position vector (0 to 1) + * + r - angle of the position vector with y axis in clockwise direction in radians + * + w - width of the screen + * + h - height of the screen + * + b - 1 if a beat has occured else 0 + * + * @param {object} options - options object + * @param {string} [options.code.init] - code to be run at startup + * @param {string} [options.code.onBeat] - code to be run when a beat occurs + * @param {string} [options.code.perFrame] - code to be run on every frame + * @param {string} [options.code.perPixel] - code that will be run once for every pixel. should set + * `x`, `y` or `d`, `r` variables (depending on coord) to specify point location. Note: state + * of this code does not persist. + * @param {number} [options.gridW=16] - width of the interpolation grid + * @param {number} [options.gridH=16] - height of the interpolation grid + * @param {boolean} [options.noGrid=false] - if true, then interpolation grid is not used + * ie. movement will be pixel accurate + * @param {boolean} [options.compat=false] - if true, then calculations are low precision. + * useful to map winamp AVS behaviour more closely + * @param {boolean} [options.bFilter=true] - use bilinear interpolation for pixel sampling + * @param {string} [options.coord="POLAR"] - coordinate system to be used viz. `POLAR`, `RECT` + * @augments Webvs.Component + * @constructor + * @memberof Webvs + * @constructor + */ +function DynamicMovement(options) { + Webvs.checkRequiredOptions(options, ["code"]); + options = _.defaults(options, { + gridW: 16, + gridH: 16, + noGrid: false, + bFilter: true, + compat: false, + coord: "POLAR" + }); + + var codeSrc; + if(_.isObject(options.code)) { + codeSrc = options.code; + } else { + throw new Error("Invalid Dynamic movement code"); + } + var codeGen = new Webvs.ExprCodeGenerator(codeSrc, ["x", "y", "r", "d", "b", "w", "h"]); + var genResult = codeGen.generateCode(["init", "onBeat", "perFrame"], ["perPixel"], ["x", "y", "d", "r"]); + this.code = genResult[0]; + this.inited = false; + + this.noGrid = options.noGrid; + this.gridW = options.gridW; + this.gridH = options.gridH; + + this.coordMode = options.coord; + this.bFilter = options.bFilter; + this.compat = options.compat; + + if(this.noGrid) { + this.program = new Webvs.DMovProgramNG(this.coordMode, this.bFilter, + this.compat, this.code.hasRandom, + genResult[1]); + } else { + this.program = new Webvs.DMovProgram(this.coordMode, this.bFilter, + this.compat, this.code.hasRandom, + genResult[1]); + } + + DynamicMovement.super.constructor.call(this); +} +Webvs.DynamicMovement = Webvs.defineClass(DynamicMovement, Webvs.Component, { + componentName: "DynamicMovement", + + /** + * initializes the DynamicMovement component + * @memberof Webvs.DynamicMovement + */ + init: function(gl, main, parent) { + DynamicMovement.super.init.call(this, gl, main, parent); + + this.program.init(gl); + + this.code.setup(main, parent); + + // calculate grid vertices + if(!this.noGrid) { + var nGridW = (this.gridW/this.main.canvas.width)*2; + var nGridH = (this.gridH/this.main.canvas.height)*2; + var gridCountAcross = Math.ceil(this.main.canvas.width/this.gridW); + var gridCountDown = Math.ceil(this.main.canvas.height/this.gridH); + var gridVertices = new Float32Array(gridCountAcross*gridCountDown*6*2); + var pbi = 0; + var curx = -1; + var cury = -1; + for(var i = 0;i < gridCountDown;i++) { + for(var j = 0;j < gridCountAcross;j++) { + var cornx = Math.min(curx+nGridW, 1); + var corny = Math.min(cury+nGridH, 1); + + gridVertices[pbi++] = curx; + gridVertices[pbi++] = cury; + gridVertices[pbi++] = cornx; + gridVertices[pbi++] = cury; + gridVertices[pbi++] = curx; + gridVertices[pbi++] = corny; + + gridVertices[pbi++] = cornx; + gridVertices[pbi++] = cury; + gridVertices[pbi++] = cornx; + gridVertices[pbi++] = corny; + gridVertices[pbi++] = curx; + gridVertices[pbi++] = corny; + + curx += nGridW; + } + curx = -1; + cury += nGridH; + } + this.gridVertices = gridVertices; + this.gridVerticesSize = pbi/2; + } + }, + + /** + * moves the pixels + * @memberof Webvs.DynamicMovement + */ + update: function() { + var code = this.code; + + // run init, if required + if(!this.inited) { + code.init(); + this.inited = true; + } + + var beat = this.main.analyser.beat; + code.b = beat?1:0; + // run per frame + code.perFrame(); + // run on beat + if(beat) { + code.onBeat(); + } + + if(this.noGrid) { + this.program.run(this.parent.fm, null, this.code); + } else { + this.program.run(this.parent.fm, null, this.code, this.gridVertices, this.gridVerticesSize); + } + }, + + /** + * releases resources + * @memberof Webvs.DynamicMovement + */ + destroy: function() { + DynamicMovement.super.destroy.call(this); + this.program.cleanup(); + } +}); + +var GlslHelpers = { + glslRectToPolar: function(coordMode) { + if(coordMode === "POLAR") { + return [ + "d = distance(vec2(x, y), vec2(0,0))/sqrt(2.0);", + "r = mod(atan(y, x)+PI*0.5, 2.0*PI);" + ].join("\n"); + } else { + return ""; + } + }, + + glslPolarToRect: function(coordMode) { + if(coordMode === "POLAR") { + return [ + "d = d*sqrt(2.0);", + "x = d*sin(r);", + "y = -d*cos(r);" + ].join("\n"); + } else { + return ""; + } + }, + + glslFilter: function(bFilter, compat) { + if(bFilter && !compat) { + return [ + "vec3 filter(vec2 point) {", + " vec2 texel = 1.0/(u_resolution-vec2(1,1));", + " vec2 coord = (point+1.0)/2.0;", + " vec2 cornoff = fract(coord/texel);", + " vec2 corn = floor(coord/texel)*texel;", + + " vec3 tl = getSrcColorAtPos(corn).rgb;", + " vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;", + " vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;", + " vec3 br = getSrcColorAtPos(corn + texel).rgb;", + + " vec3 pt = mix(tl, tr, cornoff.x);", + " vec3 pb = mix(bl, br, cornoff.x);", + " return mix(pt, pb, cornoff.y);", + "}" + ].join("\n"); + } else if(bFilter && compat) { + return [ + "vec3 filter(vec2 point) {", + " vec2 texel = 1.0/(u_resolution-vec2(1,1));", + " vec2 coord = (point+1.0)/2.0;", + " vec2 corn = floor(coord/texel)*texel;", + + " vec3 tl = getSrcColorAtPos(corn).rgb;", + " vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;", + " vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;", + " vec3 br = getSrcColorAtPos(corn + texel).rgb;", + + " float xp = floor(fract(coord.x/texel.x)*255.0);", + " float yp = floor(fract(coord.y/texel.y)*255.0);", + + " #define g_blendtable(i, j) floor(((i)/255.0)*(j))", + + " float a1 = g_blendtable(255.0-xp, 255.0-yp);", + " float a2 = g_blendtable(xp, 255.0-yp);", + " float a3 = g_blendtable(255.0-xp, yp);", + " float a4 = g_blendtable(xp, yp);", + + " float r = (floor(a1*tl.r) + floor(a2*tr.r) + floor(a3*bl.r) + floor(a4*br.r))/255.0;", + " float g = (floor(a1*tl.g) + floor(a2*tr.g) + floor(a3*bl.g) + floor(a4*br.g))/255.0;", + " float b = (floor(a1*tl.b) + floor(a2*tr.b) + floor(a3*bl.b) + floor(a4*br.b))/255.0;", + " return vec3(r, g, b);", + "}" + ].join("\n"); + } else { + return [ + "vec3 filter(vec2 point) {", + " return getSrcColorAtPos((point+1.0)/2.0).rgb;", + "}" + ].join("\n"); + } + } +}; + +function DMovProgramNG(coordMode, bFilter, compat, randSeed, exprCode) { + var fragmentShader = [ + exprCode, + this.glslFilter(bFilter, compat), + "void main() {", + (randSeed?"__randSeed = v_position;":""), + " x = v_position.x*2.0-1.0;", + " y = -(v_position.y*2.0-1.0);", + this.glslRectToPolar(coordMode), + " perPixel();", + this.glslPolarToRect(coordMode), + " setFragColor(vec4(filter(vec2(x, -y)), 1));", + "}" + ]; + + DMovProgramNG.super.constructor.call(this, { + fragmentShader: fragmentShader, + swapFrame: true + }); +} +Webvs.DMovProgramNG = Webvs.defineClass(DMovProgramNG, Webvs.QuadBoxProgram, GlslHelpers, { + draw: function(code) { + code.bindUniforms(this); + DMovProgramNG.super.draw.call(this); + } +}); + +function DMovProgram(coordMode, bFilter, compat, randSeed, exprCode) { + var vertexShader = [ + "attribute vec2 a_position;", + "varying vec2 v_newPoint;", + "uniform int u_coordMode;", + exprCode, + "void main() {", + (randSeed?"__randSeed = a_position;":""), + " x = a_position.x;", + " y = -a_position.y;", + this.glslRectToPolar(coordMode), + " perPixel();", + this.glslPolarToRect(coordMode), + " v_newPoint = vec2(x,-y);", + " setPosition(a_position);", + "}" + ]; + + var fragmentShader = [ + "varying vec2 v_newPoint;", + this.glslFilter(bFilter, compat), + "void main() {", + " setFragColor(vec4(filter(v_newPoint), 1));", + "}" + ]; + + DMovProgram.super.constructor.call(this, { + fragmentShader: fragmentShader, + vertexShader: vertexShader, + swapFrame: true + }); +} +Webvs.DMovProgram = Webvs.defineClass(DMovProgram, Webvs.ShaderProgram, GlslHelpers, { + draw: function(code, gridVertices, gridVerticesSize) { + code.bindUniforms(this); + this.setVertexAttribArray("a_position", gridVertices, 2, this.gl.FLOAT, false, 0, 0); + this.gl.drawArrays(this.gl.TRIANGLES, 0, gridVerticesSize); + } +}); + +DynamicMovement.ui = { + type: "DynamicMovement", + disp: "Dynamic Movement", + schema: { + code: { + type: "object", + title: "Code", + default: {}, + properties: { + init: { + type: "string", + title: "Init", + }, + onBeat: { + type: "string", + title: "On Beat", + }, + perFrame: { + type: "string", + title: "Per Frame", + }, + perPixel: { + type: "string", + title: "Per Point", + } + }, + }, + gridW: { + type: "number", + title: "Grid Width", + default: 16, + }, + gridH: { + type: "number", + title: "Grid Height", + default: 16, + }, + coord: { + type: "string", + title: "Coordinate System", + enum: ["POLAR", "RECT"], + default: "POLAR" + } + }, + form: [ + { key: "code.init", type: "textarea" }, + { key: "code.onBeat", type: "textarea" }, + { key: "code.perFrame", type: "textarea" }, + { key: "code.perPixel", type: "textarea" }, + "gridW", + "gridH", + "coord" + ] +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +var channels = ["RGB", "RBG", "BRG", "BGR", "GBR", "GRB"]; + +/** + * @class + * A component that swizzles the color component + * + * @param {object} options - options object + * @param {string} [options.channel="RGB"] - the component combination + * viz. `RGB`, `RBG`, `BRG`, `BGR`, `GBR`, `GRB` + * @param {boolean} [options.onBeatRandom=false] - if set then the color components + * combination is changed randomly on beat + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function ChannelShift(options) { + options = _.defaults(options, { + channel: "RGB", + onBeatRandom: false + }); + + this.channel = channels.indexOf(options.channel); + if(this.channel == -1) { + throw new Error("Invalid Channel"); + } + this.onBeatRandom = options.onBeatRandom; + + this.program = new ChannelShiftProgram(); + + ChannelShift.super.constructor.call(this); +} +Webvs.ChannelShift = Webvs.defineClass(ChannelShift, Webvs.Component, { + componentName: "ChannelShift", + + /** + * initializes the ChannelShift component + * @memberof Webvs.ChannelShift + */ + init: function(gl, main, parent) { + ChannelShift.super.init.call(this, gl, main, parent); + + this.program.init(gl); + }, + + /** + * shifts the colors + * @memberof Webvs.ChannelShift + */ + update: function() { + if(this.onBeatRandom && this.main.analyser.beat) { + this.channel = Math.floor(Math.random() * channels.length); + } + this.program.run(this.parent.fm, null, this.channel); + }, + + /** + * releases resources + * @memberof Webvs.ChannelShift + */ + destroy: function() { + ChannelShift.super.destroy.call(this); + this.program.cleanup(); + } + +}); + +function ChannelShiftProgram() { + ChannelShiftProgram.super.constructor.call(this, { + swapFrame: true, + fragmentShader: [ + "uniform int u_channel;", + "void main() {", + " vec3 color = getSrcColor().rgb;", + + _.flatMap(channels, function(channel, index) { + return [ + "if(u_channel == "+index+") {", + " setFragColor(vec4(color." + channel.toLowerCase() + ",1));", + "}" + ]; + }).join("\n"), + "}" + ] + }); +} +Webvs.ChannelShiftProgram = Webvs.defineClass(ChannelShiftProgram, Webvs.QuadBoxProgram, { + draw: function(channel) { + this.setUniform("u_channel", "1i", channel); + ChannelShiftProgram.super.draw.call(this); + } +}); + +ChannelShift.ui = { + disp: "Channel Shift", + type: "ChannelShift", + schema: { + channel: { + type: "string", + title: "Channel", + enum: channels + }, + onBeatRandom: { + type: "boolean", + title: "On beat random", + } + } +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A generic scope, that can draw points or lines based on user code + * + * #### Code variables + * + * The following variables are available in the code + * + * + n (default: 100) - the number of points. + * + i - 0-1 normalized loop counter + * + v - the value of the superscope at current position + * + x - x position of the dot (-1 to +1) + * + y - y position of the dot (-1 to +1) + * + w - width of the screen + * + h - height of the screen + * + b - 1 if a beat has occured else 0 + * + red (default: set from colors option) - red component of color (0-1) + * + green (default: set from colors option) - green component of color (0-1) + * + blue (default: set from colors option) - blue component of color (0-1) + * + cid - the clone id of this component. if it is a clone + * + * @param {object} options - options object + * @param {string} [options.code.init] - code to be run at startup + * @param {string} [options.code.onBeat] - code to be run when a beat occurs + * @param {string} [options.code.perFrame] - code to be run on every frame + * @param {string} [options.code.perPoint] - code that will be run once for every point. should set + * `x`, `y` variables to specify point location. set `red`, `green` or `blue` variables + * to specify point color + * @param {string} [options.source="SPECTRUM"] - the scope data source viz. `SPECTRUM`, `WAVEFORM` + * @param {string} [options.drawMode="LINES"] - switch between drawing `LINES` or `DOTS` + * @param {Array.} [options.colors=["#FFFFFF"]] - rendering color cycles through these colors + * @param {number} [options.thickness] - thickenss of line or dot + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function SuperScope(options) { + Webvs.checkRequiredOptions(options, ["code"]); + options = _.defaults(options, { + source: "SPECTRUM", + drawMode: "LINES", + colors: ["#ffffff"] + }); + + var codeSrc; + if(_.isObject(options.code)) { + codeSrc = options.code; + } else { + throw new Error("Invalid superscope"); + } + var codeGen = new Webvs.ExprCodeGenerator(codeSrc, ["n", "v", "i", "x", "y", "b", "w", "h", "red", "green", "blue", "cid"]); + var genResult = codeGen.generateCode(["init", "onBeat", "perFrame", "perPoint"], [], []); + this.code = genResult[0]; + this.code.n = 100; + + this.spectrum = options.source == "SPECTRUM"; + this.dots = options.drawMode == "DOTS"; + + this.colors = _.map(options.colors, Webvs.parseColorNorm); + this.currentColor = this.colors[0]; + this.maxStep = 100; + + this.step = this.maxStep; // so that we compute steps, the first time + this.colorId = 0; + this.colorStep = [0,0,0]; + + this.thickness = options.thickness?options.thickness:1; + + this.inited = false; + + this.program = new SuperScopeShader(); + + SuperScope.super.constructor.call(this); +} +Webvs.SuperScope = Webvs.defineClass(SuperScope, Webvs.Component, { + componentName: "SuperScope", + + /** + * initializes the SuperScope component + * @memberof Webvs.SuperScope + */ + init: function(gl, main, parent) { + SuperScope.super.init.call(this, gl, main, parent); + this.program.init(gl); + this.code.setup(main, this); + }, + + /** + * renders the scope + * @memberof Webvs.SuperScope + */ + update: function() { + var gl = this.gl; + var code = this.code; + + this._stepColor(); + code.red = this.currentColor[0]; + code.green = this.currentColor[1]; + code.blue = this.currentColor[2]; + + if(!this.inited) { + code.init(); + this.inited = true; + } + + var beat = this.main.analyser.beat; + code.b = beat?1:0; + code.perFrame(); + if(beat) { + code.onBeat(); + } + + var nPoints = Math.floor(code.n); + var data = this.spectrum ? this.main.analyser.getSpectrum() : this.main.analyser.getWaveform(); + var bucketSize = data.length/nPoints; + var pbi = 0; + var cdi = 0; + + var pointBufferData = new Float32Array((this.dots?nPoints:(nPoints*2-2)) * 2); + var colorData = new Float32Array((this.dots?nPoints:(nPoints*2-2)) * 3); + for(var i = 0;i < nPoints;i++) { + var value = 0; + var size = 0; + for(var j = Math.floor(i*bucketSize);j < (i+1)*bucketSize;j++,size++) { + value += data[j]; + } + value = value/size; + + var pos = i/(nPoints-1); + code.i = pos; + code.v = value; + code.perPoint(); + pointBufferData[pbi++] = code.x; + pointBufferData[pbi++] = code.y*-1; + if(i !== 0 && i != nPoints-1 && !this.dots) { + pointBufferData[pbi++] = code.x; + pointBufferData[pbi++] = code.y*-1; + } + if(this.dots) { + colorData[cdi++] = code.red; + colorData[cdi++] = code.green; + colorData[cdi++] = code.blue; + } else if(i !== 0) { + colorData[cdi++] = code.red; + colorData[cdi++] = code.green; + colorData[cdi++] = code.blue; + colorData[cdi++] = code.red; + colorData[cdi++] = code.green; + colorData[cdi++] = code.blue; + } + } + + this.program.run(this.parent.fm, null, pointBufferData, colorData, this.dots, this.thickness); + }, + + /** + * releases resources + * @memberof Webvs.SuperScope + */ + destroy: function() { + SuperScope.super.destroy.call(this); + this.program.cleanup(); + }, + + _stepColor: function() { + var i; + if(this.colors.length > 1) { + if(this.step == this.maxStep) { + var curColor = this.colors[this.colorId]; + this.colorId = (this.colorId+1)%this.colors.length; + var nextColor = this.colors[this.colorId]; + for(i = 0;i < 3;i++) { + this.colorStep[i] = (nextColor[i]-curColor[i])/this.maxStep; + } + this.step = 0; + this.currentColor = curColor; + } else { + for(i = 0;i < 3;i++) { + this.currentColor[i] += this.colorStep[i]; + } + this.step++; + } + } + } +}); + +function SuperScopeShader() { + SuperScopeShader.super.constructor.call(this, { + copyOnSwap: true, + vertexShader: [ + "attribute vec2 a_position;", + "attribute vec3 a_color;", + "varying vec3 v_color;", + "uniform float u_pointSize;", + "void main() {", + " gl_PointSize = u_pointSize;", + " setPosition(clamp(a_position, vec2(-1,-1), vec2(1,1)));", + " v_color = a_color;", + "}" + ], + fragmentShader: [ + "varying vec3 v_color;", + "void main() {", + " setFragColor(vec4(v_color, 1));", + "}" + ] + }); +} +Webvs.SuperScopeShader = Webvs.defineClass(SuperScopeShader, Webvs.ShaderProgram, { + draw: function(points, colors, dots, thickness) { + var gl = this.gl; + + this.setUniform("u_pointSize", "1f", thickness); + this.setVertexAttribArray("a_position", points, 2, gl.FLOAT, false, 0, 0); + this.setVertexAttribArray("a_color", colors, 3, gl.FLOAT, false, 0, 0); + + var prevLineWidth; + if(!dots) { + prevLineWidth = gl.getParameter(gl.LINE_WIDTH); + gl.lineWidth(thickness); + } + + gl.drawArrays(dots?gl.POINTS:gl.LINES, 0, points.length/2); + + if(!dots) { + gl.lineWidth(prevLineWidth); + } + } +}); + +SuperScope.ui = { + disp: "SuperScope", + type: "SuperScope", + schema: { + code: { + type: "object", + title: "Code", + default: {}, + properties: { + init: { + type: "string", + title: "Init", + }, + onBeat: { + type: "string", + title: "On Beat", + }, + perFrame: { + type: "string", + title: "Per Frame", + }, + perPoint: { + type: "string", + title: "Per Point", + } + }, + }, + source: { + type: "string", + title: "Source", + default: "WAVEFORM", + enum: ["WAVEFORM", "SPECTRUM"] + }, + drawMode: { + type: "string", + title: "Draw Mode", + default: "LINES", + enum: ["DOTS", "LINES"] + }, + colors: { + type: "array", + title: "Cycle Colors", + items: { + type: "string", + format: "color", + default: "#FFFFFF" + } + } + } +}; + + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that clears the screen + * + * @param {object} options - options object + * @param {number} [options.n=0] - beat counter, screen will be cleared for every n beats. + * use 0 to clear all frames. + * @param {string} [options.color="#000000"] - color to which screen is to be cleared + * @param {string} [options.blendMode="REPLACE"] - blend clearing onto previous buffer + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function ClearScreen(options) { + options = _.defaults(options, { + n: 0, + color: "#000000", + blendMode: "REPLACE" + }); + this.n = options.n; + this.color = Webvs.parseColorNorm(options.color); + + this.outputBlendMode = Webvs.blendModes[options.blendMode]; + + this.prevBeat = false; + this.beatCount = 0; + + this.program = new Webvs.ClearScreenProgram(this.outputBlendMode); + + ClearScreen.super.constructor.call(this); +} +Webvs.ClearScreen = Webvs.defineClass(ClearScreen, Webvs.Component, { + componentName: "ClearScreen", + + /** + * initializes the ClearScreen component + * @memberof Webvs.ClearScreen + */ + init: function(gl, main, parent) { + ClearScreen.super.init.call(this, gl, main, parent); + this.program.init(gl); + }, + + /** + * clears the screen + * @memberof Webvs.ClearScreen + */ + update: function() { + var clear = false; + if(this.n === 0) { + clear = true; + } else { + if(this.main.analyser.beat && !this.prevBeat) { + this.beatCount++; + if(this.beatCount == this.n) { + clear = true; + this.beatCount = 0; + } + } + this.prevBeat = this.main.analyser.beat; + } + + if(clear) { + this.program.run(this.parent.fm, null, this.color); + } + }, + + /** + * releases resources + * @memberof Webvs.ClearScreen + */ + destroy: function() { + this.program.cleanup(); + } +}); + +ClearScreen.ui = { + type: "ClearScreen", + disp: "Clear Screen", + schema: { + n: { + type: "number", + title: "Clear on beat (0 = always clear)", + default: 0 + }, + color: { + type: "string", + title: "Clear color", + format: "color", + default: "#000000" + }, + blendMode: { + type: "string", + title: "Blend Mode", + enum: _.keys(Webvs.blendModes) + } + } +}; + +})(Webvs); + +/** + * Copyright (c) 2013 Azeem Arshad + * See the file license.txt for copying permission. + */ + +(function(Webvs) { + +/** + * @class + * A component that renders an image onto the screen + * + * @param {object} options - options object + * @param {string} src - image file source + * @param {number} x - image x position + * @param {number} y - image y position + * @augments Webvs.Component + * @constructor + * @memberof Webvs + */ +function Picture(options) { + Webvs.checkRequiredOptions(options, ["src", "x", "y"]); + + this.x = options.x; + this.y = options.y; + this.src = options.src; + + this.program = new Webvs.PictureProgram(); + Picture.super.constructor.call(this, options); +} +Webvs.Picture = Webvs.defineClass(Picture, Webvs.Component, { + /** + * initializes the ClearScreen component + * @memberof Webvs.Picture + */ + init: function(gl, main, parent) { + Picture.super.init.call(this, gl, main, parent); + + this.program.init(gl); + + var _this = this; + var image = new Image(); + image.src = this.src; + var promise = new Webvs.Promise(); + image.onload = function() { + _this.width = image.width; + _this.height = image.height; + _this.texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, _this.texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + promise.resolve(); + }; + + return promise; + }, + + /** + * renders the image + * @memberof Webvs.Picture + */ + update: function() { + this.program.run(this.parent.fm, null, this.x, this.y, this.texture, this.width, this.height); + }, + + /** + * releases resources + * @memberof Webvs.Picture + */ + destroy: function() { + this.program.cleanup(); + this.gl.deleteTexture(this.texture); + } +}); + +function PictureProgram() { + PictureProgram.super.constructor.call(this, { + copyOnSwap: true, + vertexShader: [ + "attribute vec2 a_texVertex;", + "uniform vec2 u_pos;", + "uniform vec2 u_texRes;", + "varying vec2 v_texCoord;", + + "void main() {", + " v_texCoord = a_texVertex;", + " setPosition(a_texVertex*(u_texRes/u_resolution)*vec2(2,-2)+u_pos);", + "}" + ], + fragmentShader: [ + "uniform sampler2D u_image;", + "varying vec2 v_texCoord;", + "void main() {", + " setFragColor(texture2D(u_image, v_texCoord));", + "}" + ] + }); +} +Webvs.PictureProgram = Webvs.defineClass(PictureProgram, Webvs.ShaderProgram, { + draw: function(x, y, image, imgw, imgh) { + this.setUniform("u_pos", "2f", x, -y); + this.setUniform("u_texRes", "2f", imgw, imgh); + this.setUniform("u_image", "texture2D", image); + this.setVertexAttribArray( + "a_texVertex", + new Float32Array([ + 0, 0, + 0, 1, + 1, 1, + 0, 0, + 1, 1, + 1, 0 + ]) + ); + this.gl.drawArrays(this.gl.TRIANGLES, 0, 6); + } +}); + +})(Webvs); diff --git a/dist/webvs.full.min.js b/dist/webvs.full.min.js index 232c413..5607ba4 100644 --- a/dist/webvs.full.min.js +++ b/dist/webvs.full.min.js @@ -1,4 +1,4 @@ function FourierTransform(a,b){this.bufferSize=a,this.sampleRate=b,this.bandwidth=2/a*b/2,this.spectrum=new Float32Array(a/2),this.real=new Float32Array(a),this.imag=new Float32Array(a),this.peakBand=0,this.peak=0,this.getBandFrequency=function(a){return this.bandwidth*a+this.bandwidth/2},this.calculateSpectrum=function(){for(var b,c,d,e=this.spectrum,f=this.real,g=this.imag,h=2/this.bufferSize,i=Math.sqrt,j=0,k=a/2;k>j;j++)b=f[j],c=g[j],d=h*i(b*b+c*c),d>this.peak&&(this.peakBand=j,this.peak=d),e[j]=d}}function FFT(a,b){FourierTransform.call(this,a,b),this.reverseTable=new Uint32Array(a);for(var c,d=1,e=a>>1;a>d;){for(c=0;d>c;c++)this.reverseTable[c+d]=this.reverseTable[c]+e;d<<=1,e>>=1}for(this.sinTable=new Float32Array(a),this.cosTable=new Float32Array(a),c=0;a>c;c++)this.sinTable[c]=Math.sin(-Math.PI/c),this.cosTable[c]=Math.cos(-Math.PI/c)}function FourierTransform(a,b){this.bufferSize=a,this.sampleRate=b,this.bandwidth=2/a*b/2,this.spectrum=new Float32Array(a/2),this.real=new Float32Array(a),this.imag=new Float32Array(a),this.peakBand=0,this.peak=0,this.getBandFrequency=function(a){return this.bandwidth*a+this.bandwidth/2},this.calculateSpectrum=function(){for(var b,c,d,e=this.spectrum,f=this.real,g=this.imag,h=2/this.bufferSize,i=Math.sqrt,j=0,k=a/2;k>j;j++)b=f[j],c=g[j],d=h*i(b*b+c*c),d>this.peak&&(this.peakBand=j,this.peak=d),e[j]=d}}function FFT(a,b){FourierTransform.call(this,a,b),this.reverseTable=new Uint32Array(a);for(var c,d=1,e=a>>1;a>d;){for(c=0;d>c;c++)this.reverseTable[c+d]=this.reverseTable[c]+e;d<<=1,e>>=1}for(this.sinTable=new Float32Array(a),this.cosTable=new Float32Array(a),c=0;a>c;c++)this.sinTable[c]=Math.sin(-Math.PI/c),this.cosTable[c]=Math.cos(-Math.PI/c)}(function(){var a=this,b=a._,c={},d=Array.prototype,e=Object.prototype,f=Function.prototype,g=d.push,h=d.slice,i=d.concat,j=e.toString,k=e.hasOwnProperty,l=d.forEach,m=d.map,n=d.reduce,o=d.reduceRight,p=d.filter,q=d.every,r=d.some,s=d.indexOf,t=d.lastIndexOf,u=Array.isArray,v=Object.keys,w=f.bind,x=function(a){return a instanceof x?a:this instanceof x?(this._wrapped=a,void 0):new x(a)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=x),exports._=x):a._=x,x.VERSION="1.5.1";var y=x.each=x.forEach=function(a,b,d){if(null!=a)if(l&&a.forEach===l)a.forEach(b,d);else if(a.length===+a.length){for(var e=0,f=a.length;f>e;e++)if(b.call(d,a[e],e,a)===c)return}else for(var g in a)if(x.has(a,g)&&b.call(d,a[g],g,a)===c)return};x.map=x.collect=function(a,b,c){var d=[];return null==a?d:m&&a.map===m?a.map(b,c):(y(a,function(a,e,f){d.push(b.call(c,a,e,f))}),d)};var z="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(a,b,c,d){var e=arguments.length>2;if(null==a&&(a=[]),n&&a.reduce===n)return d&&(b=x.bind(b,d)),e?a.reduce(b,c):a.reduce(b);if(y(a,function(a,f,g){e?c=b.call(d,c,a,f,g):(c=a,e=!0)}),!e)throw new TypeError(z);return c},x.reduceRight=x.foldr=function(a,b,c,d){var e=arguments.length>2;if(null==a&&(a=[]),o&&a.reduceRight===o)return d&&(b=x.bind(b,d)),e?a.reduceRight(b,c):a.reduceRight(b);var f=a.length;if(f!==+f){var g=x.keys(a);f=g.length}if(y(a,function(h,i,j){i=g?g[--f]:--f,e?c=b.call(d,c,a[i],i,j):(c=a[i],e=!0)}),!e)throw new TypeError(z);return c},x.find=x.detect=function(a,b,c){var d;return A(a,function(a,e,f){return b.call(c,a,e,f)?(d=a,!0):void 0}),d},x.filter=x.select=function(a,b,c){var d=[];return null==a?d:p&&a.filter===p?a.filter(b,c):(y(a,function(a,e,f){b.call(c,a,e,f)&&d.push(a)}),d)},x.reject=function(a,b,c){return x.filter(a,function(a,d,e){return!b.call(c,a,d,e)},c)},x.every=x.all=function(a,b,d){b||(b=x.identity);var e=!0;return null==a?e:q&&a.every===q?a.every(b,d):(y(a,function(a,f,g){return(e=e&&b.call(d,a,f,g))?void 0:c}),!!e)};var A=x.some=x.any=function(a,b,d){b||(b=x.identity);var e=!1;return null==a?e:r&&a.some===r?a.some(b,d):(y(a,function(a,f,g){return e||(e=b.call(d,a,f,g))?c:void 0}),!!e)};x.contains=x.include=function(a,b){return null==a?!1:s&&a.indexOf===s?-1!=a.indexOf(b):A(a,function(a){return a===b})},x.invoke=function(a,b){var c=h.call(arguments,2),d=x.isFunction(b);return x.map(a,function(a){return(d?b:a[b]).apply(a,c)})},x.pluck=function(a,b){return x.map(a,function(a){return a[b]})},x.where=function(a,b,c){return x.isEmpty(b)?c?void 0:[]:x[c?"find":"filter"](a,function(a){for(var c in b)if(b[c]!==a[c])return!1;return!0})},x.findWhere=function(a,b){return x.where(a,b,!0)},x.max=function(a,b,c){if(!b&&x.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.max.apply(Math,a);if(!b&&x.isEmpty(a))return-1/0;var d={computed:-1/0,value:-1/0};return y(a,function(a,e,f){var g=b?b.call(c,a,e,f):a;g>d.computed&&(d={value:a,computed:g})}),d.value},x.min=function(a,b,c){if(!b&&x.isArray(a)&&a[0]===+a[0]&&a.length<65535)return Math.min.apply(Math,a);if(!b&&x.isEmpty(a))return 1/0;var d={computed:1/0,value:1/0};return y(a,function(a,e,f){var g=b?b.call(c,a,e,f):a;gd||void 0===c)return 1;if(d>c||void 0===d)return-1}return a.indexf;){var h=f+g>>>1;c.call(d,a[h])=0})})},x.difference=function(a){var b=i.apply(d,h.call(arguments,1));return x.filter(a,function(a){return!x.contains(b,a)})},x.zip=function(){for(var a=x.max(x.pluck(arguments,"length").concat(0)),b=new Array(a),c=0;a>c;c++)b[c]=x.pluck(arguments,""+c);return b},x.object=function(a,b){if(null==a)return{};for(var c={},d=0,e=a.length;e>d;d++)b?c[a[d]]=b[d]:c[a[d][0]]=a[d][1];return c},x.indexOf=function(a,b,c){if(null==a)return-1;var d=0,e=a.length;if(c){if("number"!=typeof c)return d=x.sortedIndex(a,b),a[d]===b?d:-1;d=0>c?Math.max(0,e+c):c}if(s&&a.indexOf===s)return a.indexOf(b,c);for(;e>d;d++)if(a[d]===b)return d;return-1},x.lastIndexOf=function(a,b,c){if(null==a)return-1;var d=null!=c;if(t&&a.lastIndexOf===t)return d?a.lastIndexOf(b,c):a.lastIndexOf(b);for(var e=d?c:a.length;e--;)if(a[e]===b)return e;return-1},x.range=function(a,b,c){arguments.length<=1&&(b=a||0,a=0),c=arguments[2]||1;for(var d=Math.max(Math.ceil((b-a)/c),0),e=0,f=new Array(d);d>e;)f[e++]=a,a+=c;return f};var E=function(){};x.bind=function(a,b){var c,d;if(w&&a.bind===w)return w.apply(a,h.call(arguments,1));if(!x.isFunction(a))throw new TypeError;return c=h.call(arguments,2),d=function(){if(!(this instanceof d))return a.apply(b,c.concat(h.call(arguments)));E.prototype=a.prototype;var e=new E;E.prototype=null;var f=a.apply(e,c.concat(h.call(arguments)));return Object(f)===f?f:e}},x.partial=function(a){var b=h.call(arguments,1);return function(){return a.apply(this,b.concat(h.call(arguments)))}},x.bindAll=function(a){var b=h.call(arguments,1);if(0===b.length)throw new Error("bindAll must be passed function names");return y(b,function(b){a[b]=x.bind(a[b],a)}),a},x.memoize=function(a,b){var c={};return b||(b=x.identity),function(){var d=b.apply(this,arguments);return x.has(c,d)?c[d]:c[d]=a.apply(this,arguments)}},x.delay=function(a,b){var c=h.call(arguments,2);return setTimeout(function(){return a.apply(null,c)},b)},x.defer=function(a){return x.delay.apply(x,[a,1].concat(h.call(arguments,1)))},x.throttle=function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date,g=null,f=a.apply(d,e)};return function(){var j=new Date;h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k?(clearTimeout(g),g=null,h=j,f=a.apply(d,e)):g||c.trailing===!1||(g=setTimeout(i,k)),f}},x.debounce=function(a,b,c){var d,e=null;return function(){var f=this,g=arguments,h=function(){e=null,c||(d=a.apply(f,g))},i=c&&!e;return clearTimeout(e),e=setTimeout(h,b),i&&(d=a.apply(f,g)),d}},x.once=function(a){var b,c=!1;return function(){return c?b:(c=!0,b=a.apply(this,arguments),a=null,b)}},x.wrap=function(a,b){return function(){var c=[a];return g.apply(c,arguments),b.apply(this,c)}},x.compose=function(){var a=arguments;return function(){for(var b=arguments,c=a.length-1;c>=0;c--)b=[a[c].apply(this,b)];return b[0]}},x.after=function(a,b){return function(){return--a<1?b.apply(this,arguments):void 0}},x.keys=v||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[];for(var c in a)x.has(a,c)&&b.push(c);return b},x.values=function(a){var b=[];for(var c in a)x.has(a,c)&&b.push(a[c]);return b},x.pairs=function(a){var b=[];for(var c in a)x.has(a,c)&&b.push([c,a[c]]);return b},x.invert=function(a){var b={};for(var c in a)x.has(a,c)&&(b[a[c]]=c);return b},x.functions=x.methods=function(a){var b=[];for(var c in a)x.isFunction(a[c])&&b.push(c);return b.sort()},x.extend=function(a){return y(h.call(arguments,1),function(b){if(b)for(var c in b)a[c]=b[c]}),a},x.pick=function(a){var b={},c=i.apply(d,h.call(arguments,1));return y(c,function(c){c in a&&(b[c]=a[c])}),b},x.omit=function(a){var b={},c=i.apply(d,h.call(arguments,1));for(var e in a)x.contains(c,e)||(b[e]=a[e]);return b},x.defaults=function(a){return y(h.call(arguments,1),function(b){if(b)for(var c in b)void 0===a[c]&&(a[c]=b[c])}),a},x.clone=function(a){return x.isObject(a)?x.isArray(a)?a.slice():x.extend({},a):a},x.tap=function(a,b){return b(a),a};var F=function(a,b,c,d){if(a===b)return 0!==a||1/a==1/b;if(null==a||null==b)return a===b;a instanceof x&&(a=a._wrapped),b instanceof x&&(b=b._wrapped);var e=j.call(a);if(e!=j.call(b))return!1;switch(e){case"[object String]":return a==String(b);case"[object Number]":return a!=+a?b!=+b:0==a?1/a==1/b:a==+b;case"[object Date]":case"[object Boolean]":return+a==+b;case"[object RegExp]":return a.source==b.source&&a.global==b.global&&a.multiline==b.multiline&&a.ignoreCase==b.ignoreCase}if("object"!=typeof a||"object"!=typeof b)return!1;for(var f=c.length;f--;)if(c[f]==a)return d[f]==b;var g=a.constructor,h=b.constructor;if(g!==h&&!(x.isFunction(g)&&g instanceof g&&x.isFunction(h)&&h instanceof h))return!1;c.push(a),d.push(b);var i=0,k=!0;if("[object Array]"==e){if(i=a.length,k=i==b.length)for(;i--&&(k=F(a[i],b[i],c,d)););}else{for(var l in a)if(x.has(a,l)&&(i++,!(k=x.has(b,l)&&F(a[l],b[l],c,d))))break;if(k){for(l in b)if(x.has(b,l)&&!i--)break;k=!i}}return c.pop(),d.pop(),k};x.isEqual=function(a,b){return F(a,b,[],[])},x.isEmpty=function(a){if(null==a)return!0;if(x.isArray(a)||x.isString(a))return 0===a.length;for(var b in a)if(x.has(a,b))return!1;return!0},x.isElement=function(a){return!(!a||1!==a.nodeType)},x.isArray=u||function(a){return"[object Array]"==j.call(a)},x.isObject=function(a){return a===Object(a)},y(["Arguments","Function","String","Number","Date","RegExp"],function(a){x["is"+a]=function(b){return j.call(b)=="[object "+a+"]"}}),x.isArguments(arguments)||(x.isArguments=function(a){return!(!a||!x.has(a,"callee"))}),"function"!=typeof/./&&(x.isFunction=function(a){return"function"==typeof a}),x.isFinite=function(a){return isFinite(a)&&!isNaN(parseFloat(a))},x.isNaN=function(a){return x.isNumber(a)&&a!=+a},x.isBoolean=function(a){return a===!0||a===!1||"[object Boolean]"==j.call(a)},x.isNull=function(a){return null===a},x.isUndefined=function(a){return void 0===a},x.has=function(a,b){return k.call(a,b)},x.noConflict=function(){return a._=b,this},x.identity=function(a){return a},x.times=function(a,b,c){for(var d=Array(Math.max(0,a)),e=0;a>e;e++)d[e]=b.call(c,e);return d},x.random=function(a,b){return null==b&&(b=a,a=0),a+Math.floor(Math.random()*(b-a+1))};var G={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};G.unescape=x.invert(G.escape);var H={escape:new RegExp("["+x.keys(G.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(G.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(a){x[a]=function(b){return null==b?"":(""+b).replace(H[a],function(b){return G[a][b]})}}),x.result=function(a,b){if(null==a)return void 0;var c=a[b];return x.isFunction(c)?c.call(a):c},x.mixin=function(a){y(x.functions(a),function(b){var c=x[b]=a[b];x.prototype[b]=function(){var a=[this._wrapped];return g.apply(a,arguments),M.call(this,c.apply(x,a))}})};var I=0;x.uniqueId=function(a){var b=++I+"";return a?a+b:b},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var J=/(.)^/,K={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},L=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(a,b,c){var d;c=x.defaults({},c,x.templateSettings);var e=new RegExp([(c.escape||J).source,(c.interpolate||J).source,(c.evaluate||J).source].join("|")+"|$","g"),f=0,g="__p+='";a.replace(e,function(b,c,d,e,h){return g+=a.slice(f,h).replace(L,function(a){return"\\"+K[a]}),c&&(g+="'+\n((__t=("+c+"))==null?'':_.escape(__t))+\n'"),d&&(g+="'+\n((__t=("+d+"))==null?'':__t)+\n'"),e&&(g+="';\n"+e+"\n__p+='"),f=h+b.length,b}),g+="';\n",c.variable||(g="with(obj||{}){\n"+g+"}\n"),g="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+g+"return __p;\n";try{d=new Function(c.variable||"obj","_",g)}catch(h){throw h.source=g,h}if(b)return d(b,x);var i=function(a){return d.call(this,a,x)};return i.source="function("+(c.variable||"obj")+"){\n"+g+"}",i},x.chain=function(a){return x(a).chain()};var M=function(a){return this._chain?x(a).chain():a};x.mixin(x),y(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=d[a];x.prototype[a]=function(){var c=this._wrapped;return b.apply(c,arguments),"shift"!=a&&"splice"!=a||0!==c.length||delete c[0],M.call(this,c)}}),y(["concat","join","slice"],function(a){var b=d[a];x.prototype[a]=function(){return M.call(this,b.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),FFT.prototype.forward=function(a){var b=this.bufferSize,c=this.cosTable,d=this.sinTable,e=this.reverseTable,f=this.real,g=this.imag;this.spectrum;var h=Math.floor(Math.log(b)/Math.LN2);if(Math.pow(2,h)!==b)throw"Invalid buffer size, must be a power of 2.";if(b!==a.length)throw"Supplied buffer is not the same size as defined FFT. FFT Size: "+b+" Buffer Size: "+a.length;var i,j,k,l,m,n,o,p,q,r=1;for(q=0;b>q;q++)f[q]=a[e[q]],g[q]=0;for(;b>r;){i=c[r],j=d[r],k=1,l=0;for(var s=0;r>s;s++){for(q=s;b>q;)m=q+r,n=k*f[m]-l*g[m],o=k*g[m]+l*f[m],f[m]=f[q]-n,g[m]=g[q]-o,f[q]+=n,g[q]+=o,q+=r<<1;p=k,k=p*i-l*j,l=p*j+l*i}r<<=1}return this.calculateSpectrum()},function(){function a(){for(var a in this.sections)this.sections[a].condition()&&this.sections[a].callback.call(this)}var b=function(){this.audioAdapter=b._getAdapter(this),this.events={},this.sections=[],this.bind("update",a)};b.adapters={},b.prototype={load:function(a){return a instanceof HTMLElement?(this.source=a,"flash"===b.isSupported()&&(this.source={src:b._getMP3SrcFromAudio(a)})):(this.source=window.Audio?new Audio:{},this.source.src=b._makeSupportedPath(a.src,a.codecs)),this.audio=this.audioAdapter.load(this.source),this},play:function(){return this.audioAdapter.play(),this},pause:function(){return this.audioAdapter.pause(),this},setVolume:function(a){return this.audioAdapter.setVolume(a),this},createKick:function(a){return new b.Kick(this,a)},bind:function(a,b){return this.events[a]||(this.events[a]=[]),this.events[a].push(b),this},unbind:function(a){return this.events[a]&&delete this.events[a],this},trigger:function(a){var b=this;return this.events[a]&&this.events[a].forEach(function(a){a.call(b)}),this},getVolume:function(){return this.audioAdapter.getVolume()},getProgress:function(){return this.audioAdapter.getProgress()},getTime:function(){return this.audioAdapter.getTime()},getFrequency:function(a,b){var c=0;if(void 0!==b){for(var d=a;b>=d;d++)c+=this.getSpectrum()[d];return c/(b-a+1)}return this.getSpectrum()[a]},getWaveform:function(){return this.audioAdapter.getWaveform()},getSpectrum:function(){return this.audioAdapter.getSpectrum()},isLoaded:function(){return this.audioAdapter.isLoaded},isPlaying:function(){return this.audioAdapter.isPlaying},after:function(a,b){var c=this;return this.sections.push({condition:function(){return c.getTime()>a},callback:b}),this},before:function(a,b){var c=this;return this.sections.push({condition:function(){return c.getTime()a&&d.getTime()a&&!this.called},callback:function(){b.call(this),d.called=!0},called:!1}),d=this.sections[this.sections.length-1],this}},window.Dancer=b}(),function(a){function b(){var a=!!(navigator.vendor||"").match(/Apple/),b=navigator.userAgent.match(/Version\/([^ ]*)/);return b=b?parseFloat(b[1]):0,a&&6>=b}var c={mp3:"audio/mpeg;",ogg:'audio/ogg; codecs="vorbis"',wav:'audio/wav; codecs="1"',aac:'audio/mp4; codecs="mp4a.40.2"'},d=document.createElement("audio");a.options={},a.setOptions=function(b){for(var c in b)b.hasOwnProperty(c)&&(a.options[c]=b[c])},a.isSupported=function(){return window.Float32Array&&window.Uint32Array?b()||!window.AudioContext&&!window.webkitAudioContext?d&&d.mozSetup?"audiodata":FlashDetect.versionAtLeast(9)?"flash":"":"webaudio":null},a.canPlay=function(b){return d.canPlayType,!!("flash"===a.isSupported()?"mp3"===b.toLowerCase():d.canPlayType&&d.canPlayType(c[b.toLowerCase()]).replace(/no/,""))},a.addPlugin=function(b,c){void 0===a.prototype[b]&&(a.prototype[b]=c)},a._makeSupportedPath=function(b,c){if(!c)return b;for(var d=0;d=this.currentThreshold&&a>=this.threshold?(this.currentThreshold=a,this.onKick&&this.onKick.call(this.dancer,a)):(this.offKick&&this.offKick.call(this.dancer,a),this.currentThreshold-=this.decay)}},maxAmplitude:function(a){var b=0,c=this.dancer.getSpectrum();if(!a.length)return a=d;d++)c[d]>b&&(b=c[d]);return b}},window.Dancer.Kick=b}(),function(){function a(){this.source=this.context.createMediaElementSource(this.audio),this.source.connect(this.proc),this.source.connect(this.gain),this.gain.connect(this.context.destination),this.proc.connect(this.context.destination),this.isLoaded=!0,this.progress=1,this.dancer.trigger("loaded")}var b=2048,c=44100,d=function(a){this.dancer=a,this.audio=new Audio,this.context=window.AudioContext?new window.AudioContext:new window.webkitAudioContext};d.prototype={load:function(d){var e=this;return this.audio=d,this.isLoaded=!1,this.progress=0,this.proc=this.context.createJavaScriptNode(b/2,1,1),this.proc.onaudioprocess=function(a){e.update.call(e,a)},this.gain=this.context.createGainNode(),this.fft=new FFT(b/2,c),this.signal=new Float32Array(b/2),this.audio.readyState<3?this.audio.addEventListener("canplay",function(){a.call(e)}):a.call(e),this.audio.addEventListener("progress",function(a){a.currentTarget.duration&&(e.progress=a.currentTarget.seekable.end(0)/a.currentTarget.duration)}),this.audio},play:function(){this.audio.play(),this.isPlaying=!0},pause:function(){this.audio.pause(),this.isPlaying=!1},setVolume:function(a){this.gain.gain.value=a},getVolume:function(){return this.gain.gain.value},getProgress:function(){return this.progress},getWaveform:function(){return this.signal},getSpectrum:function(){return this.fft.spectrum},getTime:function(){return this.audio.currentTime},update:function(a){if(this.isPlaying&&this.isLoaded){var c,d=[],e=a.inputBuffer.numberOfChannels,f=b/e,g=function(a,b){return a[c]+b[c]};for(c=e;c--;)d.push(a.inputBuffer.getChannelData(c));for(c=0;f>c;c++)this.signal[c]=e>1?d.reduce(g(prev,curr))/e:d[0][c];this.fft.forward(this.signal),this.dancer.trigger("update")}}},Dancer.adapters.webkit=d}(),function(){function a(){this.fbLength=this.audio.mozFrameBufferLength,this.channels=this.audio.mozChannels,this.rate=this.audio.mozSampleRate,this.fft=new FFT(this.fbLength/this.channels,this.rate),this.signal=new Float32Array(this.fbLength/this.channels),this.isLoaded=!0,this.progress=1,this.dancer.trigger("loaded")}var b=function(a){this.dancer=a,this.audio=new Audio};b.prototype={load:function(b){var c=this;return this.audio=b,this.isLoaded=!1,this.progress=0,this.audio.readyState<3?this.audio.addEventListener("loadedmetadata",function(){a.call(c)},!1):a.call(c),this.audio.addEventListener("MozAudioAvailable",function(a){c.update(a)},!1),this.audio.addEventListener("progress",function(a){a.currentTarget.duration&&(c.progress=a.currentTarget.seekable.end(0)/a.currentTarget.duration)},!1),this.audio},play:function(){this.audio.play(),this.isPlaying=!0},pause:function(){this.audio.pause(),this.isPlaying=!1},setVolume:function(a){this.audio.volume=a},getVolume:function(){return this.audio.volume},getProgress:function(){return this.progress},getWaveform:function(){return this.signal},getSpectrum:function(){return this.fft.spectrum},getTime:function(){return this.audio.currentTime},update:function(a){if(this.isPlaying&&this.isLoaded){for(var b=0,c=this.fbLength/2;c>b;b++)this.signal[b]=(a.frameBuffer[2*b]+a.frameBuffer[2*b+1])/2;this.fft.forward(this.signal),this.dancer.trigger("update")}}},Dancer.adapters.moz=b}(),function(){function a(){var a=this;f=!0,b(Dancer.options.flashJS,function(){soundManager=new SoundManager,soundManager.flashVersion=9,soundManager.flash9Options.useWaveformData=!0,soundManager.useWaveformData=!0,soundManager.useHighPerformance=!0,soundManager.useFastPolling=!0,soundManager.multiShot=!1,soundManager.debugMode=!1,soundManager.debugFlash=!1,soundManager.url=Dancer.options.flashSWF,soundManager.onready(function(){e=!0,a.load()}),soundManager.ontimeout(function(){console.error("Error loading SoundManager2.swf")}),soundManager.beginDelayedInit()})}function b(a,b){var c=document.createElement("script"),d=document.getElementsByTagName("script")[0];c.type="text/javascript",c.src=a,c.onload=b,d.parentNode.insertBefore(c,d)}var c=1024,d=44100,e=!1,f=!1,g=.93,h=function(a){this.dancer=a,this.wave_L=[],this.wave_R=[],this.spectrum=[],window.SM2_DEFER=!0};h.prototype={load:function(b){var e=this;return this.path=b?b.src:this.path,this.isLoaded=!1,this.progress=0,!window.soundManager&&!f&&a.call(this),window.soundManager&&(this.audio=soundManager.createSound({id:"dancer"+Math.random(),url:this.path,stream:!0,autoPlay:!1,autoLoad:!0,whileplaying:function(){e.update()},whileloading:function(){e.progress=this.bytesLoaded/this.bytesTotal},onload:function(){e.fft=new FFT(c,d),e.signal=new Float32Array(c),e.waveform=new Float32Array(c),e.isLoaded=!0,e.progress=1,e.dancer.trigger("loaded")}}),this.dancer.audio=this.audio),this.audio},play:function(){this.audio.play(),this.isPlaying=!0},pause:function(){this.audio.pause(),this.isPlaying=!1},setVolume:function(a){this.audio.setVolume(100*a)},getVolume:function(){return this.audio.volume/100},getProgress:function(){return this.progress},getWaveform:function(){return this.waveform},getSpectrum:function(){return this.fft.spectrum},getTime:function(){return this.audio.position/1e3},update:function(){if(this.isPlaying||this.isLoaded){this.wave_L=this.audio.waveformData.left,this.wave_R=this.audio.waveformData.right;for(var a,b=0,c=this.wave_L.length;c>b;b++)a=parseFloat(this.wave_L[b])+parseFloat(this.wave_R[b]),this.waveform[2*b]=a/2,this.waveform[2*b+1]=a/2,this.signal[2*b]=a*g,this.signal[2*b+1]=a*g;this.fft.forward(this.signal),this.dancer.trigger("update")}}},Dancer.adapters.flash=h}(),FFT.prototype.forward=function(a){var b=this.bufferSize,c=this.cosTable,d=this.sinTable,e=this.reverseTable,f=this.real,g=this.imag;this.spectrum;var h=Math.floor(Math.log(b)/Math.LN2);if(Math.pow(2,h)!==b)throw"Invalid buffer size, must be a power of 2.";if(b!==a.length)throw"Supplied buffer is not the same size as defined FFT. FFT Size: "+b+" Buffer Size: "+a.length;var i,j,k,l,m,n,o,p,q,r=1;for(q=0;b>q;q++)f[q]=a[e[q]],g[q]=0;for(;b>r;){i=c[r],j=d[r],k=1,l=0;for(var s=0;r>s;s++){for(q=s;b>q;)m=q+r,n=k*f[m]-l*g[m],o=k*g[m]+l*f[m],f[m]=f[q]-n,g[m]=g[q]-o,f[q]+=n,g[q]+=o,q+=r<<1;p=k,k=p*i-l*j,l=p*j+l*i}r<<=1}return this.calculateSpectrum()};var FlashDetect=new function(){var a=this;a.installed=!1,a.raw="",a.major=-1,a.minor=-1,a.revision=-1,a.revisionStr="";var b=[{name:"ShockwaveFlash.ShockwaveFlash.7",version:function(a){return c(a)}},{name:"ShockwaveFlash.ShockwaveFlash.6",version:function(a){var b="6,0,21";try{a.AllowScriptAccess="always",b=c(a)}catch(d){}return b}},{name:"ShockwaveFlash.ShockwaveFlash",version:function(a){return c(a)}}],c=function(a){var b=-1;try{b=a.GetVariable("$version")}catch(c){}return b},d=function(a){var b=-1;try{b=new ActiveXObject(a)}catch(c){b={activeXError:!0}}return b},e=function(a){var b=a.split(",");return{raw:a,major:parseInt(b[0].split(" ")[1],10),minor:parseInt(b[1],10),revision:parseInt(b[2],10),revisionStr:b[2]}},f=function(a){var b=a.split(/ +/),c=b[2].split(/\./),d=b[3];return{raw:a,major:parseInt(c[0],10),minor:parseInt(c[1],10),revisionStr:d,revision:g(d)}},g=function(b){return parseInt(b.replace(/[a-zA-Z]/g,""),10)||a.revision};a.majorAtLeast=function(b){return a.major>=b},a.minorAtLeast=function(b){return a.minor>=b},a.revisionAtLeast=function(b){return a.revision>=b},a.versionAtLeast=function(){var b=[a.major,a.minor,a.revision],c=Math.min(b.length,arguments.length);for(i=0;c>i;i++){if(b[i]>=arguments[i]){if(c>i+1&&b[i]==arguments[i])continue;return!0}return!1}},a.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var c="application/x-shockwave-flash",g=navigator.mimeTypes;if(g&&g[c]&&g[c].enabledPlugin&&g[c].enabledPlugin.description){var h=g[c].enabledPlugin.description,i=f(h);a.raw=i.raw,a.major=i.major,a.minor=i.minor,a.revisionStr=i.revisionStr,a.revision=i.revision,a.installed=!0}}else if(-1==navigator.appVersion.indexOf("Mac")&&window.execScript)for(var h=-1,j=0;jb+1e3&&(f=Math.round(1e3*i/(j-b)),g=Math.min(g,f),h=Math.max(h,f),m.textContent=f+" FPS ("+g+"-"+h+")",t(n,Math.min(30,30-30*(f/100))),b=j,i=0),j},update:function(){a=this.end()}}};!function(a){var b={};a.Webvs=b,b.defineClass=function(a,b){return a.prototype=Object.create(b.prototype),a.prototype.constructor=a,a.super=b.prototype,_.chain(arguments).drop(2).each(function(b){_.extend(a.prototype,b)}),a},b.noop=function(){},b.checkRequiredOptions=function(a,b){for(var c in b){var d=b[c];if(!(d in a))throw new Error("Required option "+d+"not found")}},b.glslFloatRepr=function(a){return a+(0===a%1?".0":"")},b.parseColor=function(a){if(_.isArray(a)&&3==a.length)return a;if(_.isString(a)){var b;if(a=a.toLowerCase(),b=a.match(/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/))return _.chain(b).last(3).map(function(a){return parseInt(a,16)}).value();if(b=a.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/))return _.chain(b).last(3).map(function(a){return Math.min(parseInt(a,10),255) -}).value()}throw new Error("Invalid Color Format")},b.parseColorNorm=function(a){return _.map(b.parseColor(a),function(a){return a/255})},b.logShaderError=function(a,b){var c=a.split("\n"),d=c.length.toString().length,e=b.match(/(\d+):(\d+)/);e&&(e=[parseInt(e[1],10),parseInt(e[2],10)]);var f=_.map(c,function(a,c){var f,g=c+1+"";for(f=0;f0&&this._frameCounter--,0!==this._frameCounter)){if(this.fm.setRenderTarget(),(this.clearFrame||this.first)&&(a.clearColor(0,0,0,1),a.clear(a.COLOR_BUFFER_BIT),this.first=!1),-1!==this.input){var c=this.parent.fm.getCurrentTexture();this.main.copier.run(this.fm,this.input,c)}for(var d=this.components,e=0;ee;e++){var f=b.charAt(e);"\n"===f?(a.seenCR||a.line++,a.column=1,a.seenCR=!1):"\r"===f||"\u2028"===f||"\u2029"===f?(a.line++,a.column=1,a.seenCR=!0):(a.column++,a.seenCR=!1)}a.offset+=c}function f(a){F.offsetH.offset&&(H=d(F),I=[]),I.push(a))}function g(){var a="program@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,i,j,k,l,m,n,o,p,q;if(o=d(F),p=d(F),g=h(),null!==g)if(i=x(),null!==i){for(j=[],q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==k;)j.push(k),q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==j?(59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),k=null!==k?k:"",null!==k?g=[g,i,j,k]:(g=null,F=d(p))):(g=null,F=d(p))}else g=null,F=d(p);else g=null,F=d(p);return null!==g&&(g=function(a,b,c,d){var e=[d[0]];return e=e.concat(_.map(d[2],function(a){return a[2]})),new Webvs.AstProgram(e)}(o.offset,o.line,o.column,g)),null===g&&(F=d(o)),J[a]={nextPos:d(F),result:g},g}function h(){var a="statement@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n;return l=d(F),n=d(F),g=s(),null!==g?(h=x(),null!==h?(61===b.charCodeAt(F.offset)?(i="=",e(F,1)):(i=null,0===G&&f('"="')),null!==i?(j=x(),null!==j?(k=m(),null!==k?g=[g,h,i,j,k]:(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d,e){return new Webvs.AstAssignment(d,e)}(l.offset,l.line,l.column,g[0],g[4])),null===g&&(F=d(l)),null===g&&(g=m()),J[a]={nextPos:d(F),result:g},g}function i(){var a="unary_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function j(){var a="additive_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function k(){var a="multiplicative_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 42===b.charCodeAt(F.offset)?(g="*",e(F,1)):(g=null,0===G&&f('"*"')),null===g&&(47===b.charCodeAt(F.offset)?(g="/",e(F,1)):(g=null,0===G&&f('"/"')),null===g&&(37===b.charCodeAt(F.offset)?(g="%",e(F,1)):(g=null,0===G&&f('"%"')))),J[a]={nextPos:d(F),result:g},g}function l(){var a="boolean_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 38===b.charCodeAt(F.offset)?(g="&",e(F,1)):(g=null,0===G&&f('"&"')),null===g&&(124===b.charCodeAt(F.offset)?(g="|",e(F,1)):(g=null,0===G&&f('"|"'))),J[a]={nextPos:d(F),result:g},g}function m(){var a="boolean_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,k,m;if(j=d(F),k=d(F),c=n(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(k))}else c=null,F=d(k);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function n(){var a="additive_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,k,l,m;if(k=d(F),l=d(F),c=o(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(k.offset,k.line,k.column,c[0],c[1])),null===c&&(F=d(k)),J[a]={nextPos:d(F),result:c},c}function o(){var a="multiplicative_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,l,m;if(j=d(F),l=d(F),c=p(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function p(){var a="unary@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h;return g=d(F),h=d(F),c=i(),null!==c?(e=x(),null!==e?(f=q(),null!==f?c=[c,e,f]:(c=null,F=d(h))):(c=null,F=d(h))):(c=null,F=d(h)),null!==c&&(c=function(a,b,c,d,e){return new Webvs.AstUnaryExpr(d,e)}(g.offset,g.line,g.column,c[0],c[2])),null===c&&(F=d(g)),null===c&&(c=q()),J[a]={nextPos:d(F),result:c},c}function q(){var a="func_call@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n,o,p,q,s,t;if(p=d(F),q=d(F),s=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(s))}else g=null,F=d(s);if(null!==g)if(h=x(),null!==h)if(40===b.charCodeAt(F.offset)?(i="(",e(F,1)):(i=null,0===G&&f('"("')),null!==i){for(s=d(F),j=[],t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==k;)j.push(k),t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==j?(k=x(),null!==k?(l=m(),null!==l?j=[j,k,l]:(j=null,F=d(s))):(j=null,F=d(s))):(j=null,F=d(s)),j=null!==j?j:"",null!==j?(k=x(),null!==k?(41===b.charCodeAt(F.offset)?(l=")",e(F,1)):(l=null,0===G&&f('")"')),null!==l?g=[g,h,i,j,k,l]:(g=null,F=d(q))):(g=null,F=d(q))):(g=null,F=d(q))}else g=null,F=d(q);else g=null,F=d(q);else g=null,F=d(q);return null!==g&&(g=function(a,b,c,d,e){var f=[];return _.each(e[0],function(a){f.push(a[1])}),f.push(e[2]),new Webvs.AstFuncCall(D(d),f)}(p.offset,p.line,p.column,g[0],g[3])),null===g&&(F=d(p)),null===g&&(g=r()),J[a]={nextPos:d(F),result:g},g}function r(){var a="primary_expr@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;return g=w(),null===g&&(g=u(),null===g&&(g=v(),null===g&&(g=t(),null===g&&(j=d(F),k=d(F),40===b.charCodeAt(F.offset)?(g="(",e(F,1)):(g=null,0===G&&f('"("')),null!==g?(h=m(),null!==h?(41===b.charCodeAt(F.offset)?(i=")",e(F,1)):(i=null,0===G&&f('")"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))):(g=null,F=d(k)),null!==g&&(g=function(a,b,c,d){return d}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)))))),J[a]={nextPos:d(F),result:g},g}function s(){var a="assignable@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c;return c=v(),null===c&&(c=t()),J[a]={nextPos:d(F),result:c},c}function t(){var a="identifier@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"ID")}(j.offset,j.line,j.column,g)),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function u(){var a="constant@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),36===b.charCodeAt(F.offset)?(g="$",e(F,1)):(g=null,0===G&&f('"$"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"CONST")}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function v(){var a="register@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(l=d(F),m=d(F),64===b.charCodeAt(F.offset)?(g="@",e(F,1)):(g=null,0===G&&f('"@"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(m))}else g=null,F=d(m);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_AT_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g[1])),null===g&&(F=d(l)),null===g&&(l=d(F),m=d(F),/^[rR]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[rR]")),null!==g?(/^[eE]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[eE]")),null!==h?(/^[gG]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[gG]")),null!==i?(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j?(/^[0-9]/.test(b.charAt(F.offset))?(k=b.charAt(F.offset),e(F,1)):(k=null,0===G&&f("[0-9]")),null!==k?g=[g,h,i,j,k]:(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g)),null===g&&(F=d(l))),J[a]={nextPos:d(F),result:g},g}function w(){var a="value@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m,n,o;for(m=d(F),n=d(F),g=[],/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));if(null!==g)if(46===b.charCodeAt(F.offset)?(h=".",e(F,1)):(h=null,0===G&&f('"."')),null!==h){if(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j)for(i=[];null!==j;)i.push(j),/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]"));else i=null;if(null!==i){if(o=d(F),/^[Ee]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[Ee]")),null!==j){if(/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]")),null!==l)for(k=[];null!==l;)k.push(l),/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]"));else k=null;null!==k?j=[j,k]:(j=null,F=d(o))}else j=null,F=d(o);j=null!==j?j:"",null!==j?g=[g,h,i,j]:(g=null,F=d(n))}else g=null,F=d(n)}else g=null,F=d(n);else g=null,F=d(n);if(null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseFloat(D(d)),"VALUE")}(m.offset,m.line,m.column,g)),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]"));else g=null;if(null!==g?(/^[hH]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[hH]")),null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),16),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));else g=null;null!==g?(/^[dD]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[dD]")),h=null!==h?h:"",null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),10),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m))}}return J[a]={nextPos:d(F),result:g},g}function x(){var a="__@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e;for(c=[],e=y(),null===e&&(e=z(),null===e&&(e=A()));null!==e;)c.push(e),e=y(),null===e&&(e=z(),null===e&&(e=A()));return J[a]={nextPos:d(F),result:c},c}function y(){var a="whiteSpace@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\t\x0B\f \xA0\uFEFF]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\t\\x0B\\f \\xA0\\uFEFF]")),J[a]={nextPos:d(F),result:g},g}function z(){var a="lineEnd@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\n\r\u2028\u2029]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\n\\r\\u2028\\u2029]")),J[a]={nextPos:d(F),result:g},g}function A(){var a="comment@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(k=d(F),"/*"===b.substr(F.offset,2)?(g="/*",e(F,2)):(g=null,0===G&&f('"/*"')),null!==g){for(h=[],l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?("*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))}else g=null,F=d(k);if(null===g)if(k=d(F),"//"===b.substr(F.offset,2)?(g="//",e(F,2)):(g=null,0===G&&f('"//"')),null!==g){for(h=[],l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return J[a]={nextPos:d(F),result:g},g}function B(a){a.sort();for(var b=null,c=[],d=0;dH.offset?F:H;throw new this.SyntaxError(B(I),M,L,N.line,N.column)}return K},toSource:function(){return this._source}};return b.SyntaxError=function(b,c,d,e,f){function g(b,c){var d,e; -switch(b.length){case 0:d="end of input";break;case 1:d=b[0];break;default:d=b.slice(0,b.length-1).join(", ")+" or "+b[b.length-1]}return e=c?a(c):"end of input","Expected "+d+" but "+e+" found."}this.name="SyntaxError",this.expected=b,this.found=c,this.message=g(b,c),this.offset=d,this.line=e,this.column=f},b.SyntaxError.prototype=Error.prototype,b}(),function(a){function b(){}a.CodeInstance=a.defineClass(b,Object,{rand:function(a){return Math.floor(Math.random()*a)+1},gettime:function(a){switch(a){case 0:var b=(new Date).getTime();return(b-this._bootTime)/1e3;default:throw new Error("Invalid startTime mode for gettime call")}},getosc:function(a,b){for(var c=this._analyser.getWaveform(),d=Math.floor((a-b/2)*c.length),e=Math.floor((a+b/2)*c.length),f=0,g=d;e>=g;g++)f+=c[g];return f/(e-d+1)},bindUniforms:function(a){var b=this,c=_.difference(_.keys(this),this._treatAsNonUniform);if(_.each(c,function(c){var d=b[c];"number"==typeof d&&a.setUniform(c,"1f",d)}),_.each(this._registerUsages,function(b){a.setUniform(b,"1f",this._registerBank[b])}),this.hasRandom){var d=[Math.random()/100,Math.random()/100];a.setUniform("__randStep","2fv",d)}if(this.hasGettime){var e=((new Date).getTime()-this._bootTime)/1e3;a.setUniform("__gettime0","1f",e)}_.each(this._preCompute,function(b){var c=_.map(_.last(b,b.length-2),function(a){return _.isString(a)?"__REG"==a.substring(0,5)?this._registerBank[a]:this[a]:a}),d=this[b[0]].apply(this,c);a.setUniform(b[1],"1f",d)})},setup:function(a,b){this._registerBank=a.registerBank,this._bootTime=a.bootTime,this._analyser=a.analyser,this.w=a.canvas.width,this.h=a.canvas.height,this.cid=b.cloneId,_.each(this._registerUsages,function(b){_.has(a.registerBank,b)||(a.registerBank[b]=0)})}})}(Webvs),function(a){function b(a,b){this.codeSrc=a,this.externalVars=b?b:[],this._parseSrc()}a.ExprCodeGenerator=a.defineClass(b,Object,{_parseSrc:function(){var b={},c=[],d={},e=[];for(var f in this.codeSrc)try{var g=this.codeSrc[f];_.isArray(g)&&(g=g.join("\n")),b[f]=a.PegExprParser.parse(g);var h=[];this._getVars(b[f],c,h,e),d[f]=h}catch(i){throw new Error("Error parsing "+f+"("+i.line+":"+i.column+")"+" : "+i)}this.codeAst=b,this.funcUsages=d,this.instanceVars=_.uniq(this.externalVars.concat(c)),this.registerUsages=_.uniq(e)},generateCode:function(b,c,d){var e=new a.CodeInstance,f=this,g=[];_.each(this.instanceVars,function(a){e[a]=0;var b="";_.contains(d,a)||(b="uniform "),g.push(b+"float "+a+";")});var h=_.intersection(_.keys(this.codeAst),b),i=_.difference(b,h);_.each(h,function(a){var b=f.codeAst[a],c=f._generateJs(b);e[a]=new Function(c)}),_.each(i,function(b){e[b]=a.noop});var j=_.intersection(_.keys(this.codeAst),c),k=_.difference(c,j),l=_.uniq(_.flatMap(j,function(a){return f.funcUsages[a]}));_.each(l,function(a){var b=f.glslFuncCode[a];b&&g.push(b)});var m=[],n=[];return _.each(j,function(a){var b=f.codeAst[a],c=f._generateGlsl(b,m);n.push("void "+a+"() {"),n.push(c),n.push("}")}),g=g.concat(_.map(m,function(a){return"uniform float "+a[1]+";"})),g=g.concat(n),e._preCompute=m,_.each(k,function(a){g.push("void "+a+"() {}")}),_.contains(j,"rand")&&(e.hasRandom=!0),_.contains(j,"gettime")&&(e.hasGettime=!0),e._treatAsNonUniform=d,e._registerUsages=this.registerUsages,[e,g.join("")]},funcArgLengths:{above:2,below:2,equal:2,pow:2,sqr:1,sqrt:1,invsqrt:1,floor:1,ceil:1,abs:1,"if":3,sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,log:1,band:2,bor:2,bnot:1,rand:1,gettime:1,getosc:3,select:{min:2}},jsMathFuncs:["sin","cos","abs","tan","asin","acos","atan","log","pow","sqrt","floor","ceil"],glslFuncCode:{rand:["uniform vec2 __randStep;","vec2 __randSeed;","float rand(float max) {"," __randCur += __randStep;"," float val = fract(sin(dot(__randSeed.xy ,vec2(12.9898,78.233))) * 43758.5453);"," return (floor(val*max)+1);","}"].join("\n"),gettime:["uniform float __gettime0;","int gettime(int startTime) {"," int time = 0;"," if(startTime == 0) {"," time = __gettime0;"," }"," return time;","}"].join("\n")},_checkFunc:function(a){var b=this.funcArgLengths[a.funcName];if(void 0===b)throw Error("Unknown function "+a.funcName);if(_.isNumber(b)){if(a.args.length!=b)throw Error(a.funcName+" accepts "+b+" arguments")}else if(b.min&&a.args.length",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"below":return["(",this._generateGlsl(b.args[0],c),"<",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"equal":return["(",this._generateGlsl(b.args[0],c),"==",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"if":return["(",this._generateGlsl(b.args[0],c),"!=0.0?",this._generateGlsl(b.args[1],c),":",this._generateGlsl(b.args[2],c),")"].join("");case"select":var e=this._generateGlsl(b.args[0],c),f=function(a,b){return 1==a.length?d._generateGlsl(a[0],c):["(("+e+" === "+b+")?","("+d._generateGlsl(a[0],c)+"):","("+f(_.last(a,a.length-1),b+1)+"))"].join("")};return f(_.last(b.args,b.args.length-1),0);case"sqr":return"(pow(("+this._generateGlsl(b.args[0],c)+"), 2))";case"band":return"(float(("+this._generateGlsl(b.args[0],c)+")&&("+this._generateGlsl(b.args[1],c)+")))";case"bor":return"(float(("+this._generateGlsl(b.args[0],c)+")||("+this._generateGlsl(b.args[1],c)+")))";case"bnot":return"(float(!("+this._generateGlsl(b.args[0],c)+")))";case"invsqrt":return"(1/sqrt("+this._generateGlsl(b.args[0],c)+"))";case"atan2":return"(atan(("+this._generateGlsl(b.args[0],c)+"),("+this._generateGlsl(b.args[1],c)+"))";case"getosc":var g=_.every(b.args,function(b){return b instanceof a.AstPrimaryExpr});if(!g)throw new Error("Non Pre-Computable arguments for getosc in shader code, use variables or constants");var h="__PC_"+b.funcName+"_"+j,i=[b.funcName,h].concat(_.map(b.args,function(a){return a.value})),j=_.indexOf(c,i);return-1==j&&(c.push(i),j=c.length-1),h;default:var k=_.map(b.args,function(a){return d._generateGlsl(a,c)}).join(","),l=b.funcName;return _.contains(this.varArgFuncs,b.funcName)&&(l+=b.args.length),"("+l+"("+k+"))"}if(b instanceof a.AstAssignment)return this._generateGlsl(b.lhs,c)+"="+this._generateGlsl(b.expr,c);if(b instanceof a.AstProgram){var m=_.map(b.statements,function(a){return d._generateGlsl(a,c)});return m.join(";\n")+";"}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?a.glslFloatRepr(b.value):b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&("ID"===b.type||"REG"===b.type)?b.value:void 0},_generateJs:function(b){var c,d=this;if(b instanceof a.AstBinaryExpr)return"("+this._generateJs(b.leftOperand)+b.operator+this._generateJs(b.rightOperand)+")";if(b instanceof a.AstUnaryExpr)return"("+b.operator+this._generateJs(b.operand)+")";if(b instanceof a.AstFuncCall)switch(this._checkFunc(b),b.funcName){case"above":return["(",this._generateJs(b.args[0]),">",this._generateJs(b.args[1]),"?1:0)"].join("");case"below":return["(",this._generateJs(b.args[0]),"<",this._generateJs(b.args[1]),"?1:0)"].join("");case"equal":return["(",this._generateJs(b.args[0]),"==",this._generateJs(b.args[1]),"?1:0)"].join("");case"if":return["(",this._generateJs(b.args[0]),"!==0?",this._generateJs(b.args[1]),":",this._generateJs(b.args[2]),")"].join("");case"select":var e=["((function() {"];return e.push("switch("+this._generateJs(b.args[0])+") {"),_.each(_.last(b.args,b.args.length-1),function(a,b){e.push("case "+b+": return "+this._generateJs(a)+";")},this),e.push("default : throw new Error('Unknown selector value in select');"),e.push("}}).call(this))"),e.join("");case"sqr":return"(Math.pow(("+this._generateJs(b.args[0])+"),2))";case"band":return"((("+this._generateJs(b.args[0])+")&&("+this._generateJs(b.args[1])+"))?1:0)";case"bor":return"((("+this._generateJs(b.args[0])+")||("+this._generateJs(b.args[1])+"))?1:0)";case"bnot":return"((!("+this._generateJs(b.args[0])+"))?1:0)";case"invsqrt":return"(1/Math.sqrt("+this._generateJs(b.args[0])+"))";case"atan2":return"(Math.atan(("+this._generateJs(b.args[0])+")/("+this._generateJs(b.args[1])+")))";default:var f=_.map(b.args,function(a){return d._generateJs(a)}).join(",");return c=_.contains(this.jsMathFuncs,b.funcName)?"Math.":"this.","("+c+b.funcName+"("+f+"))"}if(b instanceof a.AstAssignment)return this._generateJs(b.lhs)+"="+this._generateJs(b.expr);if(b instanceof a.AstProgram){var g=_.map(b.statements,function(a){return d._generateJs(a)});return g.join(";\n")}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?b.value.toString():b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&"ID"===b.type?"this."+b.value:b instanceof a.AstPrimaryExpr&&"REG"===b.type?'this._registerBank["'+b.value+'"]':void 0},_getVars:function(b,c,d,e){var f=this;b instanceof a.AstBinaryExpr?(this._getVars(b.leftOperand,c,d,e),this._getVars(b.rightOperand,c,d,e)):b instanceof a.AstUnaryExpr?this._getVars(b.operand,c,d,e):b instanceof a.AstFuncCall?(d.push(b.funcName),_.each(b.args,function(a){f._getVars(a,c,d,e)})):b instanceof a.AstAssignment?(this._getVars(b.lhs,c,d,e),this._getVars(b.expr,c,d,e)):b instanceof a.AstProgram?_.each(b.statements,function(a){f._getVars(a,c,d,e)}):b instanceof a.AstPrimaryExpr&&"ID"===b.type?c.push(b.value):b instanceof a.AstPrimaryExpr&&"REG"===b.type&&e.push(b.value)},_translateConstants:function(a){switch(a){case"pi":return Math.PI;case"e":return Math.E;case"phi":return 1.6180339887;default:throw new Error("Unknown constant "+a)}}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]);var d=new a.ExprCodeGenerator(c.code,["b","w","h"]),e=d.generateCode(["init","onBeat","perFrame"],[],[]);this.code=e[0],this.inited=!1,b.super.constructor.call(this)}a.GlobalVar=a.defineClass(b,a.Component,{init:function(a,c,d){b.super.init.call(this,a,c,d),this.code.setup(c,this)},update:function(){var a=this.code;a.b=this.main.analyser.beat?1:0,this.inited||(a.init(),this.inited=!0),this.main.analyser.beat&&a.onBeat(),a.perFrame()}}),b.ui={disp:"Global Var",type:"GlobalVar",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"}}}}}}(Webvs),function(a){function b(c){if(c=_.defaults(c,{action:"SAVE",bufferId:1,blendMode:"REPLACE"}),this.blendMode=a.blendModes[c.blendMode],this.action=this.actions[c.action],!this.action)throw new Error("Unknown BufferSave action "+c.action);this.action==this.actions.SAVERESTORE?this._nextAction=this.actions.SAVE:this.action==this.actions.RESTORESAVE&&(this._nextAction=this.actions.RESTORE),this._bufferId="__BUFFERSAVE_"+c.bufferId,b.super.constructor.call(this)}a.BufferSave=a.defineClass(b,a.Component,{actions:{SAVE:1,RESTORE:2,SAVERESTORE:3,RESTORESAVE:4},init:function(c,d,e){if(b.super.init.call(this,c,d,e),!d.registerBank[this._bufferId]){var f=new a.FrameBufferManager(d.canvas.width,d.canvas.height,c,d.copier,1);d.registerBank[this._bufferId]=f}},update:function(){this.gl;var a,b=this.main.registerBank[this._bufferId];switch(this.action==this.actions.SAVERESTORE||this.action==this.RESTORESAVE?(a=this._nextAction,this._nextAction=this._nextAction==this.actions.SAVE?this.actions.RESTORE:this.actions.SAVE):a=this.action,a){case this.actions.SAVE:b.setRenderTarget(),this.main.copier.run(null,null,this.parent.fm.getCurrentTexture()),b.restoreRenderTarget();break;case this.actions.RESTORE:this.main.copier.run(this.parent.fm,this.blendMode,b.getCurrentTexture())}},destroy:function(){b.super.destroy.call(this),this.main.registerBank[this._bufferId].destroy()}}),b.ui={disp:"Buffer Save",type:"BufferSave",schema:{action:{type:"string",title:"Buffer save action","enum":["SAVE","RESTORE","SAVERESTORE","RESTORESAVE"]},bufferId:{type:"number",title:"Buffer Id","enum":[1,2,3,4,5,6,7,8]},blendMode:{type:"string",title:"Blend mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{speed:1,color:"#000000"}),this.color=a.parseColorNorm(c.color),this.frameCount=0,this.maxFrameCount=Math.floor(1/c.speed),this.program=new a.ClearScreenProgram(a.AVERAGE),b.super.constructor.call(this)}a.FadeOut=a.defineClass(b,a.Component,{componentName:"FadeOut",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.gl,this.frameCount++,this.frameCount==this.maxFrameCount&&(this.frameCount=0,this.program.run(this.parent.fm,null,this.color))},destroy:function(){b.super.destroyComponent.call(this),this.program.cleanup()}}),b.ui={type:"FadeOut",disp:"Fade Out",schema:{speed:{type:"number",title:"Speed",maximum:0,minimum:1,"default":1},color:{type:"string",title:"Fadeout color",format:"color","default":"#FFFFFF"}},form:[{key:"speed",type:"range",step:"0.05"},"color"]}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["kernel"]),c=_.defaults(c,{edgeMode:"EXTEND",bias:0});var d;if(c.kernel in b.kernels)d=b.kernels[c.kernel];else{if(!_.isArray(c.kernel)||1!==c.kernel.length%2)throw new Error("Invalid convolution kernel");d=c.kernel}var e=Math.floor(Math.sqrt(d.length));if(e*e!=d.length)throw new Error("Invalid convolution kernel");this.program=new a.ConvolutionProgram(d,e,c.edgeMode,c.scale,c.bias),b.super.constructor.call(this)}function c(b,d,e,f,g){var h="";switch(e){case"WRAP":h="pos = vec2(pos.x<0?pos.x+1.0:pos.x%1, pos.y<0?pos.y+1.0:pos.y%1);";break;case"EXTEND":h="pos = clamp(pos, vec2(0,0), vec2(1,1));";break;default:throw new Error("Invalid edge mode")}var i,j,k=[],l=Math.floor(d/2);for(i=0;d>i;i++)for(j=0;d>j;j++){var m=b[i*d+j];0!==m&&(k.push("pos = v_position + onePixel * vec2("+(i-l)+","+(j-l)+");"),k.push(h),k.push("colorSum += texture2D(u_srcTexture, pos) * "+a.glslFloatRepr(m)+";"))}_.isUndefined(f)&&(f=_.reduce(b,function(a,b){return a+b},0)),c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["void main() {"," vec2 onePixel = vec2(1.0, 1.0)/u_resolution;"," vec2 pos;"," vec4 colorSum = vec4(0,0,0,0);",k.join("\n")," setFragColor(vec4(((colorSum+"+a.glslFloatRepr(g)+") / "+a.glslFloatRepr(f)+").rgb, 1.0));","}"]})}a.Convolution=a.defineClass(b,a.Component,{componentName:"Convolution",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),b.kernels={normal:[0,0,0,0,1,0,0,0,0],gaussianBlur:[.045,.122,.045,.122,.332,.122,.045,.122,.045],unsharpen:[-1,-1,-1,-1,9,-1,-1,-1,-1],emboss:[-2,-1,0,-1,1,1,0,1,2],blur:[1,1,1,1,1,1,1,1,1]},a.ConvolutionProgram=a.defineClass(c,a.QuadBoxProgram)}(Webvs),function(a){function b(c){if(a.checkRequiredOptions(c,["maps"]),c=_.defaults(c,{key:"RED",output:"REPLACE",mapCycleMode:"SINGLE"}),this.maps=c.maps,this.currentMap=0,this.mapCycleMode=this.mapCycleModes[c.mapCycleMode],!this.mapCycleMode)throw new Error("Unknown mapCycleMode "+c.mapCycleMode);this.program=new a.ColorMapProgram(c.key,a.blendModes[c.output]),b.super.constructor.call(this)}function c(a,b){var d="";switch(a){case"RED":d="srcColor.r";break;case"GREEN":d="srcColor.g";break;case"BLUE":d="srcColor.b";break;case"(R+G+B)/2":d="mod((srcColor.r+srcColor.g+srcColor.b)/2.0, 1.0)";break;case"(R+G+B)/3":d="(srcColor.r+srcColor.g+srcColor.b)/3.0";break;case"MAX":d="max(srcColor.r, max(srcColor.g, srcColor.b))";break;default:throw new Error("Unknown colormap key function "+options.key)}c.super.constructor.call(this,{outputBlendMode:b,swapFrame:!0,fragmentShader:["uniform sampler2D u_colorMap;","void main() {"," vec4 srcColor = getSrcColor();"," setFragColor(texture2D(u_colorMap, vec2(("+d+"), 0)));","}"]})}a.ColorMap=a.defineClass(b,a.Component,{mapCycleModes:{SINGLE:1,ONBEATRANDOM:2,ONBEATSEQUENTIAL:3},init:function(a,c,d){b.super.init.call(this,a,c,d),this.colorMaps=_.map(this.maps,function(a){return this._buildColorMap(a)},this),this.currentMap=0,this.program.init(a)},update:function(){if(this.main.analyser.beat)switch(this.mapCycleMode){case this.mapCycleModes.ONBEATRANDOM:this.currentMap=Math.floor(Math.random()*this.colorMaps.length);break;case this.mapCycleModes.ONBEATSEQUENTIAL:this.currentMap=(this.currentMap+1)%this.colorMaps.length}this.program.run(this.parent.fm,null,this.colorMaps[this.currentMap])},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_buildColorMap:function(b){var c=this.gl;b=_.sortBy(b,function(a){return a.index});var d=_.map(b,function(a){return a.index});if(_.uniq(d).length!=d.length)throw new Error("map cannot have repeated indices");var e=_.first(b);0!==e.index&&b.splice(0,0,{color:e.color,index:0});var f=_.last(b);255!==f.index&&b.push({color:f.color,index:255}),b=_.map(b,function(b){var c=a.parseColor(b.color);return{color:c,index:b.index}});var g=new Uint8Array(1024),h=0,i=_.zip(_.first(b,b.length-1),_.last(b,b.length-1));_.each(i,function(a){var b=a[0],c=a[1],d=c.index-b.index,e=[(c.color[0]-b.color[0])/d,(c.color[1]-b.color[1])/d,(c.color[2]-b.color[2])/d];_.times(d,function(a){g[h++]=b.color[0]+e[0]*a,g[h++]=b.color[1]+e[1]*a,g[h++]=b.color[2]+e[2]*a,g[h++]=255})}),g[h++]=f.color[0],g[h++]=f.color[1],g[h++]=f.color[2],g[h++]=255;var j=c.createTexture();return c.bindTexture(c.TEXTURE_2D,j),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,256,1,0,c.RGBA,c.UNSIGNED_BYTE,g),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),j}}),a.ColorMapProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_colorMap","texture2D",a),c.super.draw.call(this)}}),b.ui={disp:"Color Map",type:"ColorMap",schema:{maps:{type:"array",items:{type:"array",title:"Map",items:{type:"object",properties:{color:{type:"string",title:"Color",format:"color","default":"#FFFFFF"},index:{type:"number",title:"Index",minimum:0,maximum:255}}}}},key:{type:"string",title:"Map key","enum":["RED","GREEN","BLUE","(R+G+B)/2","(R+G+B)/3","MAX"],"default":"RED"},mapCycleMode:{type:"string",title:"Map Cycle Mode","enum":["SINGLE","ONBEATRANDOM","ONBEATSEQUENTIAL"],"default":"SINGLE"},output:{type:"string",title:"Output blend mode","enum":_.keys(a.blendModes),"default":"REPLACE"}}}}(Webvs),function(a){function b(b){if(a.checkRequiredOptions(b,["mode","color","outColor"]),b=_.defaults(b,{mode:"BELOW",color:"#202020",outColor:"#202020",level:0}),this.mode=_.indexOf(this.modes,b.mode),-1==this.mode)throw new Error("ColorClip: invalid mode");this.color=a.parseColorNorm(b.color),this.outColor=a.parseColorNorm(b.outColor),this.level=b.level,this.program=new a.ColorClipProgram}function c(){c.super.constructor({swapFrame:!0,fragmentShader:["uniform int u_mode;","uniform vec3 u_color;","uniform vec3 u_outColor;","uniform float u_level;","void main() {"," vec4 inColor4 = getSrcColor();"," vec3 inColor = inColor4.rgb;"," bool clip = false;"," if(u_mode == 0) {"," clip = all(lessThanEqual(inColor, u_color));"," }"," if(u_mode == 1) {"," clip = all(greaterThanEqual(inColor, u_color));"," }"," if(u_mode == 2) {"," clip = (distance(inColor, u_color) <= u_level*0.5);"," }"," if(clip) {"," setFragColor(vec4(u_outColor, inColor4.a));"," } else {"," setFragColor(inColor4);"," }","}"]})}a.ColorClip=a.defineClass(b,a.Component,{modes:["BELOW","ABOVE","NEAR"],componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null,this.mode,this.color,this.outColor,this.level)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ColorClipProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a,b,d,e){this.setUniform("u_mode","1i",a),this.setUniform.apply(this,["u_color","3f"].concat(b)),this.setUniform.apply(this,["u_outColor","3f"].concat(d)),this.setUniform("u_level","1f",e),c.super.draw.call(this)}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]),c=_.defaults(c,{gridW:16,gridH:16,noGrid:!1,bFilter:!0,compat:!1,coord:"POLAR"});var d;if(!_.isObject(c.code))throw new Error("Invalid Dynamic movement code");d=c.code;var e=new a.ExprCodeGenerator(d,["x","y","r","d","b","w","h"]),f=e.generateCode(["init","onBeat","perFrame"],["perPixel"],["x","y","d","r"]);this.code=f[0],this.inited=!1,this.noGrid=c.noGrid,this.gridW=c.gridW,this.gridH=c.gridH,this.coordMode=c.coord,this.bFilter=c.bFilter,this.compat=c.compat,this.program=this.noGrid?new a.DMovProgramNG(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]):new a.DMovProgram(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]),b.super.constructor.call(this)}function c(a,b,d,e,f){var g=[f,this.glslFilter(b,d),"void main() {",e?"__randSeed = v_position;":""," x = v_position.x*2.0-1.0;"," y = -(v_position.y*2.0-1.0);",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," setFragColor(vec4(filter(vec2(x, -y)), 1));","}"];c.super.constructor.call(this,{fragmentShader:g,swapFrame:!0})}function d(a,b,c,e,f){var g=["attribute vec2 a_position;","varying vec2 v_newPoint;","uniform int u_coordMode;",f,"void main() {",e?"__randSeed = a_position;":""," x = a_position.x;"," y = -a_position.y;",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," v_newPoint = vec2(x,-y);"," setPosition(a_position);","}"],h=["varying vec2 v_newPoint;",this.glslFilter(b,c),"void main() {"," setFragColor(vec4(filter(v_newPoint), 1));","}"];d.super.constructor.call(this,{fragmentShader:h,vertexShader:g,swapFrame:!0})}a.DynamicMovement=a.defineClass(b,a.Component,{componentName:"DynamicMovement",init:function(a,c,d){if(b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,d),!this.noGrid){for(var e=2*(this.gridW/this.main.canvas.width),f=2*(this.gridH/this.main.canvas.height),g=Math.ceil(this.main.canvas.width/this.gridW),h=Math.ceil(this.main.canvas.height/this.gridH),i=new Float32Array(2*6*g*h),j=0,k=-1,l=-1,m=0;h>m;m++){for(var n=0;g>n;n++){var o=Math.min(k+e,1),p=Math.min(l+f,1);i[j++]=k,i[j++]=l,i[j++]=o,i[j++]=l,i[j++]=k,i[j++]=p,i[j++]=o,i[j++]=l,i[j++]=o,i[j++]=p,i[j++]=k,i[j++]=p,k+=e}k=-1,l+=f}this.gridVertices=i,this.gridVerticesSize=j/2}},update:function(){var a=this.code;this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat(),this.noGrid?this.program.run(this.parent.fm,null,this.code):this.program.run(this.parent.fm,null,this.code,this.gridVertices,this.gridVerticesSize)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}});var e={glslRectToPolar:function(a){return"POLAR"===a?["d = distance(vec2(x, y), vec2(0,0))/sqrt(2.0);","r = mod(atan(y, x)+PI*0.5, 2.0*PI);"].join("\n"):""},glslPolarToRect:function(a){return"POLAR"===a?["d = d*sqrt(2.0);","x = d*sin(r);","y = -d*cos(r);"].join("\n"):""},glslFilter:function(a,b){return a&&!b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 cornoff = fract(coord/texel);"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," vec3 pt = mix(tl, tr, cornoff.x);"," vec3 pb = mix(bl, br, cornoff.x);"," return mix(pt, pb, cornoff.y);","}"].join("\n"):a&&b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," float xp = floor(fract(coord.x/texel.x)*255.0);"," float yp = floor(fract(coord.y/texel.y)*255.0);"," #define g_blendtable(i, j) floor(((i)/255.0)*(j))"," float a1 = g_blendtable(255.0-xp, 255.0-yp);"," float a2 = g_blendtable(xp, 255.0-yp);"," float a3 = g_blendtable(255.0-xp, yp);"," float a4 = g_blendtable(xp, yp);"," float r = (floor(a1*tl.r) + floor(a2*tr.r) + floor(a3*bl.r) + floor(a4*br.r))/255.0;"," float g = (floor(a1*tl.g) + floor(a2*tr.g) + floor(a3*bl.g) + floor(a4*br.g))/255.0;"," float b = (floor(a1*tl.b) + floor(a2*tr.b) + floor(a3*bl.b) + floor(a4*br.b))/255.0;"," return vec3(r, g, b);","}"].join("\n"):["vec3 filter(vec2 point) {"," return getSrcColorAtPos((point+1.0)/2.0).rgb;","}"].join("\n")}};a.DMovProgramNG=a.defineClass(c,a.QuadBoxProgram,e,{draw:function(a){a.bindUniforms(this),c.super.draw.call(this)}}),a.DMovProgram=a.defineClass(d,a.ShaderProgram,e,{draw:function(a,b,c){a.bindUniforms(this),this.setVertexAttribArray("a_position",b,2,this.gl.FLOAT,!1,0,0),this.gl.drawArrays(this.gl.TRIANGLES,0,c)}}),b.ui={type:"DynamicMovement",disp:"Dynamic Movement",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPixel:{type:"string",title:"Per Point"}}},gridW:{type:"number",title:"Grid Width","default":16},gridH:{type:"number",title:"Grid Height","default":16},coord:{type:"string",title:"Coordinate System","enum":["POLAR","RECT"],"default":"POLAR"}},form:[{key:"code.init",type:"textarea"},{key:"code.onBeat",type:"textarea"},{key:"code.perFrame",type:"textarea"},{key:"code.perPixel",type:"textarea"},"gridW","gridH","coord"]}}(Webvs),function(a){function b(a){if(a=_.defaults(a,{channel:"RGB",onBeatRandom:!1}),this.channel=d.indexOf(a.channel),-1==this.channel)throw new Error("Invalid Channel");this.onBeatRandom=a.onBeatRandom,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["uniform int u_channel;","void main() {"," vec3 color = getSrcColor().rgb;",_.flatMap(d,function(a,b){return["if(u_channel == "+b+") {"," setFragColor(vec4(color."+a.toLowerCase()+",1));","}"]}).join("\n"),"}"]})}var d=["RGB","RBG","BRG","BGR","GBR","GRB"];a.ChannelShift=a.defineClass(b,a.Component,{componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.onBeatRandom&&this.main.analyser.beat&&(this.channel=Math.floor(Math.random()*d.length)),this.program.run(this.parent.fm,null,this.channel)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ChannelShiftProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_channel","1i",a),c.super.draw.call(this)}}),b.ui={disp:"Channel Shift",type:"ChannelShift",schema:{channel:{type:"string",title:"Channel","enum":d},onBeatRandom:{type:"boolean",title:"On beat random"}}}}(Webvs),function(a){function b(d){a.checkRequiredOptions(d,["code"]),d=_.defaults(d,{source:"SPECTRUM",drawMode:"LINES",colors:["#ffffff"]});var e;if(!_.isObject(d.code))throw new Error("Invalid superscope");e=d.code;var f=new a.ExprCodeGenerator(e,["n","v","i","x","y","b","w","h","red","green","blue","cid"]),g=f.generateCode(["init","onBeat","perFrame","perPoint"],[],[]);this.code=g[0],this.code.n=100,this.spectrum="SPECTRUM"==d.source,this.dots="DOTS"==d.drawMode,this.colors=_.map(d.colors,a.parseColorNorm),this.currentColor=this.colors[0],this.maxStep=100,this.step=this.maxStep,this.colorId=0,this.colorStep=[0,0,0],this.thickness=d.thickness?d.thickness:1,this.inited=!1,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_position;","attribute vec3 a_color;","varying vec3 v_color;","uniform float u_pointSize;","void main() {"," gl_PointSize = u_pointSize;"," setPosition(clamp(a_position, vec2(-1,-1), vec2(1,1)));"," v_color = a_color;","}"],fragmentShader:["varying vec3 v_color;","void main() {"," setFragColor(vec4(v_color, 1));","}"]})}a.SuperScope=a.defineClass(b,a.Component,{componentName:"SuperScope",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,this)},update:function(){this.gl;var a=this.code;this._stepColor(),a.red=this.currentColor[0],a.green=this.currentColor[1],a.blue=this.currentColor[2],this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat();for(var c=Math.floor(a.n),d=this.spectrum?this.main.analyser.getSpectrum():this.main.analyser.getWaveform(),e=d.length/c,f=0,g=0,h=new Float32Array(2*(this.dots?c:2*c-2)),i=new Float32Array(3*(this.dots?c:2*c-2)),j=0;c>j;j++){for(var k=0,l=0,m=Math.floor(j*e);(j+1)*e>m;m++,l++)k+=d[m];k/=l;var n=j/(c-1);a.i=n,a.v=k,a.perPoint(),h[f++]=a.x,h[f++]=-1*a.y,0===j||j==c-1||this.dots||(h[f++]=a.x,h[f++]=-1*a.y),this.dots?(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue):0!==j&&(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue,i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue)}this.program.run(this.parent.fm,null,h,i,this.dots,this.thickness)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_stepColor:function(){var a;if(this.colors.length>1)if(this.step==this.maxStep){var b=this.colors[this.colorId];this.colorId=(this.colorId+1)%this.colors.length;var c=this.colors[this.colorId];for(a=0;3>a;a++)this.colorStep[a]=(c[a]-b[a])/this.maxStep;this.step=0,this.currentColor=b}else{for(a=0;3>a;a++)this.currentColor[a]+=this.colorStep[a];this.step++}}}),a.SuperScopeShader=a.defineClass(c,a.ShaderProgram,{draw:function(a,b,c,d){var e=this.gl;this.setUniform("u_pointSize","1f",d),this.setVertexAttribArray("a_position",a,2,e.FLOAT,!1,0,0),this.setVertexAttribArray("a_color",b,3,e.FLOAT,!1,0,0);var f;c||(f=e.getParameter(e.LINE_WIDTH),e.lineWidth(d)),e.drawArrays(c?e.POINTS:e.LINES,0,a.length/2),c||e.lineWidth(f)}}),b.ui={disp:"SuperScope",type:"SuperScope",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPoint:{type:"string",title:"Per Point"}}},source:{type:"string",title:"Source","default":"WAVEFORM","enum":["WAVEFORM","SPECTRUM"]},drawMode:{type:"string",title:"Draw Mode","default":"LINES","enum":["DOTS","LINES"]},colors:{type:"array",title:"Cycle Colors",items:{type:"string",format:"color","default":"#FFFFFF"}}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{n:0,color:"#000000",blendMode:"REPLACE"}),this.n=c.n,this.color=a.parseColorNorm(c.color),this.outputBlendMode=a.blendModes[c.blendMode],this.prevBeat=!1,this.beatCount=0,this.program=new a.ClearScreenProgram(this.outputBlendMode),b.super.constructor.call(this)}a.ClearScreen=a.defineClass(b,a.Component,{componentName:"ClearScreen",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){var a=!1;0===this.n?a=!0:(this.main.analyser.beat&&!this.prevBeat&&(this.beatCount++,this.beatCount==this.n&&(a=!0,this.beatCount=0)),this.prevBeat=this.main.analyser.beat),a&&this.program.run(this.parent.fm,null,this.color)},destroy:function(){this.program.cleanup()}}),b.ui={type:"ClearScreen",disp:"Clear Screen",schema:{n:{type:"number",title:"Clear on beat (0 = always clear)","default":0},color:{type:"string",title:"Clear color",format:"color","default":"#000000"},blendMode:{type:"string",title:"Blend Mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["src","x","y"]),this.x=c.x,this.y=c.y,this.src=c.src,this.program=new a.PictureProgram,b.super.constructor.call(this,c)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_texVertex;","uniform vec2 u_pos;","uniform vec2 u_texRes;","varying vec2 v_texCoord;","void main() {"," v_texCoord = a_texVertex;"," setPosition(a_texVertex*(u_texRes/u_resolution)*vec2(2,-2)+u_pos);","}"],fragmentShader:["uniform sampler2D u_image;","varying vec2 v_texCoord;","void main() {"," setFragColor(texture2D(u_image, v_texCoord));","}"]}) +}).value()}throw new Error("Invalid Color Format")},b.parseColorNorm=function(a){return _.map(b.parseColor(a),function(a){return a/255})},b.logShaderError=function(a,b){var c=a.split("\n"),d=c.length.toString().length,e=b.match(/(\d+):(\d+)/);e&&(e=[parseInt(e[1],10),parseInt(e[2],10)]);var f=_.map(c,function(a,c){var f,g=c+1+"";for(f=0;f0&&this._frameCounter--,0!==this._frameCounter)){if(this.fm.setRenderTarget(),(this.clearFrame||this.first)&&(a.clearColor(0,0,0,1),a.clear(a.COLOR_BUFFER_BIT),this.first=!1),-1!==this.input){var c=this.parent.fm.getCurrentTexture();this.main.copier.run(this.fm,this.input,c)}for(var d=this.components,e=0;ee;e++){var f=b.charAt(e);"\n"===f?(a.seenCR||a.line++,a.column=1,a.seenCR=!1):"\r"===f||"\u2028"===f||"\u2029"===f?(a.line++,a.column=1,a.seenCR=!0):(a.column++,a.seenCR=!1)}a.offset+=c}function f(a){F.offsetH.offset&&(H=d(F),I=[]),I.push(a))}function g(){var a="program@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,i,j,k,l,m,n,o,p,q;if(o=d(F),p=d(F),g=h(),null!==g)if(i=x(),null!==i){for(j=[],q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==k;)j.push(k),q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==j?(59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),k=null!==k?k:"",null!==k?g=[g,i,j,k]:(g=null,F=d(p))):(g=null,F=d(p))}else g=null,F=d(p);else g=null,F=d(p);return null!==g&&(g=function(a,b,c,d){var e=[d[0]];return e=e.concat(_.map(d[2],function(a){return a[2]})),new Webvs.AstProgram(e)}(o.offset,o.line,o.column,g)),null===g&&(F=d(o)),J[a]={nextPos:d(F),result:g},g}function h(){var a="statement@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n;return l=d(F),n=d(F),g=s(),null!==g?(h=x(),null!==h?(61===b.charCodeAt(F.offset)?(i="=",e(F,1)):(i=null,0===G&&f('"="')),null!==i?(j=x(),null!==j?(k=m(),null!==k?g=[g,h,i,j,k]:(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d,e){return new Webvs.AstAssignment(d,e)}(l.offset,l.line,l.column,g[0],g[4])),null===g&&(F=d(l)),null===g&&(g=m()),J[a]={nextPos:d(F),result:g},g}function i(){var a="unary_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function j(){var a="additive_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function k(){var a="multiplicative_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 42===b.charCodeAt(F.offset)?(g="*",e(F,1)):(g=null,0===G&&f('"*"')),null===g&&(47===b.charCodeAt(F.offset)?(g="/",e(F,1)):(g=null,0===G&&f('"/"')),null===g&&(37===b.charCodeAt(F.offset)?(g="%",e(F,1)):(g=null,0===G&&f('"%"')))),J[a]={nextPos:d(F),result:g},g}function l(){var a="boolean_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 38===b.charCodeAt(F.offset)?(g="&",e(F,1)):(g=null,0===G&&f('"&"')),null===g&&(124===b.charCodeAt(F.offset)?(g="|",e(F,1)):(g=null,0===G&&f('"|"'))),J[a]={nextPos:d(F),result:g},g}function m(){var a="boolean_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,k,m;if(j=d(F),k=d(F),c=n(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(k))}else c=null,F=d(k);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function n(){var a="additive_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,k,l,m;if(k=d(F),l=d(F),c=o(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(k.offset,k.line,k.column,c[0],c[1])),null===c&&(F=d(k)),J[a]={nextPos:d(F),result:c},c}function o(){var a="multiplicative_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,l,m;if(j=d(F),l=d(F),c=p(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function p(){var a="unary@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h;return g=d(F),h=d(F),c=i(),null!==c?(e=x(),null!==e?(f=q(),null!==f?c=[c,e,f]:(c=null,F=d(h))):(c=null,F=d(h))):(c=null,F=d(h)),null!==c&&(c=function(a,b,c,d,e){return new Webvs.AstUnaryExpr(d,e)}(g.offset,g.line,g.column,c[0],c[2])),null===c&&(F=d(g)),null===c&&(c=q()),J[a]={nextPos:d(F),result:c},c}function q(){var a="func_call@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n,o,p,q,s,t;if(p=d(F),q=d(F),s=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(s))}else g=null,F=d(s);if(null!==g)if(h=x(),null!==h)if(40===b.charCodeAt(F.offset)?(i="(",e(F,1)):(i=null,0===G&&f('"("')),null!==i){for(s=d(F),j=[],t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==k;)j.push(k),t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==j?(k=x(),null!==k?(l=m(),null!==l?j=[j,k,l]:(j=null,F=d(s))):(j=null,F=d(s))):(j=null,F=d(s)),j=null!==j?j:"",null!==j?(k=x(),null!==k?(41===b.charCodeAt(F.offset)?(l=")",e(F,1)):(l=null,0===G&&f('")"')),null!==l?g=[g,h,i,j,k,l]:(g=null,F=d(q))):(g=null,F=d(q))):(g=null,F=d(q))}else g=null,F=d(q);else g=null,F=d(q);else g=null,F=d(q);return null!==g&&(g=function(a,b,c,d,e){var f=[];return _.each(e[0],function(a){f.push(a[1])}),f.push(e[2]),new Webvs.AstFuncCall(D(d),f)}(p.offset,p.line,p.column,g[0],g[3])),null===g&&(F=d(p)),null===g&&(g=r()),J[a]={nextPos:d(F),result:g},g}function r(){var a="primary_expr@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;return g=w(),null===g&&(g=u(),null===g&&(g=v(),null===g&&(g=t(),null===g&&(j=d(F),k=d(F),40===b.charCodeAt(F.offset)?(g="(",e(F,1)):(g=null,0===G&&f('"("')),null!==g?(h=m(),null!==h?(41===b.charCodeAt(F.offset)?(i=")",e(F,1)):(i=null,0===G&&f('")"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))):(g=null,F=d(k)),null!==g&&(g=function(a,b,c,d){return d}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)))))),J[a]={nextPos:d(F),result:g},g}function s(){var a="assignable@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c;return c=v(),null===c&&(c=t()),J[a]={nextPos:d(F),result:c},c}function t(){var a="identifier@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"ID")}(j.offset,j.line,j.column,g)),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function u(){var a="constant@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),36===b.charCodeAt(F.offset)?(g="$",e(F,1)):(g=null,0===G&&f('"$"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"CONST")}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function v(){var a="register@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(l=d(F),m=d(F),64===b.charCodeAt(F.offset)?(g="@",e(F,1)):(g=null,0===G&&f('"@"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(m))}else g=null,F=d(m);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_AT_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g[1])),null===g&&(F=d(l)),null===g&&(l=d(F),m=d(F),/^[rR]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[rR]")),null!==g?(/^[eE]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[eE]")),null!==h?(/^[gG]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[gG]")),null!==i?(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j?(/^[0-9]/.test(b.charAt(F.offset))?(k=b.charAt(F.offset),e(F,1)):(k=null,0===G&&f("[0-9]")),null!==k?g=[g,h,i,j,k]:(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g)),null===g&&(F=d(l))),J[a]={nextPos:d(F),result:g},g}function w(){var a="value@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m,n,o;for(m=d(F),n=d(F),g=[],/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));if(null!==g)if(46===b.charCodeAt(F.offset)?(h=".",e(F,1)):(h=null,0===G&&f('"."')),null!==h){if(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j)for(i=[];null!==j;)i.push(j),/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]"));else i=null;if(null!==i){if(o=d(F),/^[Ee]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[Ee]")),null!==j){if(/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]")),null!==l)for(k=[];null!==l;)k.push(l),/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]"));else k=null;null!==k?j=[j,k]:(j=null,F=d(o))}else j=null,F=d(o);j=null!==j?j:"",null!==j?g=[g,h,i,j]:(g=null,F=d(n))}else g=null,F=d(n)}else g=null,F=d(n);else g=null,F=d(n);if(null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseFloat(D(d)),"VALUE")}(m.offset,m.line,m.column,g)),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]"));else g=null;if(null!==g?(/^[hH]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[hH]")),null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),16),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));else g=null;null!==g?(/^[dD]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[dD]")),h=null!==h?h:"",null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),10),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m))}}return J[a]={nextPos:d(F),result:g},g}function x(){var a="__@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e;for(c=[],e=y(),null===e&&(e=z(),null===e&&(e=A()));null!==e;)c.push(e),e=y(),null===e&&(e=z(),null===e&&(e=A()));return J[a]={nextPos:d(F),result:c},c}function y(){var a="whiteSpace@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\t\x0B\f \xA0\uFEFF]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\t\\x0B\\f \\xA0\\uFEFF]")),J[a]={nextPos:d(F),result:g},g}function z(){var a="lineEnd@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\n\r\u2028\u2029]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\n\\r\\u2028\\u2029]")),J[a]={nextPos:d(F),result:g},g}function A(){var a="comment@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(k=d(F),"/*"===b.substr(F.offset,2)?(g="/*",e(F,2)):(g=null,0===G&&f('"/*"')),null!==g){for(h=[],l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?("*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))}else g=null,F=d(k);if(null===g)if(k=d(F),"//"===b.substr(F.offset,2)?(g="//",e(F,2)):(g=null,0===G&&f('"//"')),null!==g){for(h=[],l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return J[a]={nextPos:d(F),result:g},g}function B(a){a.sort();for(var b=null,c=[],d=0;dH.offset?F:H;throw new this.SyntaxError(B(I),M,L,N.line,N.column)}return K},toSource:function(){return this._source}};return b.SyntaxError=function(b,c,d,e,f){function g(b,c){var d,e; +switch(b.length){case 0:d="end of input";break;case 1:d=b[0];break;default:d=b.slice(0,b.length-1).join(", ")+" or "+b[b.length-1]}return e=c?a(c):"end of input","Expected "+d+" but "+e+" found."}this.name="SyntaxError",this.expected=b,this.found=c,this.message=g(b,c),this.offset=d,this.line=e,this.column=f},b.SyntaxError.prototype=Error.prototype,b}(),function(a){function b(){}a.CodeInstance=a.defineClass(b,Object,{rand:function(a){return Math.floor(Math.random()*a)+1},gettime:function(a){switch(a){case 0:var b=(new Date).getTime();return(b-this._bootTime)/1e3;default:throw new Error("Invalid startTime mode for gettime call")}},getosc:function(a,b){for(var c=this._analyser.getWaveform(),d=Math.floor((a-b/2)*(c.length-1)),e=Math.floor((a+b/2)*(c.length-1)),f=0,g=d;e>=g;g++)f+=c[g];return f/(e-d+1)},bindUniforms:function(a){var b=this,c=_.difference(_.keys(this),this._treatAsNonUniform);if(_.each(c,function(c){var d=b[c];"number"==typeof d&&a.setUniform(c,"1f",d)}),_.each(this._registerUsages,function(b){a.setUniform(b,"1f",this._registerBank[b])}),this.hasRandom){var d=[Math.random()/100,Math.random()/100];a.setUniform("__randStep","2fv",d)}if(this.hasGettime){var e=((new Date).getTime()-this._bootTime)/1e3;a.setUniform("__gettime0","1f",e)}_.each(this._preCompute,function(b){var c=_.map(_.last(b,b.length-2),function(a){return _.isString(a)?"__REG"==a.substring(0,5)?this._registerBank[a]:this[a]:a}),d=this[b[0]].apply(this,c);a.setUniform(b[1],"1f",d)})},setup:function(a,b){this._registerBank=a.registerBank,this._bootTime=a.bootTime,this._analyser=a.analyser,this.w=a.canvas.width,this.h=a.canvas.height,this.cid=b.cloneId,_.each(this._registerUsages,function(b){_.has(a.registerBank,b)||(a.registerBank[b]=0)})}})}(Webvs),function(a){function b(a,b){this.codeSrc=a,this.externalVars=b?b:[],this._parseSrc()}a.ExprCodeGenerator=a.defineClass(b,Object,{_parseSrc:function(){var b={},c=[],d={},e=[];for(var f in this.codeSrc)try{var g=this.codeSrc[f];_.isArray(g)&&(g=g.join("\n")),b[f]=a.PegExprParser.parse(g);var h=[];this._getVars(b[f],c,h,e),d[f]=h}catch(i){throw new Error("Error parsing "+f+"("+i.line+":"+i.column+")"+" : "+i)}this.codeAst=b,this.funcUsages=d,this.instanceVars=_.uniq(this.externalVars.concat(c)),this.registerUsages=_.uniq(e)},generateCode:function(b,c,d){var e=new a.CodeInstance,f=this,g=[];_.each(this.instanceVars,function(a){e[a]=0;var b="";_.contains(d,a)||(b="uniform "),g.push(b+"float "+a+";")});var h=_.intersection(_.keys(this.codeAst),b),i=_.difference(b,h);_.each(h,function(a){var b=f.codeAst[a],c=f._generateJs(b);e[a]=new Function(c)}),_.each(i,function(b){e[b]=a.noop});var j=_.intersection(_.keys(this.codeAst),c),k=_.difference(c,j),l=_.uniq(_.flatMap(j,function(a){return f.funcUsages[a]}));_.each(l,function(a){var b=f.glslFuncCode[a];b&&g.push(b)});var m=[],n=[];return _.each(j,function(a){var b=f.codeAst[a],c=f._generateGlsl(b,m);n.push("void "+a+"() {"),n.push(c),n.push("}")}),g=g.concat(_.map(m,function(a){return"uniform float "+a[1]+";"})),g=g.concat(n),e._preCompute=m,_.each(k,function(a){g.push("void "+a+"() {}")}),_.contains(j,"rand")&&(e.hasRandom=!0),_.contains(j,"gettime")&&(e.hasGettime=!0),e._treatAsNonUniform=d,e._registerUsages=this.registerUsages,[e,g.join("")]},funcArgLengths:{above:2,below:2,equal:2,pow:2,sqr:1,sqrt:1,invsqrt:1,floor:1,ceil:1,abs:1,"if":3,sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,log:1,band:2,bor:2,bnot:1,rand:1,gettime:1,getosc:3,select:{min:2}},jsMathFuncs:["sin","cos","abs","tan","asin","acos","atan","log","pow","sqrt","floor","ceil"],glslFuncCode:{rand:["uniform vec2 __randStep;","vec2 __randSeed;","float rand(float max) {"," __randCur += __randStep;"," float val = fract(sin(dot(__randSeed.xy ,vec2(12.9898,78.233))) * 43758.5453);"," return (floor(val*max)+1);","}"].join("\n"),gettime:["uniform float __gettime0;","int gettime(int startTime) {"," int time = 0;"," if(startTime == 0) {"," time = __gettime0;"," }"," return time;","}"].join("\n")},_checkFunc:function(a){var b=this.funcArgLengths[a.funcName];if(void 0===b)throw Error("Unknown function "+a.funcName);if(_.isNumber(b)){if(a.args.length!=b)throw Error(a.funcName+" accepts "+b+" arguments")}else if(b.min&&a.args.length",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"below":return["(",this._generateGlsl(b.args[0],c),"<",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"equal":return["(",this._generateGlsl(b.args[0],c),"==",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"if":return["(",this._generateGlsl(b.args[0],c),"!=0.0?",this._generateGlsl(b.args[1],c),":",this._generateGlsl(b.args[2],c),")"].join("");case"select":var e=this._generateGlsl(b.args[0],c),f=function(a,b){return 1==a.length?d._generateGlsl(a[0],c):["(("+e+" === "+b+")?","("+d._generateGlsl(a[0],c)+"):","("+f(_.last(a,a.length-1),b+1)+"))"].join("")};return f(_.last(b.args,b.args.length-1),0);case"sqr":return"(pow(("+this._generateGlsl(b.args[0],c)+"), 2))";case"band":return"(float(("+this._generateGlsl(b.args[0],c)+")&&("+this._generateGlsl(b.args[1],c)+")))";case"bor":return"(float(("+this._generateGlsl(b.args[0],c)+")||("+this._generateGlsl(b.args[1],c)+")))";case"bnot":return"(float(!("+this._generateGlsl(b.args[0],c)+")))";case"invsqrt":return"(1/sqrt("+this._generateGlsl(b.args[0],c)+"))";case"atan2":return"(atan(("+this._generateGlsl(b.args[0],c)+"),("+this._generateGlsl(b.args[1],c)+"))";case"getosc":var g=_.every(b.args,function(b){return b instanceof a.AstPrimaryExpr});if(!g)throw new Error("Non Pre-Computable arguments for getosc in shader code, use variables or constants");var h="__PC_"+b.funcName+"_"+j,i=[b.funcName,h].concat(_.map(b.args,function(a){return a.value})),j=_.indexOf(c,i);return-1==j&&(c.push(i),j=c.length-1),h;default:var k=_.map(b.args,function(a){return d._generateGlsl(a,c)}).join(","),l=b.funcName;return _.contains(this.varArgFuncs,b.funcName)&&(l+=b.args.length),"("+l+"("+k+"))"}if(b instanceof a.AstAssignment)return this._generateGlsl(b.lhs,c)+"="+this._generateGlsl(b.expr,c);if(b instanceof a.AstProgram){var m=_.map(b.statements,function(a){return d._generateGlsl(a,c)});return m.join(";\n")+";"}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?a.glslFloatRepr(b.value):b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&("ID"===b.type||"REG"===b.type)?b.value:void 0},_generateJs:function(b){var c,d=this;if(b instanceof a.AstBinaryExpr)return"("+this._generateJs(b.leftOperand)+b.operator+this._generateJs(b.rightOperand)+")";if(b instanceof a.AstUnaryExpr)return"("+b.operator+this._generateJs(b.operand)+")";if(b instanceof a.AstFuncCall)switch(this._checkFunc(b),b.funcName){case"above":return["(",this._generateJs(b.args[0]),">",this._generateJs(b.args[1]),"?1:0)"].join("");case"below":return["(",this._generateJs(b.args[0]),"<",this._generateJs(b.args[1]),"?1:0)"].join("");case"equal":return["(",this._generateJs(b.args[0]),"==",this._generateJs(b.args[1]),"?1:0)"].join("");case"if":return["(",this._generateJs(b.args[0]),"!==0?",this._generateJs(b.args[1]),":",this._generateJs(b.args[2]),")"].join("");case"select":var e=["((function() {"];return e.push("switch("+this._generateJs(b.args[0])+") {"),_.each(_.last(b.args,b.args.length-1),function(a,b){e.push("case "+b+": return "+this._generateJs(a)+";")},this),e.push("default : throw new Error('Unknown selector value in select');"),e.push("}}).call(this))"),e.join("");case"sqr":return"(Math.pow(("+this._generateJs(b.args[0])+"),2))";case"band":return"((("+this._generateJs(b.args[0])+")&&("+this._generateJs(b.args[1])+"))?1:0)";case"bor":return"((("+this._generateJs(b.args[0])+")||("+this._generateJs(b.args[1])+"))?1:0)";case"bnot":return"((!("+this._generateJs(b.args[0])+"))?1:0)";case"invsqrt":return"(1/Math.sqrt("+this._generateJs(b.args[0])+"))";case"atan2":return"(Math.atan(("+this._generateJs(b.args[0])+")/("+this._generateJs(b.args[1])+")))";default:var f=_.map(b.args,function(a){return d._generateJs(a)}).join(",");return c=_.contains(this.jsMathFuncs,b.funcName)?"Math.":"this.","("+c+b.funcName+"("+f+"))"}if(b instanceof a.AstAssignment)return this._generateJs(b.lhs)+"="+this._generateJs(b.expr);if(b instanceof a.AstProgram){var g=_.map(b.statements,function(a){return d._generateJs(a)});return g.join(";\n")}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?b.value.toString():b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&"ID"===b.type?"this."+b.value:b instanceof a.AstPrimaryExpr&&"REG"===b.type?'this._registerBank["'+b.value+'"]':void 0},_getVars:function(b,c,d,e){var f=this;b instanceof a.AstBinaryExpr?(this._getVars(b.leftOperand,c,d,e),this._getVars(b.rightOperand,c,d,e)):b instanceof a.AstUnaryExpr?this._getVars(b.operand,c,d,e):b instanceof a.AstFuncCall?(d.push(b.funcName),_.each(b.args,function(a){f._getVars(a,c,d,e)})):b instanceof a.AstAssignment?(this._getVars(b.lhs,c,d,e),this._getVars(b.expr,c,d,e)):b instanceof a.AstProgram?_.each(b.statements,function(a){f._getVars(a,c,d,e)}):b instanceof a.AstPrimaryExpr&&"ID"===b.type?c.push(b.value):b instanceof a.AstPrimaryExpr&&"REG"===b.type&&e.push(b.value)},_translateConstants:function(a){switch(a){case"pi":return Math.PI;case"e":return Math.E;case"phi":return 1.6180339887;default:throw new Error("Unknown constant "+a)}}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]);var d=new a.ExprCodeGenerator(c.code,["b","w","h"]),e=d.generateCode(["init","onBeat","perFrame"],[],[]);this.code=e[0],this.inited=!1,b.super.constructor.call(this)}a.GlobalVar=a.defineClass(b,a.Component,{init:function(a,c,d){b.super.init.call(this,a,c,d),this.code.setup(c,this)},update:function(){var a=this.code;a.b=this.main.analyser.beat?1:0,this.inited||(a.init(),this.inited=!0),this.main.analyser.beat&&a.onBeat(),a.perFrame()}}),b.ui={disp:"Global Var",type:"GlobalVar",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"}}}}}}(Webvs),function(a){function b(c){if(c=_.defaults(c,{action:"SAVE",bufferId:1,blendMode:"REPLACE"}),this.blendMode=a.blendModes[c.blendMode],this.action=this.actions[c.action],!this.action)throw new Error("Unknown BufferSave action "+c.action);this.action==this.actions.SAVERESTORE?this._nextAction=this.actions.SAVE:this.action==this.actions.RESTORESAVE&&(this._nextAction=this.actions.RESTORE),this._bufferId="__BUFFERSAVE_"+c.bufferId,b.super.constructor.call(this)}a.BufferSave=a.defineClass(b,a.Component,{actions:{SAVE:1,RESTORE:2,SAVERESTORE:3,RESTORESAVE:4},init:function(c,d,e){if(b.super.init.call(this,c,d,e),!d.registerBank[this._bufferId]){var f=new a.FrameBufferManager(d.canvas.width,d.canvas.height,c,d.copier,1);d.registerBank[this._bufferId]=f}},update:function(){this.gl;var a,b=this.main.registerBank[this._bufferId];switch(this.action==this.actions.SAVERESTORE||this.action==this.RESTORESAVE?(a=this._nextAction,this._nextAction=this._nextAction==this.actions.SAVE?this.actions.RESTORE:this.actions.SAVE):a=this.action,a){case this.actions.SAVE:b.setRenderTarget(),this.main.copier.run(null,null,this.parent.fm.getCurrentTexture()),b.restoreRenderTarget();break;case this.actions.RESTORE:this.main.copier.run(this.parent.fm,this.blendMode,b.getCurrentTexture())}},destroy:function(){b.super.destroy.call(this),this.main.registerBank[this._bufferId].destroy()}}),b.ui={disp:"Buffer Save",type:"BufferSave",schema:{action:{type:"string",title:"Buffer save action","enum":["SAVE","RESTORE","SAVERESTORE","RESTORESAVE"]},bufferId:{type:"number",title:"Buffer Id","enum":[1,2,3,4,5,6,7,8]},blendMode:{type:"string",title:"Blend mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{speed:1,color:"#000000"}),this.color=a.parseColorNorm(c.color),this.frameCount=0,this.maxFrameCount=Math.floor(1/c.speed),this.program=new a.ClearScreenProgram(a.AVERAGE),b.super.constructor.call(this)}a.FadeOut=a.defineClass(b,a.Component,{componentName:"FadeOut",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.gl,this.frameCount++,this.frameCount==this.maxFrameCount&&(this.frameCount=0,this.program.run(this.parent.fm,null,this.color))},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),b.ui={type:"FadeOut",disp:"Fade Out",schema:{speed:{type:"number",title:"Speed",maximum:0,minimum:1,"default":1},color:{type:"string",title:"Fadeout color",format:"color","default":"#FFFFFF"}},form:[{key:"speed",type:"range",step:"0.05"},"color"]}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["kernel"]),c=_.defaults(c,{edgeMode:"EXTEND",bias:0});var d;if(c.kernel in b.kernels)d=b.kernels[c.kernel];else{if(!_.isArray(c.kernel)||1!==c.kernel.length%2)throw new Error("Invalid convolution kernel");d=c.kernel}var e=Math.floor(Math.sqrt(d.length));if(e*e!=d.length)throw new Error("Invalid convolution kernel");this.program=new a.ConvolutionProgram(d,e,c.edgeMode,c.scale,c.bias),b.super.constructor.call(this)}function c(b,d,e,f,g){var h="";switch(e){case"WRAP":h="pos = vec2(pos.x<0?pos.x+1.0:pos.x%1, pos.y<0?pos.y+1.0:pos.y%1);";break;case"EXTEND":h="pos = clamp(pos, vec2(0,0), vec2(1,1));";break;default:throw new Error("Invalid edge mode")}var i,j,k=[],l=Math.floor(d/2);for(i=0;d>i;i++)for(j=0;d>j;j++){var m=b[i*d+j];0!==m&&(k.push("pos = v_position + onePixel * vec2("+(i-l)+","+(j-l)+");"),k.push(h),k.push("colorSum += texture2D(u_srcTexture, pos) * "+a.glslFloatRepr(m)+";"))}_.isUndefined(f)&&(f=_.reduce(b,function(a,b){return a+b},0)),c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["void main() {"," vec2 onePixel = vec2(1.0, 1.0)/u_resolution;"," vec2 pos;"," vec4 colorSum = vec4(0,0,0,0);",k.join("\n")," setFragColor(vec4(((colorSum+"+a.glslFloatRepr(g)+") / "+a.glslFloatRepr(f)+").rgb, 1.0));","}"]})}a.Convolution=a.defineClass(b,a.Component,{componentName:"Convolution",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),b.kernels={normal:[0,0,0,0,1,0,0,0,0],gaussianBlur:[.045,.122,.045,.122,.332,.122,.045,.122,.045],unsharpen:[-1,-1,-1,-1,9,-1,-1,-1,-1],emboss:[-2,-1,0,-1,1,1,0,1,2],blur:[1,1,1,1,1,1,1,1,1]},a.ConvolutionProgram=a.defineClass(c,a.QuadBoxProgram)}(Webvs),function(a){function b(c){if(a.checkRequiredOptions(c,["maps"]),c=_.defaults(c,{key:"RED",output:"REPLACE",mapCycleMode:"SINGLE"}),this.maps=c.maps,this.currentMap=0,this.mapCycleMode=this.mapCycleModes[c.mapCycleMode],!this.mapCycleMode)throw new Error("Unknown mapCycleMode "+c.mapCycleMode);this.program=new a.ColorMapProgram(c.key,a.blendModes[c.output]),b.super.constructor.call(this)}function c(a,b){var d="";switch(a){case"RED":d="srcColor.r";break;case"GREEN":d="srcColor.g";break;case"BLUE":d="srcColor.b";break;case"(R+G+B)/2":d="mod((srcColor.r+srcColor.g+srcColor.b)/2.0, 1.0)";break;case"(R+G+B)/3":d="(srcColor.r+srcColor.g+srcColor.b)/3.0";break;case"MAX":d="max(srcColor.r, max(srcColor.g, srcColor.b))";break;default:throw new Error("Unknown colormap key function "+options.key)}c.super.constructor.call(this,{outputBlendMode:b,swapFrame:!0,fragmentShader:["uniform sampler2D u_colorMap;","void main() {"," vec4 srcColor = getSrcColor();"," setFragColor(texture2D(u_colorMap, vec2(("+d+"), 0)));","}"]})}a.ColorMap=a.defineClass(b,a.Component,{mapCycleModes:{SINGLE:1,ONBEATRANDOM:2,ONBEATSEQUENTIAL:3},init:function(a,c,d){b.super.init.call(this,a,c,d),this.colorMaps=_.map(this.maps,function(a){return this._buildColorMap(a)},this),this.currentMap=0,this.program.init(a)},update:function(){if(this.main.analyser.beat)switch(this.mapCycleMode){case this.mapCycleModes.ONBEATRANDOM:this.currentMap=Math.floor(Math.random()*this.colorMaps.length);break;case this.mapCycleModes.ONBEATSEQUENTIAL:this.currentMap=(this.currentMap+1)%this.colorMaps.length}this.program.run(this.parent.fm,null,this.colorMaps[this.currentMap])},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_buildColorMap:function(b){var c=this.gl;b=_.sortBy(b,function(a){return a.index});var d=_.map(b,function(a){return a.index});if(_.uniq(d).length!=d.length)throw new Error("map cannot have repeated indices");var e=_.first(b);0!==e.index&&b.splice(0,0,{color:e.color,index:0});var f=_.last(b);255!==f.index&&b.push({color:f.color,index:255}),b=_.map(b,function(b){var c=a.parseColor(b.color);return{color:c,index:b.index}});var g=new Uint8Array(1024),h=0,i=_.zip(_.first(b,b.length-1),_.last(b,b.length-1));_.each(i,function(a){var b=a[0],c=a[1],d=c.index-b.index,e=[(c.color[0]-b.color[0])/d,(c.color[1]-b.color[1])/d,(c.color[2]-b.color[2])/d];_.times(d,function(a){g[h++]=b.color[0]+e[0]*a,g[h++]=b.color[1]+e[1]*a,g[h++]=b.color[2]+e[2]*a,g[h++]=255})}),g[h++]=f.color[0],g[h++]=f.color[1],g[h++]=f.color[2],g[h++]=255;var j=c.createTexture();return c.bindTexture(c.TEXTURE_2D,j),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,256,1,0,c.RGBA,c.UNSIGNED_BYTE,g),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),j}}),a.ColorMapProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_colorMap","texture2D",a),c.super.draw.call(this)}}),b.ui={disp:"Color Map",type:"ColorMap",schema:{maps:{type:"array",items:{type:"array",title:"Map",items:{type:"object",properties:{color:{type:"string",title:"Color",format:"color","default":"#FFFFFF"},index:{type:"number",title:"Index",minimum:0,maximum:255}}}}},key:{type:"string",title:"Map key","enum":["RED","GREEN","BLUE","(R+G+B)/2","(R+G+B)/3","MAX"],"default":"RED"},mapCycleMode:{type:"string",title:"Map Cycle Mode","enum":["SINGLE","ONBEATRANDOM","ONBEATSEQUENTIAL"],"default":"SINGLE"},output:{type:"string",title:"Output blend mode","enum":_.keys(a.blendModes),"default":"REPLACE"}}}}(Webvs),function(a){function b(b){if(a.checkRequiredOptions(b,["mode","color","outColor"]),b=_.defaults(b,{mode:"BELOW",color:"#202020",outColor:"#202020",level:0}),this.mode=_.indexOf(this.modes,b.mode),-1==this.mode)throw new Error("ColorClip: invalid mode");this.color=a.parseColorNorm(b.color),this.outColor=a.parseColorNorm(b.outColor),this.level=b.level,this.program=new a.ColorClipProgram}function c(){c.super.constructor({swapFrame:!0,fragmentShader:["uniform int u_mode;","uniform vec3 u_color;","uniform vec3 u_outColor;","uniform float u_level;","void main() {"," vec4 inColor4 = getSrcColor();"," vec3 inColor = inColor4.rgb;"," bool clip = false;"," if(u_mode == 0) {"," clip = all(lessThanEqual(inColor, u_color));"," }"," if(u_mode == 1) {"," clip = all(greaterThanEqual(inColor, u_color));"," }"," if(u_mode == 2) {"," clip = (distance(inColor, u_color) <= u_level*0.5);"," }"," if(clip) {"," setFragColor(vec4(u_outColor, inColor4.a));"," } else {"," setFragColor(inColor4);"," }","}"]})}a.ColorClip=a.defineClass(b,a.Component,{modes:["BELOW","ABOVE","NEAR"],componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null,this.mode,this.color,this.outColor,this.level)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ColorClipProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a,b,d,e){this.setUniform("u_mode","1i",a),this.setUniform.apply(this,["u_color","3f"].concat(b)),this.setUniform.apply(this,["u_outColor","3f"].concat(d)),this.setUniform("u_level","1f",e),c.super.draw.call(this)}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]),c=_.defaults(c,{gridW:16,gridH:16,noGrid:!1,bFilter:!0,compat:!1,coord:"POLAR"});var d;if(!_.isObject(c.code))throw new Error("Invalid Dynamic movement code");d=c.code;var e=new a.ExprCodeGenerator(d,["x","y","r","d","b","w","h"]),f=e.generateCode(["init","onBeat","perFrame"],["perPixel"],["x","y","d","r"]);this.code=f[0],this.inited=!1,this.noGrid=c.noGrid,this.gridW=c.gridW,this.gridH=c.gridH,this.coordMode=c.coord,this.bFilter=c.bFilter,this.compat=c.compat,this.program=this.noGrid?new a.DMovProgramNG(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]):new a.DMovProgram(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]),b.super.constructor.call(this)}function c(a,b,d,e,f){var g=[f,this.glslFilter(b,d),"void main() {",e?"__randSeed = v_position;":""," x = v_position.x*2.0-1.0;"," y = -(v_position.y*2.0-1.0);",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," setFragColor(vec4(filter(vec2(x, -y)), 1));","}"];c.super.constructor.call(this,{fragmentShader:g,swapFrame:!0})}function d(a,b,c,e,f){var g=["attribute vec2 a_position;","varying vec2 v_newPoint;","uniform int u_coordMode;",f,"void main() {",e?"__randSeed = a_position;":""," x = a_position.x;"," y = -a_position.y;",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," v_newPoint = vec2(x,-y);"," setPosition(a_position);","}"],h=["varying vec2 v_newPoint;",this.glslFilter(b,c),"void main() {"," setFragColor(vec4(filter(v_newPoint), 1));","}"];d.super.constructor.call(this,{fragmentShader:h,vertexShader:g,swapFrame:!0})}a.DynamicMovement=a.defineClass(b,a.Component,{componentName:"DynamicMovement",init:function(a,c,d){if(b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,d),!this.noGrid){for(var e=2*(this.gridW/this.main.canvas.width),f=2*(this.gridH/this.main.canvas.height),g=Math.ceil(this.main.canvas.width/this.gridW),h=Math.ceil(this.main.canvas.height/this.gridH),i=new Float32Array(2*6*g*h),j=0,k=-1,l=-1,m=0;h>m;m++){for(var n=0;g>n;n++){var o=Math.min(k+e,1),p=Math.min(l+f,1);i[j++]=k,i[j++]=l,i[j++]=o,i[j++]=l,i[j++]=k,i[j++]=p,i[j++]=o,i[j++]=l,i[j++]=o,i[j++]=p,i[j++]=k,i[j++]=p,k+=e}k=-1,l+=f}this.gridVertices=i,this.gridVerticesSize=j/2}},update:function(){var a=this.code;this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat(),this.noGrid?this.program.run(this.parent.fm,null,this.code):this.program.run(this.parent.fm,null,this.code,this.gridVertices,this.gridVerticesSize)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}});var e={glslRectToPolar:function(a){return"POLAR"===a?["d = distance(vec2(x, y), vec2(0,0))/sqrt(2.0);","r = mod(atan(y, x)+PI*0.5, 2.0*PI);"].join("\n"):""},glslPolarToRect:function(a){return"POLAR"===a?["d = d*sqrt(2.0);","x = d*sin(r);","y = -d*cos(r);"].join("\n"):""},glslFilter:function(a,b){return a&&!b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 cornoff = fract(coord/texel);"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," vec3 pt = mix(tl, tr, cornoff.x);"," vec3 pb = mix(bl, br, cornoff.x);"," return mix(pt, pb, cornoff.y);","}"].join("\n"):a&&b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," float xp = floor(fract(coord.x/texel.x)*255.0);"," float yp = floor(fract(coord.y/texel.y)*255.0);"," #define g_blendtable(i, j) floor(((i)/255.0)*(j))"," float a1 = g_blendtable(255.0-xp, 255.0-yp);"," float a2 = g_blendtable(xp, 255.0-yp);"," float a3 = g_blendtable(255.0-xp, yp);"," float a4 = g_blendtable(xp, yp);"," float r = (floor(a1*tl.r) + floor(a2*tr.r) + floor(a3*bl.r) + floor(a4*br.r))/255.0;"," float g = (floor(a1*tl.g) + floor(a2*tr.g) + floor(a3*bl.g) + floor(a4*br.g))/255.0;"," float b = (floor(a1*tl.b) + floor(a2*tr.b) + floor(a3*bl.b) + floor(a4*br.b))/255.0;"," return vec3(r, g, b);","}"].join("\n"):["vec3 filter(vec2 point) {"," return getSrcColorAtPos((point+1.0)/2.0).rgb;","}"].join("\n")}};a.DMovProgramNG=a.defineClass(c,a.QuadBoxProgram,e,{draw:function(a){a.bindUniforms(this),c.super.draw.call(this)}}),a.DMovProgram=a.defineClass(d,a.ShaderProgram,e,{draw:function(a,b,c){a.bindUniforms(this),this.setVertexAttribArray("a_position",b,2,this.gl.FLOAT,!1,0,0),this.gl.drawArrays(this.gl.TRIANGLES,0,c)}}),b.ui={type:"DynamicMovement",disp:"Dynamic Movement",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPixel:{type:"string",title:"Per Point"}}},gridW:{type:"number",title:"Grid Width","default":16},gridH:{type:"number",title:"Grid Height","default":16},coord:{type:"string",title:"Coordinate System","enum":["POLAR","RECT"],"default":"POLAR"}},form:[{key:"code.init",type:"textarea"},{key:"code.onBeat",type:"textarea"},{key:"code.perFrame",type:"textarea"},{key:"code.perPixel",type:"textarea"},"gridW","gridH","coord"]}}(Webvs),function(a){function b(a){if(a=_.defaults(a,{channel:"RGB",onBeatRandom:!1}),this.channel=d.indexOf(a.channel),-1==this.channel)throw new Error("Invalid Channel");this.onBeatRandom=a.onBeatRandom,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["uniform int u_channel;","void main() {"," vec3 color = getSrcColor().rgb;",_.flatMap(d,function(a,b){return["if(u_channel == "+b+") {"," setFragColor(vec4(color."+a.toLowerCase()+",1));","}"]}).join("\n"),"}"]})}var d=["RGB","RBG","BRG","BGR","GBR","GRB"];a.ChannelShift=a.defineClass(b,a.Component,{componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.onBeatRandom&&this.main.analyser.beat&&(this.channel=Math.floor(Math.random()*d.length)),this.program.run(this.parent.fm,null,this.channel)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ChannelShiftProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_channel","1i",a),c.super.draw.call(this)}}),b.ui={disp:"Channel Shift",type:"ChannelShift",schema:{channel:{type:"string",title:"Channel","enum":d},onBeatRandom:{type:"boolean",title:"On beat random"}}}}(Webvs),function(a){function b(d){a.checkRequiredOptions(d,["code"]),d=_.defaults(d,{source:"SPECTRUM",drawMode:"LINES",colors:["#ffffff"]});var e;if(!_.isObject(d.code))throw new Error("Invalid superscope");e=d.code;var f=new a.ExprCodeGenerator(e,["n","v","i","x","y","b","w","h","red","green","blue","cid"]),g=f.generateCode(["init","onBeat","perFrame","perPoint"],[],[]);this.code=g[0],this.code.n=100,this.spectrum="SPECTRUM"==d.source,this.dots="DOTS"==d.drawMode,this.colors=_.map(d.colors,a.parseColorNorm),this.currentColor=this.colors[0],this.maxStep=100,this.step=this.maxStep,this.colorId=0,this.colorStep=[0,0,0],this.thickness=d.thickness?d.thickness:1,this.inited=!1,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_position;","attribute vec3 a_color;","varying vec3 v_color;","uniform float u_pointSize;","void main() {"," gl_PointSize = u_pointSize;"," setPosition(clamp(a_position, vec2(-1,-1), vec2(1,1)));"," v_color = a_color;","}"],fragmentShader:["varying vec3 v_color;","void main() {"," setFragColor(vec4(v_color, 1));","}"]})}a.SuperScope=a.defineClass(b,a.Component,{componentName:"SuperScope",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,this)},update:function(){this.gl;var a=this.code;this._stepColor(),a.red=this.currentColor[0],a.green=this.currentColor[1],a.blue=this.currentColor[2],this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat();for(var c=Math.floor(a.n),d=this.spectrum?this.main.analyser.getSpectrum():this.main.analyser.getWaveform(),e=d.length/c,f=0,g=0,h=new Float32Array(2*(this.dots?c:2*c-2)),i=new Float32Array(3*(this.dots?c:2*c-2)),j=0;c>j;j++){for(var k=0,l=0,m=Math.floor(j*e);(j+1)*e>m;m++,l++)k+=d[m];k/=l;var n=j/(c-1);a.i=n,a.v=k,a.perPoint(),h[f++]=a.x,h[f++]=-1*a.y,0===j||j==c-1||this.dots||(h[f++]=a.x,h[f++]=-1*a.y),this.dots?(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue):0!==j&&(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue,i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue)}this.program.run(this.parent.fm,null,h,i,this.dots,this.thickness)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_stepColor:function(){var a;if(this.colors.length>1)if(this.step==this.maxStep){var b=this.colors[this.colorId];this.colorId=(this.colorId+1)%this.colors.length;var c=this.colors[this.colorId];for(a=0;3>a;a++)this.colorStep[a]=(c[a]-b[a])/this.maxStep;this.step=0,this.currentColor=b}else{for(a=0;3>a;a++)this.currentColor[a]+=this.colorStep[a];this.step++}}}),a.SuperScopeShader=a.defineClass(c,a.ShaderProgram,{draw:function(a,b,c,d){var e=this.gl;this.setUniform("u_pointSize","1f",d),this.setVertexAttribArray("a_position",a,2,e.FLOAT,!1,0,0),this.setVertexAttribArray("a_color",b,3,e.FLOAT,!1,0,0);var f;c||(f=e.getParameter(e.LINE_WIDTH),e.lineWidth(d)),e.drawArrays(c?e.POINTS:e.LINES,0,a.length/2),c||e.lineWidth(f)}}),b.ui={disp:"SuperScope",type:"SuperScope",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPoint:{type:"string",title:"Per Point"}}},source:{type:"string",title:"Source","default":"WAVEFORM","enum":["WAVEFORM","SPECTRUM"]},drawMode:{type:"string",title:"Draw Mode","default":"LINES","enum":["DOTS","LINES"]},colors:{type:"array",title:"Cycle Colors",items:{type:"string",format:"color","default":"#FFFFFF"}}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{n:0,color:"#000000",blendMode:"REPLACE"}),this.n=c.n,this.color=a.parseColorNorm(c.color),this.outputBlendMode=a.blendModes[c.blendMode],this.prevBeat=!1,this.beatCount=0,this.program=new a.ClearScreenProgram(this.outputBlendMode),b.super.constructor.call(this)}a.ClearScreen=a.defineClass(b,a.Component,{componentName:"ClearScreen",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){var a=!1;0===this.n?a=!0:(this.main.analyser.beat&&!this.prevBeat&&(this.beatCount++,this.beatCount==this.n&&(a=!0,this.beatCount=0)),this.prevBeat=this.main.analyser.beat),a&&this.program.run(this.parent.fm,null,this.color)},destroy:function(){this.program.cleanup()}}),b.ui={type:"ClearScreen",disp:"Clear Screen",schema:{n:{type:"number",title:"Clear on beat (0 = always clear)","default":0},color:{type:"string",title:"Clear color",format:"color","default":"#000000"},blendMode:{type:"string",title:"Blend Mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["src","x","y"]),this.x=c.x,this.y=c.y,this.src=c.src,this.program=new a.PictureProgram,b.super.constructor.call(this,c)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_texVertex;","uniform vec2 u_pos;","uniform vec2 u_texRes;","varying vec2 v_texCoord;","void main() {"," v_texCoord = a_texVertex;"," setPosition(a_texVertex*(u_texRes/u_resolution)*vec2(2,-2)+u_pos);","}"],fragmentShader:["uniform sampler2D u_image;","varying vec2 v_texCoord;","void main() {"," setFragColor(texture2D(u_image, v_texCoord));","}"]}) }a.Picture=a.defineClass(b,a.Component,{init:function(c,d,e){b.super.init.call(this,c,d,e),this.program.init(c);var f=this,g=new Image;g.src=this.src;var h=new a.Promise;return g.onload=function(){f.width=g.width,f.height=g.height,f.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,f.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,g),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),h.resolve()},h},update:function(){this.program.run(this.parent.fm,null,this.x,this.y,this.texture,this.width,this.height)},destroy:function(){this.program.cleanup(),this.gl.deleteTexture(this.texture)}}),a.PictureProgram=a.defineClass(c,a.ShaderProgram,{draw:function(a,b,c,d,e){this.setUniform("u_pos","2f",a,-b),this.setUniform("u_texRes","2f",d,e),this.setUniform("u_image","texture2D",c),this.setVertexAttribArray("a_texVertex",new Float32Array([0,0,0,1,1,1,0,0,1,1,1,0])),this.gl.drawArrays(this.gl.TRIANGLES,0,6)}})}(Webvs); \ No newline at end of file diff --git a/dist/webvs.min.js b/dist/webvs.min.js index e3ecc07..66e6106 100644 --- a/dist/webvs.min.js +++ b/dist/webvs.min.js @@ -1,3 +1,3 @@ -!function(a){var b={};a.Webvs=b,b.defineClass=function(a,b){return a.prototype=Object.create(b.prototype),a.prototype.constructor=a,a.super=b.prototype,_.chain(arguments).drop(2).each(function(b){_.extend(a.prototype,b)}),a},b.noop=function(){},b.checkRequiredOptions=function(a,b){for(var c in b){var d=b[c];if(!(d in a))throw new Error("Required option "+d+"not found")}},b.glslFloatRepr=function(a){return a+(0===a%1?".0":"")},b.parseColor=function(a){if(_.isArray(a)&&3==a.length)return a;if(_.isString(a)){var b;if(a=a.toLowerCase(),b=a.match(/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/))return _.chain(b).last(3).map(function(a){return parseInt(a,16)}).value();if(b=a.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/))return _.chain(b).last(3).map(function(a){return Math.min(parseInt(a,10),255)}).value()}throw new Error("Invalid Color Format")},b.parseColorNorm=function(a){return _.map(b.parseColor(a),function(a){return a/255})},b.logShaderError=function(a,b){var c=a.split("\n"),d=c.length.toString().length,e=b.match(/(\d+):(\d+)/);e&&(e=[parseInt(e[1],10),parseInt(e[2],10)]);var f=_.map(c,function(a,c){var f,g=c+1+"";for(f=0;f0&&this._frameCounter--,0!==this._frameCounter)){if(this.fm.setRenderTarget(),(this.clearFrame||this.first)&&(a.clearColor(0,0,0,1),a.clear(a.COLOR_BUFFER_BIT),this.first=!1),-1!==this.input){var c=this.parent.fm.getCurrentTexture();this.main.copier.run(this.fm,this.input,c)}for(var d=this.components,e=0;ee;e++){var f=b.charAt(e);"\n"===f?(a.seenCR||a.line++,a.column=1,a.seenCR=!1):"\r"===f||"\u2028"===f||"\u2029"===f?(a.line++,a.column=1,a.seenCR=!0):(a.column++,a.seenCR=!1)}a.offset+=c}function f(a){F.offsetH.offset&&(H=d(F),I=[]),I.push(a))}function g(){var a="program@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,i,j,k,l,m,n,o,p,q;if(o=d(F),p=d(F),g=h(),null!==g)if(i=x(),null!==i){for(j=[],q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==k;)j.push(k),q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==j?(59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),k=null!==k?k:"",null!==k?g=[g,i,j,k]:(g=null,F=d(p))):(g=null,F=d(p))}else g=null,F=d(p);else g=null,F=d(p);return null!==g&&(g=function(a,b,c,d){var e=[d[0]];return e=e.concat(_.map(d[2],function(a){return a[2]})),new Webvs.AstProgram(e)}(o.offset,o.line,o.column,g)),null===g&&(F=d(o)),J[a]={nextPos:d(F),result:g},g}function h(){var a="statement@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n;return l=d(F),n=d(F),g=s(),null!==g?(h=x(),null!==h?(61===b.charCodeAt(F.offset)?(i="=",e(F,1)):(i=null,0===G&&f('"="')),null!==i?(j=x(),null!==j?(k=m(),null!==k?g=[g,h,i,j,k]:(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d,e){return new Webvs.AstAssignment(d,e)}(l.offset,l.line,l.column,g[0],g[4])),null===g&&(F=d(l)),null===g&&(g=m()),J[a]={nextPos:d(F),result:g},g}function i(){var a="unary_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function j(){var a="additive_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function k(){var a="multiplicative_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 42===b.charCodeAt(F.offset)?(g="*",e(F,1)):(g=null,0===G&&f('"*"')),null===g&&(47===b.charCodeAt(F.offset)?(g="/",e(F,1)):(g=null,0===G&&f('"/"')),null===g&&(37===b.charCodeAt(F.offset)?(g="%",e(F,1)):(g=null,0===G&&f('"%"')))),J[a]={nextPos:d(F),result:g},g}function l(){var a="boolean_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 38===b.charCodeAt(F.offset)?(g="&",e(F,1)):(g=null,0===G&&f('"&"')),null===g&&(124===b.charCodeAt(F.offset)?(g="|",e(F,1)):(g=null,0===G&&f('"|"'))),J[a]={nextPos:d(F),result:g},g}function m(){var a="boolean_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,k,m;if(j=d(F),k=d(F),c=n(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(k))}else c=null,F=d(k);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function n(){var a="additive_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,k,l,m;if(k=d(F),l=d(F),c=o(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(k.offset,k.line,k.column,c[0],c[1])),null===c&&(F=d(k)),J[a]={nextPos:d(F),result:c},c}function o(){var a="multiplicative_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,l,m;if(j=d(F),l=d(F),c=p(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function p(){var a="unary@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h;return g=d(F),h=d(F),c=i(),null!==c?(e=x(),null!==e?(f=q(),null!==f?c=[c,e,f]:(c=null,F=d(h))):(c=null,F=d(h))):(c=null,F=d(h)),null!==c&&(c=function(a,b,c,d,e){return new Webvs.AstUnaryExpr(d,e)}(g.offset,g.line,g.column,c[0],c[2])),null===c&&(F=d(g)),null===c&&(c=q()),J[a]={nextPos:d(F),result:c},c}function q(){var a="func_call@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n,o,p,q,s,t;if(p=d(F),q=d(F),s=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(s))}else g=null,F=d(s);if(null!==g)if(h=x(),null!==h)if(40===b.charCodeAt(F.offset)?(i="(",e(F,1)):(i=null,0===G&&f('"("')),null!==i){for(s=d(F),j=[],t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==k;)j.push(k),t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==j?(k=x(),null!==k?(l=m(),null!==l?j=[j,k,l]:(j=null,F=d(s))):(j=null,F=d(s))):(j=null,F=d(s)),j=null!==j?j:"",null!==j?(k=x(),null!==k?(41===b.charCodeAt(F.offset)?(l=")",e(F,1)):(l=null,0===G&&f('")"')),null!==l?g=[g,h,i,j,k,l]:(g=null,F=d(q))):(g=null,F=d(q))):(g=null,F=d(q))}else g=null,F=d(q);else g=null,F=d(q);else g=null,F=d(q);return null!==g&&(g=function(a,b,c,d,e){var f=[];return _.each(e[0],function(a){f.push(a[1])}),f.push(e[2]),new Webvs.AstFuncCall(D(d),f)}(p.offset,p.line,p.column,g[0],g[3])),null===g&&(F=d(p)),null===g&&(g=r()),J[a]={nextPos:d(F),result:g},g}function r(){var a="primary_expr@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;return g=w(),null===g&&(g=u(),null===g&&(g=v(),null===g&&(g=t(),null===g&&(j=d(F),k=d(F),40===b.charCodeAt(F.offset)?(g="(",e(F,1)):(g=null,0===G&&f('"("')),null!==g?(h=m(),null!==h?(41===b.charCodeAt(F.offset)?(i=")",e(F,1)):(i=null,0===G&&f('")"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))):(g=null,F=d(k)),null!==g&&(g=function(a,b,c,d){return d}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)))))),J[a]={nextPos:d(F),result:g},g}function s(){var a="assignable@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c;return c=v(),null===c&&(c=t()),J[a]={nextPos:d(F),result:c},c}function t(){var a="identifier@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"ID")}(j.offset,j.line,j.column,g)),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function u(){var a="constant@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),36===b.charCodeAt(F.offset)?(g="$",e(F,1)):(g=null,0===G&&f('"$"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"CONST")}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function v(){var a="register@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(l=d(F),m=d(F),64===b.charCodeAt(F.offset)?(g="@",e(F,1)):(g=null,0===G&&f('"@"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(m))}else g=null,F=d(m);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_AT_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g[1])),null===g&&(F=d(l)),null===g&&(l=d(F),m=d(F),/^[rR]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[rR]")),null!==g?(/^[eE]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[eE]")),null!==h?(/^[gG]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[gG]")),null!==i?(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j?(/^[0-9]/.test(b.charAt(F.offset))?(k=b.charAt(F.offset),e(F,1)):(k=null,0===G&&f("[0-9]")),null!==k?g=[g,h,i,j,k]:(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g)),null===g&&(F=d(l))),J[a]={nextPos:d(F),result:g},g}function w(){var a="value@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m,n,o;for(m=d(F),n=d(F),g=[],/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));if(null!==g)if(46===b.charCodeAt(F.offset)?(h=".",e(F,1)):(h=null,0===G&&f('"."')),null!==h){if(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j)for(i=[];null!==j;)i.push(j),/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]"));else i=null;if(null!==i){if(o=d(F),/^[Ee]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[Ee]")),null!==j){if(/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]")),null!==l)for(k=[];null!==l;)k.push(l),/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]"));else k=null;null!==k?j=[j,k]:(j=null,F=d(o))}else j=null,F=d(o);j=null!==j?j:"",null!==j?g=[g,h,i,j]:(g=null,F=d(n))}else g=null,F=d(n)}else g=null,F=d(n);else g=null,F=d(n);if(null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseFloat(D(d)),"VALUE")}(m.offset,m.line,m.column,g)),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]"));else g=null;if(null!==g?(/^[hH]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[hH]")),null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),16),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));else g=null;null!==g?(/^[dD]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[dD]")),h=null!==h?h:"",null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),10),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m))}}return J[a]={nextPos:d(F),result:g},g}function x(){var a="__@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e;for(c=[],e=y(),null===e&&(e=z(),null===e&&(e=A()));null!==e;)c.push(e),e=y(),null===e&&(e=z(),null===e&&(e=A()));return J[a]={nextPos:d(F),result:c},c}function y(){var a="whiteSpace@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\t\x0B\f \xA0\uFEFF]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\t\\x0B\\f \\xA0\\uFEFF]")),J[a]={nextPos:d(F),result:g},g}function z(){var a="lineEnd@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\n\r\u2028\u2029]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\n\\r\\u2028\\u2029]")),J[a]={nextPos:d(F),result:g},g}function A(){var a="comment@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(k=d(F),"/*"===b.substr(F.offset,2)?(g="/*",e(F,2)):(g=null,0===G&&f('"/*"')),null!==g){for(h=[],l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?("*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))}else g=null,F=d(k);if(null===g)if(k=d(F),"//"===b.substr(F.offset,2)?(g="//",e(F,2)):(g=null,0===G&&f('"//"')),null!==g){for(h=[],l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return J[a]={nextPos:d(F),result:g},g}function B(a){a.sort();for(var b=null,c=[],d=0;dH.offset?F:H;throw new this.SyntaxError(B(I),M,L,N.line,N.column)}return K},toSource:function(){return this._source}};return b.SyntaxError=function(b,c,d,e,f){function g(b,c){var d,e;switch(b.length){case 0:d="end of input";break;case 1:d=b[0];break;default:d=b.slice(0,b.length-1).join(", ")+" or "+b[b.length-1]}return e=c?a(c):"end of input","Expected "+d+" but "+e+" found."}this.name="SyntaxError",this.expected=b,this.found=c,this.message=g(b,c),this.offset=d,this.line=e,this.column=f},b.SyntaxError.prototype=Error.prototype,b}(),function(a){function b(){}a.CodeInstance=a.defineClass(b,Object,{rand:function(a){return Math.floor(Math.random()*a)+1},gettime:function(a){switch(a){case 0:var b=(new Date).getTime();return(b-this._bootTime)/1e3;default:throw new Error("Invalid startTime mode for gettime call")}},getosc:function(a,b){for(var c=this._analyser.getWaveform(),d=Math.floor((a-b/2)*c.length),e=Math.floor((a+b/2)*c.length),f=0,g=d;e>=g;g++)f+=c[g];return f/(e-d+1)},bindUniforms:function(a){var b=this,c=_.difference(_.keys(this),this._treatAsNonUniform);if(_.each(c,function(c){var d=b[c];"number"==typeof d&&a.setUniform(c,"1f",d)}),_.each(this._registerUsages,function(b){a.setUniform(b,"1f",this._registerBank[b])}),this.hasRandom){var d=[Math.random()/100,Math.random()/100];a.setUniform("__randStep","2fv",d)}if(this.hasGettime){var e=((new Date).getTime()-this._bootTime)/1e3;a.setUniform("__gettime0","1f",e)}_.each(this._preCompute,function(b){var c=_.map(_.last(b,b.length-2),function(a){return _.isString(a)?"__REG"==a.substring(0,5)?this._registerBank[a]:this[a]:a}),d=this[b[0]].apply(this,c);a.setUniform(b[1],"1f",d)})},setup:function(a,b){this._registerBank=a.registerBank,this._bootTime=a.bootTime,this._analyser=a.analyser,this.w=a.canvas.width,this.h=a.canvas.height,this.cid=b.cloneId,_.each(this._registerUsages,function(b){_.has(a.registerBank,b)||(a.registerBank[b]=0)})}})}(Webvs),function(a){function b(a,b){this.codeSrc=a,this.externalVars=b?b:[],this._parseSrc()}a.ExprCodeGenerator=a.defineClass(b,Object,{_parseSrc:function(){var b={},c=[],d={},e=[];for(var f in this.codeSrc)try{var g=this.codeSrc[f];_.isArray(g)&&(g=g.join("\n")),b[f]=a.PegExprParser.parse(g);var h=[];this._getVars(b[f],c,h,e),d[f]=h}catch(i){throw new Error("Error parsing "+f+"("+i.line+":"+i.column+")"+" : "+i)}this.codeAst=b,this.funcUsages=d,this.instanceVars=_.uniq(this.externalVars.concat(c)),this.registerUsages=_.uniq(e)},generateCode:function(b,c,d){var e=new a.CodeInstance,f=this,g=[];_.each(this.instanceVars,function(a){e[a]=0;var b="";_.contains(d,a)||(b="uniform "),g.push(b+"float "+a+";")});var h=_.intersection(_.keys(this.codeAst),b),i=_.difference(b,h);_.each(h,function(a){var b=f.codeAst[a],c=f._generateJs(b);e[a]=new Function(c)}),_.each(i,function(b){e[b]=a.noop});var j=_.intersection(_.keys(this.codeAst),c),k=_.difference(c,j),l=_.uniq(_.flatMap(j,function(a){return f.funcUsages[a]}));_.each(l,function(a){var b=f.glslFuncCode[a];b&&g.push(b)});var m=[],n=[];return _.each(j,function(a){var b=f.codeAst[a],c=f._generateGlsl(b,m);n.push("void "+a+"() {"),n.push(c),n.push("}")}),g=g.concat(_.map(m,function(a){return"uniform float "+a[1]+";"})),g=g.concat(n),e._preCompute=m,_.each(k,function(a){g.push("void "+a+"() {}")}),_.contains(j,"rand")&&(e.hasRandom=!0),_.contains(j,"gettime")&&(e.hasGettime=!0),e._treatAsNonUniform=d,e._registerUsages=this.registerUsages,[e,g.join("")]},funcArgLengths:{above:2,below:2,equal:2,pow:2,sqr:1,sqrt:1,invsqrt:1,floor:1,ceil:1,abs:1,"if":3,sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,log:1,band:2,bor:2,bnot:1,rand:1,gettime:1,getosc:3,select:{min:2}},jsMathFuncs:["sin","cos","abs","tan","asin","acos","atan","log","pow","sqrt","floor","ceil"],glslFuncCode:{rand:["uniform vec2 __randStep;","vec2 __randSeed;","float rand(float max) {"," __randCur += __randStep;"," float val = fract(sin(dot(__randSeed.xy ,vec2(12.9898,78.233))) * 43758.5453);"," return (floor(val*max)+1);","}"].join("\n"),gettime:["uniform float __gettime0;","int gettime(int startTime) {"," int time = 0;"," if(startTime == 0) {"," time = __gettime0;"," }"," return time;","}"].join("\n")},_checkFunc:function(a){var b=this.funcArgLengths[a.funcName];if(void 0===b)throw Error("Unknown function "+a.funcName);if(_.isNumber(b)){if(a.args.length!=b)throw Error(a.funcName+" accepts "+b+" arguments")}else if(b.min&&a.args.length",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"below":return["(",this._generateGlsl(b.args[0],c),"<",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"equal":return["(",this._generateGlsl(b.args[0],c),"==",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"if":return["(",this._generateGlsl(b.args[0],c),"!=0.0?",this._generateGlsl(b.args[1],c),":",this._generateGlsl(b.args[2],c),")"].join("");case"select":var e=this._generateGlsl(b.args[0],c),f=function(a,b){return 1==a.length?d._generateGlsl(a[0],c):["(("+e+" === "+b+")?","("+d._generateGlsl(a[0],c)+"):","("+f(_.last(a,a.length-1),b+1)+"))"].join("")};return f(_.last(b.args,b.args.length-1),0);case"sqr":return"(pow(("+this._generateGlsl(b.args[0],c)+"), 2))";case"band":return"(float(("+this._generateGlsl(b.args[0],c)+")&&("+this._generateGlsl(b.args[1],c)+")))";case"bor":return"(float(("+this._generateGlsl(b.args[0],c)+")||("+this._generateGlsl(b.args[1],c)+")))";case"bnot":return"(float(!("+this._generateGlsl(b.args[0],c)+")))";case"invsqrt":return"(1/sqrt("+this._generateGlsl(b.args[0],c)+"))";case"atan2":return"(atan(("+this._generateGlsl(b.args[0],c)+"),("+this._generateGlsl(b.args[1],c)+"))";case"getosc":var g=_.every(b.args,function(b){return b instanceof a.AstPrimaryExpr});if(!g)throw new Error("Non Pre-Computable arguments for getosc in shader code, use variables or constants");var h="__PC_"+b.funcName+"_"+j,i=[b.funcName,h].concat(_.map(b.args,function(a){return a.value})),j=_.indexOf(c,i);return-1==j&&(c.push(i),j=c.length-1),h;default:var k=_.map(b.args,function(a){return d._generateGlsl(a,c)}).join(","),l=b.funcName;return _.contains(this.varArgFuncs,b.funcName)&&(l+=b.args.length),"("+l+"("+k+"))"}if(b instanceof a.AstAssignment)return this._generateGlsl(b.lhs,c)+"="+this._generateGlsl(b.expr,c);if(b instanceof a.AstProgram){var m=_.map(b.statements,function(a){return d._generateGlsl(a,c)});return m.join(";\n")+";"}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?a.glslFloatRepr(b.value):b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&("ID"===b.type||"REG"===b.type)?b.value:void 0},_generateJs:function(b){var c,d=this;if(b instanceof a.AstBinaryExpr)return"("+this._generateJs(b.leftOperand)+b.operator+this._generateJs(b.rightOperand)+")";if(b instanceof a.AstUnaryExpr)return"("+b.operator+this._generateJs(b.operand)+")";if(b instanceof a.AstFuncCall)switch(this._checkFunc(b),b.funcName){case"above":return["(",this._generateJs(b.args[0]),">",this._generateJs(b.args[1]),"?1:0)"].join("");case"below":return["(",this._generateJs(b.args[0]),"<",this._generateJs(b.args[1]),"?1:0)"].join("");case"equal":return["(",this._generateJs(b.args[0]),"==",this._generateJs(b.args[1]),"?1:0)"].join("");case"if":return["(",this._generateJs(b.args[0]),"!==0?",this._generateJs(b.args[1]),":",this._generateJs(b.args[2]),")"].join("");case"select":var e=["((function() {"];return e.push("switch("+this._generateJs(b.args[0])+") {"),_.each(_.last(b.args,b.args.length-1),function(a,b){e.push("case "+b+": return "+this._generateJs(a)+";")},this),e.push("default : throw new Error('Unknown selector value in select');"),e.push("}}).call(this))"),e.join("");case"sqr":return"(Math.pow(("+this._generateJs(b.args[0])+"),2))";case"band":return"((("+this._generateJs(b.args[0])+")&&("+this._generateJs(b.args[1])+"))?1:0)";case"bor":return"((("+this._generateJs(b.args[0])+")||("+this._generateJs(b.args[1])+"))?1:0)";case"bnot":return"((!("+this._generateJs(b.args[0])+"))?1:0)";case"invsqrt":return"(1/Math.sqrt("+this._generateJs(b.args[0])+"))";case"atan2":return"(Math.atan(("+this._generateJs(b.args[0])+")/("+this._generateJs(b.args[1])+")))";default:var f=_.map(b.args,function(a){return d._generateJs(a)}).join(",");return c=_.contains(this.jsMathFuncs,b.funcName)?"Math.":"this.","("+c+b.funcName+"("+f+"))"}if(b instanceof a.AstAssignment)return this._generateJs(b.lhs)+"="+this._generateJs(b.expr);if(b instanceof a.AstProgram){var g=_.map(b.statements,function(a){return d._generateJs(a)});return g.join(";\n")}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?b.value.toString():b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&"ID"===b.type?"this."+b.value:b instanceof a.AstPrimaryExpr&&"REG"===b.type?'this._registerBank["'+b.value+'"]':void 0},_getVars:function(b,c,d,e){var f=this;b instanceof a.AstBinaryExpr?(this._getVars(b.leftOperand,c,d,e),this._getVars(b.rightOperand,c,d,e)):b instanceof a.AstUnaryExpr?this._getVars(b.operand,c,d,e):b instanceof a.AstFuncCall?(d.push(b.funcName),_.each(b.args,function(a){f._getVars(a,c,d,e)})):b instanceof a.AstAssignment?(this._getVars(b.lhs,c,d,e),this._getVars(b.expr,c,d,e)):b instanceof a.AstProgram?_.each(b.statements,function(a){f._getVars(a,c,d,e)}):b instanceof a.AstPrimaryExpr&&"ID"===b.type?c.push(b.value):b instanceof a.AstPrimaryExpr&&"REG"===b.type&&e.push(b.value)},_translateConstants:function(a){switch(a){case"pi":return Math.PI;case"e":return Math.E;case"phi":return 1.6180339887;default:throw new Error("Unknown constant "+a)}}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]);var d=new a.ExprCodeGenerator(c.code,["b","w","h"]),e=d.generateCode(["init","onBeat","perFrame"],[],[]);this.code=e[0],this.inited=!1,b.super.constructor.call(this)}a.GlobalVar=a.defineClass(b,a.Component,{init:function(a,c,d){b.super.init.call(this,a,c,d),this.code.setup(c,this)},update:function(){var a=this.code;a.b=this.main.analyser.beat?1:0,this.inited||(a.init(),this.inited=!0),this.main.analyser.beat&&a.onBeat(),a.perFrame()}}),b.ui={disp:"Global Var",type:"GlobalVar",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"}}}}}}(Webvs),function(a){function b(c){if(c=_.defaults(c,{action:"SAVE",bufferId:1,blendMode:"REPLACE"}),this.blendMode=a.blendModes[c.blendMode],this.action=this.actions[c.action],!this.action)throw new Error("Unknown BufferSave action "+c.action);this.action==this.actions.SAVERESTORE?this._nextAction=this.actions.SAVE:this.action==this.actions.RESTORESAVE&&(this._nextAction=this.actions.RESTORE),this._bufferId="__BUFFERSAVE_"+c.bufferId,b.super.constructor.call(this)}a.BufferSave=a.defineClass(b,a.Component,{actions:{SAVE:1,RESTORE:2,SAVERESTORE:3,RESTORESAVE:4},init:function(c,d,e){if(b.super.init.call(this,c,d,e),!d.registerBank[this._bufferId]){var f=new a.FrameBufferManager(d.canvas.width,d.canvas.height,c,d.copier,1);d.registerBank[this._bufferId]=f}},update:function(){this.gl;var a,b=this.main.registerBank[this._bufferId];switch(this.action==this.actions.SAVERESTORE||this.action==this.RESTORESAVE?(a=this._nextAction,this._nextAction=this._nextAction==this.actions.SAVE?this.actions.RESTORE:this.actions.SAVE):a=this.action,a){case this.actions.SAVE:b.setRenderTarget(),this.main.copier.run(null,null,this.parent.fm.getCurrentTexture()),b.restoreRenderTarget();break;case this.actions.RESTORE:this.main.copier.run(this.parent.fm,this.blendMode,b.getCurrentTexture())}},destroy:function(){b.super.destroy.call(this),this.main.registerBank[this._bufferId].destroy()}}),b.ui={disp:"Buffer Save",type:"BufferSave",schema:{action:{type:"string",title:"Buffer save action","enum":["SAVE","RESTORE","SAVERESTORE","RESTORESAVE"]},bufferId:{type:"number",title:"Buffer Id","enum":[1,2,3,4,5,6,7,8]},blendMode:{type:"string",title:"Blend mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{speed:1,color:"#000000"}),this.color=a.parseColorNorm(c.color),this.frameCount=0,this.maxFrameCount=Math.floor(1/c.speed),this.program=new a.ClearScreenProgram(a.AVERAGE),b.super.constructor.call(this)}a.FadeOut=a.defineClass(b,a.Component,{componentName:"FadeOut",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.gl,this.frameCount++,this.frameCount==this.maxFrameCount&&(this.frameCount=0,this.program.run(this.parent.fm,null,this.color))},destroy:function(){b.super.destroyComponent.call(this),this.program.cleanup()}}),b.ui={type:"FadeOut",disp:"Fade Out",schema:{speed:{type:"number",title:"Speed",maximum:0,minimum:1,"default":1},color:{type:"string",title:"Fadeout color",format:"color","default":"#FFFFFF"}},form:[{key:"speed",type:"range",step:"0.05"},"color"]}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["kernel"]),c=_.defaults(c,{edgeMode:"EXTEND",bias:0});var d;if(c.kernel in b.kernels)d=b.kernels[c.kernel];else{if(!_.isArray(c.kernel)||1!==c.kernel.length%2)throw new Error("Invalid convolution kernel");d=c.kernel}var e=Math.floor(Math.sqrt(d.length));if(e*e!=d.length)throw new Error("Invalid convolution kernel");this.program=new a.ConvolutionProgram(d,e,c.edgeMode,c.scale,c.bias),b.super.constructor.call(this)}function c(b,d,e,f,g){var h="";switch(e){case"WRAP":h="pos = vec2(pos.x<0?pos.x+1.0:pos.x%1, pos.y<0?pos.y+1.0:pos.y%1);";break;case"EXTEND":h="pos = clamp(pos, vec2(0,0), vec2(1,1));";break;default:throw new Error("Invalid edge mode")}var i,j,k=[],l=Math.floor(d/2);for(i=0;d>i;i++)for(j=0;d>j;j++){var m=b[i*d+j];0!==m&&(k.push("pos = v_position + onePixel * vec2("+(i-l)+","+(j-l)+");"),k.push(h),k.push("colorSum += texture2D(u_srcTexture, pos) * "+a.glslFloatRepr(m)+";"))}_.isUndefined(f)&&(f=_.reduce(b,function(a,b){return a+b},0)),c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["void main() {"," vec2 onePixel = vec2(1.0, 1.0)/u_resolution;"," vec2 pos;"," vec4 colorSum = vec4(0,0,0,0);",k.join("\n")," setFragColor(vec4(((colorSum+"+a.glslFloatRepr(g)+") / "+a.glslFloatRepr(f)+").rgb, 1.0));","}"]})}a.Convolution=a.defineClass(b,a.Component,{componentName:"Convolution",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),b.kernels={normal:[0,0,0,0,1,0,0,0,0],gaussianBlur:[.045,.122,.045,.122,.332,.122,.045,.122,.045],unsharpen:[-1,-1,-1,-1,9,-1,-1,-1,-1],emboss:[-2,-1,0,-1,1,1,0,1,2],blur:[1,1,1,1,1,1,1,1,1]},a.ConvolutionProgram=a.defineClass(c,a.QuadBoxProgram)}(Webvs),function(a){function b(c){if(a.checkRequiredOptions(c,["maps"]),c=_.defaults(c,{key:"RED",output:"REPLACE",mapCycleMode:"SINGLE"}),this.maps=c.maps,this.currentMap=0,this.mapCycleMode=this.mapCycleModes[c.mapCycleMode],!this.mapCycleMode)throw new Error("Unknown mapCycleMode "+c.mapCycleMode);this.program=new a.ColorMapProgram(c.key,a.blendModes[c.output]),b.super.constructor.call(this)}function c(a,b){var d="";switch(a){case"RED":d="srcColor.r";break;case"GREEN":d="srcColor.g";break;case"BLUE":d="srcColor.b";break;case"(R+G+B)/2":d="mod((srcColor.r+srcColor.g+srcColor.b)/2.0, 1.0)";break;case"(R+G+B)/3":d="(srcColor.r+srcColor.g+srcColor.b)/3.0";break;case"MAX":d="max(srcColor.r, max(srcColor.g, srcColor.b))";break;default:throw new Error("Unknown colormap key function "+options.key)}c.super.constructor.call(this,{outputBlendMode:b,swapFrame:!0,fragmentShader:["uniform sampler2D u_colorMap;","void main() {"," vec4 srcColor = getSrcColor();"," setFragColor(texture2D(u_colorMap, vec2(("+d+"), 0)));","}"]})}a.ColorMap=a.defineClass(b,a.Component,{mapCycleModes:{SINGLE:1,ONBEATRANDOM:2,ONBEATSEQUENTIAL:3},init:function(a,c,d){b.super.init.call(this,a,c,d),this.colorMaps=_.map(this.maps,function(a){return this._buildColorMap(a)},this),this.currentMap=0,this.program.init(a)},update:function(){if(this.main.analyser.beat)switch(this.mapCycleMode){case this.mapCycleModes.ONBEATRANDOM:this.currentMap=Math.floor(Math.random()*this.colorMaps.length);break;case this.mapCycleModes.ONBEATSEQUENTIAL:this.currentMap=(this.currentMap+1)%this.colorMaps.length}this.program.run(this.parent.fm,null,this.colorMaps[this.currentMap])},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_buildColorMap:function(b){var c=this.gl;b=_.sortBy(b,function(a){return a.index});var d=_.map(b,function(a){return a.index});if(_.uniq(d).length!=d.length)throw new Error("map cannot have repeated indices");var e=_.first(b);0!==e.index&&b.splice(0,0,{color:e.color,index:0});var f=_.last(b);255!==f.index&&b.push({color:f.color,index:255}),b=_.map(b,function(b){var c=a.parseColor(b.color);return{color:c,index:b.index}});var g=new Uint8Array(1024),h=0,i=_.zip(_.first(b,b.length-1),_.last(b,b.length-1));_.each(i,function(a){var b=a[0],c=a[1],d=c.index-b.index,e=[(c.color[0]-b.color[0])/d,(c.color[1]-b.color[1])/d,(c.color[2]-b.color[2])/d];_.times(d,function(a){g[h++]=b.color[0]+e[0]*a,g[h++]=b.color[1]+e[1]*a,g[h++]=b.color[2]+e[2]*a,g[h++]=255})}),g[h++]=f.color[0],g[h++]=f.color[1],g[h++]=f.color[2],g[h++]=255;var j=c.createTexture();return c.bindTexture(c.TEXTURE_2D,j),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,256,1,0,c.RGBA,c.UNSIGNED_BYTE,g),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),j}}),a.ColorMapProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_colorMap","texture2D",a),c.super.draw.call(this)}}),b.ui={disp:"Color Map",type:"ColorMap",schema:{maps:{type:"array",items:{type:"array",title:"Map",items:{type:"object",properties:{color:{type:"string",title:"Color",format:"color","default":"#FFFFFF"},index:{type:"number",title:"Index",minimum:0,maximum:255}}}}},key:{type:"string",title:"Map key","enum":["RED","GREEN","BLUE","(R+G+B)/2","(R+G+B)/3","MAX"],"default":"RED"},mapCycleMode:{type:"string",title:"Map Cycle Mode","enum":["SINGLE","ONBEATRANDOM","ONBEATSEQUENTIAL"],"default":"SINGLE"},output:{type:"string",title:"Output blend mode","enum":_.keys(a.blendModes),"default":"REPLACE"}}}}(Webvs),function(a){function b(b){if(a.checkRequiredOptions(b,["mode","color","outColor"]),b=_.defaults(b,{mode:"BELOW",color:"#202020",outColor:"#202020",level:0}),this.mode=_.indexOf(this.modes,b.mode),-1==this.mode)throw new Error("ColorClip: invalid mode");this.color=a.parseColorNorm(b.color),this.outColor=a.parseColorNorm(b.outColor),this.level=b.level,this.program=new a.ColorClipProgram}function c(){c.super.constructor({swapFrame:!0,fragmentShader:["uniform int u_mode;","uniform vec3 u_color;","uniform vec3 u_outColor;","uniform float u_level;","void main() {"," vec4 inColor4 = getSrcColor();"," vec3 inColor = inColor4.rgb;"," bool clip = false;"," if(u_mode == 0) {"," clip = all(lessThanEqual(inColor, u_color));"," }"," if(u_mode == 1) {"," clip = all(greaterThanEqual(inColor, u_color));"," }"," if(u_mode == 2) {"," clip = (distance(inColor, u_color) <= u_level*0.5);"," }"," if(clip) {"," setFragColor(vec4(u_outColor, inColor4.a));"," } else {"," setFragColor(inColor4);"," }","}"]})}a.ColorClip=a.defineClass(b,a.Component,{modes:["BELOW","ABOVE","NEAR"],componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null,this.mode,this.color,this.outColor,this.level)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ColorClipProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a,b,d,e){this.setUniform("u_mode","1i",a),this.setUniform.apply(this,["u_color","3f"].concat(b)),this.setUniform.apply(this,["u_outColor","3f"].concat(d)),this.setUniform("u_level","1f",e),c.super.draw.call(this)}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]),c=_.defaults(c,{gridW:16,gridH:16,noGrid:!1,bFilter:!0,compat:!1,coord:"POLAR"});var d;if(!_.isObject(c.code))throw new Error("Invalid Dynamic movement code");d=c.code;var e=new a.ExprCodeGenerator(d,["x","y","r","d","b","w","h"]),f=e.generateCode(["init","onBeat","perFrame"],["perPixel"],["x","y","d","r"]);this.code=f[0],this.inited=!1,this.noGrid=c.noGrid,this.gridW=c.gridW,this.gridH=c.gridH,this.coordMode=c.coord,this.bFilter=c.bFilter,this.compat=c.compat,this.program=this.noGrid?new a.DMovProgramNG(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]):new a.DMovProgram(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]),b.super.constructor.call(this)}function c(a,b,d,e,f){var g=[f,this.glslFilter(b,d),"void main() {",e?"__randSeed = v_position;":""," x = v_position.x*2.0-1.0;"," y = -(v_position.y*2.0-1.0);",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," setFragColor(vec4(filter(vec2(x, -y)), 1));","}"];c.super.constructor.call(this,{fragmentShader:g,swapFrame:!0})}function d(a,b,c,e,f){var g=["attribute vec2 a_position;","varying vec2 v_newPoint;","uniform int u_coordMode;",f,"void main() {",e?"__randSeed = a_position;":""," x = a_position.x;"," y = -a_position.y;",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," v_newPoint = vec2(x,-y);"," setPosition(a_position);","}"],h=["varying vec2 v_newPoint;",this.glslFilter(b,c),"void main() {"," setFragColor(vec4(filter(v_newPoint), 1));","}"];d.super.constructor.call(this,{fragmentShader:h,vertexShader:g,swapFrame:!0})}a.DynamicMovement=a.defineClass(b,a.Component,{componentName:"DynamicMovement",init:function(a,c,d){if(b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,d),!this.noGrid){for(var e=2*(this.gridW/this.main.canvas.width),f=2*(this.gridH/this.main.canvas.height),g=Math.ceil(this.main.canvas.width/this.gridW),h=Math.ceil(this.main.canvas.height/this.gridH),i=new Float32Array(2*6*g*h),j=0,k=-1,l=-1,m=0;h>m;m++){for(var n=0;g>n;n++){var o=Math.min(k+e,1),p=Math.min(l+f,1);i[j++]=k,i[j++]=l,i[j++]=o,i[j++]=l,i[j++]=k,i[j++]=p,i[j++]=o,i[j++]=l,i[j++]=o,i[j++]=p,i[j++]=k,i[j++]=p,k+=e}k=-1,l+=f}this.gridVertices=i,this.gridVerticesSize=j/2}},update:function(){var a=this.code;this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat(),this.noGrid?this.program.run(this.parent.fm,null,this.code):this.program.run(this.parent.fm,null,this.code,this.gridVertices,this.gridVerticesSize)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}});var e={glslRectToPolar:function(a){return"POLAR"===a?["d = distance(vec2(x, y), vec2(0,0))/sqrt(2.0);","r = mod(atan(y, x)+PI*0.5, 2.0*PI);"].join("\n"):""},glslPolarToRect:function(a){return"POLAR"===a?["d = d*sqrt(2.0);","x = d*sin(r);","y = -d*cos(r);"].join("\n"):""},glslFilter:function(a,b){return a&&!b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 cornoff = fract(coord/texel);"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," vec3 pt = mix(tl, tr, cornoff.x);"," vec3 pb = mix(bl, br, cornoff.x);"," return mix(pt, pb, cornoff.y);","}"].join("\n"):a&&b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," float xp = floor(fract(coord.x/texel.x)*255.0);"," float yp = floor(fract(coord.y/texel.y)*255.0);"," #define g_blendtable(i, j) floor(((i)/255.0)*(j))"," float a1 = g_blendtable(255.0-xp, 255.0-yp);"," float a2 = g_blendtable(xp, 255.0-yp);"," float a3 = g_blendtable(255.0-xp, yp);"," float a4 = g_blendtable(xp, yp);"," float r = (floor(a1*tl.r) + floor(a2*tr.r) + floor(a3*bl.r) + floor(a4*br.r))/255.0;"," float g = (floor(a1*tl.g) + floor(a2*tr.g) + floor(a3*bl.g) + floor(a4*br.g))/255.0;"," float b = (floor(a1*tl.b) + floor(a2*tr.b) + floor(a3*bl.b) + floor(a4*br.b))/255.0;"," return vec3(r, g, b);","}"].join("\n"):["vec3 filter(vec2 point) {"," return getSrcColorAtPos((point+1.0)/2.0).rgb;","}"].join("\n")}};a.DMovProgramNG=a.defineClass(c,a.QuadBoxProgram,e,{draw:function(a){a.bindUniforms(this),c.super.draw.call(this)}}),a.DMovProgram=a.defineClass(d,a.ShaderProgram,e,{draw:function(a,b,c){a.bindUniforms(this),this.setVertexAttribArray("a_position",b,2,this.gl.FLOAT,!1,0,0),this.gl.drawArrays(this.gl.TRIANGLES,0,c)}}),b.ui={type:"DynamicMovement",disp:"Dynamic Movement",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPixel:{type:"string",title:"Per Point"}}},gridW:{type:"number",title:"Grid Width","default":16},gridH:{type:"number",title:"Grid Height","default":16},coord:{type:"string",title:"Coordinate System","enum":["POLAR","RECT"],"default":"POLAR"}},form:[{key:"code.init",type:"textarea"},{key:"code.onBeat",type:"textarea"},{key:"code.perFrame",type:"textarea"},{key:"code.perPixel",type:"textarea"},"gridW","gridH","coord"]}}(Webvs),function(a){function b(a){if(a=_.defaults(a,{channel:"RGB",onBeatRandom:!1}),this.channel=d.indexOf(a.channel),-1==this.channel)throw new Error("Invalid Channel");this.onBeatRandom=a.onBeatRandom,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["uniform int u_channel;","void main() {"," vec3 color = getSrcColor().rgb;",_.flatMap(d,function(a,b){return["if(u_channel == "+b+") {"," setFragColor(vec4(color."+a.toLowerCase()+",1));","}"]}).join("\n"),"}"]})}var d=["RGB","RBG","BRG","BGR","GBR","GRB"];a.ChannelShift=a.defineClass(b,a.Component,{componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.onBeatRandom&&this.main.analyser.beat&&(this.channel=Math.floor(Math.random()*d.length)),this.program.run(this.parent.fm,null,this.channel)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ChannelShiftProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_channel","1i",a),c.super.draw.call(this)}}),b.ui={disp:"Channel Shift",type:"ChannelShift",schema:{channel:{type:"string",title:"Channel","enum":d},onBeatRandom:{type:"boolean",title:"On beat random"}}}}(Webvs),function(a){function b(d){a.checkRequiredOptions(d,["code"]),d=_.defaults(d,{source:"SPECTRUM",drawMode:"LINES",colors:["#ffffff"]});var e;if(!_.isObject(d.code))throw new Error("Invalid superscope");e=d.code;var f=new a.ExprCodeGenerator(e,["n","v","i","x","y","b","w","h","red","green","blue","cid"]),g=f.generateCode(["init","onBeat","perFrame","perPoint"],[],[]);this.code=g[0],this.code.n=100,this.spectrum="SPECTRUM"==d.source,this.dots="DOTS"==d.drawMode,this.colors=_.map(d.colors,a.parseColorNorm),this.currentColor=this.colors[0],this.maxStep=100,this.step=this.maxStep,this.colorId=0,this.colorStep=[0,0,0],this.thickness=d.thickness?d.thickness:1,this.inited=!1,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_position;","attribute vec3 a_color;","varying vec3 v_color;","uniform float u_pointSize;","void main() {"," gl_PointSize = u_pointSize;"," setPosition(clamp(a_position, vec2(-1,-1), vec2(1,1)));"," v_color = a_color;","}"],fragmentShader:["varying vec3 v_color;","void main() {"," setFragColor(vec4(v_color, 1));","}"]})}a.SuperScope=a.defineClass(b,a.Component,{componentName:"SuperScope",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,this)},update:function(){this.gl;var a=this.code;this._stepColor(),a.red=this.currentColor[0],a.green=this.currentColor[1],a.blue=this.currentColor[2],this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat();for(var c=Math.floor(a.n),d=this.spectrum?this.main.analyser.getSpectrum():this.main.analyser.getWaveform(),e=d.length/c,f=0,g=0,h=new Float32Array(2*(this.dots?c:2*c-2)),i=new Float32Array(3*(this.dots?c:2*c-2)),j=0;c>j;j++){for(var k=0,l=0,m=Math.floor(j*e);(j+1)*e>m;m++,l++)k+=d[m];k/=l;var n=j/(c-1);a.i=n,a.v=k,a.perPoint(),h[f++]=a.x,h[f++]=-1*a.y,0===j||j==c-1||this.dots||(h[f++]=a.x,h[f++]=-1*a.y),this.dots?(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue):0!==j&&(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue,i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue)}this.program.run(this.parent.fm,null,h,i,this.dots,this.thickness)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_stepColor:function(){var a;if(this.colors.length>1)if(this.step==this.maxStep){var b=this.colors[this.colorId];this.colorId=(this.colorId+1)%this.colors.length;var c=this.colors[this.colorId];for(a=0;3>a;a++)this.colorStep[a]=(c[a]-b[a])/this.maxStep;this.step=0,this.currentColor=b}else{for(a=0;3>a;a++)this.currentColor[a]+=this.colorStep[a];this.step++}}}),a.SuperScopeShader=a.defineClass(c,a.ShaderProgram,{draw:function(a,b,c,d){var e=this.gl;this.setUniform("u_pointSize","1f",d),this.setVertexAttribArray("a_position",a,2,e.FLOAT,!1,0,0),this.setVertexAttribArray("a_color",b,3,e.FLOAT,!1,0,0);var f;c||(f=e.getParameter(e.LINE_WIDTH),e.lineWidth(d)),e.drawArrays(c?e.POINTS:e.LINES,0,a.length/2),c||e.lineWidth(f)}}),b.ui={disp:"SuperScope",type:"SuperScope",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPoint:{type:"string",title:"Per Point"}}},source:{type:"string",title:"Source","default":"WAVEFORM","enum":["WAVEFORM","SPECTRUM"]},drawMode:{type:"string",title:"Draw Mode","default":"LINES","enum":["DOTS","LINES"]},colors:{type:"array",title:"Cycle Colors",items:{type:"string",format:"color","default":"#FFFFFF"}}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{n:0,color:"#000000",blendMode:"REPLACE"}),this.n=c.n,this.color=a.parseColorNorm(c.color),this.outputBlendMode=a.blendModes[c.blendMode],this.prevBeat=!1,this.beatCount=0,this.program=new a.ClearScreenProgram(this.outputBlendMode),b.super.constructor.call(this)}a.ClearScreen=a.defineClass(b,a.Component,{componentName:"ClearScreen",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){var a=!1;0===this.n?a=!0:(this.main.analyser.beat&&!this.prevBeat&&(this.beatCount++,this.beatCount==this.n&&(a=!0,this.beatCount=0)),this.prevBeat=this.main.analyser.beat),a&&this.program.run(this.parent.fm,null,this.color) +!function(a){var b={};a.Webvs=b,b.defineClass=function(a,b){return a.prototype=Object.create(b.prototype),a.prototype.constructor=a,a.super=b.prototype,_.chain(arguments).drop(2).each(function(b){_.extend(a.prototype,b)}),a},b.noop=function(){},b.checkRequiredOptions=function(a,b){for(var c in b){var d=b[c];if(!(d in a))throw new Error("Required option "+d+"not found")}},b.glslFloatRepr=function(a){return a+(0===a%1?".0":"")},b.parseColor=function(a){if(_.isArray(a)&&3==a.length)return a;if(_.isString(a)){var b;if(a=a.toLowerCase(),b=a.match(/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/))return _.chain(b).last(3).map(function(a){return parseInt(a,16)}).value();if(b=a.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/))return _.chain(b).last(3).map(function(a){return Math.min(parseInt(a,10),255)}).value()}throw new Error("Invalid Color Format")},b.parseColorNorm=function(a){return _.map(b.parseColor(a),function(a){return a/255})},b.logShaderError=function(a,b){var c=a.split("\n"),d=c.length.toString().length,e=b.match(/(\d+):(\d+)/);e&&(e=[parseInt(e[1],10),parseInt(e[2],10)]);var f=_.map(c,function(a,c){var f,g=c+1+"";for(f=0;f0&&this._frameCounter--,0!==this._frameCounter)){if(this.fm.setRenderTarget(),(this.clearFrame||this.first)&&(a.clearColor(0,0,0,1),a.clear(a.COLOR_BUFFER_BIT),this.first=!1),-1!==this.input){var c=this.parent.fm.getCurrentTexture();this.main.copier.run(this.fm,this.input,c)}for(var d=this.components,e=0;ee;e++){var f=b.charAt(e);"\n"===f?(a.seenCR||a.line++,a.column=1,a.seenCR=!1):"\r"===f||"\u2028"===f||"\u2029"===f?(a.line++,a.column=1,a.seenCR=!0):(a.column++,a.seenCR=!1)}a.offset+=c}function f(a){F.offsetH.offset&&(H=d(F),I=[]),I.push(a))}function g(){var a="program@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,i,j,k,l,m,n,o,p,q;if(o=d(F),p=d(F),g=h(),null!==g)if(i=x(),null!==i){for(j=[],q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==k;)j.push(k),q=d(F),59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),null!==k?(l=x(),null!==l?(m=h(),null!==m?(n=x(),null!==n?k=[k,l,m,n]:(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q))):(k=null,F=d(q));null!==j?(59===b.charCodeAt(F.offset)?(k=";",e(F,1)):(k=null,0===G&&f('";"')),k=null!==k?k:"",null!==k?g=[g,i,j,k]:(g=null,F=d(p))):(g=null,F=d(p))}else g=null,F=d(p);else g=null,F=d(p);return null!==g&&(g=function(a,b,c,d){var e=[d[0]];return e=e.concat(_.map(d[2],function(a){return a[2]})),new Webvs.AstProgram(e)}(o.offset,o.line,o.column,g)),null===g&&(F=d(o)),J[a]={nextPos:d(F),result:g},g}function h(){var a="statement@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n;return l=d(F),n=d(F),g=s(),null!==g?(h=x(),null!==h?(61===b.charCodeAt(F.offset)?(i="=",e(F,1)):(i=null,0===G&&f('"="')),null!==i?(j=x(),null!==j?(k=m(),null!==k?g=[g,h,i,j,k]:(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d,e){return new Webvs.AstAssignment(d,e)}(l.offset,l.line,l.column,g[0],g[4])),null===g&&(F=d(l)),null===g&&(g=m()),J[a]={nextPos:d(F),result:g},g}function i(){var a="unary_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function j(){var a="additive_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 43===b.charCodeAt(F.offset)?(g="+",e(F,1)):(g=null,0===G&&f('"+"')),null===g&&(45===b.charCodeAt(F.offset)?(g="-",e(F,1)):(g=null,0===G&&f('"-"'))),J[a]={nextPos:d(F),result:g},g}function k(){var a="multiplicative_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 42===b.charCodeAt(F.offset)?(g="*",e(F,1)):(g=null,0===G&&f('"*"')),null===g&&(47===b.charCodeAt(F.offset)?(g="/",e(F,1)):(g=null,0===G&&f('"/"')),null===g&&(37===b.charCodeAt(F.offset)?(g="%",e(F,1)):(g=null,0===G&&f('"%"')))),J[a]={nextPos:d(F),result:g},g}function l(){var a="boolean_ops@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return 38===b.charCodeAt(F.offset)?(g="&",e(F,1)):(g=null,0===G&&f('"&"')),null===g&&(124===b.charCodeAt(F.offset)?(g="|",e(F,1)):(g=null,0===G&&f('"|"'))),J[a]={nextPos:d(F),result:g},g}function m(){var a="boolean_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,k,m;if(j=d(F),k=d(F),c=n(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=l(),null!==g?(h=x(),null!==h?(i=n(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(k))}else c=null,F=d(k);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function n(){var a="additive_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,k,l,m;if(k=d(F),l=d(F),c=o(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=j(),null!==g?(h=x(),null!==h?(i=o(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(k.offset,k.line,k.column,c[0],c[1])),null===c&&(F=d(k)),J[a]={nextPos:d(F),result:c},c}function o(){var a="multiplicative_expr@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h,i,j,l,m;if(j=d(F),l=d(F),c=p(),null!==c){for(e=[],m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==f;)e.push(f),m=d(F),f=x(),null!==f?(g=k(),null!==g?(h=x(),null!==h?(i=p(),null!==i?f=[f,g,h,i]:(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m))):(f=null,F=d(m));null!==e?c=[c,e]:(c=null,F=d(l))}else c=null,F=d(l);return null!==c&&(c=function(a,b,c,d,e){return C(d,e)}(j.offset,j.line,j.column,c[0],c[1])),null===c&&(F=d(j)),J[a]={nextPos:d(F),result:c},c}function p(){var a="unary@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e,f,g,h;return g=d(F),h=d(F),c=i(),null!==c?(e=x(),null!==e?(f=q(),null!==f?c=[c,e,f]:(c=null,F=d(h))):(c=null,F=d(h))):(c=null,F=d(h)),null!==c&&(c=function(a,b,c,d,e){return new Webvs.AstUnaryExpr(d,e)}(g.offset,g.line,g.column,c[0],c[2])),null===c&&(F=d(g)),null===c&&(c=q()),J[a]={nextPos:d(F),result:c},c}function q(){var a="func_call@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,n,o,p,q,s,t;if(p=d(F),q=d(F),s=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(s))}else g=null,F=d(s);if(null!==g)if(h=x(),null!==h)if(40===b.charCodeAt(F.offset)?(i="(",e(F,1)):(i=null,0===G&&f('"("')),null!==i){for(s=d(F),j=[],t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==k;)j.push(k),t=d(F),k=x(),null!==k?(l=m(),null!==l?(n=x(),null!==n?(44===b.charCodeAt(F.offset)?(o=",",e(F,1)):(o=null,0===G&&f('","')),null!==o?k=[k,l,n,o]:(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t))):(k=null,F=d(t));null!==j?(k=x(),null!==k?(l=m(),null!==l?j=[j,k,l]:(j=null,F=d(s))):(j=null,F=d(s))):(j=null,F=d(s)),j=null!==j?j:"",null!==j?(k=x(),null!==k?(41===b.charCodeAt(F.offset)?(l=")",e(F,1)):(l=null,0===G&&f('")"')),null!==l?g=[g,h,i,j,k,l]:(g=null,F=d(q))):(g=null,F=d(q))):(g=null,F=d(q))}else g=null,F=d(q);else g=null,F=d(q);else g=null,F=d(q);return null!==g&&(g=function(a,b,c,d,e){var f=[];return _.each(e[0],function(a){f.push(a[1])}),f.push(e[2]),new Webvs.AstFuncCall(D(d),f)}(p.offset,p.line,p.column,g[0],g[3])),null===g&&(F=d(p)),null===g&&(g=r()),J[a]={nextPos:d(F),result:g},g}function r(){var a="primary_expr@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;return g=w(),null===g&&(g=u(),null===g&&(g=v(),null===g&&(g=t(),null===g&&(j=d(F),k=d(F),40===b.charCodeAt(F.offset)?(g="(",e(F,1)):(g=null,0===G&&f('"("')),null!==g?(h=m(),null!==h?(41===b.charCodeAt(F.offset)?(i=")",e(F,1)):(i=null,0===G&&f('")"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))):(g=null,F=d(k)),null!==g&&(g=function(a,b,c,d){return d}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)))))),J[a]={nextPos:d(F),result:g},g}function s(){var a="assignable@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c;return c=v(),null===c&&(c=t()),J[a]={nextPos:d(F),result:c},c}function t(){var a="identifier@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),/^[a-zA-Z_]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[a-zA-Z_]")),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"ID")}(j.offset,j.line,j.column,g)),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function u(){var a="constant@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k;if(j=d(F),k=d(F),36===b.charCodeAt(F.offset)?(g="$",e(F,1)):(g=null,0===G&&f('"$"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(D(d).toLowerCase(),"CONST")}(j.offset,j.line,j.column,g[1])),null===g&&(F=d(j)),J[a]={nextPos:d(F),result:g},g}function v(){var a="register@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(l=d(F),m=d(F),64===b.charCodeAt(F.offset)?(g="@",e(F,1)):(g=null,0===G&&f('"@"')),null!==g){for(h=[],/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==i;)h.push(i),/^[a-zA-Z_0-9]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[a-zA-Z_0-9]"));null!==h?g=[g,h]:(g=null,F=d(m))}else g=null,F=d(m);return null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_AT_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g[1])),null===g&&(F=d(l)),null===g&&(l=d(F),m=d(F),/^[rR]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[rR]")),null!==g?(/^[eE]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[eE]")),null!==h?(/^[gG]/.test(b.charAt(F.offset))?(i=b.charAt(F.offset),e(F,1)):(i=null,0===G&&f("[gG]")),null!==i?(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j?(/^[0-9]/.test(b.charAt(F.offset))?(k=b.charAt(F.offset),e(F,1)):(k=null,0===G&&f("[0-9]")),null!==k?g=[g,h,i,j,k]:(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m))):(g=null,F=d(m)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr("__REG_"+D(d).toLowerCase(),"REG")}(l.offset,l.line,l.column,g)),null===g&&(F=d(l))),J[a]={nextPos:d(F),result:g},g}function w(){var a="value@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m,n,o;for(m=d(F),n=d(F),g=[],/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));if(null!==g)if(46===b.charCodeAt(F.offset)?(h=".",e(F,1)):(h=null,0===G&&f('"."')),null!==h){if(/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]")),null!==j)for(i=[];null!==j;)i.push(j),/^[0-9]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[0-9]"));else i=null;if(null!==i){if(o=d(F),/^[Ee]/.test(b.charAt(F.offset))?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("[Ee]")),null!==j){if(/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]")),null!==l)for(k=[];null!==l;)k.push(l),/^[0-9]/.test(b.charAt(F.offset))?(l=b.charAt(F.offset),e(F,1)):(l=null,0===G&&f("[0-9]"));else k=null;null!==k?j=[j,k]:(j=null,F=d(o))}else j=null,F=d(o);j=null!==j?j:"",null!==j?g=[g,h,i,j]:(g=null,F=d(n))}else g=null,F=d(n)}else g=null,F=d(n);else g=null,F=d(n);if(null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseFloat(D(d)),"VALUE")}(m.offset,m.line,m.column,g)),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[a-fA-F0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[a-fA-F0-9]"));else g=null;if(null!==g?(/^[hH]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[hH]")),null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),16),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m)),null===g){if(m=d(F),n=d(F),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]")),null!==h)for(g=[];null!==h;)g.push(h),/^[0-9]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[0-9]"));else g=null;null!==g?(/^[dD]/.test(b.charAt(F.offset))?(h=b.charAt(F.offset),e(F,1)):(h=null,0===G&&f("[dD]")),h=null!==h?h:"",null!==h?g=[g,h]:(g=null,F=d(n))):(g=null,F=d(n)),null!==g&&(g=function(a,b,c,d){return new Webvs.AstPrimaryExpr(parseInt(D(d),10),"VALUE")}(m.offset,m.line,m.column,g[0])),null===g&&(F=d(m))}}return J[a]={nextPos:d(F),result:g},g}function x(){var a="__@"+F.offset,b=J[a];if(b)return F=d(b.nextPos),b.result;var c,e;for(c=[],e=y(),null===e&&(e=z(),null===e&&(e=A()));null!==e;)c.push(e),e=y(),null===e&&(e=z(),null===e&&(e=A()));return J[a]={nextPos:d(F),result:c},c}function y(){var a="whiteSpace@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\t\x0B\f \xA0\uFEFF]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\t\\x0B\\f \\xA0\\uFEFF]")),J[a]={nextPos:d(F),result:g},g}function z(){var a="lineEnd@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g;return/^[\n\r\u2028\u2029]/.test(b.charAt(F.offset))?(g=b.charAt(F.offset),e(F,1)):(g=null,0===G&&f("[\\n\\r\\u2028\\u2029]")),J[a]={nextPos:d(F),result:g},g}function A(){var a="comment@"+F.offset,c=J[a];if(c)return F=d(c.nextPos),c.result;var g,h,i,j,k,l,m;if(k=d(F),"/*"===b.substr(F.offset,2)?(g="/*",e(F,2)):(g=null,0===G&&f('"/*"')),null!==g){for(h=[],l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,"*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?("*/"===b.substr(F.offset,2)?(i="*/",e(F,2)):(i=null,0===G&&f('"*/"')),null!==i?g=[g,h,i]:(g=null,F=d(k))):(g=null,F=d(k))}else g=null,F=d(k);if(null===g)if(k=d(F),"//"===b.substr(F.offset,2)?(g="//",e(F,2)):(g=null,0===G&&f('"//"')),null!==g){for(h=[],l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==i;)h.push(i),l=d(F),m=d(F),G++,i=z(),G--,null===i?i="":(i=null,F=d(m)),null!==i?(b.length>F.offset?(j=b.charAt(F.offset),e(F,1)):(j=null,0===G&&f("any character")),null!==j?i=[i,j]:(i=null,F=d(l))):(i=null,F=d(l));null!==h?g=[g,h]:(g=null,F=d(k))}else g=null,F=d(k);return J[a]={nextPos:d(F),result:g},g}function B(a){a.sort();for(var b=null,c=[],d=0;dH.offset?F:H;throw new this.SyntaxError(B(I),M,L,N.line,N.column)}return K},toSource:function(){return this._source}};return b.SyntaxError=function(b,c,d,e,f){function g(b,c){var d,e;switch(b.length){case 0:d="end of input";break;case 1:d=b[0];break;default:d=b.slice(0,b.length-1).join(", ")+" or "+b[b.length-1]}return e=c?a(c):"end of input","Expected "+d+" but "+e+" found."}this.name="SyntaxError",this.expected=b,this.found=c,this.message=g(b,c),this.offset=d,this.line=e,this.column=f},b.SyntaxError.prototype=Error.prototype,b}(),function(a){function b(){}a.CodeInstance=a.defineClass(b,Object,{rand:function(a){return Math.floor(Math.random()*a)+1},gettime:function(a){switch(a){case 0:var b=(new Date).getTime();return(b-this._bootTime)/1e3;default:throw new Error("Invalid startTime mode for gettime call")}},getosc:function(a,b){for(var c=this._analyser.getWaveform(),d=Math.floor((a-b/2)*(c.length-1)),e=Math.floor((a+b/2)*(c.length-1)),f=0,g=d;e>=g;g++)f+=c[g];return f/(e-d+1)},bindUniforms:function(a){var b=this,c=_.difference(_.keys(this),this._treatAsNonUniform);if(_.each(c,function(c){var d=b[c];"number"==typeof d&&a.setUniform(c,"1f",d)}),_.each(this._registerUsages,function(b){a.setUniform(b,"1f",this._registerBank[b])}),this.hasRandom){var d=[Math.random()/100,Math.random()/100];a.setUniform("__randStep","2fv",d)}if(this.hasGettime){var e=((new Date).getTime()-this._bootTime)/1e3;a.setUniform("__gettime0","1f",e)}_.each(this._preCompute,function(b){var c=_.map(_.last(b,b.length-2),function(a){return _.isString(a)?"__REG"==a.substring(0,5)?this._registerBank[a]:this[a]:a}),d=this[b[0]].apply(this,c);a.setUniform(b[1],"1f",d)})},setup:function(a,b){this._registerBank=a.registerBank,this._bootTime=a.bootTime,this._analyser=a.analyser,this.w=a.canvas.width,this.h=a.canvas.height,this.cid=b.cloneId,_.each(this._registerUsages,function(b){_.has(a.registerBank,b)||(a.registerBank[b]=0)})}})}(Webvs),function(a){function b(a,b){this.codeSrc=a,this.externalVars=b?b:[],this._parseSrc()}a.ExprCodeGenerator=a.defineClass(b,Object,{_parseSrc:function(){var b={},c=[],d={},e=[];for(var f in this.codeSrc)try{var g=this.codeSrc[f];_.isArray(g)&&(g=g.join("\n")),b[f]=a.PegExprParser.parse(g);var h=[];this._getVars(b[f],c,h,e),d[f]=h}catch(i){throw new Error("Error parsing "+f+"("+i.line+":"+i.column+")"+" : "+i)}this.codeAst=b,this.funcUsages=d,this.instanceVars=_.uniq(this.externalVars.concat(c)),this.registerUsages=_.uniq(e)},generateCode:function(b,c,d){var e=new a.CodeInstance,f=this,g=[];_.each(this.instanceVars,function(a){e[a]=0;var b="";_.contains(d,a)||(b="uniform "),g.push(b+"float "+a+";")});var h=_.intersection(_.keys(this.codeAst),b),i=_.difference(b,h);_.each(h,function(a){var b=f.codeAst[a],c=f._generateJs(b);e[a]=new Function(c)}),_.each(i,function(b){e[b]=a.noop});var j=_.intersection(_.keys(this.codeAst),c),k=_.difference(c,j),l=_.uniq(_.flatMap(j,function(a){return f.funcUsages[a]}));_.each(l,function(a){var b=f.glslFuncCode[a];b&&g.push(b)});var m=[],n=[];return _.each(j,function(a){var b=f.codeAst[a],c=f._generateGlsl(b,m);n.push("void "+a+"() {"),n.push(c),n.push("}")}),g=g.concat(_.map(m,function(a){return"uniform float "+a[1]+";"})),g=g.concat(n),e._preCompute=m,_.each(k,function(a){g.push("void "+a+"() {}")}),_.contains(j,"rand")&&(e.hasRandom=!0),_.contains(j,"gettime")&&(e.hasGettime=!0),e._treatAsNonUniform=d,e._registerUsages=this.registerUsages,[e,g.join("")]},funcArgLengths:{above:2,below:2,equal:2,pow:2,sqr:1,sqrt:1,invsqrt:1,floor:1,ceil:1,abs:1,"if":3,sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,log:1,band:2,bor:2,bnot:1,rand:1,gettime:1,getosc:3,select:{min:2}},jsMathFuncs:["sin","cos","abs","tan","asin","acos","atan","log","pow","sqrt","floor","ceil"],glslFuncCode:{rand:["uniform vec2 __randStep;","vec2 __randSeed;","float rand(float max) {"," __randCur += __randStep;"," float val = fract(sin(dot(__randSeed.xy ,vec2(12.9898,78.233))) * 43758.5453);"," return (floor(val*max)+1);","}"].join("\n"),gettime:["uniform float __gettime0;","int gettime(int startTime) {"," int time = 0;"," if(startTime == 0) {"," time = __gettime0;"," }"," return time;","}"].join("\n")},_checkFunc:function(a){var b=this.funcArgLengths[a.funcName];if(void 0===b)throw Error("Unknown function "+a.funcName);if(_.isNumber(b)){if(a.args.length!=b)throw Error(a.funcName+" accepts "+b+" arguments")}else if(b.min&&a.args.length",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"below":return["(",this._generateGlsl(b.args[0],c),"<",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"equal":return["(",this._generateGlsl(b.args[0],c),"==",this._generateGlsl(b.args[1],c),"?1.0:0.0)"].join("");case"if":return["(",this._generateGlsl(b.args[0],c),"!=0.0?",this._generateGlsl(b.args[1],c),":",this._generateGlsl(b.args[2],c),")"].join("");case"select":var e=this._generateGlsl(b.args[0],c),f=function(a,b){return 1==a.length?d._generateGlsl(a[0],c):["(("+e+" === "+b+")?","("+d._generateGlsl(a[0],c)+"):","("+f(_.last(a,a.length-1),b+1)+"))"].join("")};return f(_.last(b.args,b.args.length-1),0);case"sqr":return"(pow(("+this._generateGlsl(b.args[0],c)+"), 2))";case"band":return"(float(("+this._generateGlsl(b.args[0],c)+")&&("+this._generateGlsl(b.args[1],c)+")))";case"bor":return"(float(("+this._generateGlsl(b.args[0],c)+")||("+this._generateGlsl(b.args[1],c)+")))";case"bnot":return"(float(!("+this._generateGlsl(b.args[0],c)+")))";case"invsqrt":return"(1/sqrt("+this._generateGlsl(b.args[0],c)+"))";case"atan2":return"(atan(("+this._generateGlsl(b.args[0],c)+"),("+this._generateGlsl(b.args[1],c)+"))";case"getosc":var g=_.every(b.args,function(b){return b instanceof a.AstPrimaryExpr});if(!g)throw new Error("Non Pre-Computable arguments for getosc in shader code, use variables or constants");var h="__PC_"+b.funcName+"_"+j,i=[b.funcName,h].concat(_.map(b.args,function(a){return a.value})),j=_.indexOf(c,i);return-1==j&&(c.push(i),j=c.length-1),h;default:var k=_.map(b.args,function(a){return d._generateGlsl(a,c)}).join(","),l=b.funcName;return _.contains(this.varArgFuncs,b.funcName)&&(l+=b.args.length),"("+l+"("+k+"))"}if(b instanceof a.AstAssignment)return this._generateGlsl(b.lhs,c)+"="+this._generateGlsl(b.expr,c);if(b instanceof a.AstProgram){var m=_.map(b.statements,function(a){return d._generateGlsl(a,c)});return m.join(";\n")+";"}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?a.glslFloatRepr(b.value):b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&("ID"===b.type||"REG"===b.type)?b.value:void 0},_generateJs:function(b){var c,d=this;if(b instanceof a.AstBinaryExpr)return"("+this._generateJs(b.leftOperand)+b.operator+this._generateJs(b.rightOperand)+")";if(b instanceof a.AstUnaryExpr)return"("+b.operator+this._generateJs(b.operand)+")";if(b instanceof a.AstFuncCall)switch(this._checkFunc(b),b.funcName){case"above":return["(",this._generateJs(b.args[0]),">",this._generateJs(b.args[1]),"?1:0)"].join("");case"below":return["(",this._generateJs(b.args[0]),"<",this._generateJs(b.args[1]),"?1:0)"].join("");case"equal":return["(",this._generateJs(b.args[0]),"==",this._generateJs(b.args[1]),"?1:0)"].join("");case"if":return["(",this._generateJs(b.args[0]),"!==0?",this._generateJs(b.args[1]),":",this._generateJs(b.args[2]),")"].join("");case"select":var e=["((function() {"];return e.push("switch("+this._generateJs(b.args[0])+") {"),_.each(_.last(b.args,b.args.length-1),function(a,b){e.push("case "+b+": return "+this._generateJs(a)+";")},this),e.push("default : throw new Error('Unknown selector value in select');"),e.push("}}).call(this))"),e.join("");case"sqr":return"(Math.pow(("+this._generateJs(b.args[0])+"),2))";case"band":return"((("+this._generateJs(b.args[0])+")&&("+this._generateJs(b.args[1])+"))?1:0)";case"bor":return"((("+this._generateJs(b.args[0])+")||("+this._generateJs(b.args[1])+"))?1:0)";case"bnot":return"((!("+this._generateJs(b.args[0])+"))?1:0)";case"invsqrt":return"(1/Math.sqrt("+this._generateJs(b.args[0])+"))";case"atan2":return"(Math.atan(("+this._generateJs(b.args[0])+")/("+this._generateJs(b.args[1])+")))";default:var f=_.map(b.args,function(a){return d._generateJs(a)}).join(",");return c=_.contains(this.jsMathFuncs,b.funcName)?"Math.":"this.","("+c+b.funcName+"("+f+"))"}if(b instanceof a.AstAssignment)return this._generateJs(b.lhs)+"="+this._generateJs(b.expr);if(b instanceof a.AstProgram){var g=_.map(b.statements,function(a){return d._generateJs(a)});return g.join(";\n")}return b instanceof a.AstPrimaryExpr&&"VALUE"===b.type?b.value.toString():b instanceof a.AstPrimaryExpr&&"CONST"===b.type?this._translateConstants(b.value).toString():b instanceof a.AstPrimaryExpr&&"ID"===b.type?"this."+b.value:b instanceof a.AstPrimaryExpr&&"REG"===b.type?'this._registerBank["'+b.value+'"]':void 0},_getVars:function(b,c,d,e){var f=this;b instanceof a.AstBinaryExpr?(this._getVars(b.leftOperand,c,d,e),this._getVars(b.rightOperand,c,d,e)):b instanceof a.AstUnaryExpr?this._getVars(b.operand,c,d,e):b instanceof a.AstFuncCall?(d.push(b.funcName),_.each(b.args,function(a){f._getVars(a,c,d,e)})):b instanceof a.AstAssignment?(this._getVars(b.lhs,c,d,e),this._getVars(b.expr,c,d,e)):b instanceof a.AstProgram?_.each(b.statements,function(a){f._getVars(a,c,d,e)}):b instanceof a.AstPrimaryExpr&&"ID"===b.type?c.push(b.value):b instanceof a.AstPrimaryExpr&&"REG"===b.type&&e.push(b.value)},_translateConstants:function(a){switch(a){case"pi":return Math.PI;case"e":return Math.E;case"phi":return 1.6180339887;default:throw new Error("Unknown constant "+a)}}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]);var d=new a.ExprCodeGenerator(c.code,["b","w","h"]),e=d.generateCode(["init","onBeat","perFrame"],[],[]);this.code=e[0],this.inited=!1,b.super.constructor.call(this)}a.GlobalVar=a.defineClass(b,a.Component,{init:function(a,c,d){b.super.init.call(this,a,c,d),this.code.setup(c,this)},update:function(){var a=this.code;a.b=this.main.analyser.beat?1:0,this.inited||(a.init(),this.inited=!0),this.main.analyser.beat&&a.onBeat(),a.perFrame()}}),b.ui={disp:"Global Var",type:"GlobalVar",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"}}}}}}(Webvs),function(a){function b(c){if(c=_.defaults(c,{action:"SAVE",bufferId:1,blendMode:"REPLACE"}),this.blendMode=a.blendModes[c.blendMode],this.action=this.actions[c.action],!this.action)throw new Error("Unknown BufferSave action "+c.action);this.action==this.actions.SAVERESTORE?this._nextAction=this.actions.SAVE:this.action==this.actions.RESTORESAVE&&(this._nextAction=this.actions.RESTORE),this._bufferId="__BUFFERSAVE_"+c.bufferId,b.super.constructor.call(this)}a.BufferSave=a.defineClass(b,a.Component,{actions:{SAVE:1,RESTORE:2,SAVERESTORE:3,RESTORESAVE:4},init:function(c,d,e){if(b.super.init.call(this,c,d,e),!d.registerBank[this._bufferId]){var f=new a.FrameBufferManager(d.canvas.width,d.canvas.height,c,d.copier,1);d.registerBank[this._bufferId]=f}},update:function(){this.gl;var a,b=this.main.registerBank[this._bufferId];switch(this.action==this.actions.SAVERESTORE||this.action==this.RESTORESAVE?(a=this._nextAction,this._nextAction=this._nextAction==this.actions.SAVE?this.actions.RESTORE:this.actions.SAVE):a=this.action,a){case this.actions.SAVE:b.setRenderTarget(),this.main.copier.run(null,null,this.parent.fm.getCurrentTexture()),b.restoreRenderTarget();break;case this.actions.RESTORE:this.main.copier.run(this.parent.fm,this.blendMode,b.getCurrentTexture())}},destroy:function(){b.super.destroy.call(this),this.main.registerBank[this._bufferId].destroy()}}),b.ui={disp:"Buffer Save",type:"BufferSave",schema:{action:{type:"string",title:"Buffer save action","enum":["SAVE","RESTORE","SAVERESTORE","RESTORESAVE"]},bufferId:{type:"number",title:"Buffer Id","enum":[1,2,3,4,5,6,7,8]},blendMode:{type:"string",title:"Blend mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{speed:1,color:"#000000"}),this.color=a.parseColorNorm(c.color),this.frameCount=0,this.maxFrameCount=Math.floor(1/c.speed),this.program=new a.ClearScreenProgram(a.AVERAGE),b.super.constructor.call(this)}a.FadeOut=a.defineClass(b,a.Component,{componentName:"FadeOut",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.gl,this.frameCount++,this.frameCount==this.maxFrameCount&&(this.frameCount=0,this.program.run(this.parent.fm,null,this.color))},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),b.ui={type:"FadeOut",disp:"Fade Out",schema:{speed:{type:"number",title:"Speed",maximum:0,minimum:1,"default":1},color:{type:"string",title:"Fadeout color",format:"color","default":"#FFFFFF"}},form:[{key:"speed",type:"range",step:"0.05"},"color"]}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["kernel"]),c=_.defaults(c,{edgeMode:"EXTEND",bias:0});var d;if(c.kernel in b.kernels)d=b.kernels[c.kernel];else{if(!_.isArray(c.kernel)||1!==c.kernel.length%2)throw new Error("Invalid convolution kernel");d=c.kernel}var e=Math.floor(Math.sqrt(d.length));if(e*e!=d.length)throw new Error("Invalid convolution kernel");this.program=new a.ConvolutionProgram(d,e,c.edgeMode,c.scale,c.bias),b.super.constructor.call(this)}function c(b,d,e,f,g){var h="";switch(e){case"WRAP":h="pos = vec2(pos.x<0?pos.x+1.0:pos.x%1, pos.y<0?pos.y+1.0:pos.y%1);";break;case"EXTEND":h="pos = clamp(pos, vec2(0,0), vec2(1,1));";break;default:throw new Error("Invalid edge mode")}var i,j,k=[],l=Math.floor(d/2);for(i=0;d>i;i++)for(j=0;d>j;j++){var m=b[i*d+j];0!==m&&(k.push("pos = v_position + onePixel * vec2("+(i-l)+","+(j-l)+");"),k.push(h),k.push("colorSum += texture2D(u_srcTexture, pos) * "+a.glslFloatRepr(m)+";"))}_.isUndefined(f)&&(f=_.reduce(b,function(a,b){return a+b},0)),c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["void main() {"," vec2 onePixel = vec2(1.0, 1.0)/u_resolution;"," vec2 pos;"," vec4 colorSum = vec4(0,0,0,0);",k.join("\n")," setFragColor(vec4(((colorSum+"+a.glslFloatRepr(g)+") / "+a.glslFloatRepr(f)+").rgb, 1.0));","}"]})}a.Convolution=a.defineClass(b,a.Component,{componentName:"Convolution",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),b.kernels={normal:[0,0,0,0,1,0,0,0,0],gaussianBlur:[.045,.122,.045,.122,.332,.122,.045,.122,.045],unsharpen:[-1,-1,-1,-1,9,-1,-1,-1,-1],emboss:[-2,-1,0,-1,1,1,0,1,2],blur:[1,1,1,1,1,1,1,1,1]},a.ConvolutionProgram=a.defineClass(c,a.QuadBoxProgram)}(Webvs),function(a){function b(c){if(a.checkRequiredOptions(c,["maps"]),c=_.defaults(c,{key:"RED",output:"REPLACE",mapCycleMode:"SINGLE"}),this.maps=c.maps,this.currentMap=0,this.mapCycleMode=this.mapCycleModes[c.mapCycleMode],!this.mapCycleMode)throw new Error("Unknown mapCycleMode "+c.mapCycleMode);this.program=new a.ColorMapProgram(c.key,a.blendModes[c.output]),b.super.constructor.call(this)}function c(a,b){var d="";switch(a){case"RED":d="srcColor.r";break;case"GREEN":d="srcColor.g";break;case"BLUE":d="srcColor.b";break;case"(R+G+B)/2":d="mod((srcColor.r+srcColor.g+srcColor.b)/2.0, 1.0)";break;case"(R+G+B)/3":d="(srcColor.r+srcColor.g+srcColor.b)/3.0";break;case"MAX":d="max(srcColor.r, max(srcColor.g, srcColor.b))";break;default:throw new Error("Unknown colormap key function "+options.key)}c.super.constructor.call(this,{outputBlendMode:b,swapFrame:!0,fragmentShader:["uniform sampler2D u_colorMap;","void main() {"," vec4 srcColor = getSrcColor();"," setFragColor(texture2D(u_colorMap, vec2(("+d+"), 0)));","}"]})}a.ColorMap=a.defineClass(b,a.Component,{mapCycleModes:{SINGLE:1,ONBEATRANDOM:2,ONBEATSEQUENTIAL:3},init:function(a,c,d){b.super.init.call(this,a,c,d),this.colorMaps=_.map(this.maps,function(a){return this._buildColorMap(a)},this),this.currentMap=0,this.program.init(a)},update:function(){if(this.main.analyser.beat)switch(this.mapCycleMode){case this.mapCycleModes.ONBEATRANDOM:this.currentMap=Math.floor(Math.random()*this.colorMaps.length);break;case this.mapCycleModes.ONBEATSEQUENTIAL:this.currentMap=(this.currentMap+1)%this.colorMaps.length}this.program.run(this.parent.fm,null,this.colorMaps[this.currentMap])},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_buildColorMap:function(b){var c=this.gl;b=_.sortBy(b,function(a){return a.index});var d=_.map(b,function(a){return a.index});if(_.uniq(d).length!=d.length)throw new Error("map cannot have repeated indices");var e=_.first(b);0!==e.index&&b.splice(0,0,{color:e.color,index:0});var f=_.last(b);255!==f.index&&b.push({color:f.color,index:255}),b=_.map(b,function(b){var c=a.parseColor(b.color);return{color:c,index:b.index}});var g=new Uint8Array(1024),h=0,i=_.zip(_.first(b,b.length-1),_.last(b,b.length-1));_.each(i,function(a){var b=a[0],c=a[1],d=c.index-b.index,e=[(c.color[0]-b.color[0])/d,(c.color[1]-b.color[1])/d,(c.color[2]-b.color[2])/d];_.times(d,function(a){g[h++]=b.color[0]+e[0]*a,g[h++]=b.color[1]+e[1]*a,g[h++]=b.color[2]+e[2]*a,g[h++]=255})}),g[h++]=f.color[0],g[h++]=f.color[1],g[h++]=f.color[2],g[h++]=255;var j=c.createTexture();return c.bindTexture(c.TEXTURE_2D,j),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,256,1,0,c.RGBA,c.UNSIGNED_BYTE,g),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),j}}),a.ColorMapProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_colorMap","texture2D",a),c.super.draw.call(this)}}),b.ui={disp:"Color Map",type:"ColorMap",schema:{maps:{type:"array",items:{type:"array",title:"Map",items:{type:"object",properties:{color:{type:"string",title:"Color",format:"color","default":"#FFFFFF"},index:{type:"number",title:"Index",minimum:0,maximum:255}}}}},key:{type:"string",title:"Map key","enum":["RED","GREEN","BLUE","(R+G+B)/2","(R+G+B)/3","MAX"],"default":"RED"},mapCycleMode:{type:"string",title:"Map Cycle Mode","enum":["SINGLE","ONBEATRANDOM","ONBEATSEQUENTIAL"],"default":"SINGLE"},output:{type:"string",title:"Output blend mode","enum":_.keys(a.blendModes),"default":"REPLACE"}}}}(Webvs),function(a){function b(b){if(a.checkRequiredOptions(b,["mode","color","outColor"]),b=_.defaults(b,{mode:"BELOW",color:"#202020",outColor:"#202020",level:0}),this.mode=_.indexOf(this.modes,b.mode),-1==this.mode)throw new Error("ColorClip: invalid mode");this.color=a.parseColorNorm(b.color),this.outColor=a.parseColorNorm(b.outColor),this.level=b.level,this.program=new a.ColorClipProgram}function c(){c.super.constructor({swapFrame:!0,fragmentShader:["uniform int u_mode;","uniform vec3 u_color;","uniform vec3 u_outColor;","uniform float u_level;","void main() {"," vec4 inColor4 = getSrcColor();"," vec3 inColor = inColor4.rgb;"," bool clip = false;"," if(u_mode == 0) {"," clip = all(lessThanEqual(inColor, u_color));"," }"," if(u_mode == 1) {"," clip = all(greaterThanEqual(inColor, u_color));"," }"," if(u_mode == 2) {"," clip = (distance(inColor, u_color) <= u_level*0.5);"," }"," if(clip) {"," setFragColor(vec4(u_outColor, inColor4.a));"," } else {"," setFragColor(inColor4);"," }","}"]})}a.ColorClip=a.defineClass(b,a.Component,{modes:["BELOW","ABOVE","NEAR"],componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.program.run(this.parent.fm,null,this.mode,this.color,this.outColor,this.level)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ColorClipProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a,b,d,e){this.setUniform("u_mode","1i",a),this.setUniform.apply(this,["u_color","3f"].concat(b)),this.setUniform.apply(this,["u_outColor","3f"].concat(d)),this.setUniform("u_level","1f",e),c.super.draw.call(this)}})}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["code"]),c=_.defaults(c,{gridW:16,gridH:16,noGrid:!1,bFilter:!0,compat:!1,coord:"POLAR"});var d;if(!_.isObject(c.code))throw new Error("Invalid Dynamic movement code");d=c.code;var e=new a.ExprCodeGenerator(d,["x","y","r","d","b","w","h"]),f=e.generateCode(["init","onBeat","perFrame"],["perPixel"],["x","y","d","r"]);this.code=f[0],this.inited=!1,this.noGrid=c.noGrid,this.gridW=c.gridW,this.gridH=c.gridH,this.coordMode=c.coord,this.bFilter=c.bFilter,this.compat=c.compat,this.program=this.noGrid?new a.DMovProgramNG(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]):new a.DMovProgram(this.coordMode,this.bFilter,this.compat,this.code.hasRandom,f[1]),b.super.constructor.call(this)}function c(a,b,d,e,f){var g=[f,this.glslFilter(b,d),"void main() {",e?"__randSeed = v_position;":""," x = v_position.x*2.0-1.0;"," y = -(v_position.y*2.0-1.0);",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," setFragColor(vec4(filter(vec2(x, -y)), 1));","}"];c.super.constructor.call(this,{fragmentShader:g,swapFrame:!0})}function d(a,b,c,e,f){var g=["attribute vec2 a_position;","varying vec2 v_newPoint;","uniform int u_coordMode;",f,"void main() {",e?"__randSeed = a_position;":""," x = a_position.x;"," y = -a_position.y;",this.glslRectToPolar(a)," perPixel();",this.glslPolarToRect(a)," v_newPoint = vec2(x,-y);"," setPosition(a_position);","}"],h=["varying vec2 v_newPoint;",this.glslFilter(b,c),"void main() {"," setFragColor(vec4(filter(v_newPoint), 1));","}"];d.super.constructor.call(this,{fragmentShader:h,vertexShader:g,swapFrame:!0})}a.DynamicMovement=a.defineClass(b,a.Component,{componentName:"DynamicMovement",init:function(a,c,d){if(b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,d),!this.noGrid){for(var e=2*(this.gridW/this.main.canvas.width),f=2*(this.gridH/this.main.canvas.height),g=Math.ceil(this.main.canvas.width/this.gridW),h=Math.ceil(this.main.canvas.height/this.gridH),i=new Float32Array(2*6*g*h),j=0,k=-1,l=-1,m=0;h>m;m++){for(var n=0;g>n;n++){var o=Math.min(k+e,1),p=Math.min(l+f,1);i[j++]=k,i[j++]=l,i[j++]=o,i[j++]=l,i[j++]=k,i[j++]=p,i[j++]=o,i[j++]=l,i[j++]=o,i[j++]=p,i[j++]=k,i[j++]=p,k+=e}k=-1,l+=f}this.gridVertices=i,this.gridVerticesSize=j/2}},update:function(){var a=this.code;this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat(),this.noGrid?this.program.run(this.parent.fm,null,this.code):this.program.run(this.parent.fm,null,this.code,this.gridVertices,this.gridVerticesSize)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}});var e={glslRectToPolar:function(a){return"POLAR"===a?["d = distance(vec2(x, y), vec2(0,0))/sqrt(2.0);","r = mod(atan(y, x)+PI*0.5, 2.0*PI);"].join("\n"):""},glslPolarToRect:function(a){return"POLAR"===a?["d = d*sqrt(2.0);","x = d*sin(r);","y = -d*cos(r);"].join("\n"):""},glslFilter:function(a,b){return a&&!b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 cornoff = fract(coord/texel);"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," vec3 pt = mix(tl, tr, cornoff.x);"," vec3 pb = mix(bl, br, cornoff.x);"," return mix(pt, pb, cornoff.y);","}"].join("\n"):a&&b?["vec3 filter(vec2 point) {"," vec2 texel = 1.0/(u_resolution-vec2(1,1));"," vec2 coord = (point+1.0)/2.0;"," vec2 corn = floor(coord/texel)*texel;"," vec3 tl = getSrcColorAtPos(corn).rgb;"," vec3 tr = getSrcColorAtPos(corn + vec2(texel.x, 0)).rgb;"," vec3 bl = getSrcColorAtPos(corn + vec2(0, texel.y)).rgb;"," vec3 br = getSrcColorAtPos(corn + texel).rgb;"," float xp = floor(fract(coord.x/texel.x)*255.0);"," float yp = floor(fract(coord.y/texel.y)*255.0);"," #define g_blendtable(i, j) floor(((i)/255.0)*(j))"," float a1 = g_blendtable(255.0-xp, 255.0-yp);"," float a2 = g_blendtable(xp, 255.0-yp);"," float a3 = g_blendtable(255.0-xp, yp);"," float a4 = g_blendtable(xp, yp);"," float r = (floor(a1*tl.r) + floor(a2*tr.r) + floor(a3*bl.r) + floor(a4*br.r))/255.0;"," float g = (floor(a1*tl.g) + floor(a2*tr.g) + floor(a3*bl.g) + floor(a4*br.g))/255.0;"," float b = (floor(a1*tl.b) + floor(a2*tr.b) + floor(a3*bl.b) + floor(a4*br.b))/255.0;"," return vec3(r, g, b);","}"].join("\n"):["vec3 filter(vec2 point) {"," return getSrcColorAtPos((point+1.0)/2.0).rgb;","}"].join("\n")}};a.DMovProgramNG=a.defineClass(c,a.QuadBoxProgram,e,{draw:function(a){a.bindUniforms(this),c.super.draw.call(this)}}),a.DMovProgram=a.defineClass(d,a.ShaderProgram,e,{draw:function(a,b,c){a.bindUniforms(this),this.setVertexAttribArray("a_position",b,2,this.gl.FLOAT,!1,0,0),this.gl.drawArrays(this.gl.TRIANGLES,0,c)}}),b.ui={type:"DynamicMovement",disp:"Dynamic Movement",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPixel:{type:"string",title:"Per Point"}}},gridW:{type:"number",title:"Grid Width","default":16},gridH:{type:"number",title:"Grid Height","default":16},coord:{type:"string",title:"Coordinate System","enum":["POLAR","RECT"],"default":"POLAR"}},form:[{key:"code.init",type:"textarea"},{key:"code.onBeat",type:"textarea"},{key:"code.perFrame",type:"textarea"},{key:"code.perPixel",type:"textarea"},"gridW","gridH","coord"]}}(Webvs),function(a){function b(a){if(a=_.defaults(a,{channel:"RGB",onBeatRandom:!1}),this.channel=d.indexOf(a.channel),-1==this.channel)throw new Error("Invalid Channel");this.onBeatRandom=a.onBeatRandom,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{swapFrame:!0,fragmentShader:["uniform int u_channel;","void main() {"," vec3 color = getSrcColor().rgb;",_.flatMap(d,function(a,b){return["if(u_channel == "+b+") {"," setFragColor(vec4(color."+a.toLowerCase()+",1));","}"]}).join("\n"),"}"]})}var d=["RGB","RBG","BRG","BGR","GBR","GRB"];a.ChannelShift=a.defineClass(b,a.Component,{componentName:"ChannelShift",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){this.onBeatRandom&&this.main.analyser.beat&&(this.channel=Math.floor(Math.random()*d.length)),this.program.run(this.parent.fm,null,this.channel)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()}}),a.ChannelShiftProgram=a.defineClass(c,a.QuadBoxProgram,{draw:function(a){this.setUniform("u_channel","1i",a),c.super.draw.call(this)}}),b.ui={disp:"Channel Shift",type:"ChannelShift",schema:{channel:{type:"string",title:"Channel","enum":d},onBeatRandom:{type:"boolean",title:"On beat random"}}}}(Webvs),function(a){function b(d){a.checkRequiredOptions(d,["code"]),d=_.defaults(d,{source:"SPECTRUM",drawMode:"LINES",colors:["#ffffff"]});var e;if(!_.isObject(d.code))throw new Error("Invalid superscope");e=d.code;var f=new a.ExprCodeGenerator(e,["n","v","i","x","y","b","w","h","red","green","blue","cid"]),g=f.generateCode(["init","onBeat","perFrame","perPoint"],[],[]);this.code=g[0],this.code.n=100,this.spectrum="SPECTRUM"==d.source,this.dots="DOTS"==d.drawMode,this.colors=_.map(d.colors,a.parseColorNorm),this.currentColor=this.colors[0],this.maxStep=100,this.step=this.maxStep,this.colorId=0,this.colorStep=[0,0,0],this.thickness=d.thickness?d.thickness:1,this.inited=!1,this.program=new c,b.super.constructor.call(this)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_position;","attribute vec3 a_color;","varying vec3 v_color;","uniform float u_pointSize;","void main() {"," gl_PointSize = u_pointSize;"," setPosition(clamp(a_position, vec2(-1,-1), vec2(1,1)));"," v_color = a_color;","}"],fragmentShader:["varying vec3 v_color;","void main() {"," setFragColor(vec4(v_color, 1));","}"]})}a.SuperScope=a.defineClass(b,a.Component,{componentName:"SuperScope",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a),this.code.setup(c,this)},update:function(){this.gl;var a=this.code;this._stepColor(),a.red=this.currentColor[0],a.green=this.currentColor[1],a.blue=this.currentColor[2],this.inited||(a.init(),this.inited=!0);var b=this.main.analyser.beat;a.b=b?1:0,a.perFrame(),b&&a.onBeat();for(var c=Math.floor(a.n),d=this.spectrum?this.main.analyser.getSpectrum():this.main.analyser.getWaveform(),e=d.length/c,f=0,g=0,h=new Float32Array(2*(this.dots?c:2*c-2)),i=new Float32Array(3*(this.dots?c:2*c-2)),j=0;c>j;j++){for(var k=0,l=0,m=Math.floor(j*e);(j+1)*e>m;m++,l++)k+=d[m];k/=l;var n=j/(c-1);a.i=n,a.v=k,a.perPoint(),h[f++]=a.x,h[f++]=-1*a.y,0===j||j==c-1||this.dots||(h[f++]=a.x,h[f++]=-1*a.y),this.dots?(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue):0!==j&&(i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue,i[g++]=a.red,i[g++]=a.green,i[g++]=a.blue)}this.program.run(this.parent.fm,null,h,i,this.dots,this.thickness)},destroy:function(){b.super.destroy.call(this),this.program.cleanup()},_stepColor:function(){var a;if(this.colors.length>1)if(this.step==this.maxStep){var b=this.colors[this.colorId];this.colorId=(this.colorId+1)%this.colors.length;var c=this.colors[this.colorId];for(a=0;3>a;a++)this.colorStep[a]=(c[a]-b[a])/this.maxStep;this.step=0,this.currentColor=b}else{for(a=0;3>a;a++)this.currentColor[a]+=this.colorStep[a];this.step++}}}),a.SuperScopeShader=a.defineClass(c,a.ShaderProgram,{draw:function(a,b,c,d){var e=this.gl;this.setUniform("u_pointSize","1f",d),this.setVertexAttribArray("a_position",a,2,e.FLOAT,!1,0,0),this.setVertexAttribArray("a_color",b,3,e.FLOAT,!1,0,0);var f;c||(f=e.getParameter(e.LINE_WIDTH),e.lineWidth(d)),e.drawArrays(c?e.POINTS:e.LINES,0,a.length/2),c||e.lineWidth(f)}}),b.ui={disp:"SuperScope",type:"SuperScope",schema:{code:{type:"object",title:"Code","default":{},properties:{init:{type:"string",title:"Init"},onBeat:{type:"string",title:"On Beat"},perFrame:{type:"string",title:"Per Frame"},perPoint:{type:"string",title:"Per Point"}}},source:{type:"string",title:"Source","default":"WAVEFORM","enum":["WAVEFORM","SPECTRUM"]},drawMode:{type:"string",title:"Draw Mode","default":"LINES","enum":["DOTS","LINES"]},colors:{type:"array",title:"Cycle Colors",items:{type:"string",format:"color","default":"#FFFFFF"}}}}}(Webvs),function(a){function b(c){c=_.defaults(c,{n:0,color:"#000000",blendMode:"REPLACE"}),this.n=c.n,this.color=a.parseColorNorm(c.color),this.outputBlendMode=a.blendModes[c.blendMode],this.prevBeat=!1,this.beatCount=0,this.program=new a.ClearScreenProgram(this.outputBlendMode),b.super.constructor.call(this)}a.ClearScreen=a.defineClass(b,a.Component,{componentName:"ClearScreen",init:function(a,c,d){b.super.init.call(this,a,c,d),this.program.init(a)},update:function(){var a=!1;0===this.n?a=!0:(this.main.analyser.beat&&!this.prevBeat&&(this.beatCount++,this.beatCount==this.n&&(a=!0,this.beatCount=0)),this.prevBeat=this.main.analyser.beat),a&&this.program.run(this.parent.fm,null,this.color) },destroy:function(){this.program.cleanup()}}),b.ui={type:"ClearScreen",disp:"Clear Screen",schema:{n:{type:"number",title:"Clear on beat (0 = always clear)","default":0},color:{type:"string",title:"Clear color",format:"color","default":"#000000"},blendMode:{type:"string",title:"Blend Mode","enum":_.keys(a.blendModes)}}}}(Webvs),function(a){function b(c){a.checkRequiredOptions(c,["src","x","y"]),this.x=c.x,this.y=c.y,this.src=c.src,this.program=new a.PictureProgram,b.super.constructor.call(this,c)}function c(){c.super.constructor.call(this,{copyOnSwap:!0,vertexShader:["attribute vec2 a_texVertex;","uniform vec2 u_pos;","uniform vec2 u_texRes;","varying vec2 v_texCoord;","void main() {"," v_texCoord = a_texVertex;"," setPosition(a_texVertex*(u_texRes/u_resolution)*vec2(2,-2)+u_pos);","}"],fragmentShader:["uniform sampler2D u_image;","varying vec2 v_texCoord;","void main() {"," setFragColor(texture2D(u_image, v_texCoord));","}"]})}a.Picture=a.defineClass(b,a.Component,{init:function(c,d,e){b.super.init.call(this,c,d,e),this.program.init(c);var f=this,g=new Image;g.src=this.src;var h=new a.Promise;return g.onload=function(){f.width=g.width,f.height=g.height,f.texture=c.createTexture(),c.bindTexture(c.TEXTURE_2D,f.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,g),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),h.resolve()},h},update:function(){this.program.run(this.parent.fm,null,this.x,this.y,this.texture,this.width,this.height)},destroy:function(){this.program.cleanup(),this.gl.deleteTexture(this.texture)}}),a.PictureProgram=a.defineClass(c,a.ShaderProgram,{draw:function(a,b,c,d,e){this.setUniform("u_pos","2f",a,-b),this.setUniform("u_texRes","2f",d,e),this.setUniform("u_image","texture2D",c),this.setVertexAttribArray("a_texVertex",new Float32Array([0,0,0,1,1,1,0,0,1,1,1,0])),this.gl.drawArrays(this.gl.TRIANGLES,0,6)}})}(Webvs); \ No newline at end of file