package llama_core

  1. Overview
  2. Docs

Source file signal.ml

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
open StdLabels

module Ctx = struct
  type t = { sample_index : int; sample_rate_hz : float }
end

module Raw = struct
  type 'a t = Ctx.t -> 'a

  let with_state ~init ~f =
    let state = ref init in
    fun ctx ->
      let new_state = f !state ctx in
      state := new_state;
      new_state

  let with_state' ~init ~f =
    let state = ref init in
    fun ctx ->
      let new_state, x = f !state ctx in
      state := new_state;
      x

  let map t ~f ctx = f (t ctx)
  let bind t ~f ctx = f (t ctx) ctx
end

type 'a t = {
  raw : 'a Raw.t;
  mutable buffered_sample : 'a option;
  mutable next_sample_index : int;
}

let of_raw raw = { raw; buffered_sample = None; next_sample_index = 0 }

let sample_and_update t ctx =
  let x = t.raw ctx in
  t.buffered_sample <- Some x;
  x

let sample t (ctx : Ctx.t) =
  if ctx.sample_index < t.next_sample_index then
    match t.buffered_sample with
    | Some sample -> sample
    | None -> sample_and_update t ctx
  else (
    t.next_sample_index <- t.next_sample_index + 1;
    sample_and_update t ctx)

let map_ctx t ~f =
  of_raw (fun ctx ->
      let x = sample t ctx in
      f x ctx)

let map t ~f =
  of_raw (fun ctx ->
      let x = sample t ctx in
      f x)

let both a b =
  of_raw (fun ctx ->
      let xa = sample a ctx in
      let xb = sample b ctx in
      (xa, xb))

let map2 t1 t2 ~f = both t1 t2 |> map ~f:(fun (x1, x2) -> f x1 x2)

let map3 t1 t2 t3 ~f =
  both t1 (both t2 t3) |> map ~f:(fun (x1, (x2, x3)) -> f x1 x2 x3)

let const x = of_raw (Fun.const x)
let of_ref ref = of_raw (fun _ -> !ref)

let var x =
  let ref = ref x in
  (of_ref ref, ref)

let silence = const 0.0
let never = const false
let scale s = map ~f:(fun x -> x *. s)
let scale_div s = map ~f:(fun x -> x /. s)
let offset s = map ~f:(fun x -> x +. s)

let exp_01 k =
  if Float.equal k 0.0 then Fun.id
  else
    let b = 1.0 /. (Float.exp k -. 1.0) in
    let a = -.(Float.log b /. k) in
    map ~f:(fun x -> Float.exp (k *. (x -. a)) -. b)

let debug t ~f =
  map t ~f:(fun x ->
      f x;
      x)

let debug_print_float_endline =
  debug ~f:(fun x -> print_endline (Printf.sprintf "%f" x))

let debug_print_sample_index_on_true =
  map_ctx ~f:(fun x ctx ->
      if x then print_endline (Printf.sprintf "%d" ctx.sample_index);
      x)

let sum ts =
  of_raw (fun ctx ->
      List.fold_left ts ~init:0.0 ~f:(fun acc signal ->
          acc +. sample signal ctx))

let mean ts =
  let length = Int.to_float (List.length ts) in
  sum ts |> map ~f:(fun sum -> sum /. length)

let recip = map ~f:(fun x -> 1.0 /. x)
let to_01 = map ~f:(fun x -> (x +. 1.0) /. 2.0)
let add a b = both a b |> map ~f:(fun (a, b) -> a +. b)
let ( +.. ) a b = add a b
let mul a b = both a b |> map ~f:(fun (a, b) -> a *. b)
let ( *.. ) a b = mul a b
let sub a b = both a b |> map ~f:(fun (a, b) -> a -. b)
let ( -.. ) a b = sub a b
let div a b = both a b |> map ~f:(fun (a, b) -> a /. b)
let ( /.. ) a b = div a b

module Trigger = struct
  type nonrec t = bool t

  let rising_edge ?(init = false) t =
    of_raw
      (let previous = ref init in
       fun ctx ->
         let sample = sample t ctx in
         let trigger_sample = sample && not !previous in
         previous := sample;
         trigger_sample)

  let of_signal_unsafe t = t
  let to_signal t = t
  let sample = sample
  let never = never
  let debug_print_sample_index_on_true = debug_print_sample_index_on_true
end

module Gate = struct
  type nonrec t = bool t

  let of_signal t = t
  let to_signal t = t
  let to_trigger t = Trigger.rising_edge t
  let sample = sample
  let debug_print_sample_index_on_true = debug_print_sample_index_on_true
end

let gate = Gate.of_signal
OCaml

Innovation. Community. Security.