partch

0.15.0 • Public • Published

Partch

Image of Harry Partch with his instruments

A lightweight Web Audio API patching library.

Please note: this is UNDER CONSTRUCTION & should not be considered stable.

Example

First

let P = Partch()

then

P.Synth(({ frequency }) => P({
  saw: P.Saw(frequency),
  sqr: P.Sqr({ frequency, octave: -2, detune: 10 }),
  vcf: P.Lpf(20),
  vca: P.Gain(0),
  env: P.Adsr({ a: 0.01, d: 0.1, s: 0.6, r: 1 })
},
  'saw > vcf > vca > out',
  'sqr > vcf',
  'env > vcf.frequencyCv',
  'env > vca.gainCv'
)).monitor().sequence([
  { t: 0/8, nn: 69 },
  { t: 1/8, nn: 72 },
  { t: 2/8, nn: 76 },
  { t: 3/8, nn: 81 },
  { t: 4/8, nn: 76 },
  { t: 5/8, nn: 72 }
], { loopLength: 6/8, tempo: 190 })

Introduction

Partch is a library designed to simplify the creation of new instruments and FX with the Web Audio API. It has a number of elements which all work together for a pleasurable patching experience.

  • A terse syntax for creating native Web Audio API nodes, with sane defaults.
  • A handful of additional nodes that fill in notable gaps in the Web Audio API.
  • Useful additions and tweaks to the API of created nodes.
  • A Patch function for wiring nodes together into patches.
  • A Synth function for creating polyphonic synthesizers from individual voice functions.

Installation

First yarn add partch or npm install partch --save.

Then, if you're using a bundler such as webpack, simply import Partch from 'partch'.

Alternatively load it directly in the browser with the script tag <script src="path/to/partch.js"></script>.

API

Partch([context])

  • context - AudioContext - Defaults to a new AudioContext.

Returns a Patch function (henceforth abbreviated as P) with a number of attached Node Factory functions. Note that the nodes returned by all these node factories are patched to provide an API which slightly extends the standard functionality of Web Audio API nodes, this Audio Node Extension API is described after the node factories.

P(nodes, [...connections])

  • nodes - Object - An object where the keys are node names and the values are audio nodes, or arrays of audio nodes.
  • connections - Array of String - Strings representing connections between nodes.

Returns a patch node which implements the standard Audio Node Extension API plus the nodes attribute. Note that any array values in the nodes object will be connected in parallel using the Parallel node below.

Connection Strings

Connection strings take the form of a list of nodes separated by a > character. Each node may be either a node name specified in the nodes object, or a dot-separated node path, e.g. synth.filter.frequencyCv. When using a node path, any onward connections after the node will be from the top-level node, i.e. the node whose name comes first in the path.

P.Adsr([config])

  • config - Object | Number - Either the release time or the following config object:
    • attack or a - Number - The attack time in seconds. Defaults to 0.01.
    • decay or d - Number - The decay time in seconds. Defaults to 0.
    • sustain or s - Number - The sustain level. Defaults to 1.
    • release or r - Number - The release time in seconds. Defaults to 1.
    • level - Number - The envelope maximum value (i.e. sustain is multiplied by this). Defaults to 1.

Returns an ASDR envelope node which can be used to control parameters of other nodes. Note that the rise and fall slopes are linear, so if you want exponential slopes, e.g. for controlling filter cutoff, you should connect the signal to one of the provided CV inputs.

P.Const([config])

  • config - Object | Number - Either the offset or the following config object:
    • offset - Number - The constant output level. Defaults to 1.
    • startTime - Number - The AudioContext time at which to start the node. Defaults to immediately.

Returns a Web Audio API ConstantSourceNode.

P.context

The AudioContext with which the Patch function was instantiated.

P.Delay([config])

  • config - Object | Number - Either the delay time or the following config object:
    • delayTime - Number - The delay time in seconds. Defaults to 1.

