• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gabyfle / SoundML / 40

26 Jul 2025 12:07PM UTC coverage: 68.286% (+14.9%) from 53.422%
40

push

github

gabyfle
Migrating IO to RavenML

25 of 27 new or added lines in 3 files covered. (92.59%)

32 existing lines in 3 files now uncovered.

239 of 350 relevant lines covered (68.29%)

5.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.47
/src/utils.ml
1
(*****************************************************************************)
2
(*                                                                           *)
3
(*                                                                           *)
4
(*  Copyright (C) 2023-2025                                                  *)
5
(*    Gabriel Santamaria                                                     *)
6
(*                                                                           *)
7
(*                                                                           *)
8
(*  Licensed under the Apache License, Version 2.0 (the "License");          *)
9
(*  you may not use this file except in compliance with the License.         *)
10
(*  You may obtain a copy of the License at                                  *)
11
(*                                                                           *)
12
(*    http://www.apache.org/licenses/LICENSE-2.0                             *)
13
(*                                                                           *)
14
(*  Unless required by applicable law or agreed to in writing, software      *)
15
(*  distributed under the License is distributed on an "AS IS" BASIS,        *)
16
(*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *)
17
(*  See the License for the specific language governing permissions and      *)
18
(*  limitations under the License.                                           *)
19
(*                                                                           *)
20
(*****************************************************************************)
21

22
open Nx
23

24
module Convert = struct
UNCOV
25
  let mel_to_hz ?(htk = false) mels =
×
26
    let dtype = Nx.dtype mels in
3✔
27
    if htk then
3✔
28
      let term = Nx.div_s mels 2595. in
2✔
29
      let term = Nx.pow (Nx.scalar dtype 10.) term in
2✔
30
      let term = Nx.sub_s term 1. in
2✔
31
      Nx.mul_s term 700.
2✔
32
    else
33
      let f_min = 0.0 in
1✔
34
      let f_sp = 200.0 /. 3. in
35
      let min_log_hz = 1000. in
36
      let min_log_mel = (min_log_hz -. f_min) /. f_sp in
37
      let logstep = Float.log 6.4 /. 27.0 in
1✔
38
      let linear_mask = Nx.less_equal mels (Nx.scalar dtype min_log_mel) in
1✔
39
      let linear_result = Nx.(add_s (mul_s mels f_sp) f_min) in
1✔
40
      let log_result =
41
        Nx.(mul_s (exp (mul_s (sub_s mels min_log_mel) logstep)) min_log_hz)
1✔
42
      in
43
      Nx.where linear_mask linear_result log_result
44

UNCOV
45
  let hz_to_mel ?(htk = false) freqs =
×
46
    let dtype = Nx.dtype freqs in
3✔
47
    if htk then
3✔
48
      let term = Nx.div_s freqs 700. in
2✔
49
      let term = Nx.add_s term 1. in
2✔
50
      let term = Nx.log term in
2✔
51
      let term = Nx.div_s term (Float.log 10.) in
2✔
52
      Nx.mul_s term 2595.
2✔
53
    else
54
      let f_min = 0.0 in
1✔
55
      let f_sp = 200.0 /. 3. in
56
      let min_log_hz = 1000. in
57
      let min_log_mel = (min_log_hz -. f_min) /. f_sp in
58
      let logstep = Float.log 6.4 /. 27.0 in
1✔
59
      let linear_mask = Nx.less_equal freqs (Nx.scalar dtype min_log_hz) in
1✔
60
      let linear_result = Nx.(div_s (sub_s freqs f_min) f_sp) in
1✔
61
      let log_result =
62
        Nx.(add_s (div_s (log (div_s freqs min_log_hz)) logstep) min_log_mel)
1✔
63
      in
64
      let res = Nx.where linear_mask linear_result log_result in
65
      Nx.map_item (fun x -> if Float.is_nan x then 0.0 else x) res
×
66

67
  type reference =
68
    | RefFloat of float
69
    | RefFunction of ((float, float32_elt) t -> float)
70

UNCOV
71
  let power_to_db ?(amin = 1e-10) ?(top_db : float option = Some 80.) ref
×
72
      (s : (float, float32_elt) t) =
73
    assert (amin > 0.) ;
3✔
74
    let ref_value = match ref with RefFloat x -> x | RefFunction f -> f s in
1✔
75
    let log_spec = Nx.mul_s (Nx.div_s (Nx.log s) (Float.log 10.)) 10. in
3✔
76
    let log_spec =
3✔
77
      Nx.(
78
        sub log_spec
3✔
79
          (mul_s
3✔
80
             (div_s
3✔
81
                (log
3✔
82
                   (maximum
3✔
83
                      (scalar (dtype s) amin)
3✔
84
                      (scalar (dtype s) ref_value) ) )
3✔
85
                (Float.log 10.) )
3✔
86
             10. ) )
87
    in
88
    match top_db with
89
    | None ->
1✔
90
        log_spec
91
    | Some top_db ->
2✔
92
        assert (top_db >= 0.0) ;
2✔
93
        let max_val =
94
          Nx.max
95
            (Nx.where (Nx.isfinite log_spec) log_spec
2✔
96
               (Nx.scalar (Nx.dtype log_spec) (-1e8)) )
2✔
97
          |> Nx.to_array
2✔
98
        in
99
        Nx.maximum_s log_spec (max_val.(0) -. top_db)
2✔
100

101
  let db_to_power ?(amin = 1e-10) (ref : reference) (s : ('a, float32_elt) t) =
1✔
102
    assert (amin > 0.) ;
1✔
UNCOV
103
    let ref_value = match ref with RefFloat x -> x | RefFunction f -> f s in
×
104
    let amin_t = Nx.scalar (Nx.dtype s) amin in
1✔
105
    let ref_value_t = Nx.scalar (Nx.dtype s) ref_value in
1✔
106
    let log_ref =
1✔
107
      Nx.mul_s
108
        (Nx.div_s (Nx.log (Nx.maximum amin_t ref_value_t)) (Float.log 10.))
1✔
109
        10.
110
    in
111
    let spec = Nx.add s log_ref in
1✔
112
    let spec = Nx.div_s spec 10. in
1✔
113
    Nx.pow (Nx.scalar (Nx.dtype s) 10.) spec
1✔
114
end
115

116
let pad_center (data : ('a, 'b) t) (target_size : int) (value : 'a) : ('a, 'b) t
117
    =
118
  let size = (Nx.shape data).(0) in
8✔
119
  if size = target_size then data
2✔
120
  else if size > target_size then
6✔
121
    raise
2✔
122
      (Invalid_argument
123
         "An error occured while trying to pad: current_size > target_size" )
124
  else if size = 0 then Nx.full (Nx.dtype data) [|target_size|] value
1✔
125
  else
126
    let pad_total = target_size - size in
3✔
127
    let pad_left = pad_total / 2 in
128
    let pad_right = pad_total - pad_left in
129
    Nx.pad [|(pad_left, pad_right)|] value data
130

131
let fftfreq (n : int) (d : float) =
132
  let nslice = ((n - 1) / 2) + 1 in
2✔
133
  let fhalf = Nx.arange Float32 0 nslice 1 in
134
  let shalf = Nx.arange Float32 (-n / 2) 0 1 in
2✔
135
  let v = Nx.concatenate ~axis:0 [fhalf; shalf] in
2✔
136
  Nx.mul (Nx.scalar Float32 (1. /. (d *. float_of_int n))) v
2✔
137

138
let rfftfreq (kd : ('a, 'b) Nx.dtype) (n : int) (d : float) =
139
  let nslice = n / 2 in
2✔
140
  let res = Nx.arange kd 0 (nslice + 1) 1 in
141
  let factor = 1. /. (d *. float_of_int n) in
2✔
142
  let factor_nx = Nx.scalar kd factor in
143
  Nx.mul factor_nx res
2✔
144

145
let melfreq ?(nmels = 128) ?(fmin = 0.) ?(fmax = 11025.) ?(htk = false)
1✔
146
    (kd : ('a, 'b) Nx.dtype) =
147
  let bounds = Nx.create kd [|2|] [|fmin; fmax|] |> Convert.hz_to_mel ~htk in
2✔
148
  let mel_f =
2✔
149
    Nx.linspace kd (Nx.get_item [0] bounds) (Nx.get_item [1] bounds) nmels
2✔
150
  in
151
  Convert.mel_to_hz mel_f ~htk
2✔
152

153
let unwrap ?(discont = None) ?(axis = -1) ?(period = 2. *. Float.pi)
1✔
154
    (p : (float, 'a) t) =
155
  let ndim = Nx.ndim p in
3✔
156
  let axis = if axis < 0 then ndim + axis else axis in
1✔
157
  let diff (p : (float, 'a) t) =
158
    let p_swapped = Nx.swapaxes axis (-1) p in
3✔
159
    let ndim = Nx.ndim p_swapped in
3✔
160
    let shape = Nx.shape p_swapped in
3✔
161
    let n = shape.(ndim - 1) in
3✔
162
    if n <= 1 then (
×
163
      let new_shape = Array.copy (Nx.shape p) in
×
164
      new_shape.(axis) <- 0 ;
×
UNCOV
165
      Nx.empty (Nx.dtype p) new_shape )
×
166
    else
167
      let starts1 = Array.make ndim 0 in
3✔
168
      starts1.(ndim - 1) <- 1 ;
3✔
169
      let stops1 = shape in
3✔
170
      let p1 =
171
        Nx.slice_ranges (Array.to_list starts1) (Array.to_list stops1) p_swapped
3✔
172
      in
173
      let starts2 = Array.make ndim 0 in
3✔
174
      let stops2 = Array.copy shape in
3✔
175
      stops2.(ndim - 1) <- n - 1 ;
3✔
176
      let p2 =
3✔
177
        Nx.slice_ranges (Array.to_list starts2) (Array.to_list stops2) p_swapped
3✔
178
      in
179
      let d = Nx.sub p1 p2 in
3✔
180
      Nx.swapaxes axis (-1) d
3✔
181
  in
182
  let cumsum (x : (float, 'a) t) =
183
    let x_moved = Nx.moveaxis axis 0 x in
3✔
184
    let shape = Nx.shape x_moved in
3✔
185
    let n = shape.(0) in
3✔
UNCOV
186
    if n = 0 then x
×
187
    else
188
      let result = Nx.copy x_moved in
3✔
189
      for i = 1 to n - 1 do
3✔
190
        let current_slice = Nx.slice [I i] result in
10✔
191
        let prev_slice = Nx.slice [I (i - 1)] result in
10✔
192
        let new_slice = Nx.add current_slice prev_slice in
10✔
193
        Nx.set_slice [I i] result new_slice
10✔
194
      done ;
195
      Nx.moveaxis 0 axis result
196
  in
197
  let d = diff p in
198
  let d =
3✔
199
    let pad_shape = Array.copy (Nx.shape p) in
3✔
200
    pad_shape.(axis) <- 1 ;
3✔
201
    let padding = Nx.zeros (Nx.dtype p) pad_shape in
3✔
202
    Nx.concatenate ~axis [padding; d]
3✔
203
  in
204
  let discont = match discont with Some d -> d | None -> period /. 2. in
×
205
  let d_mod = Nx.sub d (Nx.mul_s (Nx.round (Nx.div_s d period)) period) in
3✔
206
  let php = period /. 2. in
3✔
207
  let cond1 = Nx.equal d_mod (Nx.scalar (Nx.dtype p) (-.php)) in
3✔
208
  let cond2 = Nx.greater d (Nx.scalar (Nx.dtype p) 0.) in
3✔
209
  let cond = Nx.logical_and cond1 cond2 in
3✔
210
  let php_scalar = Nx.full_like d_mod php in
3✔
211
  let d_mod = Nx.where cond php_scalar d_mod in
3✔
212
  let ph_correct = Nx.sub d_mod d in
3✔
213
  let cond_abs = Nx.less (Nx.abs d) (Nx.scalar (Nx.dtype p) discont) in
3✔
214
  let p_correct = Nx.where cond_abs (Nx.zeros_like ph_correct) ph_correct in
3✔
215
  let up = cumsum p_correct in
3✔
216
  Nx.add p up
3✔
217

218
let outer (op : ('a, 'b) t -> ('a, 'b) t -> ('a, 'b) t) (x : ('a, 'b) t)
219
    (y : ('a, 'b) t) =
220
  let nx = (Nx.shape x).(0) in
2✔
221
  let ny = (Nx.shape y).(0) in
2✔
222
  let x = Nx.reshape [|nx; 1|] x in
2✔
223
  let y = Nx.reshape [|1; ny|] y in
2✔
224
  op x y
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc