hdf-0.15: HDF: Uniform Rate Audio Signal Processing in Haskell

Description

Data flow node functions, or unit generators.

Synopsis

# Tuples

split :: a -> (a, a) Source

Duplicate a value into a tuple.

`split 1 == (1,1)`

swap :: a -> b -> (b, a) Source

Reversed tuple constructor, (ie. `flip (,)`)

`swap 2 1 == (1,2)`

# Math

two_pi :: Floating a => a Source

Two pi.

`two_pi == 6.283185307179586`

midi_cps :: Floating a => a -> a Source

Midi note number to cycles per second.

`midi_cps 69 == 440`

mul_add :: Num a => a -> a -> a -> a Source

`map (mul_add 2 3) [1,2] == [5,7] && map (mul_add 3 4) [1,2] == [7,10]`

calc_fb :: Floating a => a -> a -> a Source

Calculate feedback multipler in comb filter circuit given delay and decay times.

`calc_fb 0.2 3.0 == 0.6309573444801932`

lin_lin :: Fractional a => a -> a -> a -> a -> a -> a Source

Linear range conversion.

`map (\i -> lin_lin i (-1) 1 0 1) [-1,-0.9 .. 1.0]`
`import Sound.DF.Uniform.GADT {- hdf -}`
```let {s = lf_saw 1.0 0.0
;o = sin_osc (lin_lin s (-1.0) 1.0 220.0 440.0) 0.0}
in audition_rju [] (out1 (o * 0.1))```

lin_exp :: Floating a => a -> a -> a -> a -> a -> a Source

Exponential range conversion.

`map (\i -> lin_exp i 1 2 1 3) [1,1.1 .. 2]`
```let {s = lf_saw 0.25 0.0
;o = sin_osc (lin_exp (s + 1.0) 0.0 2.0 220.0 440.0) 0.0}
in audition_rju [] (out1 (o * 0.1))```

clip2 :: (Num a, Ord a) => a -> a -> a Source

Constrain p in (-q,q).

```let r = -10 : -10 : [-10,-9 .. 10]
in map (flip clip2 10) [-12,-11 .. 12] == r```

hz_to_incr :: Fractional a => a -> a -> a -> a Source

sr = sample rate, r = cycle (two-pi), hz = frequency

```hz_to_incr 48000 128 375 == 1
hz_to_incr 48000 two_pi 458.3662361046586 == 6e-2```

incr_to_hz :: Fractional a => a -> a -> a -> a Source

Inverse of `hz_to_incr`.

`incr_to_hz 48000 128 1 == 375`

lin_pan2 :: Fractional t => t -> t -> (t, t) Source

Linear pan.

`map (lin_pan2 1) [-1,0,1] == [(1,0),(0.5,0.5),(0,1)]`
```let {o = sin_osc 440.0 0.0
;l = sin_osc 0.5 0.0
;(p,q) = lin_pan2 (o * 0.1) l}
in audition_rju [] (out2 p q)```

# Environment

k_sample_rate :: Fractional n => n Source

Compile time sample rate constant.

k_sample_dur :: Fractional n => n Source

Compile time sample duration (in seconds) constant.

Environment value, `recip` of `w_sample_rate`.

Environment value, equal to `two_pi / w_sample_rate`.

# Tbl

tbl_guard :: [a] -> [a] Source

`tbl_guard [1,2,3] == [1,2,3,1]`

tbl_sin :: Floating n => Int -> [n] Source

Generate guarded sin table.

`map (round . (* 100)) (tbl_sin 12) == [0,50,87,100,87,50,0,-50,-87,-100,-87,-50,0]`

# Phasor

clipr :: K_Num a => DF a -> DF a -> DF a Source

If 'q >= p' then 'q - p' else `q`.

df_clip2 :: K_Num a => DF a -> DF a -> DF a Source

`clip2` variant.

```let o = sin_osc 440 0
in audition_rju [] (out1 (df_clip2 (o * 2) 0.1))```

