genish.js
Version:
293 lines (225 loc) • 6.38 kB
JavaScript
'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 }