gibberwocky
Version:
music sequencing for Live and Max/MSP
1,948 lines (1,474 loc) • 742 kB
JavaScript
const window = {};
let Gibberish = null;
let initialized = false;
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Gibberish = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
name:'abs',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet ? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ [ this.name ]: isWorklet ? 'Math.abs' : Math.abs })
out = `${ref}abs( ${inputs[0]} )`
} else {
out = Math.abs( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let abs = Object.create( proto )
abs.inputs = [ x ]
return abs
}
},{"./gen.js":30}],2:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'accum',
gen() {
let code,
inputs = gen.getInputs( this ),
genName = 'gen.' + this.name,
functionBody
gen.requestMemory( this.memory )
gen.memory.heap[ this.memory.value.idx ] = this.initialValue
functionBody = this.callback( genName, inputs[0], inputs[1], `memory[${this.memory.value.idx}]` )
//gen.closures.add({ [ this.name ]: this })
gen.memo[ this.name ] = this.name + '_value'
return [ this.name + '_value', functionBody ]
},
callback( _name, _incr, _reset, valueRef ) {
let diff = this.max - this.min,
out = '',
wrap = ''
/* three different methods of wrapping, third is most expensive:
*
* 1: range {0,1}: y = x - (x | 0)
* 2: log2(this.max) == integer: y = x & (this.max - 1)
* 3: all others: if( x >= this.max ) y = this.max -x
*
*/
// must check for reset before storing value for output
if( !(typeof this.inputs[1] === 'number' && this.inputs[1] < 1) ) {
if( this.resetValue !== this.min ) {
out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.resetValue}\n\n`
//out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.min}\n\n`
}else{
out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.min}\n\n`
//out += ` if( ${_reset} >=1 ) ${valueRef} = ${this.initialValue}\n\n`
}
}
out += ` var ${this.name}_value = ${valueRef}\n`
if( this.shouldWrap === false && this.shouldClamp === true ) {
out += ` if( ${valueRef} < ${this.max } ) ${valueRef} += ${_incr}\n`
}else{
out += ` ${valueRef} += ${_incr}\n` // store output value before accumulating
}
if( this.max !== Infinity && this.shouldWrapMax ) wrap += ` if( ${valueRef} >= ${this.max} ) ${valueRef} -= ${diff}\n`
if( this.min !== -Infinity && this.shouldWrapMin ) wrap += ` if( ${valueRef} < ${this.min} ) ${valueRef} += ${diff}\n`
//if( this.min === 0 && this.max === 1 ) {
// wrap = ` ${valueRef} = ${valueRef} - (${valueRef} | 0)\n\n`
//} else if( this.min === 0 && ( Math.log2( this.max ) | 0 ) === Math.log2( this.max ) ) {
// wrap = ` ${valueRef} = ${valueRef} & (${this.max} - 1)\n\n`
//} else if( this.max !== Infinity ){
// wrap = ` if( ${valueRef} >= ${this.max} ) ${valueRef} -= ${diff}\n\n`
//}
out = out + wrap + '\n'
return out
},
defaults : { min:0, max:1, resetValue:0, initialValue:0, shouldWrap:true, shouldWrapMax: true, shouldWrapMin:true, shouldClamp:false }
}
module.exports = ( incr, reset=0, properties ) => {
const ugen = Object.create( proto )
Object.assign( ugen,
{
uid: gen.getUID(),
inputs: [ incr, reset ],
memory: {
value: { length:1, idx:null }
}
},
proto.defaults,
properties
)
if( properties !== undefined && properties.shouldWrapMax === undefined && properties.shouldWrapMin === undefined ) {
if( properties.shouldWrap !== undefined ) {
ugen.shouldWrapMin = ugen.shouldWrapMax = properties.shouldWrap
}
}
if( properties !== undefined && properties.resetValue === undefined ) {
ugen.resetValue = ugen.min
}
if( ugen.initialValue === undefined ) ugen.initialValue = ugen.min
Object.defineProperty( ugen, 'value', {
get() {
//console.log( 'gen:', gen, gen.memory )
return gen.memory.heap[ this.memory.value.idx ]
},
set(v) { gen.memory.heap[ this.memory.value.idx ] = v }
})
ugen.name = `${ugen.basename}${ugen.uid}`
return ugen
}
},{"./gen.js":30}],3:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'acos',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet ? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ 'acos': isWorklet ? 'Math.acos' :Math.acos })
out = `${ref}acos( ${inputs[0]} )`
} else {
out = Math.acos( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let acos = Object.create( proto )
acos.inputs = [ x ]
acos.id = gen.getUID()
acos.name = `${acos.basename}{acos.id}`
return acos
}
},{"./gen.js":30}],4:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
mul = require( './mul.js' ),
sub = require( './sub.js' ),
div = require( './div.js' ),
data = require( './data.js' ),
peek = require( './peek.js' ),
accum = require( './accum.js' ),
ifelse = require( './ifelseif.js' ),
lt = require( './lt.js' ),
bang = require( './bang.js' ),
env = require( './env.js' ),
add = require( './add.js' ),
poke = require( './poke.js' ),
neq = require( './neq.js' ),
and = require( './and.js' ),
gte = require( './gte.js' ),
memo = require( './memo.js' ),
utilities= require( './utilities.js' )
module.exports = ( attackTime = 44100, decayTime = 44100, _props ) => {
const props = Object.assign({}, { shape:'exponential', alpha:5, trigger:null }, _props )
const _bang = props.trigger !== null ? props.trigger : bang(),
phase = accum( 1, _bang, { min:0, max: Infinity, initialValue:-Infinity, shouldWrap:false })
let bufferData, bufferDataReverse, decayData, out, buffer
//console.log( 'shape:', props.shape, 'attack time:', attackTime, 'decay time:', decayTime )
let completeFlag = data( [0] )
// slightly more efficient to use existing phase accumulator for linear envelopes
if( props.shape === 'linear' ) {
out = ifelse(
and( gte( phase, 0), lt( phase, attackTime )),
div( phase, attackTime ),
and( gte( phase, 0), lt( phase, add( attackTime, decayTime ) ) ),
sub( 1, div( sub( phase, attackTime ), decayTime ) ),
neq( phase, -Infinity),
poke( completeFlag, 1, 0, { inline:0 }),
0
)
} else {
bufferData = env({ length:1024, type:props.shape, alpha:props.alpha })
bufferDataReverse = env({ length:1024, type:props.shape, alpha:props.alpha, reverse:true })
out = ifelse(
and( gte( phase, 0), lt( phase, attackTime ) ),
peek( bufferData, div( phase, attackTime ), { boundmode:'clamp' } ),
and( gte(phase,0), lt( phase, add( attackTime, decayTime ) ) ),
peek( bufferDataReverse, div( sub( phase, attackTime ), decayTime ), { boundmode:'clamp' }),
neq( phase, -Infinity ),
poke( completeFlag, 1, 0, { inline:0 }),
0
)
}
const usingWorklet = gen.mode === 'worklet'
if( usingWorklet === true ) {
out.node = null
utilities.register( out )
}
// needed for gibberish... getting this to work right with worklets
// via promises will probably be tricky
out.isComplete = ()=> {
if( usingWorklet === true && out.node !== null ) {
const p = new Promise( resolve => {
out.node.getMemoryValue( completeFlag.memory.values.idx, resolve )
})
return p
}else{
return gen.memory.heap[ completeFlag.memory.values.idx ]
}
}
out.trigger = ()=> {
if( usingWorklet === true && out.node !== null ) {
out.node.port.postMessage({ key:'set', idx:completeFlag.memory.values.idx, value:0 })
}else{
gen.memory.heap[ completeFlag.memory.values.idx ] = 0
}
_bang.trigger()
}
return out
}
},{"./accum.js":2,"./add.js":5,"./and.js":7,"./bang.js":11,"./data.js":18,"./div.js":23,"./env.js":24,"./gen.js":30,"./gte.js":32,"./ifelseif.js":35,"./lt.js":38,"./memo.js":42,"./mul.js":48,"./neq.js":49,"./peek.js":54,"./poke.js":56,"./sub.js":66,"./utilities.js":72}],5:[function(require,module,exports){
'use strict'
const gen = require('./gen.js')
const proto = {
basename:'add',
gen() {
let inputs = gen.getInputs( this ),
out='',
sum = 0, numCount = 0, adderAtEnd = false, alreadyFullSummed = true
if( inputs.length === 0 ) return 0
out = ` var ${this.name} = `
inputs.forEach( (v,i) => {
if( isNaN( v ) ) {
out += v
if( i < inputs.length -1 ) {
adderAtEnd = true
out += ' + '
}
alreadyFullSummed = false
}else{
sum += parseFloat( v )
numCount++
}
})
if( numCount > 0 ) {
out += adderAtEnd || alreadyFullSummed ? sum : ' + ' + sum
}
out += '\n'
gen.memo[ this.name ] = this.name
return [ this.name, out ]
}
}
module.exports = ( ...args ) => {
const add = Object.create( proto )
add.id = gen.getUID()
add.name = add.basename + add.id
add.inputs = args
return add
}
},{"./gen.js":30}],6:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
mul = require( './mul.js' ),
sub = require( './sub.js' ),
div = require( './div.js' ),
data = require( './data.js' ),
peek = require( './peek.js' ),
accum = require( './accum.js' ),
ifelse = require( './ifelseif.js' ),
lt = require( './lt.js' ),
bang = require( './bang.js' ),
env = require( './env.js' ),
param = require( './param.js' ),
add = require( './add.js' ),
gtp = require( './gtp.js' ),
not = require( './not.js' ),
and = require( './and.js' ),
neq = require( './neq.js' ),
poke = require( './poke.js' )
module.exports = ( attackTime=44, decayTime=22050, sustainTime=44100, sustainLevel=.6, releaseTime=44100, _props ) => {
let envTrigger = bang(),
phase = accum( 1, envTrigger, { max: Infinity, shouldWrap:false, initialValue:Infinity }),
shouldSustain = param( 1 ),
defaults = {
shape: 'exponential',
alpha: 5,
triggerRelease: false,
},
props = Object.assign({}, defaults, _props ),
bufferData, decayData, out, buffer, sustainCondition, releaseAccum, releaseCondition
const completeFlag = data( [0] )
bufferData = env({ length:1024, alpha:props.alpha, shift:0, type:props.shape })
sustainCondition = props.triggerRelease
? shouldSustain
: lt( phase, add( attackTime, decayTime, sustainTime ) )
releaseAccum = props.triggerRelease
? gtp( sub( sustainLevel, accum( div( sustainLevel, releaseTime ) , 0, { shouldWrap:false }) ), 0 )
: sub( sustainLevel, mul( div( sub( phase, add( attackTime, decayTime, sustainTime ) ), releaseTime ), sustainLevel ) ),
releaseCondition = props.triggerRelease
? not( shouldSustain )
: lt( phase, add( attackTime, decayTime, sustainTime, releaseTime ) )
out = ifelse(
// attack
lt( phase, attackTime ),
peek( bufferData, div( phase, attackTime ), { boundmode:'clamp' } ),
// decay
lt( phase, add( attackTime, decayTime ) ),
peek( bufferData, sub( 1, mul( div( sub( phase, attackTime ), decayTime ), sub( 1, sustainLevel ) ) ), { boundmode:'clamp' }),
// sustain
and( sustainCondition, neq( phase, Infinity ) ),
peek( bufferData, sustainLevel ),
// release
releaseCondition, //lt( phase, attackTime + decayTime + sustainTime + releaseTime ),
peek(
bufferData,
releaseAccum,
//sub( sustainLevel, mul( div( sub( phase, attackTime + decayTime + sustainTime), releaseTime ), sustainLevel ) ),
{ boundmode:'clamp' }
),
neq( phase, Infinity ),
poke( completeFlag, 1, 0, { inline:0 }),
0
)
const usingWorklet = gen.mode === 'worklet'
if( usingWorklet === true ) {
out.node = null
utilities.register( out )
}
out.trigger = ()=> {
shouldSustain.value = 1
envTrigger.trigger()
}
// needed for gibberish... getting this to work right with worklets
// via promises will probably be tricky
out.isComplete = ()=> {
if( usingWorklet === true && out.node !== null ) {
const p = new Promise( resolve => {
out.node.getMemoryValue( completeFlag.memory.values.idx, resolve )
})
return p
}else{
return gen.memory.heap[ completeFlag.memory.values.idx ]
}
}
out.release = ()=> {
shouldSustain.value = 0
// XXX pretty nasty... grabs accum inside of gtp and resets value manually
// unfortunately envTrigger won't work as it's back to 0 by the time the release block is triggered...
if( usingWorklet && out.node !== null ) {
console.log( 'worklet??' )
out.node.port.postMessage({ key:'set', idx:releaseAccum.inputs[0].inputs[1].memory.value.idx, value:0 })
}else{
console.log( 'non-worklet...' )
gen.memory.heap[ releaseAccum.inputs[0].inputs[1].memory.value.idx ] = 0
}
}
return out
}
},{"./accum.js":2,"./add.js":5,"./and.js":7,"./bang.js":11,"./data.js":18,"./div.js":23,"./env.js":24,"./gen.js":30,"./gtp.js":33,"./ifelseif.js":35,"./lt.js":38,"./mul.js":48,"./neq.js":49,"./not.js":51,"./param.js":53,"./peek.js":54,"./poke.js":56,"./sub.js":66}],7:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' )
let proto = {
basename:'and',
gen() {
let inputs = gen.getInputs( this ), out
out = ` var ${this.name} = (${inputs[0]} !== 0 && ${inputs[1]} !== 0) | 0\n\n`
gen.memo[ this.name ] = `${this.name}`
return [ `${this.name}`, out ]
},
}
module.exports = ( in1, in2 ) => {
let ugen = Object.create( proto )
Object.assign( ugen, {
uid: gen.getUID(),
inputs: [ in1, in2 ],
})
ugen.name = `${ugen.basename}${ugen.uid}`
return ugen
}
},{"./gen.js":30}],8:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'asin',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet ? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ 'asin': isWorklet ? 'Math.sin' : Math.asin })
out = `${ref}asin( ${inputs[0]} )`
} else {
out = Math.asin( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let asin = Object.create( proto )
asin.inputs = [ x ]
asin.id = gen.getUID()
asin.name = `${asin.basename}{asin.id}`
return asin
}
},{"./gen.js":30}],9:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'atan',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet ? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ 'atan': isWorklet ? 'Math.atan' : Math.atan })
out = `${ref}atan( ${inputs[0]} )`
} else {
out = Math.atan( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let atan = Object.create( proto )
atan.inputs = [ x ]
atan.id = gen.getUID()
atan.name = `${atan.basename}{atan.id}`
return atan
}
},{"./gen.js":30}],10:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
history = require( './history.js' ),
mul = require( './mul.js' ),
sub = require( './sub.js' )
module.exports = ( decayTime = 44100 ) => {
let ssd = history ( 1 ),
t60 = Math.exp( -6.907755278921 / decayTime )
ssd.in( mul( ssd.out, t60 ) )
ssd.out.trigger = ()=> {
ssd.value = 1
}
return sub( 1, ssd.out )
}
},{"./gen.js":30,"./history.js":34,"./mul.js":48,"./sub.js":66}],11:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
gen() {
gen.requestMemory( this.memory )
let out =
` var ${this.name} = memory[${this.memory.value.idx}]
if( ${this.name} === 1 ) memory[${this.memory.value.idx}] = 0
`
gen.memo[ this.name ] = this.name
return [ this.name, out ]
}
}
module.exports = ( _props ) => {
let ugen = Object.create( proto ),
props = Object.assign({}, { min:0, max:1 }, _props )
ugen.name = 'bang' + gen.getUID()
ugen.min = props.min
ugen.max = props.max
const usingWorklet = gen.mode === 'worklet'
if( usingWorklet === true ) {
ugen.node = null
utilities.register( ugen )
}
ugen.trigger = () => {
if( usingWorklet === true && ugen.node !== null ) {
ugen.node.port.postMessage({ key:'set', idx:ugen.memory.value.idx, value:ugen.max })
}else{
gen.memory.heap[ ugen.memory.value.idx ] = ugen.max
}
}
ugen.memory = {
value: { length:1, idx:null }
}
return ugen
}
},{"./gen.js":30}],12:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' )
let proto = {
basename:'bool',
gen() {
let inputs = gen.getInputs( this ), out
out = `${inputs[0]} === 0 ? 0 : 1`
//gen.memo[ this.name ] = `gen.data.${this.name}`
//return [ `gen.data.${this.name}`, ' ' +out ]
return out
}
}
module.exports = ( in1 ) => {
let ugen = Object.create( proto )
Object.assign( ugen, {
uid: gen.getUID(),
inputs: [ in1 ],
})
ugen.name = `${ugen.basename}${ugen.uid}`
return ugen
}
},{"./gen.js":30}],13:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
name:'ceil',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet ? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ [ this.name ]: isWorklet ? 'Math.ceil' : Math.ceil })
out = `${ref}ceil( ${inputs[0]} )`
} else {
out = Math.ceil( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let ceil = Object.create( proto )
ceil.inputs = [ x ]
return ceil
}
},{"./gen.js":30}],14:[function(require,module,exports){
'use strict'
let gen = require('./gen.js'),
floor= require('./floor.js'),
sub = require('./sub.js'),
memo = require('./memo.js')
let proto = {
basename:'clip',
gen() {
let code,
inputs = gen.getInputs( this ),
out
out =
` var ${this.name} = ${inputs[0]}
if( ${this.name} > ${inputs[2]} ) ${this.name} = ${inputs[2]}
else if( ${this.name} < ${inputs[1]} ) ${this.name} = ${inputs[1]}
`
out = ' ' + out
gen.memo[ this.name ] = this.name
return [ this.name, out ]
},
}
module.exports = ( in1, min=-1, max=1 ) => {
let ugen = Object.create( proto )
Object.assign( ugen, {
min,
max,
uid: gen.getUID(),
inputs: [ in1, min, max ],
})
ugen.name = `${ugen.basename}${ugen.uid}`
return ugen
}
},{"./floor.js":27,"./gen.js":30,"./memo.js":42,"./sub.js":66}],15:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'cos',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet ? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ 'cos': isWorklet ? 'Math.cos' : Math.cos })
out = `${ref}cos( ${inputs[0]} )`
} else {
out = Math.cos( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let cos = Object.create( proto )
cos.inputs = [ x ]
cos.id = gen.getUID()
cos.name = `${cos.basename}{cos.id}`
return cos
}
},{"./gen.js":30}],16:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'counter',
gen() {
let code,
inputs = gen.getInputs( this ),
genName = 'gen.' + this.name,
functionBody
if( this.memory.value.idx === null ) gen.requestMemory( this.memory )
functionBody = this.callback( genName, inputs[0], inputs[1], inputs[2], inputs[3], inputs[4], `memory[${this.memory.value.idx}]`, `memory[${this.memory.wrap.idx}]` )
gen.memo[ this.name ] = this.name + '_value'
if( gen.memo[ this.wrap.name ] === undefined ) this.wrap.gen()
return [ this.name + '_value', functionBody ]
},
callback( _name, _incr, _min, _max, _reset, loops, valueRef, wrapRef ) {
let diff = this.max - this.min,
out = '',
wrap = ''
// must check for reset before storing value for output
if( !(typeof this.inputs[3] === 'number' && this.inputs[3] < 1) ) {
out += ` if( ${_reset} >= 1 ) ${valueRef} = ${_min}\n`
}
out += ` var ${this.name}_value = ${valueRef};\n ${valueRef} += ${_incr}\n` // store output value before accumulating
if( typeof this.max === 'number' && this.max !== Infinity && typeof this.min !== 'number' ) {
wrap =
` if( ${valueRef} >= ${this.max} && ${loops} > 0) {
${valueRef} -= ${diff}
${wrapRef} = 1
}else{
${wrapRef} = 0
}\n`
}else if( this.max !== Infinity && this.min !== Infinity ) {
wrap =
` if( ${valueRef} >= ${_max} && ${loops} > 0) {
${valueRef} -= ${_max} - ${_min}
${wrapRef} = 1
}else if( ${valueRef} < ${_min} && ${loops} > 0) {
${valueRef} += ${_max} - ${_min}
${wrapRef} = 1
}else{
${wrapRef} = 0
}\n`
}else{
out += '\n'
}
out = out + wrap
return out
}
}
module.exports = ( incr=1, min=0, max=Infinity, reset=0, loops=1, properties ) => {
let ugen = Object.create( proto ),
defaults = { initialValue: 0, shouldWrap:true }
if( properties !== undefined ) Object.assign( defaults, properties )
Object.assign( ugen, {
min: min,
max: max,
value: defaults.initialValue,
uid: gen.getUID(),
inputs: [ incr, min, max, reset, loops ],
memory: {
value: { length:1, idx: null },
wrap: { length:1, idx: null }
},
wrap : {
gen() {
if( ugen.memory.wrap.idx === null ) {
gen.requestMemory( ugen.memory )
}
gen.getInputs( this )
gen.memo[ this.name ] = `memory[ ${ugen.memory.wrap.idx} ]`
return `memory[ ${ugen.memory.wrap.idx} ]`
}
}
},
defaults )
Object.defineProperty( ugen, 'value', {
get() {
if( this.memory.value.idx !== null ) {
return gen.memory.heap[ this.memory.value.idx ]
}
},
set( v ) {
if( this.memory.value.idx !== null ) {
gen.memory.heap[ this.memory.value.idx ] = v
}
}
})
ugen.wrap.inputs = [ ugen ]
ugen.name = `${ugen.basename}${ugen.uid}`
ugen.wrap.name = ugen.name + '_wrap'
return ugen
}
},{"./gen.js":30}],17:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
accum= require( './phasor.js' ),
data = require( './data.js' ),
peek = require( './peek.js' ),
mul = require( './mul.js' ),
phasor=require( './phasor.js')
let proto = {
basename:'cycle',
initTable() {
let buffer = new Float32Array( 1024 )
for( let i = 0, l = buffer.length; i < l; i++ ) {
buffer[ i ] = Math.sin( ( i / l ) * ( Math.PI * 2 ) )
}
gen.globals.cycle = data( buffer, 1, { immutable:true } )
}
}
module.exports = ( frequency=1, reset=0, _props ) => {
if( typeof gen.globals.cycle === 'undefined' ) proto.initTable()
const props = Object.assign({}, { min:0 }, _props )
const ugen = peek( gen.globals.cycle, phasor( frequency, reset, props ))
ugen.name = 'cycle' + gen.getUID()
return ugen
}
},{"./data.js":18,"./gen.js":30,"./mul.js":48,"./peek.js":54,"./phasor.js":55}],18:[function(require,module,exports){
'use strict'
let gen = require('./gen.js'),
utilities = require( './utilities.js' ),
peek = require('./peek.js'),
poke = require('./poke.js')
let proto = {
basename:'data',
globals: {},
gen() {
let idx
if( gen.memo[ this.name ] === undefined ) {
let ugen = this
gen.requestMemory( this.memory, this.immutable )
idx = this.memory.values.idx
try {
gen.memory.heap.set( this.buffer, idx )
}catch( e ) {
console.log( e )
throw Error( 'error with request. asking for ' + this.buffer.length +'. current index: ' + gen.memoryIndex + ' of ' + gen.memory.heap.length )
}
//gen.data[ this.name ] = this
//return 'gen.memory' + this.name + '.buffer'
gen.memo[ this.name ] = idx
}else{
idx = gen.memo[ this.name ]
}
return idx
},
}
module.exports = ( x, y=1, properties ) => {
let ugen, buffer, shouldLoad = false
if( properties !== undefined && properties.global !== undefined ) {
if( gen.globals[ properties.global ] ) {
return gen.globals[ properties.global ]
}
}
if( typeof x === 'number' ) {
if( y !== 1 ) {
buffer = []
for( let i = 0; i < y; i++ ) {
buffer[ i ] = new Float32Array( x )
}
}else{
buffer = new Float32Array( x )
}
}else if( Array.isArray( x ) ) { //! (x instanceof Float32Array ) ) {
let size = x.length
buffer = new Float32Array( size )
for( let i = 0; i < x.length; i++ ) {
buffer[ i ] = x[ i ]
}
}else if( typeof x === 'string' ) {
buffer = { length: y > 1 ? y : gen.samplerate * 60 } // XXX what???
shouldLoad = true
}else if( x instanceof Float32Array ) {
buffer = x
}
ugen = Object.create( proto )
Object.assign( ugen, {
buffer,
name: proto.basename + gen.getUID(),
dim: buffer.length, // XXX how do we dynamically allocate this?
channels : 1,
onload: null,
then( fnc ) {
ugen.onload = fnc
return ugen
},
immutable: properties !== undefined && properties.immutable === true ? true : false,
load( filename ) {
let promise = utilities.loadSample( filename, ugen )
promise.then( ( _buffer )=> {
ugen.memory.values.length = ugen.dim = _buffer.length
ugen.onload()
})
},
memory : {
values: { length:buffer.length, idx:null }
}
})
if( shouldLoad ) ugen.load( x )
if( properties !== undefined ) {
if( properties.global !== undefined ) {
gen.globals[ properties.global ] = ugen
}
if( properties.meta === true ) {
for( let i = 0, length = ugen.buffer.length; i < length; i++ ) {
Object.defineProperty( ugen, i, {
get () {
return peek( ugen, i, { mode:'simple', interp:'none' } )
},
set( v ) {
return poke( ugen, v, i )
}
})
}
}
}
return ugen
}
},{"./gen.js":30,"./peek.js":54,"./poke.js":56,"./utilities.js":72}],19:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
history = require( './history.js' ),
sub = require( './sub.js' ),
add = require( './add.js' ),
mul = require( './mul.js' ),
memo = require( './memo.js' )
module.exports = ( in1 ) => {
let x1 = history(),
y1 = history(),
filter
//History x1, y1; y = in1 - x1 + y1*0.9997; x1 = in1; y1 = y; out1 = y;
filter = memo( add( sub( in1, x1.out ), mul( y1.out, .9997 ) ) )
x1.in( in1 )
y1.in( filter )
return filter
}
},{"./add.js":5,"./gen.js":30,"./history.js":34,"./memo.js":42,"./mul.js":48,"./sub.js":66}],20:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
history = require( './history.js' ),
mul = require( './mul.js' ),
t60 = require( './t60.js' )
module.exports = ( decayTime = 44100, props ) => {
let properties = Object.assign({}, { initValue:1 }, props ),
ssd = history ( properties.initValue )
ssd.in( mul( ssd.out, t60( decayTime ) ) )
ssd.out.trigger = ()=> {
ssd.value = 1
}
return ssd.out
}
},{"./gen.js":30,"./history.js":34,"./mul.js":48,"./t60.js":68}],21:[function(require,module,exports){
'use strict'
const gen = require( './gen.js' ),
data = require( './data.js' ),
poke = require( './poke.js' ),
peek = require( './peek.js' ),
sub = require( './sub.js' ),
wrap = require( './wrap.js' ),
accum= require( './accum.js'),
memo = require( './memo.js' )
const proto = {
basename:'delay',
gen() {
let inputs = gen.getInputs( this )
gen.memo[ this.name ] = inputs[0]
return inputs[0]
},
}
const defaults = { size: 512, interp:'none' }
module.exports = ( in1, taps, properties ) => {
const ugen = Object.create( proto )
let writeIdx, readIdx, delaydata
if( Array.isArray( taps ) === false ) taps = [ taps ]
const props = Object.assign( {}, defaults, properties )
const maxTapSize = Math.max( ...taps )
if( props.size < maxTapSize ) props.size = maxTapSize
delaydata = data( props.size )
ugen.inputs = []
writeIdx = accum( 1, 0, { max:props.size, min:0 })
for( let i = 0; i < taps.length; i++ ) {
ugen.inputs[ i ] = peek( delaydata, wrap( sub( writeIdx, taps[i] ), 0, props.size ),{ mode:'samples', interp:props.interp })
}
ugen.outputs = ugen.inputs // XXX ugh, Ugh, UGH! but i guess it works.
poke( delaydata, in1, writeIdx )
ugen.name = `${ugen.basename}${gen.getUID()}`
return ugen
}
},{"./accum.js":2,"./data.js":18,"./gen.js":30,"./memo.js":42,"./peek.js":54,"./poke.js":56,"./sub.js":66,"./wrap.js":74}],22:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' ),
history = require( './history.js' ),
sub = require( './sub.js' )
module.exports = ( in1 ) => {
let n1 = history()
n1.in( in1 )
let ugen = sub( in1, n1.out )
ugen.name = 'delta'+gen.getUID()
return ugen
}
},{"./gen.js":30,"./history.js":34,"./sub.js":66}],23:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
const proto = {
basename:'div',
gen() {
let inputs = gen.getInputs( this ),
out=` var ${this.name} = `,
diff = 0,
numCount = 0,
lastNumber = inputs[ 0 ],
lastNumberIsUgen = isNaN( lastNumber ),
divAtEnd = false
inputs.forEach( (v,i) => {
if( i === 0 ) return
let isNumberUgen = isNaN( v ),
isFinalIdx = i === inputs.length - 1
if( !lastNumberIsUgen && !isNumberUgen ) {
lastNumber = lastNumber / v
out += lastNumber
}else{
out += `${lastNumber} / ${v}`
}
if( !isFinalIdx ) out += ' / '
})
out += '\n'
gen.memo[ this.name ] = this.name
return [ this.name, out ]
}
}
module.exports = (...args) => {
const div = Object.create( proto )
Object.assign( div, {
id: gen.getUID(),
inputs: args,
})
div.name = div.basename + div.id
return div
}
},{"./gen.js":30}],24:[function(require,module,exports){
'use strict'
let gen = require( './gen' ),
windows = require( './windows' ),
data = require( './data' ),
peek = require( './peek' ),
phasor = require( './phasor' ),
defaults = {
type:'triangular', length:1024, alpha:.15, shift:0, reverse:false
}
module.exports = props => {
let properties = Object.assign( {}, defaults, props )
let buffer = new Float32Array( properties.length )
let name = properties.type + '_' + properties.length + '_' + properties.shift + '_' + properties.reverse + '_' + properties.alpha
if( typeof gen.globals.windows[ name ] === 'undefined' ) {
for( let i = 0; i < properties.length; i++ ) {
buffer[ i ] = windows[ properties.type ]( properties.length, i, properties.alpha, properties.shift )
}
if( properties.reverse === true ) {
buffer.reverse()
}
gen.globals.windows[ name ] = data( buffer )
}
let ugen = gen.globals.windows[ name ]
ugen.name = 'env' + gen.getUID()
return ugen
}
},{"./data":18,"./gen":30,"./peek":54,"./phasor":55,"./windows":73}],25:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' )
let proto = {
basename:'eq',
gen() {
let inputs = gen.getInputs( this ), out
out = this.inputs[0] === this.inputs[1] ? 1 : ` var ${this.name} = (${inputs[0]} === ${inputs[1]}) | 0\n\n`
gen.memo[ this.name ] = `${this.name}`
return [ `${this.name}`, out ]
},
}
module.exports = ( in1, in2 ) => {
let ugen = Object.create( proto )
Object.assign( ugen, {
uid: gen.getUID(),
inputs: [ in1, in2 ],
})
ugen.name = `${ugen.basename}${ugen.uid}`
return ugen
}
},{"./gen.js":30}],26:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
name:'exp',
gen() {
let out,
inputs = gen.getInputs( this )
const isWorklet = gen.mode === 'worklet'
const ref = isWorklet? '' : 'gen.'
if( isNaN( inputs[0] ) ) {
gen.closures.add({ [ this.name ]: isWorklet ? 'Math.exp' : Math.exp })
out = `${ref}exp( ${inputs[0]} )`
} else {
out = Math.exp( parseFloat( inputs[0] ) )
}
return out
}
}
module.exports = x => {
let exp = Object.create( proto )
exp.inputs = [ x ]
return exp
}
},{"./gen.js":30}],27:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
name:'floor',
gen() {
let out,
inputs = gen.getInputs( this )
if( isNaN( inputs[0] ) ) {
//gen.closures.add({ [ this.name ]: Math.floor })
out = `( ${inputs[0]} | 0 )`
} else {
out = inputs[0] | 0
}
return out
}
}
module.exports = x => {
let floor = Object.create( proto )
floor.inputs = [ x ]
return floor
}
},{"./gen.js":30}],28:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'fold',
gen() {
let code,
inputs = gen.getInputs( this ),
out
out = this.createCallback( inputs[0], this.min, this.max )
gen.memo[ this.name ] = this.name + '_value'
return [ this.name + '_value', out ]
},
createCallback( v, lo, hi ) {
let out =
` var ${this.name}_value = ${v},
${this.name}_range = ${hi} - ${lo},
${this.name}_numWraps = 0
if(${this.name}_value >= ${hi}){
${this.name}_value -= ${this.name}_range
if(${this.name}_value >= ${hi}){
${this.name}_numWraps = ((${this.name}_value - ${lo}) / ${this.name}_range) | 0
${this.name}_value -= ${this.name}_range * ${this.name}_numWraps
}
${this.name}_numWraps++
} else if(${this.name}_value < ${lo}){
${this.name}_value += ${this.name}_range
if(${this.name}_value < ${lo}){
${this.name}_numWraps = ((${this.name}_value - ${lo}) / ${this.name}_range- 1) | 0
${this.name}_value -= ${this.name}_range * ${this.name}_numWraps
}
${this.name}_numWraps--
}
if(${this.name}_numWraps & 1) ${this.name}_value = ${hi} + ${lo} - ${this.name}_value
`
return ' ' + out
}
}
module.exports = ( in1, min=0, max=1 ) => {
let ugen = Object.create( proto )
Object.assign( ugen, {
min,
max,
uid: gen.getUID(),
inputs: [ in1 ],
})
ugen.name = `${ugen.basename}${ugen.uid}`
return ugen
}
},{"./gen.js":30}],29:[function(require,module,exports){
'use strict'
let gen = require( './gen.js' )
let proto = {
basename:'gate',
controlString:null, // insert into output codegen for determining indexing
gen() {
let inputs = gen.getInputs( this ), out
gen.requestMemory( this.memory )
let lastInputMemoryIdx = 'memory[ ' + this.memory.lastInput.idx + ' ]',
outputMemoryStartIdx = this.memory.lastInput.idx + 1,
inputSignal = inputs[0],
controlSignal = inputs[1]
/*
* we check to see if the current control inputs equals our last input
* if so, we store the signal input in the memory associated with the currently
* selected index. If not, we put 0 in the memory associated with the last selected index,
* change the selected index, and then store the signal in put in the memery assoicated
* with the newly selected index
*/
out =
` if( ${controlSignal} !== ${lastInputMemoryIdx} ) {
memory[ ${lastInputMemoryIdx} + ${outputMemoryStartIdx} ] = 0
${lastInputMemoryIdx} = ${controlSignal}
}
memory[ ${outputMemoryStartIdx} + ${controlSignal} ] = ${inputSignal}
`
this.controlString = inputs[1]
this.initialized = true
gen.memo[ this.name ] = this.name
this.outputs.forEach( v => v.gen() )
return [ null, ' ' + out ]
},
childgen() {
if( this.parent.initialized === false ) {
gen.getInputs( this ) // parent gate is only input of a gate output, should only be gen'd once.
}
if( gen.memo[ this.name ] === undefined ) {
gen.requestMemory( this.memory )
gen.memo[ this.name ] = `memory[ ${this.memory.value.idx} ]`
}
return `memory[ ${this.memory.value.idx} ]`
}
}
module.exports = ( control, in1, properties ) => {
let ugen = Object.create( proto ),
defaults = { count: 2 }
if( typeof properties !== undefined ) Object.assign( defaults, properties )
Object.assign( ugen, {
outputs: [],
uid: gen.getUID(),
inputs: [ in1, control ],
memory: {
lastInput: { length:1, idx:null }
},
initialized:false
},
defaults )
ugen.name = `${ugen.basename}${gen.getUID()}`
for( let i = 0; i < ugen.count; i++ ) {
ugen.outputs.push({
index:i,
gen: proto.childgen,
parent:ugen,
inputs: [ ugen ],
memory: {
value: { length:1, idx:null }
},
initialized:false,
name: `${ugen.name}_out${gen.getUID()}`
})
}
return ugen
}
},{"./gen.js":30}],30:[function(require,module,exports){
'use strict'
/* gen.js
*
* low-level code generation for unit generators
*
*/
let MemoryHelper = require( 'memory-helper' )
let gen = {
accum:0,
getUID() { return this.accum++ },
debug:false,
samplerate: 44100, // change on audiocontext creation
shouldLocalize: false,
globals:{
windows: {},
},
mode:'worklet',
/* closures
*
* Functions that are included as arguments to master callback. Examples: Math.abs, Math.random etc.
* XXX Should probably be renamed callbackProperties or something similar... closures are no longer used.
*/
closures: new Set(),
params: new Set(),
inputs: new Set(),
parameters: new Set(),
endBlock: new Set(),
histories: new Map(),
memo: {},
//data: {},
/* export
*
* place gen functions into another object for easier reference
*/
export( obj ) {},
addToEndBlock( v ) {
this.endBlock.add( ' ' + v )
},
requestMemory( memorySpec, immutable=false ) {
for( let key in memorySpec ) {
let request = memorySpec[ key ]
//console.log( 'requesting ' + key + ':' , JSON.stringify( request ) )
if( request.length === undefined ) {
console.log( 'undefined length for:', key )
continue
}
request.idx = gen.memory.alloc( request.length, immutable )
}
},
createMemory( amount, type ) {
const mem = MemoryHelper.create( mem, type )
},
/* createCallback
*
* param ugen - Head of graph to be codegen'd
*
* Generate callback function for a particular ugen graph.
* The gen.closures property stores functions that need to be
* passed as arguments to the final function; these are prefixed
* before any defined params the graph exposes. For example, given:
*
* gen.createCallback( abs( param() ) )
*
* ... the generated function will have a signature of ( abs, p0 ).
*/
createCallback( ugen, mem, debug = false, shouldInlineMemory=false, memType = Float64Array ) {
let isStereo = Array.isArray( ugen ) && ugen.length > 1,
callback,
channel1, channel2
if( typeof mem === 'number' || mem === undefined ) {
mem = MemoryHelper.create( mem, memType )
}
//console.log( 'cb memory:', mem )
this.memory = mem
this.outputIdx = this.memory.alloc( 2, true )
this.memo = {}
this.endBlock.clear()
this.closures.clear()
this.inputs.clear()
this.params.clear()
//this.globals = { windows:{} }
this.parameters.clear()
this.functionBody = " 'use strict'\n"
if( shouldInlineMemory===false ) {
this.functionBody += this.mode === 'worklet' ?
" var memory = this.memory\n\n" :
" var memory = gen.memory\n\n"
}
// call .gen() on the head of the graph we are generating the callback for
//console.log( 'HEAD', ugen )
for( let i = 0; i < 1 + isStereo; i++ ) {
if( typeof ugen[i] === 'number' ) continue
//let channel = isStereo ? ugen[i].gen() : ugen.gen(),
let channel = isStereo ? this.getInput( ugen[i] ) : this.getInput( ugen ),
body = ''
// if .gen() returns array, add ugen callback (graphOutput[1]) to our output functions body
// and then return name of ugen. If .gen() only generates a number (for really simple graphs)
// just return that number (graphOutput[0]).
body += Array.isArray( channel ) ? channel[1] + '\n' + channel[0] : channel
// split body to inject return keyword on last line
body = body.split('\n')
//if( debug ) console.log( 'functionBody length', body )
// next line is to accommodate memo as graph head
if( body[ body.length -1 ].trim().indexOf('let') > -1 ) { body.push( '\n' ) }
// get index of last line
let lastidx = body.length - 1
// insert return keyword
body[ lastidx ] = ' memory[' + (this.outputIdx + i) + '] = ' + body[ lastidx ] + '\n'
this.functionBody += body.join('\n')
}
this.histories.forEach( value => {
if( value !== null )
value.gen()
})
const returnStatement = isStereo ? ` return [ memory[${this.outputIdx}], memory[${this.outputIdx + 1}] ]` : ` return memory[${this.outputIdx}]`
this.functionBody = this.functionBody.split('\n')
if( this.endBlock.size ) {
this.functionBody = this.functionBody.concat( Array.from( this.endBlock ) )
this.functionBody.push( returnStatement )
}else{
this.functionBody.push( returnStatement )
}
// reassemble function body
this.functionBody = this.functionBody.join('\n')
// we can only dynamically create a named function by dynamically creating another function
// to construct the named function! sheesh...
//
if( shouldInlineMemory === true ) {
this.parameters.add( 'memory' )
}
let paramString = ''
if( this.mode === 'worklet' ) {
for( let name of this.parameters.values() ) {
paramString += name + ','
}
paramString = paramString.slice(0,-1)
}
const separator = this.parameters.size !== 0 && this.inputs.size > 0 ? ', ' : ''
let inputString = ''
if( this.mode === 'worklet' ) {
for( let ugen of this.inputs.values() ) {
inputString+= ugen.name + ','
}
inputString = inputString.slice(0,-1)
}
let buildString = this.mode === 'worklet'
? `return function( ${inputString} ${separator} ${paramString} ){ \n${ this.functionBody }\n}`
: `return function gen( ${ [...this.parameters].join(',') } ){ \n${ this.functionBody }\n}`
if( this.debug || debug ) console.log( buildString )
callback = new Function( buildString )()
// assign properties to named function
for( let dict of this.closures.values() ) {
let name = Object.keys( dict )[0],
value = dict[ name ]
callback[ name ] = value
}
for( let dict of this.params.values() ) {
let name = Object.keys( dict )[0],
ugen = dict[ name ]
Object.defineProperty( callback, name, {
configurable: true,
get() { return ugen.value },
set(v){ ugen.value = v }
})
//callback[ name ] = value
}
callback.members = this.closures
callback.data = this.data
callback.params = this.params
callback.inputs = this.inputs
callback.parameters = this.parameters//.slice( 0 )
callback.isStereo = isStereo
//if( MemoryHelper.isPrototypeOf( this.memory ) )
callback.memory = this.memory.heap
this.histories.clear()
return callback
},
/* getInputs
*
* Called by each individual ugen when their .gen() method is called to resolve their various inputs.
* If an input is a number, return the number. If
* it is an ugen, call .gen() on the ugen, memoize the result and return the result. If the
* ugen has previously been memoized return the memoized value.
*
*/
getInputs( ugen ) {
return ugen.inputs.map( gen.getInput )
},
getInput( input ) {
let isObject = typeof input === 'object',
processedInput
if( isObject ) { // if input is a ugen...
//console.log( input.name, gen.memo[ input.name ] )
if( gen.memo[ input.name ] ) { // if it has been memoized...
processedInput = gen.memo[ input.name ]
}else if( Array.isArray( input ) ) {
gen.getInput( input[0] )
gen.getInput( input[1] )
}else{ // if not memoized generate code
if( typeof input.gen !== 'function' ) {
console.log( 'no gen found:', input, input.gen )
}
let code = input.gen()
//if( code.indexOf( 'Object' ) > -1 ) console.log( 'bad input:', input, code )
if( Array.isArray( code ) ) {
if( !gen.shouldLocalize ) {
gen.functionBody += code[1]
}else{
gen.codeName = code[0]
gen.localizedCode.push( code[1] )
}
//console.log( 'after GEN' , this.functionBody )
processedInput = code[0]
}else{
processedInput = code
}
}
}else{ // it input is a number
processedInput = input
}
return processedInput
},
startLocalize() {
this.localizedCode = []
this.shouldLocalize = true
},
endLocalize() {
this.shouldLocalize = false
return [ this.codeName, this.localizedCode.slice(0) ]
},
free( graph ) {
if( Array.isArray( graph ) ) { // stereo ugen
for( let channel of graph ) {
this.free( channel )
}
} else {
if( typeof graph === 'object' ) {
if( graph.memory !== undefined ) {
for( let memoryKey in graph.memory ) {
this.memory.free( graph.memory[ memoryKey ].idx )
}
}
if( Array.isArray( graph.inputs ) ) {
for( let ugen of graph.inputs ) {
this.free( ugen )
}
}
}
}
}
}
module.exports = gen
},{"memory-helper":141}],31:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
basename:'gt',
gen() {
let out,
inputs = gen.getInputs( this )
out = ` var ${this.name} = `
if( isNaN( this.inputs[0] ) || isNaN( this.inputs[1] ) ) {
out += `(( ${inputs[0]} > ${inputs[1]}) | 0 )`
} else {
out += inputs[0] > inputs[1] ? 1 : 0
}
out += '\n\n'
gen.memo[ this.name ] = this.name
return [this.name, out]
}
}
module.exports = (x,y) => {
let gt = Object.create( proto )
gt.inputs = [ x,y ]
gt.name = gt.basename + gen.getUID()
return gt
}
},{"./gen.js":30}],32:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
name:'gte',
gen() {
let out,
inputs = gen.getInputs( this )
out = ` var ${this.name} = `
if( isNaN( this.inputs[0] ) || isNaN( this.inputs[1] ) ) {
out += `( ${inputs[0]} >= ${inputs[1]} | 0 )`
} else {
out += inputs[0] >= inputs[1] ? 1 : 0
}
out += '\n\n'
gen.memo[ this.name ] = this.name
return [this.name, out]
}
}
module.exports = (x,y) => {
let gt = Object.create( proto )
gt.inputs = [ x,y ]
gt.name = 'gte' + gen.getUID()
return gt
}
},{"./gen.js":30}],33:[function(require,module,exports){
'use strict'
let gen = require('./gen.js')
let proto = {
name:'gtp',
gen() {
let out,
inputs = gen.getInputs( this )
if( isNaN( this.inputs[0] ) || isNaN( this.inputs[1] ) ) {
out = `(${inputs[ 0 ]} * ( ( ${inputs[0]} > ${inputs[1]} ) | 0 ) )`
} else {
out = inputs[0] * ( ( inputs[0] > inputs[1] ) | 0 )
}
return out
}
}
module.exports = (x,y) => {
let gtp = Object.create( proto )
gtp.inputs = [ x,y ]
return gtp
}
},{"./gen.js":30}],34:[function(require,module,exports){
'use strict'
let gen = require('./gen