package tiny_libs

  1. Overview
  2. Docs
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more

Install

dune-project
 Dependency

Authors

Maintainers

Sources

0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0

doc/src/tiny_libs.audio_effects/Rack.ml.html

Source file Rack.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
(* Claude Code
 *
 * Copyright (C) 2026 Yoann Padioleau
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public License
 * (LGPL) as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *)

(* See Rack.mli *)

(* claude: fx, not effect: a keyword since OCaml 5.3 (effect handlers) *)
type stage = { fx : Effect.t; mutable on : bool }
type t = { mutable stages : stage list }

let create (effects : Effect.t list) : t = { stages = List.map (fun fx -> { fx; on = false }) effects }
let standard () : t =
  create [ Drive.fx (); Eq.fx (); Modulation.fx (); Delay.fx (); Reverb.fx (); Dynamics.fx () ]

(* an effect's knobs under its name, its switch first *)
let prefixed (name : string) (knobs : Effect.knob list) : Effect.knob list =
  { name = name ^ ".on"; control = Switch; initial = 0. }
  :: List.map (fun (k : Effect.knob) -> { k with name = name ^ "." ^ k.name }) knobs

let standard_knobs : Effect.knob list =
  List.concat_map
    (fun (name, knobs) -> prefixed name knobs)
    [
      ("drive", Drive.knobs);
      ("eq", Eq.knobs);
      ("modulation", Modulation.knobs);
      ("delay", Delay.knobs);
      ("reverb", Reverb.knobs);
      ("dynamics", Dynamics.knobs);
    ]

let knobs (t : t) : Effect.knob list = List.concat_map (fun s -> prefixed s.fx.name s.fx.knobs) t.stages

let set (t : t) (name : string) (x : float) : unit =
  match String.index_opt name '.' with
  | None -> ()
  | Some i ->
      let stage = String.sub name 0 i and knob = String.sub name (i + 1) (String.length name - i - 1) in
      List.iter
        (fun s -> if s.fx.name = stage then if knob = "on" then s.on <- Control.on x else s.fx.set knob x)
        t.stages

let order (t : t) : string list = List.map (fun s -> s.fx.name) t.stages

let reorder (t : t) (names : string list) : unit =
  let named = List.filter_map (fun n -> List.find_opt (fun s -> s.fx.name = n) t.stages) names in
  t.stages <- named @ List.filter (fun s -> not (List.memq s named)) t.stages

let process (t : t) (out : Signal.stereo) : unit = List.iter (fun s -> if s.on then s.fx.process out) t.stages

let meter (t : t) (name : string) : float =
  List.find_map
    (fun s -> List.find_map (fun (m, x) -> if s.fx.name ^ "." ^ m = name then Some x else None) (s.fx.meters ()))
    t.stages
  |> Option.value ~default:0.