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_mpeg/Imdct.ml.html

Source file Imdct.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
(* 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 Imdct.mli *)

(* cos(pi / 2n (2i + 1 + n/2)(2k + 1)), for the two sizes *)
let cosines (n : int) : float array array =
  Array.init n (fun i ->
      Array.init (n / 2) (fun k ->
          cos (Float.pi /. float_of_int (2 * n) *. float_of_int (((2 * i) + 1 + (n / 2)) * ((2 * k) + 1)))))

let cos36 = cosines 36
let cos12 = cosines 12
let table (n : int) = if n = 36 then cos36 else if n = 12 then cos12 else cosines n

(* output i, the formula: a for loop, not Array.iteri, since a float ref
 * that a closure captures is boxed, an allocation per addition
 * (notes_opti_ocaml.md) *)
let output (c : float array array) (coefficients : float array) (i : int) : float =
  let row = c.(i) and sum = ref 0. in
  for k = 0 to Array.length coefficients - 1 do
    sum := !sum +. (coefficients.(k) *. row.(k))
  done;
  !sum

(* claude: a quarter of the outputs computed, the others their mirrors,
 * where it was every output from the formula:
 *
 *   Array.init n (fun i -> output c coefficients i)
 *
 * With a = 2i + 1 + n/2, output n/2 - 1 - i has 2n - a instead, and
 * cos((2k + 1) pi - x) = -cos x: x[n/2 - 1 - i] = -x[i]; output 3n/2 - 1
 * - i has 4n - a, and cos(2 (2k + 1) pi - x) = cos x: x[3n/2 - 1 - i] =
 * x[i] -- the aliases, the halves mirrored, that the overlap cancels.
 * And coefficients all zero (the high subbands, mostly) give zeros,
 * nothing computed. Half the multiplications, and far fewer in quiet
 * bands (notes_opti_ocaml.md). *)
let imdct (coefficients : float array) : float array =
  let n = 2 * Array.length coefficients in
  let x = Array.make n 0. in
  if Array.exists (fun v -> v <> 0.) coefficients then (
    let c = table n in
    for i = 0 to (n / 4) - 1 do
      let v = output c coefficients i in
      x.(i) <- v;
      x.((n / 2) - 1 - i) <- -.v
    done;
    for i = n / 2 to (3 * n / 4) - 1 do
      let v = output c coefficients i in
      x.(i) <- v;
      x.((3 * n / 2) - 1 - i) <- v
    done);
  x

let mdct (samples : float array) : float array =
  let n = Array.length samples in
  let c = table n in
  Array.init (n / 2) (fun k ->
      let sum = ref 0. in
      for i = 0 to n - 1 do
        sum := !sum +. (samples.(i) *. c.(i).(k))
      done;
      !sum)

let sine (period : int) (i : int) : float = sin (Float.pi /. float_of_int period *. (float_of_int i +. 0.5))

let windows =
  [| Array.init 36 (sine 36);
     Array.init 36 (fun i -> if i < 18 then sine 36 i else if i < 24 then 1. else if i < 30 then sine 12 (i - 18) else 0.);
     Array.init 12 (sine 12);
     Array.init 36 (fun i -> if i < 6 then 0. else if i < 12 then sine 12 (i - 6) else if i < 18 then 1. else sine 36 i) |]

let window (block_type : int) : float array = windows.(block_type)