genish.js

A library for generating optimized, single-sample audio callbacks in JavaScript. Inspired by gen~ in Max/MSP.

try it out

http://www.charlie-roberts.com/genish/playground

Genish.js is alpha status and currently runs in Chrome and Firefox.

what?

A little more detail: genish.js will compile per-sample callback functions from a graph. Given the following code:

abs( add( mul(5,2), input() ) )

...genish will generate the following function.

function gen( in6 ){ 
  'use strict'
  let memory = gen.memory

  gen.out[0]  = gen.abs( (in6 + 10) )

  return gen.out[0]
}

abs, a reference to Math.abs, is assigned as a property to the named gen function as part of the codegen process; this removes the need to look it up in the global scope. genish is also reduces multiplcation of two numbers to a constant. A sine oscillator accepting frequency as an input could be expressed as follows:

frequency = input()
sin( mul( accum( mul( frequency, 1/gen.samplerate ) ), Math.PI * 2 ) )

... which would then be translated into the following function:

function gen( in0 ){ 
  'use strict'
  let memory = gen.memory

  let accum2_value = memory[0];
  memory[0] += (in0 * 0.000022675736961451248)
  if( memory[0] >= 1 ) memory[0] -= 1
  if( memory[0] < 0 ) memory[0] += 1

  gen.out[0]  = gen.sin( (accum2_value * 6.283185307179586) )

  return gen.out[0]
}

The sin function is assigned as a property of the named gen function in this example; this limits most objects and functions to an object in the current scope. All memory used in any generated callback (in this case only a single float) is centrally stored in a single Float32Array, which decreases the need for de-referencing throughout the callback and yields improved efficiency.

use

To use genish.js, you need to create an AudioContext and a ScriptProcessor node that will run the functions genish.js creates. Genish includes a utilities object that provides convenience methods for these tasks, as well as inserting generated functions into the callback of the ScriptProcessor. The following example performs the necessary setup and starts a sine oscillator running:

 // optionally put all genish object in global namespace
genish.export( window )

utilities.createContext().createScriptProcessor()

// second argument prints generated function body to console
utilities.playGraph( cycle( 330 ), true )

develop & test

The build script is a gulpfile. With gulp installed, run gulp or gulp watch in the top level of the repo. gulp test will run the testing suite (mocha).