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

Safe HaskellNone
LanguageHaskell98

Sound.DF.Uniform.GADT.UGen

Contents

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

Multiply and add.

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.

w_sample_dur :: DF Float Source

Environment value, recip of w_sample_rate.

w_radians_per_sample :: DF Float Source

Environment value, equal to two_pi / w_sample_rate.

Tbl

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

Add guard point.

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.GADT
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

Array

a_alloc_sec :: V_Id -> Float -> DF (Vec Float) Source

Allocate n second array, variant of df_vec.

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

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))

delay_n :: Int -> DF Float -> Float -> DF Float -> DF Float Source

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
    ;s = a_read a i}
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

tbl_phasor :: Int -> Float -> DF Float -> DF Float Source

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)

unit_trigger :: DF Bool Source

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.

fir2 :: Ternary_Op (DF Float) -> DF Float -> DF Float Source

Two place finite impulse response filter.

biquad :: Quinary_Op (DF Float) -> DF Float -> DF Float Source

Ordinary biquad filter section.

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))

unit_line :: DF Float -> DF Float Source

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

line :: DF Float -> DF Float -> DF Float -> DF Float Source

lin_lin of unit_line.

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

ramp :: DF Float -> DF Float -> DF Float Source

SC3 UGen.

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

Buffer

buf_delay :: DF Int32 -> DF Float -> DF Int32 -> DF Float Source

Buffer delay.

draw (buf_delay 0 0.0 0)

buf_comb_n :: DF Int32 -> DF Float -> DF Float -> DF Float -> DF Float Source

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

comb_n' :: V_Id -> Float -> DF Float -> DF Float -> DF Float -> DF Float Source

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] 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] 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

lcg_i32 :: Int32 -> Int32 -> Int32 -> DF Int32 Source

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_glibc :: Int32 -> DF Int32 Source

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

randi :: Int32 -> DF Int32 Source

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

randf :: Int32 -> DF Float Source

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

audition_text 24 (out1 (randf 0))

white_noise :: Int32 -> DF Float Source

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))

lf_noise1 :: Int32 -> DF Float -> DF Float Source

SC3 UGen.

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

brown_noise_f :: Binary_Op (DF Float) Source

iir1 brown noise function.

brown_noise :: Int32 -> DF Float Source

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))

dust :: Int32 -> DF Float -> DF Float Source

SC3 UGen.

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

rand :: Int32 -> DF Float -> DF Float -> DF Float Source

SC3 UGen.

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

Osc

sin_osc :: DF Float -> Float -> DF Float Source

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 :: DF Float -> Float -> DF Float Source

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.

lf_saw :: DF Float -> Float -> DF Float Source

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))

lf_pulse :: DF Float -> Float -> DF Float -> DF Float Source

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

bpz2 :: DF Float -> DF Float Source

Two zero fixed midpass filter.

brz2 :: DF Float -> DF Float Source

Two zero fixed midcut filter.

hpz1 :: DF Float -> DF Float Source

Two point difference filter

hpz2 :: DF Float -> DF Float Source

Two zero fixed highpass filter

lpz1 :: DF Float -> DF Float Source

Two point average filter

lpz2 :: DF Float -> DF Float Source

Two zero fixed lowpass filter

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

Given cf construct iir1 one-pole function.

one_pole :: DF Float -> DF Float -> DF Float Source

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 :: DF Float -> DF Float -> DF Float Source

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.

sos :: DF Float -> DF Float -> DF Float -> DF Float -> DF Float -> DF Float -> DF Float Source

Second order filter section.

resonz_f :: DF Float -> DF Float -> Ternary_Op (DF Float) Source

Given f and rq construct iir2 resonz function.

resonz :: DF Float -> DF Float -> DF Float -> DF Float Source

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)

rlpf_f :: DF Float -> DF Float -> Ternary_Op (DF Float) Source

Given f and r construct iir2 rlpf function.

rlpf' :: DF Float -> DF Float -> DF Float -> DF Float Source

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)

rlpf :: DF Float -> DF Float -> DF Float -> DF Float Source

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)

hpf :: DF Float -> DF Float -> DF Float Source

High pass filter.

lpf :: DF Float -> DF Float -> DF Float Source

Low pass filter.

Triggers

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 :: DF Bool -> DF Int32 -> DF Int32 -> DF Bool Source

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

decay_f :: DF Float -> Binary_Op (DF Float) Source

Given dt construct iir1 decay function.

decay :: DF Float -> DF Float -> DF Float Source

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))

decay2 :: DF Float -> DF Float -> DF Float -> DF Float Source

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

Delays

delay1 :: DF Float -> DF Float Source

Single sample delay.

delay2 :: DF Float -> DF Float Source

Two sample delay.

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

Lags

lag_f :: DF Float -> Binary_Op (DF Float) Source

Given t construct iir1 lag function.

lag :: DF Float -> DF Float -> DF Float Source

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))

lag2 :: DF Float -> DF Float -> DF Float Source

Nested lag filter.

lag3 :: DF Float -> DF Float -> DF Float Source

Twice nested lag filter.