UNPKG

genish.js

Version:
293 lines (225 loc) 6.38 kB
'use strict' let gen = { memo: new Map(), graph:null, accum:0, isNotNumber( v ) { return (typeof v)[0] !== 'n' }, getUID() { return this.accum++ }, out() { this.memo.clear() return this.graph.out() }, } let table = frequency => { var tableSize = 1024, table_ = new Float32Array( tableSize ), phase = 0, tableFreq = 44100 / tableSize for( var i = 0; i < table_.length; i++ ) { table_[ i ] = Math.sin( ( i / tableSize ) * ( Math.PI * 2 ) ) } return { uid: gen.getUID(), /* phase: 0, frequency, table, tableFreq: 44100 / tableSize, // replace with sample rate */ memo: gen.memo, isNotNumber: gen.isNotNumber, out: function( freq ) { var index, frac, index2, val1, val2, sign phase += freq / tableFreq //while( this.phase >= 1024 ) this.phase -= 1024 index = phase | 0 frac = phase - index index = index & 1023 index2 = index === 1023 ? 0 : index + 1 val1 = table_[ index ] val2 = table_[ index2 ] return val1 + ( frac * (val2 - val1) ) } } } let wavetable = function() { var phase = 0, tableSize = 1024, tableFreq = 44100 / 1024, table = new Float32Array( tableSize ) for( var i = 0; i < table.length; i++ ) { table[ i ] = Math.sin( ( i / tableSize ) * ( Math.PI * 2 ) ) } this.callback = function(frequency, amp, sync) { var index, frac, index2, val1, val2, sign; phase += frequency / tableFreq; while(phase >= 1024) phase -= 1024; index = phase | 0; frac = phase - index; index = index & 1023; index2 = index === 1023 ? 0 : index + 1; val1 = table[index]; val2 = table[index2]; return ( val1 + ( frac * (val2 - val1) ) ) * amp; } } let tableClosure = frequency => { let phase = 0, tableSize = 1024, tableFreq = 44100 / tableSize, table = new Float32Array( tableSize ) let ugen = function() { var index, frac, index2, val1, val2, sign phase += frequency / tableFreq //while( this.phase >= 1024 ) this.phase -= 1024 index = phase | 0 frac = phase - index index = index & 1023 index2 = index === 1023 ? 0 : index + 1 val1 = table[ index ] val2 = table[ index2 ] return ( val1 + ( frac * (val2 - val1) ) ) } for( let i = 0; i < table.length; i++ ) { table[ i ] = Math.sin( ( i / tableSize ) * ( Math.PI * 2 ) ) } return ugen.bind({ uid: gen.getUID(), frequency, phase: 0, table, tableFreq: 44100 / tableSize, // replace with sample rate memo: gen.memo, isNotNumber: gen.isNotNumber }) } let abs = x => { let ugen = function() { if( this.uid in this.memo ) return this.memo[ this.uid ] let out = this.inputs[ 0 ] if( this.isNotNumber( out ) ) out = out() out = this.abs( out ) this.memo.set( this.uid, out ) return out } return { uid: gen.getUID(), inputs: [ x ], abs: Math.abs, memo: gen.memo, isNotNumber: gen.isNotNumber, out:ugen } } let sin = x => { let ugen = function() { if( this.uid in this.memo ) return this.memo[ this.uid ] let out = this.inputs[ 0 ] if( this.isNotNumber( out ) ) out = out() out = this.sin( out ) this.memo.set( this.uid, out ) return out } return ugen.bind({ uid: gen.getUID(), inputs: [ x ], sin: Math.sin, memo: gen.memo, isNotNumber: gen.isNotNumber }) } let mul = ( x,y ) => { let ugen = function() { //if( this.uid in this.memo ) return this.memo[ this.uid ] let x = this.x, y = this.y if( xIsUgen ) x = x.out() if( yIsUgen ) y = y.out() let out = x * y //this.memo.set( this.uid, out ) return out } let xIsUgen = gen.isNotNumber( x ), yIsUgen = gen.isNotNumber( y ) return { uid: gen.getUID(), x,y,xIsUgen,yIsUgen, memo: gen.memo, isNotNumber: gen.isNotNumber, out:ugen } } let add = ( x,y ) => { let ugen = function() { if( this.uid in this.memo ) return this.memo[ this.uid ] let x = this.inputs[ 0 ], y = this.inputs[ 1 ] if( this.isNotNumber( x ) ) x = x() if( this.isNotNumber( y ) ) y = y() let out = x + y this.memo.set( this.uid, out ) return out } return ugen.bind({ uid: gen.getUID(), inputs: [ x,y ], memo: gen.memo, isNotNumber: gen.isNotNumber }) } let accum = ( incr, reset=0, min=0, max=1 ) => { let ugen = function() { if( this.uid in this.memo ) return this.memo[ this.uid ] let incr = this.inputs[ 0 ], reset = this.inputs[ 1 ] if( this.isNotNumber( incr ) ) incr = incr() if( this.isNotNumber( reset ) ) reset = reset() this.out += incr if( reset ) { this.out = this.min }else{ if( this.out > this.max ) this.out = this.min } this.memo.set( this.uid, this.out ) return this.out } return ugen.bind({ min, max, out: 0, uid: gen.getUID(), inputs: [ incr, reset ], memo: gen.memo, isNotNumber: gen.isNotNumber }) } let bus = ( ...args ) => { let ugen = function() { //if( this.uid in this.memo ) return this.memo[ this.uid ] let out = 0 for( let i = 0, l = this.inputs.length; i < l; i++ ) { let input = this.inputs[ i ] out += input.value.out()//input.isNotNumber ? input.value.out() : input.value } //this.memo.set( this.uid, out ) return out } let inputs = args.map( ( v ) => ({ isNotNumber: gen.isNotNumber( v ), value: v }) ) return { uid: gen.getUID(), inputs, memo: gen.memo, isNotNumber: gen.isNotNumber, out:ugen } } let param = value => { let p = function( v ) { if( v !== undefined ) this.value = v return this.value } return p.bind({ value }) } let PI = Math.PI, SR = 44100 module.exports = { gen, add, mul, accum, abs, sin, bus, param, table, PI, SR, tableClosure, wavetable }