Skip to content

Latest commit

 

History

History
66 lines (61 loc) · 2.52 KB

DESIGN_DOC.md

File metadata and controls

66 lines (61 loc) · 2.52 KB

Example of subgraph & nodes with metadata. Metadata starts with @ and is in toml format.

@ lowshelf node 
# Uses toml for metadata config
description = "generate the coefficients for a 2nd order IIR shelf filter"
 
[inputs]
# each input can have settings for the ui knobs. Each property is optional.
# similar to in blender, users should be able to manually enter values outside of min/max
cutoff_hz = {default = 1000.0, min = 0.0, max = 20000.0, unit = "Hz", gradient = "TBD", label = "Hz", description = "the -3dB point"}
gain_db = {default = 0.0, min = -48.0, max = 48.0, unit = "dB", gradient = "TBD", label = "gain", description = "gain in dB of the shelf"}
q_value = {default = 1.0, min = 0.01, max = 100.0, gradient = "TBD", label = "Q", description = "filter sharpness"}
@
fn lowshelf(cutoff_hz, gain_db, q_value) -> (a1, a2, a3, m0, m1, m2) {
    cutoff_hz = min(cutoff_hz, globals.sample_rate_hz * 0.5)
    a = pow(10.0, gain_db / 40.0)
    g = tan(PI * cutoff_hz / globals.sample_rate_hz) / sqrt(a)
    k = 1.0 / q_value
    a1 = 1.0 / (1.0 + g * (g + k))
    a2 = g * a1
    a3 = g * a2
    m0 = 1.0
    m1 = k * (a - 1.0)
    m2 = a * a - 1.0
}
 
// Nodes can access persistent data
filter {
    ic1eq
    ic2eq
}
 
// There can also be anonymous nodes with no metadata 
fn filter(self, audio, a1, a2, a3, m0, m1, m2) -> (audio) {
    v3 = audio - self.ic2eq
    v1 = a1 * self.ic1eq + a2 * v3
    v2 = self.ic2eq + a2 * self.ic1eq + a3 * v3
    self.ic1eq = 2.0 * v1 - self.ic1eq
    self.ic2eq = 2.0 * v2 - self.ic2eq
    audio = m0 * audio + m1 * v1 + m2 * v2
}
 
//This sub graph would be audio generated based on the graph in the UI
@ lowshelf subgraph 
description = "a subgraph that implements a stereo shelf"
[inputs]
# derive the descriptions from the other node
cutoff_hz = {derive = "lowshelf"}
gain_db = {derive = "lowshelf"}
q_value = {derive = "lowshelf"}
[nodes]
lowshelf0 = {x = 10, y = 10}
filter0 = {x = 40, y = 10}
filter1 = {x = 40, y = 40}
@
eq_shelf {
    filter0
    filter1
}
fn stereo_shelf(self, audio_l, audio_r, cutoff_hz, gain_db, q_value) -> (audio_l, audio_r) {
    vlowshelf0_a1, vlowshelf0_a2, vlowshelf0_a3, vlowshelf0_m0, vlowshelf0_m1, vlowshelf0_m2 = lowshelf(cutoff_hz, gain_db, q_value)@lowshelf0
    audio_l = filter(self.filter0, audio_l, vlowshelf0_a1, vlowshelf0_a2, vlowshelf0_a3, vlowshelf0_m0, vlowshelf0_m1, vlowshelf0_m2)@filter0
    audio_r = filter(self.filter1, audio_r, vlowshelf0_a1, vlowshelf0_a2, vlowshelf0_a3, vlowshelf0_m0, vlowshelf0_m1, vlowshelf0_m2)@filter1
}