package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
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/Phaser.ml.html
Source file Phaser.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(* 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 Phaser.mli *) type settings = { low : float; high : float; rate : float; feedback : float; mix : float } let initial = { low = 200.; high = 3000.; rate = 0.3; feedback = 0.3; mix = 1. } let stages = 4 let rate = float_of_int Signal.rate (* a first-order all-pass's memory: its last input and output *) type stage = { mutable x1 : float; mutable y1 : float } (* one side: its four stages, and the last output, fed back *) type side = { stages : stage array; mutable last : float } type t = { left : side; right : side; mutable phase : float; (* the LFO's, in turns *) (* the last block's, ramped from (nan: none yet) *) mutable last_mix : float; } let side () = { stages = Array.init stages (fun _ -> { x1 = 0.; y1 = 0. }); last = 0. } let create () : t = { left = side (); right = side (); phase = 0.; last_mix = Float.nan } let coefficient (fc : float) : float = let k = tan (Float.pi *. Float.min fc (0.49 *. rate) /. rate) in (k -. 1.) /. (k +. 1.) let through (s : side) (a : float) (feedback : float) (x : float) : float = let v = ref (x +. (feedback *. s.last)) in Array.iter (fun st -> let y = (a *. !v) +. st.x1 -. (a *. st.y1) in st.x1 <- !v; st.y1 <- y; v := y) s.stages; s.last <- !v; !v let process (t : t) (s : settings) (out : Signal.stereo) : unit = let n = Array.length out.left and feedback = Float.min 0.9 (Float.max (-0.9) s.feedback) in let from_mix = if Float.is_nan t.last_mix then s.mix else t.last_mix in (* the break frequency at an LFO phase: evenly in octaves *) let fc phase = s.low *. Float.pow (s.high /. s.low) (0.5 +. (0.5 *. sin (2. *. Float.pi *. phase))) in for i = 0 to n - 1 do let mix = Effect.ramp from_mix s.mix i n in let wet_left = through t.left (coefficient (fc t.phase)) feedback out.left.(i) and wet_right = through t.right (coefficient (fc (t.phase +. 0.25))) feedback out.right.(i) in out.left.(i) <- out.left.(i) +. (mix *. wet_left); out.right.(i) <- out.right.(i) +. (mix *. wet_right); t.phase <- t.phase +. (s.rate /. rate); if t.phase >= 1. then t.phase <- t.phase -. 1. done; t.last_mix <- s.mix
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>