Returns a Web Audio API DelayNode.

P.Filter([config])

  • config - Object | Number - Either the frequency or the following config object:
    • frequency - Number - The filter frequency in Hz. Defaults to 350.
    • frequencyCv - Number The scaled amount to add to the frequency. Defaults to 0.
    • Q - Number - The Q factor. Roughly equivalent to resonance. Defaults to 1.
    • detune - Number - The offset to add to the frequency, in cents. Defaults to 0.
    • type - String - The filter type. One of lowpass, highpass, bandpass, lowshelf, highshelf, peaking, notch or allpass. Defaults to lowpass.

Returns a Web Audio API BiquadFilterNode. The node has an additional AudioParam, frequencyCv, which is scaled to make a 0-1 input signal cover the whole audible frequency range.

P.Apf([config])

P.Bpf([config])

P.HighShelf([config])

P.Hpf([config])

P.LowShelf([config])

P.Lpf([config])

P.Notch([config])

P.Peak([config])

Aliases for the Filter node with different filter types.

P.Freeverb([config])

  • config - Object | Number - Either the wet level or the following config object:
    • wet - Number - The wet signal gain. Defaults to 0.
    • dry - Number - The dry signal gain. Defaults to 1.
    • roomSize - Number - A number from 0-1 representing the size of the reverb space. Defaults to 0.8.
    • dampening - Number - A frequency in Hz which corresponds to the amount of "ringing". Defaults to 3000.

