gibberish-dsp
Version:
Gibberish is designed to be an optimized API for audio synthesis using per-sample techniques.
138 lines (103 loc) • 3.97 kB
JavaScript
const g = require( 'genish.js' ),
ugen = require( '../ugen.js' )(),
__proxy = require( '../workletProxy.js' )
module.exports = function( Gibberish ) {
const Bus2 = Object.create( ugen )
const proxy = __proxy( Gibberish )
let bufferL, bufferR
Object.assign( Bus2, {
create( __props ) {
if( bufferL === undefined ) {
const p = g.pan()
// copy memory... otherwise the wavetables don't have memory indices.
bufferL = Gibberish.memory.alloc(1024)
Gibberish.memory.heap.set( Gibberish.genish.gen.globals.panL.buffer, bufferL )
bufferR = Gibberish.memory.alloc(1024)
Gibberish.memory.heap.set( Gibberish.genish.gen.globals.panR.buffer, bufferR )
}
// XXX must be same type as what is returned by genish for type checks to work correctly
const output = new Float64Array( 2 )
const bus = Object.create( Bus2 )
let init = false
const props = Object.assign({}, Bus2.defaults, __props )
Object.assign(
bus,
{
callback() {
output[ 0 ] = output[ 1 ] = 0
const lastIdx = arguments.length - 1
const memory = arguments[ lastIdx ]
let pan = arguments[ lastIdx - 1 ]
const gain = arguments[ lastIdx - 2 ]
for( let i = 0; i < lastIdx - 2; i+= 3 ) {
const input = arguments[ i ],
level = arguments[ i + 1 ],
isStereo = arguments[ i + 2 ]
output[ 0 ] += isStereo === true ? input[ 0 ] * level : input * level
output[ 1 ] += isStereo === true ? input[ 1 ] * level : input * level
}
if( pan < 0 ) {
pan = 0
}else if( pan > 1 ){
pan = 1
}
const panRawIndex = pan * 1023,
panBaseIndex = panRawIndex | 0,
panNextIndex = (panBaseIndex + 1) & 1023,
interpAmount = panRawIndex - panBaseIndex,
panL = memory[ bufferL + panBaseIndex ]
+ ( interpAmount * ( memory[ bufferL + panNextIndex ] - memory[ bufferL + panBaseIndex ] ) ),
panR = memory[ bufferR + panBaseIndex ]
+ ( interpAmount * ( memory[ bufferR + panNextIndex ] - memory[ bufferR + panBaseIndex ] ) )
output[0] *= gain * panL
output[1] *= gain * panR
return output
},
id : Gibberish.factory.getUID(),
dirty : false,
type : 'bus',
inputs:[ 1, .5 ],
isStereo: true,
__properties__:props
},
Bus2.defaults,
props
)
bus.ugenName = bus.callback.ugenName = 'bus2_' + bus.id
const out = bus.__useProxy__ === true ? proxy( ['Bus2'], props, bus ) : bus
// we have to include custom properties for these as the argument list for
// the compiled output function is variable
// so codegen can't know the correct argument order for the function
let pan = .5
Object.defineProperty( out, 'pan', {
get() { return pan },
set(v){
pan = v
out.inputs[ out.inputs.length - 1 ] = pan
Gibberish.dirty( out )
}
})
let gain = 1
Object.defineProperty( out, 'gain', {
get() { return gain },
set(v){
gain = v
out.inputs[ out.inputs.length - 2 ] = gain
Gibberish.dirty( out )
}
})
return out
},
disconnectUgen( ugen ) {
let removeIdx = this.inputs.indexOf( ugen )
if( removeIdx !== -1 ) {
this.inputs.splice( removeIdx, 3 )
Gibberish.dirty( this )
}
},
defaults: { gain:1, pan:.5, __useProxy__:true }
})
const constructor = Bus2.create.bind( Bus2 )
constructor.defaults = Bus2.defaults
return constructor
}