1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
let period (frequency : float) : int =
max 2 (int_of_float (Float.round ((float_of_int Signal.rate /. frequency) -. 0.5)))
let render ?(decay = 0.996) ?(tuned = true) ~(frequency : float) (seconds : float) : Signal.t =
let total = float_of_int Signal.rate /. frequency in
let p = if tuned then max 2 (int_of_float (total -. 0.6)) else period frequency in
let delta = total -. 0.5 -. float_of_int p in
let c = (1. -. delta) /. (1. +. delta) in
let x1 = ref 0. and y1 = ref 0. in
let all_pass x =
let y = (c *. x) +. !x1 -. (c *. !y1) in
x1 := x;
y1 := y;
y
in
let register = ref 1 in
for _ = 1 to 5000 do
register := Noise.step Long !register
done;
let noise =
Array.init p (fun _ ->
register := Noise.step Long !register;
if !register land 1 = 1 then 1. else -1.)
in
let mean = Array.fold_left ( +. ) 0. noise /. float_of_int p in
let line = Array.map (fun x -> x -. mean) noise in
let pos = ref 0 and older = ref 0. in
Array.init (Signal.samples seconds) (fun _ ->
let oldest = line.(!pos) in
let averaged = decay *. 0.5 *. (oldest +. !older) in
let y = if tuned then all_pass averaged else averaged in
older := oldest;
line.(!pos) <- y;
pos := (!pos + 1) mod p;
y)