iir1 :: K' a => a -> Binary_Op (DF a) -> DF a -> DF a Source

Single place infinite impulse response filter with indicated initial value.

```import Data.Int
import Sound.DF.Uniform.LL.K```
```draw (iir1 (0::Int32) (+) 1)
draw (iir1 (0::Float) (+) 1)```

phasor' :: K_Num a => DF a -> a -> DF a -> DF a Source

r = right hand edge, ip = initial phase, x = increment

```draw (phasor 9.0 (4.5::Float) 0.5)
draw (phasor 9 (0::Int32) 1)
audition_text 10 (out1 (phasor' 5.0 0.0 1.0))```

phasor :: K_Num a => DF a -> a -> DF a -> DF a Source

`lift_mce2` of `phasor'`.

# Array

Allocate n second array, variant of `df_vec`.

Array delay with phasor argument for write index.

a_delay :: DF (Vec Float) -> DF Float -> DF Int32 -> DF Float Source

Array delay. a = array, s = signal, n = number of frames.

```do {a <- df_vec_m [0,1,2]
;draw (a_delay a 0.0 0)}```
```let {f = sin_osc 0.1 0.0
;o = sin_osc (f * 200.0 + 600.0) 0.0
;a = df_vec (V_Id 0) (replicate 48000 0)
;d = a_delay a o 24000}
in audition_rju [] (out2 (o * 0.1) (d * 0.05))```

SC3 UGen.

a_tbl_sin :: V_Id -> Int -> DF (Vec Float) Source

Array fill function (sin).

```let {i = phasor 64 0 1
;a = a_tbl_sin (V_Id 0) 64
in audition_rju [] (out1 (s * 0.2))```

a_lerp :: DF (Vec Float) -> DF Float -> DF Float Source

Linear interpolating variant of `a_read`.

```let {i = phasor 64.0 0 (hz_to_incr k_sample_rate 64.0 330.0)
;a = a_tbl_sin (V_Id 0) 64
;s = a_lerp a i}
in audition_rju [] (out1 (s * 0.2))```

# Osc

`phasor` for table of z places. ip is in (0,1).

```draw (phasor 64.0 (0.0::Float) (hz_to_incr k_sample_rate 64.0 330.0))
draw (tbl_phasor 64 0.0 330.0)```

a_osc :: DF (Vec Float) -> DF Float -> Float -> DF Float Source

Table lookup oscillator. ip is in (0,1).

```let {a = a_tbl_sin (V_Id 0) 256
;f = a_osc a 4.0 0.0
;o = a_osc a (f * 200.0 + 400.0) 0.0}
in audition_rju [] (out1 (o * 0.1))```

Cancellation:

```let {a = a_tbl_sin (V_Id 0) 256
;o1 = a_osc a 440.0 0.0
;o2 = a_osc a 440.0 0.5}
in audition_rju [] (out1 (o1 + o2))```

# Filter constructors.

unit_delay :: K' a => a -> DF a -> DF a Source

Single sample delay with indicated initial value.

```draw (unit_delay (0::Int32) 1)
draw (unit_delay (0.0::Float) 1.0)```
```let {c = counter 0.0 1.0
;d = unit_delay 0.0 c}
in audition_text 12 (out2 c d)```

Signal that is initially `True` then always `False`.

`audition_text 5 (out1 (latch (white_noise 812875317) unit_trigger))`

iir2 :: K_Num a => Ternary_Op (DF a) -> DF a -> DF a Source

Two place infinite impulse response filter. Inputs are: f= function `(x0 y1 y2 -> y0)`, i = input signal.

```let {c1 = iir2 (\x y1 _ -> x + y1) 0.001
;o1 = sin_osc (c1 + 220.0) 0
;c2 = iir2 (\x _ y2 -> x + y2) 0.001
;o2 = sin_osc (c2 + 220.0) 0}
in audition_rju [] (out2 (o1 * 0.1) (o2 * 0.1))```