Returns a reverb node based on the Freeverb algorithm (imported from https://github.com/mmckegg/freeverb).

P.Gain([config])

  • config - Object | Number - Either the gain or the following config object:
    • gain - Number - The amount of gain. Defaults to 1.
    • gainCv - Number The scaled amount to add to the gain. Defaults to 0.

Returns a Web Audio API GainNode. The node has an additional AudioParam, gainCv, which is scaled to produce an exponential volume curve that sounds more natural to the human ear than the linear slope produced by automating the gain level. Specifically, a gainCv of 0.5 maps to an additional gain of 0.1.

P.load(url)

  • url - String - Url to load.

A helper function to load an audio buffer from a URL. Returns a promise which will either resolve to an AudioBuffer, or throw an error.

P.Noise([config])

  • config - Object | String - Either the noise color or the following config object:
    • color - String - The type of noise. One of brown, pink or white. Defaults to white.
    • startTime - Number - The AudioContext time at which to start the node. Defaults to immediately.

Returns a Sample node that plays the specified type of noise.

P.BrownNoise()

P.PinkNoise()

P.WhiteNoise()

Aliases for the Noise node with different color settings.

P.Osc([config])

  • config - Object | Number - Either the frequency or the following config object:
    • frequency - Number - The oscillator frequency in Hz. Defaults to 440.
    • frequencyCv - Number - The scaled amount to add to the frequency. Defaults to 0.
    • octave - Number - The number of octaves (positive or negative) by which to offset the frequency. Defaults to 0.
    • detune - Number - The offset to add to the frequency, in cents. Defaults to 0.
    • type - String - The oscillator waveform. One of sine, square, sawtooth or triangle. Defaults to sine.
    • startTime - Number - The AudioContext time at which to start the node. Defaults to immediately.

Returns a Web Audio API OscillatorNode. The node has an additional AudioParam, frequencyCv, which is scaled to make a 0-1 input signal cover the whole audible frequency range.

P.Saw([config])

P.Sin([config])

P.Sqr([config])

P.Tri([config])

Aliases for the Osc node with different waveform types.

P.Over([config])

  • config - Number - Either the drive amount or the following config object:
    • drive - Number - Gain applied before waveshaping. Defaults to 1.
    • shape - Number - Number from 0-1 representing the how much the waveshape distorts the signal. Defaults to 0.725.
    • algo - Number - Number from 0-5 specifying which shaping algorithm to use. Default is 0.
    • makeup - Number - Gain applied after waveshaping. Defaults to 1.

Returns a custom Overdrive node adapted from Tuna.js.

P.Parallel(nodes, [count])

  • nodes - Array | Function - Either an array of nodes or a function which takes a 0-based index and returns a node.
  • count - Number - If nodes is a function, the number of nodes to create.

Returns a patch with the given nodes connected in parallel, i.e. with the input connected to every node input and every node output connected to the output.

P.Sample([config])

  • config - Object | AudioBuffer - Either the buffer or the following config object:
    • buffer - AudioBuffer - The AudioBuffer to play.
    • detune - Number - The factor to adjust the frequency, in cents. Defaults to 0.
    • loop - Boolean - Whether or not to loop the sample. Defaults to false.
    • loopStart - Number - Start of the loop in seconds. Defaults to 0.
    • loopEnd - Number - End of the loop in seconds. Defaults to 0.
    • playbackRate - Number - The rate at which to play the sample where 1 is its natural rate. Defaults to 1.
    • startTime - Number - The AudioContext time at which to start the node. Defaults to immediately.

Returns a Web Audio API AudioBufferSourceNode. The node has an additional AudioParam, playbackRateCv, which is scaled to make a 0-1 input signal cover the whole audible frequency range.

P.Shaper([config])

  • config - Object | Float32Array - Either the curve or the following config object:
    • curve - Float32Array - The shaping curve.
    • oversample - String - The oversample setting. One of none, 2x or 4x.

Returns a Web Audio API WaveShaperNode.

P.Synth(Voice)

  • Voice - Function - A factory function which will construct the synth voice. Should take one parameter, the object passed to synth.play with an additional frequency property giving the frequency of the played note in standard equal temperament tuning.

Returns a node which can create new voices with the passed-in factory function and connect them to its output. In addition to the standard node methods it implements the play and sequence method.

synth.play(options)

  • options - Object
    • nn - Number - The MIDI note number to play. Defaults to 69 (middle A).
    • time or t - Number - The AudioContext time at which to play the note. Defaults to immediately.
    • dur - Number - The length of time in seconds to play the note for. If falsey, note will not be released. Defaults to 0.2.

Calls the voice function with the passed in MIDI note number converted to a frequency. Returns the new voice node.

synth.sequence(events, [options])

  • events - Array - An array of sequencer event objects.
  • options - Object
    • loopLength - Number - The time at which to loop the sequence, in Whole Notes.
    • tempo - Number - The tempo in bpm. Defaults to 120.

This is a simple wrapper around the functionality of um-sequencer. Each sequencer event object can contain the same keys as the synth.play options object, but here the time attribute is the musical time in Whole Notes from the start of the sequence. If looping is required, the loopLength option must be set.

Returns a sequencer object with stop and changeTempo(tempo) methods (see the um-sequencer docs for more information).

Audio Node Extension API

On top of the standard Web Audio API AudioNode interface, Partch makes some enhancements. Firstly, it patches connect and disconnect so that they can handle nodes which have an input property. Secondly, it adds the following members:

node.input

On a native Web Audio API this is just an alias for the node itself. On a patch node this is an alias for patch.nodes.in. When connecting from a native Web Audio API node to a patch, this should be the connection destination.

node.monitor()

Connects the patch to the context.destination. Returns the node.

node.set(config)

  • config - Object | Any - A config object or value used to update the node parameters.

This method takes the same config object or value as the factory method for the node. On a patch node it should be an object whose keys correspond with the nodes in the patch, and whose values are objects or values to be passed on to the set function on those nodes. As a result it is possible to recursively set the params of a whole "tree" of nested patches by simply passing in a nested object. Returns the node.

node.test([dur], [type])

  • dur - Number - The duration of the test in seconds. Defaults to 0.2.
  • type - String | Number - The type of test sound to use or the note to play. If the former, one of bleep or noise. Defaults to bleep.

This is a function for quickly testing a node. Firstly it monitors the node. Then, for nodes without an input, it will simply stop it after the given duration. For nodes with a play method it will play for the given duration, with the type param specifying the note. For nodes with an input, it will create a sound source of the type indicated, stop the source after the given duration, and stop the node 10 seconds after.

node.triggerAttack([time])

  • time - Number - The AudioContext time at which to trigger attack. Defaults to immediately.

If the node is an envelope, or a patch containing an envelope, triggers the attack portion of the envelope(s) at time. Returns the node.

node.triggerRelease([time])

  • time - Number - The AudioContext time at which to trigger release. Defaults to immediately.

If the node is an envelope, or a patch containing an envelope, triggers the release portion of the envelope(s) at time and then stops the node. Returns the node.

Cookbook

The philosophy of Partch is to give you a small number of fundamental building blocks while making it as easy as possible to build your own high-level abstractions from those blocks. In that spirit, components such as phasers, chorus effects, analogue-style delays, autopanners and so on are not included. Instead, here are some example patches for you to copy and paste, in the hope that you will modify them to your own taste, creating effects and instruments that are entirely unique to you.

Simple delay

P({
  dry: P.Gain(1),
  wet: P.Gain(0.5),
  delay: P.Delay(0.5),
  feedback: P.Gain(0.5)
},
  'in > dry > out',
  'in > delay > wet > out',
  'delay > feedback > delay'
).test()

Tape-style delay

P({
  dry: P.Gain(1),
  wet: P.Gain(0.5),
  delay: P.Delay(0.5),
  feedback: P.Gain(0.4),
  od: P.Over({ drive: 0.5, shape: 0.7, makeup: 0.7 }),
  highCut: P.Lpf(6000),
  lowCut: P.Hpf(60),
  wow: P.Sin(0.1),
  wowLevel: P.Gain(0.005),
  flutter: P.Sin(5.3),
  flutterLevel: P.Gain(0.00015)
},
  'in > dry > out',
  'in > od > highCut > lowCut > delay > wet > out',
  'delay > feedback > od',
  'wow > wowLevel > delay.delayTime',
  'flutter > flutterLevel > delay.delayTime'
).test()

Flanger

P({
  dry: P.Gain(1),
  wet: P.Gain(1),
  dryDelay: P.Delay(0.02),
  wetDelay: P.Delay(0.02),
  depth: P.Gain(0.02),
  feedback: P.Gain(-0.5),
  lfo: P.Sin(0.1)
},
  'in > dryDelay > dry > out',
  'in > wetDelay > wet > out',
  'wetDelay > feedback > wetDelay',
  'lfo > depth > wetDelay.delayTime'
).test(5, 'noise')

Classic three-osc synth

P.Synth(({ frequency: f }) => P({
  osc1: P.Saw(f),
  osc2: P.Saw(* 1.01),
  osc3: P.Sqr(/ 2),
  filter: P.Lpf(40),
  filterFb: P.Gain(0.3),
  filterEnv: P.Adsr({ a: 0.1, d: 0.2, s: 0.6, r: 1, level: 0.7 }),
  amp: P.Gain(0),
  ampEnv: P.Adsr({ a: 0.01, r: 1.5 })
},
  'osc1 > filter',
  'osc2 > filter',
  'osc3 > filter',
  'filter > amp > out',
  'filter > filterFb > filter',
  'filterEnv > filter.frequencyCv',
  'ampEnv > amp.gainCv'
)).test(1, 45)

Organ

P.Synth((f) => P({
  partials: [P.Sin(f), P.Sin(* 2), P.Sin(* 3)],
},
  'partials > out'
)).test(1, 45)

Package Sidebar

Install

npm i partch

Weekly Downloads

7

Version

0.15.0

License

MIT

Unpacked Size

2.03 MB

Total Files

59

Last publish

Collaborators

  • debrisapron