UNPKG

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
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 }