gibberish-dsp
Version:
Gibberish is designed to be an optimized API for audio synthesis using per-sample techniques.
116 lines (86 loc) • 3.42 kB
JavaScript
const g = require( 'genish.js' ),
filterProto = require( './filter.js' )
module.exports = function( Gibberish ) {
Gibberish.genish.zd24 = ( input, _Q, freq, isStereo=false ) => {
const iT = 1 / g.gen.samplerate,
z1 = g.history(0),
z2 = g.history(0),
z3 = g.history(0),
z4 = g.history(0)
const Q = g.memo( g.add( .5, g.mul( _Q, 23 ) ) )
// kwd = 2 * $M_PI * acf[kindx]
const kwd = g.memo( g.mul( Math.PI * 2, freq ) )
// kwa = (2/iT) * tan(kwd * iT/2)
const kwa =g.memo( g.mul( 2/iT, g.tan( g.mul( kwd, iT/2 ) ) ) )
// kG = kwa * iT/2
const kg = g.memo( g.mul( kwa, iT/2 ) )
// kk = 4.0*(kQ - 0.5)/(25.0 - 0.5)
const kk = g.memo( g.mul( 4, g.div( g.sub( Q, .5 ), 24.5 ) ) )
// kg_plus_1 = (1.0 + kg)
const kg_plus_1 = g.add( 1, kg )
// kG = kg / kg_plus_1
const kG = g.memo( g.div( kg, kg_plus_1 ) ),
kG_2 = g.memo( g.mul( kG, kG ) ),
kG_3 = g.mul( kG_2, kG ),
kGAMMA = g.mul( kG_2, kG_2 )
const kS1 = g.div( z1.out, kg_plus_1 ),
kS2 = g.div( z2.out, kg_plus_1 ),
kS3 = g.div( z3.out, kg_plus_1 ),
kS4 = g.div( z4.out, kg_plus_1 )
//kS = kG_3 * kS1 + kG_2 * kS2 + kG * kS3 + kS4
const kS = g.memo(
g.add(
g.add( g.mul(kG_3, kS1), g.mul( kG_2, kS2) ),
g.add( g.mul(kG, kS3), kS4 )
)
)
//ku = (kin - kk * kS) / (1 + kk * kGAMMA)
const ku1 = g.sub( input, g.mul( kk, kS ) )
const ku2 = g.memo( g.add( 1, g.mul( kk, kGAMMA ) ) )
const ku = g.memo( g.div( ku1, ku2 ) )
let kv = g.memo( g.mul( g.sub( ku, z1.out ), kG ) )
let klp = g.memo( g.add( kv, z1.out ) )
z1.in( g.add( klp, kv ) )
kv = g.memo( g.mul( g.sub( klp, z2.out ), kG ) )
klp = g.memo( g.add( kv, z2.out ) )
z2.in( g.add( klp, kv ) )
kv = g.memo( g.mul( g.sub( klp, z3.out ), kG ) )
klp = g.memo( g.add( kv, z3.out ) )
z3.in( g.add( klp, kv ) )
kv = g.memo( g.mul( g.sub( klp, z4.out ), kG ) )
klp = g.memo( g.add( kv, z4.out ) )
z4.in( g.add( klp, kv ) )
if( isStereo ) {
//let polesR = g.data([ 0,0,0,0 ], 1, { meta:true }),
// rezzR = g.clamp( g.mul( polesR[3], rez ) ),
// outputR = g.sub( input[1], rezzR )
//polesR[0] = g.add( polesR[0], g.mul( g.add( g.mul(-1, polesR[0] ), outputR ), cutoff ))
//polesR[1] = g.add( polesR[1], g.mul( g.add( g.mul(-1, polesR[1] ), polesR[0] ), cutoff ))
//polesR[2] = g.add( polesR[2], g.mul( g.add( g.mul(-1, polesR[2] ), polesR[1] ), cutoff ))
//polesR[3] = g.add( polesR[3], g.mul( g.add( g.mul(-1, polesR[3] ), polesR[2] ), cutoff ))
//let right = g.switch( isLowPass, polesR[3], g.sub( outputR, polesR[3] ) )
//returnValue = [left, right]
}//else{
//returnValue = klp
//}
return klp//returnValue
}
const Zd24 = inputProps => {
const filter = Object.create( filterProto )
const props = Object.assign( {}, Zd24.defaults, filter.defaults, inputProps )
const isStereo = props.input.isStereo
const __out = Gibberish.factory(
filter,
Gibberish.genish.zd24( g.in('input'), g.in('Q'), g.in('cutoff'), isStereo ),
['filters','Filter24Moog'],
props
)
return __out
}
Zd24.defaults = {
input:0,
Q: .75,
cutoff: 440,
}
return Zd24
}