fir1 :: K' a => a -> (DF a -> DF a -> DF b) -> DF a -> DF b Source

Single place finite impulse response filter.

Two place finite impulse response filter.

# Counter

counter :: K_Num a => a -> DF a -> DF a Source

Counter from indicated initial value by indicated step.

```draw (counter (0::Int32) 1)
draw (counter (0.0::Float) 1.0)```
```audition_text 10 (out1 (counter 0.0 1.0))
audition_text 10 (out1 (counter 0.0 (white_noise 165876521 * 0.25)))```

counter_reset :: K_Num a => a -> DF a -> DF Bool -> DF a Source

`counter` that resets to the initial phase at trigger.

```let tr = trigger (impulse (k_sample_rate / 3) 0.0)
in audition_text 10 (out1 (counter_reset 0.0 1.0 tr))```

Counter from 0 to 1 over duration (in seconds). Holds end value.

`lin_lin` of `unit_line`.

`audition_rju [] (out1 (sin_osc (line 110 440 100) 0 * 0.1))`

SC3 UGen.

```audition_text 20 (out1 (counter 30 10))
audition_text 20 (out1 (ramp (counter 30 10) (3 / k_sample_rate)))```

# Buffer

Buffer delay.

`draw (buf_delay 0 0.0 0)`

Non-interpolating comb filter. Inputs are: b = buffer index, i = input signal, dl = delay time, dc = decay time.

All times are in seconds. The decay time is the time for the echoes to decay by `60` decibels. If this time is negative then the feedback coefficient will be negative, thus emphasizing only odd harmonics at an octave lower.

`draw (out1 (buf_comb_n 0 0.0 0.0 0.0))`

Comb used as a resonator. The resonant fundamental is equal to reciprocal of the delay time.

`import qualified Sound.SC3 as S`
```let {n = white_noise 0
;dt = let f x = lin_exp (x + 2.0) 1.0 2.0 0.0001 0.01
in f (lf_saw 0.1 0.0)
;c = buf_comb_n 0 (n * 0.1) dt 0.2}
in audition_rju [S.b_alloc 0 48000 1] (out1 c)```

Comb used as an echo.

```let {i = impulse 0.5 0.0
;n = white_noise 0
;e = decay (i * 0.5) 0.2
;c = buf_comb_n 0 (e * n) 0.2 3.0}
in audition_rju [S.b_alloc 0 48000 1] (out1 c)```

# Comb

Array variant of `buf_comb_n`. Max delay time is in seconds.

```let {n = white_noise 0
;dt = let f x = lin_exp (x + 2.0) 1.0 2.0 0.0001 0.01
in f (lf_saw 0.1 0.0)
;c = comb_n  0.1 (n * 0.1) dt 0.2}
in audition_rju [] (out c)```
```let {i = impulse 0.5 0.0
;n = white_noise 0
;e = decay (i * 0.5) 0.2
;c = comb_n  0.2 (e * n) 0.2 3.0}
in audition_rju [] (out c)```

comb_n :: [Int] -> Float -> DF Float -> DF Float -> DF Float -> DF Float Source

Allow MCE.

# Noise

`Int32` linear congruential generator, hence signed modulo of `2^32`. Note that the state and all internal math is 32bit.

See http://en.wikipedia.org/wiki/Linear_congruential_generator for possible parameters.

`lcg_i32` 1103515245 12345, so in (minBound,maxBound).

`abs` of 'lcg_glibc, so in (0,maxBound).

`i32_to_normal_f32` of `randi`, so in (0,1).

`audition_text 24 (out1 (randf 0))`

White noise (-1,1). Generates noise whose spectrum has equal power at all frequencies.

`audition_text 24 (out1 (white_noise 0))`
```let n = white_noise 0 * 0.1
in draw (out1 (n - n))```
```let {n = white_noise 0 * 0.1
;m = white_noise 5 * 0.1}
in audition_rju [] (out1 (n - m))```

SC3 UGen.

