hayleigh-dot-dev/elm-web-audio/1.1.0

NOTE: the latest version is 1.1.1

Formerly pd-andy/elm-web-audio. Search finds this package by either name.

WebAudio.Property

Types

Properties are how we configure the behaviour of audio nodes: things like an oscillator's frequency or a filter's cutoff.

import WebAudio
import WebAudio.Property


myOsc =
    WebAudio.oscillator
        [ WebAudio.Property.linearRampToValueAtTime 1 <|
            WebAudio.Property.frequency 880
        , WebAudio.Property.type_ "sine"
        ]
        [ WebAudio.gain
            [ WebAudio.Property.gain 0.5 ]
            [ WebAudio.audioDestination ]
        ]

This example showcases the different types of properties you can construct:

  • properties like type_. These are typical object properties that are set on the node like any other JavaScript object, and might be a bool, float, string, etc.

  • audioParams like frequency are special, and represent values that can be changed over time using the scheduled updates described below. These are always Floats!

  • Scheduled updates like linearRampToValueAtTime. These describe how a property should change over time. These scheduled updates only work with audio params, and not normal properties.

type Value

Represents a value of some property. Our audio graphs are supposed to be declarative, so we don't want to be able to change the values of properties – you'd just return a different graph with the property you wanted changed.

This type enumerates the different types of values that might be assigned to a property like an Elm String or Float, etc.

Basic Constructors

property : String -> Value -> Property

Create a custom property for a node. This is like writing node.type = 'sine' in JavaScript:

import WebAudio.Property exposing (Property)


sine : Property
sine =
    WebAudio.Property.property "type" (WebAudio.Property.string "sine")

Ideally you'll end up using one of the predifined properties like type_ instead of this function, but it's provided in case you have custom audio nodes with properties we might not know about.

audioParam : String -> Float -> Property

Create a custom audio param for a node. This is like writing node.frequency.value = 880 in JavaScript:

import WebAudio.Property exposing (Property)


middleA : Property
middleA =
    WebAudio.Property.audioParam "frequency" 440

Ideally you'll end up using one of the predifined properties like frequency instead of this function, but it's provided in case you have custom audio nodes with properties we might not know about.

Schedule an update to a property to take place at some point in the future. This is like writing node.frequency.setValueAtTime(880, context.currentTime + 1) in JavaScript:

import WebAudio.Property exposing (Property)


setAfterOneSecond : Float -> Property
setAfterOneSecond time =
    WebAudio.Property.setValueAtTime
        (time + 1)
        (WebAudio.Property.frequency 880)

❗️ Note that we're taking in a Float here for the current time, and using that to calculate the time at which we want to set the value. Because our audio graphs are declarative we don't schedule things from now, but rather we schedule things for fixed, known values of time.

The best way to get the current time is to use every or at to trigger a message carrying the context's current time. If you want to trigger things to happen based on the time a particular user event such as a click occured you can use currentTime to get the current time from the context.

import WebAudio
import WebAudio.Context exposing (Context)
import WebAudio.Property


type Event
    = NoteOn Float
    | ...


audio : Context -> Event -> List WebAudio.Node
audio context event =
    case event of
        NoteOn time ->
            [ WebAudio.oscillator
                -- See the docs further down for what
                -- `linearRampToValueAtTime` does!
                [ WebAudio.Property.linearRampToValueAtTime
                    (WebAudio.Context.currentTime context + 1)
                    (WebAudio.Property.frequency 880)
                ]
                [ WebAudio.gain
                    [ WebAudio.Property.gain 0.5 ]
                    [ WebAudio.audioDestination ]
                ]
            ]


        _ ->
            ...

Be really careful when doing this, you can accidentally schedule a bunch of overlapping events if you're not paying attention!

Where setValueAtTime sets a property at a specific time, linearRampToValueAtTime will smoothly ramp the property from its current value to the target value until the given time.

Where setValueAtTime sets a property at a specific time, exponentialRampToValueAtTime will ramp the property from its current value to the target value until the given time using an exponential curve.

Often we perceive exponential curves as more natural than linear curves, so this is a good choice for things like gain or frequency.

Primatives

bool : Bool -> Value
float : Float -> Value
floatList : List Float -> Value
int : Int -> Value
string : String -> Value

Properties

amp : Float -> Property
attack : Float -> Property
curve : List Float -> Property
delayTime : Float -> Property
detune : Float -> Property
fftSize : Int -> Property
frequency : Float -> Property
freq : Float -> Property
gain : Float -> Property
knee : Float -> Property
loop : Bool -> Property
loopEnd : Float -> Property
loopStart : Float -> Property
offset : Float -> Property
oversample : String -> Property
pan : Float -> Property
positionX : Float -> Property
positionY : Float -> Property
positionZ : Float -> Property
q : Float -> Property
ratio : Float -> Property
reduction : Float -> Property
release : Float -> Property
threshold : Float -> Property
type_ : String -> Property

JSON Encoding

encode : Property -> Value