filters.js

/**
 * This module provides some syntactic sugar over the AudioContext.createBiquadFilter
 * function.
 *
 * @example
 * import { conn, square, lowpass, filter, master } from 'synth-kit'
 *
 * master.start(conn(square('C4'), lowpass('C5')))
 * master.start(conn(square('A4'), filter({ type: 'hipass', Q: 10, freq: 1000 }))
 * @module filters
 */
import { OPTS } from './utils'
import { getFreq } from './oscillators'
import { context } from './context'
import { plug, lifecycle } from './routing'

// private: create a filter
function create (type, opts) {
  opts = opts || OPTS
  var filter = context(opts.context).createBiquadFilter()
  filter.type = type || opts.type || 'lowpass'
  return lifecycle(filter, [
    plug('frequency', getFreq(opts), filter),
    plug('Q', opts.Q, filter),
    plug('detune', opts.detune, filter)
  ])
}

/**
 * Create a filter (a [BiquadFilterNode](https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode))
 *
 * @function
 * @param {Object} config - it may include:
 *
 * - frequency (or freq, or note or midi): the frequency expressed in hertzs
 * (or midi note number or note name)
 * - type: one of the BiquadFilterNode types
 * - detune: the detune of the frequency in cents (can be a number or a signal)
 * - Q: the Q of the filter (can be a number or a signal)
 * - context: the audio context to use
 *
 * Instead of a configuration object you can pass a frequency number of note
 * name just to specify the frequency.
 *
 * @return {AudioNode} the BiquadFilterNode
 * @example
 * conn(square(800), filter({ type: 'lowpass', freq: 600 }))
 */
export var filter = create.bind(null, null)

/**
 * Create a lowpass filter. An alias for `filter({ type: 'lowpass', ... })`
 *
 * @function
 * @param {Object} config - same as `filter` function but without type
 * @return {AudioNode} the lowpass filter
 * @see filter
 * @example
 * conn(square('C4'), lowpass(400))
 */
export const lowpass = create.bind(null, 'lowpass')

/**
 * Create a hipass filter. An alias for `filter({ type: 'hipass', ... })`
 *
 * @function
 * @param {Object} config - same as `filter` function but without type
 * @return {AudioNode} the hipass filter
 * @see filter
 * @example
 * conn(square(800), hipass(400))
 */
export const hipass = create.bind(null, 'highpass')

/**
 * Create a bandpass filter. An alias for `filter({ type: 'bandpass', ... })`
 *
 * @function
 * @param {Object} config - same as `filter` function but without type
 * @return {AudioNode} the bandpass filter
 * @see filter
 * @example
 * conn(square(800), bandpass(400))
 */
export const bandpass = create.bind(null, 'hipass')