```let freq = lin_lin (lf_noise1 0 1) (-1) 1 220 440
in audition_rju [] (out1 (sin_osc freq 0 * 0.1))```

`iir1` brown noise function.

Brown noise (-1,1). Generates noise whose spectrum falls off in power by 6 dB per octave.

```let n = brown_noise 0
in audition_rju [] (out1 (n * 0.1))```
```let {n = brown_noise 0
;f = lin_exp n (-1.0) 1.0 64.0 9600.0
;o = sin_osc f 0}
in audition_rju [] (out1 (o * 0.1))```

SC3 UGen.

```audition_rju [] (out1 (dust 0 200 * 0.25))
audition_rju [] (out1 (dust 0 (sin_osc 0.1 0 * 500 + 550) * 0.25))```

SC3 UGen.

`audition_rju [] (out1 (sin_osc (rand 6987612487 220.0 600.0) 0.0 * 0.1))`

# Osc

Sine oscillator. Inputs are: f = frequency (in hz), ip = initial phase.

```let o = sin_osc 440.0 0.0
in audition_rju [] (out1 (o * 0.1))```

Used as both Oscillator and LFO.

```let {f = sin_osc 4.0 0.0
;o = sin_osc (f * 200.0 + 400.0) 0.0}
in audition_rju [] (out1 (o * 0.1))```

Cancellation.

```let {o1 = sin_osc 440.0 0.0
;o2 = sin_osc 440.0 pi}
in audition_rju [] (out1 (o1 + o2))```

Impulse oscillator (non band limited). Outputs non band limited single sample impulses. Inputs are: f = frequency (in hertz), ip = phase offset (0..1)

```let o = impulse 800.0 0.0
in audition_rju [] (out1 (o * 0.1))```
```let {f = sin_osc 0.25 0.0 * 2500.0 + 2505.0
;o = impulse f 0.0}
in audition_rju [] (out1 (o * 0.1))```
```audition_text 10 (out1 (impulse (w_sample_rate / 5.0) 0.0))
audition_text 10 (out1 (impulse (k_sample_rate / 5.0) 0.0))```

# LF Osc.

Non-band limited sawtooth oscillator. Output ranges from -1 to +1. Inputs are: f = frequency (in hertz), ip = initial phase (0,2).

```let o = lf_saw 500.0 1.0
in audition_rju [] (out1 (o * 0.1))```

Used as both Oscillator and LFO.

```let {f = lf_saw 4.0 0.0
;o = lf_saw (f * 400.0 + 400.0) 0.0}
in audition_rju [] (out1 (o * 0.1))```

Non-band-limited pulse oscillator. Outputs a high value of one and a low value of zero. Inputs are: f = frequency (in hertz), ip = initial phase (0,1), w = pulse width duty cycle (0,1).

```let {o1 = lf_pulse 3.0 0.0 0.3 * 200.0 + 200.0
;o2 = lf_pulse o1 0.0 0.2 * 0.1}
in audition_rju [] (out1 o2)```

# Filters

Two zero fixed midpass filter.

Two zero fixed midcut filter.

Two point difference filter

Two zero fixed highpass filter

Two point average filter

Two zero fixed lowpass filter

one_pole_f :: Fractional a => a -> Binary_Op a Source

Given cf construct `iir1` one-pole function.

One pole filter.

```let {n = white_noise 0
;f = one_pole (n * 0.5) 0.95}
in audition_rju [] (out1 f)```

one_zero_f :: Fractional a => a -> Binary_Op a Source

Given cf construct `fir1` one-zero function.

One zero filter.

```let {n = white_noise 0
;f = one_zero (n * 0.5) 0.5}
in audition_rju [] (out1 f)```

sos_f :: Num a => a -> a -> a -> a -> a -> Quinary_Op a Source

Given coefficients construct `biquad` `sos` function.

Second order filter section.

Given f and rq construct `iir2` `resonz` function.

