package llama_core
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 153open 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