gibberish-dsp
Version:
Gibberish is designed to be an optimized API for audio synthesis using per-sample techniques.
158 lines (126 loc) • 4.79 kB
JavaScript
const serialize = require('serialize-javascript')
module.exports = function( Gibberish ) {
const replaceObj = function( obj, shouldSerializeFunctions = true ) {
if( typeof obj === 'object' && obj !== null && obj.id !== undefined ) {
if( obj.__type !== 'seq' ) { // XXX why?
return { id:obj.id, prop:obj.prop }
}else{
// shouldn't I be serializing most objects, not just seqs?
return serialize( obj )
}
}else if( typeof obj === 'function' && shouldSerializeFunctions === true ) {
return { isFunc:true, value:serialize( obj ) }
}
return obj
}
const makeAndSendObject = function( __name, values, obj ) {
const properties = {}
// object has already been sent through messageport...
for( let key in values ) {
const alreadyProcessed = (typeof values[ key ] === 'object' && values[ key ] !== null && values[ key ].__meta__ !== undefined) ||
(typeof values[key] === 'function' && values[ key ].__meta__ !== undefined )
if( alreadyProcessed ) {
properties[ key ] = { id:values[ key ].__meta__.id }
}else if( Array.isArray( values[ key ] ) ) {
const arr = []
for( let i = 0; i < values[ key ].length; i++ ) {
arr[ i ] = replaceObj( values[ key ][i], false )
}
properties[ key ] = arr
}else if( typeof values[key] === 'object' && values[key] !== null ){
properties[ key ] = replaceObj( values[ key ], false )
}else{
properties[ key ] = values[ key ]
}
}
let serializedProperties = serialize( properties )
if( Array.isArray( __name ) ) {
const oldName = __name[ __name.length - 1 ]
__name[ __name.length - 1 ] = oldName[0].toUpperCase() + oldName.substring(1)
}else{
__name = [ __name[0].toUpperCase() + __name.substring(1) ]
}
obj.__meta__ = {
address:'add',
name:__name,
properties:serializedProperties,
id:obj.id
}
Gibberish.worklet.ugens.set( obj.id, obj )
Gibberish.worklet.port.postMessage( obj.__meta__ )
}
const doNotProxy = [ 'connected', 'input', 'wrap', 'callback', 'inputNames', 'on', 'off','publish' ]
const __proxy = function( __name, values, obj ) {
if( Gibberish.mode === 'worklet' && Gibberish.preventProxy === false ) {
makeAndSendObject( __name, values, obj )
// proxy for all method calls to send to worklet
const proxy = new Proxy( obj, {
get( target, prop, receiver ) {
if( typeof target[ prop ] === 'function' && prop.indexOf('__') === -1 && doNotProxy.indexOf( prop ) === -1 ) {
const proxy = new Proxy( target[ prop ], {
apply( __target, thisArg, args ) {
if( Gibberish.proxyEnabled === true ) {
const __args = args.map( __value => replaceObj( __value, true ) )
Gibberish.worklet.port.postMessage({
address:'method',
object:obj.id,
name:prop,
args:__args
})
}
const temp = Gibberish.proxyEnabled
Gibberish.proxyEnabled = false
const out = __target.apply( thisArg, args )
Gibberish.proxyEnabled = temp
return out
}
})
return proxy
}
return target[ prop ]
},
set( target, prop, value, receiver ) {
if( doNotProxy.indexOf( prop ) === -1 ) {
if( Gibberish.proxyEnabled === true ) {
const __value = replaceObj( value )
if( __value !== undefined ) {
Gibberish.worklet.port.postMessage({
address:'set',
object:obj.id,
name:prop,
value:__value
})
}
}
}
target[ prop ] = value
// must return true for any ES6 proxy setter
return true
}
})
// XXX XXX XXX XXX XXX XXX
// REMEMBER THAT YOU MUST ASSIGN THE RETURNED VALUE TO YOUR UGEN,
// YOU CANNOT USE THIS FUNCTION TO MODIFY A UGEN IN PLACE.
// XXX XXX XXX XXX XXX XXX
return proxy
}else if( Gibberish.mode === 'processor' && Gibberish.preventProxy === false ) {
const proxy = new Proxy( obj, {
//get( target, prop, receiver ) { return target[ prop ] },
set( target, prop, value, receiver ) {
let valueType = typeof value
if( prop.indexOf('__') === -1 && valueType !== 'function' && valueType !== 'object' ) {
if( Gibberish.processor !== undefined ) {
Gibberish.processor.messages.push( obj.id, prop, value )
}
}
target[ prop ] = value
// must return true for any ES6 proxy setter
return true
}
})
return proxy
}
return obj
}
return __proxy
}