A two pole resonant filter with zeroes at z = +/- 1. Based on K. Steiglitz, "A Note on Constant-Gain Digital Resonators", Computer Music Journal, vol 18, no. 4, pp. 8-10, Winter 1994. The reciprocal of Q is used rather than Q because it saves a divide operation inside the unit generator.

Inputs are: i = input signal, f = resonant frequency (in hertz), rq = bandwidth ratio (reciprocal of Q);where rq = bandwidth / centerFreq.

```let {n = white_noise 0
;r = resonz (n * 0.5) 440.0 0.1}
in audition_rju [] (out1 r)```

Modulate frequency

```let {n = white_noise 0
;f = lf_saw 0.1 0.0 * 3500.0 + 4500.0
;r = resonz (n * 0.5) f 0.05}
in audition_rju [] (out1 r)```

Given f and r construct `iir2` `rlpf` function.

Resonant low pass filter. Inputs are: i = input signal, f = frequency (hertz), rq = reciprocal of Q (resonance).

```let {n = white_noise 0
;f = sin_osc 0.5 0.0  * 40.0 + 220.0
;r = rlpf n f 0.1}
in audition_rju [] (out1 r)```

Allow MCE.

type T5 t = (t, t, t, t, t) Source

5-tuple

lpf_or_hpf_c :: Floating t => Bool -> t -> t -> T5 t Source

2nd order Butterworth high-pass filter coefficients.

`hpf_c 48000.0 (440.0 :: DF Float)`

High pass filter.

Low pass filter.

# Triggers

positive :: K_Num a => DF a -> DF Bool Source

`df_gt` `0`.

non_positive :: K_Num a => DF a -> DF Bool Source

`df_not` of `positive`.

trigger_f :: K_Num a => DF a -> DF a -> DF Bool Source

`fir1` trigger function.

trigger :: K_Num a => DF a -> DF Bool Source

True on non-positive to positive transition.

count_true :: K_Num a => DF Bool -> DF a Source

Count `True` values at input.

```let n = white_noise 0
in audition_text 12 (out2 n (count_true (trigger n)))```

Pulse divider at `Bool`.

pulse_divider' :: K_Num a => DF a -> DF Int32 -> DF Int32 -> DF a Source

SC3 `PulseDivider`.

```let n = white_noise 0
in audition_text 12 (out2 n (pulse_divider' n 2 1))```

latch :: K_Num a => DF a -> DF Bool -> DF a Source

Sample and hold. Holds input signal value when triggered. Inputs are: i = input signal, t = trigger.

```let {n = white_noise 0
;i = impulse 9.0 0.0
;l = latch n (trigger i)
;o = sin_osc (l * 400.0 + 500.0) 0.0}
in audition_rju [] (out1 (o * 0.2))```

# Decays

Given dt construct `iir1` `decay` function.

Exponential decay. Inputs are: i = input signal, t = decay time. This is essentially the same as Integrator except that instead of supplying the coefficient directly, it is caculated from a 60 dB decay time. This is the time required for the integrator to lose 99.9 % of its value or -60dB. This is useful for exponential decaying envelopes triggered by impulses.

Used as an envelope.

```let {n = brown_noise 0
;f = lf_saw 0.1 0.0
;i = impulse (lin_lin f (-1.0) 1.0 2.0 5.0) 0.25
;e = decay i 0.2}
in audition_rju [] (out1 (e * n))```

Exponential decay (equivalent to `decay dcy - decay atk`).

# Delays

Single sample delay.

Two sample delay.

`audition_text 10 (out1 (delay2 (counter 0 1)))`

# Lags

Given t construct `iir1` `lag` function.

Simple averaging filter. Inputs are: i = input signal, t = lag time.

```let {s = sin_osc 0.05 0.0
;f = lin_lin s (-1.0) 1.0 220.0 440.0
;o = sin_osc f 0.0
;f' = lag f 1.0
;o' = sin_osc f' 0.0}
in audition_rju [] (out2 (o * 0.2) (o' * 0.2))```

Nested lag filter.

Twice nested lag filter.