Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ body:
2. Run the following OCaml code:
```ocaml
let () =
let audio, _ = Soundml.Io.read Rune.c Float32 filename in
let audio, _ = Soundml.Io.read Nx.float32 filename in
ignore audio
```
3. Observe the error output.
Expand All @@ -45,7 +45,7 @@ body:
attributes:
label: "Expected Behavior"
description: "What did you expect to happen when you followed the steps above?"
placeholder: "The audio file should load into a Rune tensor without raising an exception."
placeholder: "The audio file should load into an Nx tensor without raising an exception."
validations:
required: true
- type: textarea
Expand All @@ -68,7 +68,7 @@ body:
description: "Please provide details about the environment where you encountered the bug."
placeholder: |
- SoundML Version: 0.0.1 (or commit hash)
- OCaml Version: 5.3.0
- OCaml Version: 5.5.0
- Operating System: Ubuntu 22.04
- type: textarea
id: additional-context
Expand Down
8 changes: 2 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
matrix:
os: [ubuntu-latest] # , macos-latest, windows-latest]
ocaml-compiler:
- "5.3.0"
- "5.5.0"

runs-on: ${{ matrix.os }}

Expand All @@ -38,11 +38,7 @@ jobs:

- name: Install libsndfile, libsamplerate and librubberband
run: |
sudo apt-get install libsndfile-dev libsamplerate0-dev librubberband-dev

- name: Install llvm # required for rune
run: |
sudo apt-get install libllvm-20-ocaml-dev libllvm20 llvm-20 llvm-20-dev llvm-20-doc llvm-20-examples llvm-20-runtime
sudo apt-get install -y libsndfile-dev libsamplerate0-dev librubberband-dev

- name: Lock the dependencies
run: opam exec -- dune pkg lock
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up OCaml for linting
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: "5.3"
ocaml-compiler: "5.5"
dune-cache: true
- name: Run OCaml Lint & Format Check
uses: ocaml/setup-ocaml/lint-fmt@v2
26 changes: 3 additions & 23 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ jobs:
matrix:
os: [ubuntu-latest] # , macos-latest, windows-latest]
ocaml-compiler:
- "5.3.0"
include:
- os: ubuntu-latest
ocaml-compiler: "5.3.0"
send-coverage: true
- "5.5.0"

runs-on: ${{ matrix.os }}

Expand Down Expand Up @@ -50,11 +46,7 @@ jobs:

- name: Install libsndfile, libsamplerate and librubberband
run: |
sudo apt-get install libsndfile-dev libsamplerate0-dev librubberband-dev

- name: Install llvm # required for rune
run: |
sudo apt-get install libllvm-20-ocaml-dev libllvm20 llvm-20 llvm-20-dev llvm-20-doc llvm-20-examples llvm-20-runtime
sudo apt-get install -y libsndfile-dev libsamplerate0-dev librubberband-dev

- name: Install FFmpeg CLI (to generate test data)
run: sudo apt-get install -y ffmpeg
Expand All @@ -65,17 +57,5 @@ jobs:
shell: bash

- name: Run tests
if: matrix.send-coverage != true
run: |
opam exec -- dune runtest
shell: bash

- name: Run tests (and send converage to coveralls)
if: matrix.send-coverage == true
run: |
opam exec -- dune runtest --instrument-with bisect_ppx --force
opam exec -- bisect-ppx-report send-to Coveralls
run: opam exec -- dune runtest
shell: bash
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PULL_REQUEST_NUMBER: ${{ github.event.number }}
2 changes: 1 addition & 1 deletion .ocamlformat
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
profile = ocamlformat
wrap-comments = true
version = 0.27.0
version = 0.28.1
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

[![Build](https://github.com/gabyfle/SoundML/actions/workflows/build.yml/badge.svg)](https://github.com/gabyfle/SoundML/actions/workflows/build.yml)
[![Test](https://github.com/gabyfle/SoundML/actions/workflows/test.yml/badge.svg)](https://github.com/gabyfle/SoundML/actions/workflows/test.yml)
[![Coverage Status](https://coveralls.io/repos/github/gabyfle/SoundML/badge.svg)](https://coveralls.io/github/gabyfle/SoundML)
</div>

## About the Project
Expand Down
2 changes: 1 addition & 1 deletion doc/index.mld
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
%}

{!Soundml} is an OCaml library that enables audio processing. It provides tools to read, write, extract features and manipulate audio as time series data.
The library is built on top of the Owl library and provides a high-level API to work with audio data. It's still in an experimental stage.
The library is built on top of Raven's Nx package and provides a high-level API to work with audio data. It's still in an experimental stage.


{1 API Documentation}
Expand Down
20 changes: 7 additions & 13 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,28 @@
(documentation https://soundml.dev)

(pin
(url "git+https://github.com/raven-ml/raven.git")
(url
"git+https://github.com/raven-ml/raven.git#d9facbc227ddc80d644bdeff0d94cf76d6a0c07b")
(package (name nx)))

(pin
(url "git+https://github.com/raven-ml/raven.git")
(package (name rune)))

(package
(name soundml)
(synopsis "An OCaml library to embed sound processing in your applications")
(description
"SoundML is a library built on top of Rune to analyse sounds files. It can read, write audio, extract various features from audio files and much more.")
"SoundML is a library built on top of Raven's Nx package to analyse sound files. It can read and write audio, extract features from audio files, and much more.")
(depends
(ocaml
(>= 5.3.0))
(>= 5.5.0))
dune
(conf-sndfile :build)
(conf-rubberband :build)
; Samplerate is already a requirement of rubberband
(conf-samplerate :build)
(dune-configurator :build)
rune
(nx
(= dev))
(odoc :with-doc)
(alcotest :with-test)
(yojson :with-test)
(bisect_ppx
(and
:with-test
(>= 2.5.0))))
(yojson :with-test))
(tags
(sound spectrogram fourier digital-filters)))
13 changes: 9 additions & 4 deletions soundml.opam
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
opam-version: "2.0"
synopsis: "An OCaml library to embed sound processing in your applications"
description:
"SoundML is a library built on top of Rune to analyse sounds files. It can read, write audio, extract various features from audio files and much more."
"SoundML is a library built on top of Raven's Nx package to analyse sound files. It can read and write audio, extract features from audio files, and much more."
maintainer: ["Gabriel Santamaria <gaby.santamaria@outlook.fr>"]
authors: ["Gabriel Santamaria <gaby.santamaria@outlook.fr>"]
license: "Apache-2.0"
Expand All @@ -11,17 +11,16 @@ homepage: "https://github.com/gabyfle/SoundML"
doc: "https://soundml.dev"
bug-reports: "https://github.com/gabyfle/SoundML/issues"
depends: [
"ocaml" {>= "5.3.0"}
"ocaml" {>= "5.5.0"}
"dune" {>= "3.17"}
"conf-sndfile" {build}
"conf-rubberband" {build}
"conf-samplerate" {build}
"dune-configurator" {build}
"rune"
"nx" {= "dev"}
"odoc" {with-doc}
"alcotest" {with-test}
"yojson" {with-test}
"bisect_ppx" {with-test & >= "2.5.0"}
]
build: [
["dune" "subst"] {dev}
Expand All @@ -38,3 +37,9 @@ build: [
]
]
dev-repo: "git+https://github.com/gabyfle/SoundML.git"
pin-depends: [
[
"nx.dev"
"git+https://github.com/raven-ml/raven.git#d9facbc227ddc80d644bdeff0d94cf76d6a0c07b"
]
]
6 changes: 6 additions & 0 deletions soundml.opam.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pin-depends: [
[
"nx.dev"
"git+https://github.com/raven-ml/raven.git#d9facbc227ddc80d644bdeff0d94cf76d6a0c07b"
]
]
22 changes: 5 additions & 17 deletions src/dune
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,38 @@
(name aformat)
(package soundml)
(modules aformat)
(instrumentation
(backend bisect_ppx))
(wrapped false))

(library
(name window)
(package soundml)
(libraries rune utils)
(libraries nx utils)
(modules window)
(instrumentation
(backend bisect_ppx))
(wrapped false))

(library
(name utils)
(package soundml)
(libraries rune)
(libraries nx)
(modules utils)
(instrumentation
(backend bisect_ppx))
(wrapped false))

(library
(name transform)
(package soundml)
(modules transform)
(libraries rune window utils)
(instrumentation
(backend bisect_ppx))
(libraries nx window utils)
(wrapped false))

(library
(name filterbank)
(package soundml)
(modules filterbank)
(libraries rune utils)
(instrumentation
(backend bisect_ppx))
(libraries nx utils)
(wrapped false))

(library
(name soundml)
(public_name soundml)
(modules soundml)
(libraries aformat window io utils transform filterbank)
(instrumentation
(backend bisect_ppx)))
(libraries aformat window io utils transform filterbank))
2 changes: 0 additions & 2 deletions src/effects/dune
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
;(library
; (name effects)
; (public_name soundml.effects)
; (instrumentation
; (backend bisect_ppx))
; (modules
; time
; filter
Expand Down
2 changes: 0 additions & 2 deletions src/feature/dune
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
;(library
; (name feature)
; (public_name soundml.feature)
; (instrumentation
; (backend bisect_ppx))
; (libraries audio utils window nx)
; (modules spectral))
53 changes: 23 additions & 30 deletions src/filterbank.ml
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@
type normalization = Slaney | Power_norm of float

let mel_filterbank ?f_max ?(htk : bool = false) ?norm ~sample_rate ~n_fft
~n_mels ~f_min (device : 'dev Rune.device) (dtype : (float, 'b) Rune.dtype)
=
~n_mels ~f_min (dtype : (float, 'b) Nx.dtype) =
(* Input validation *)
if sample_rate <= 0 then invalid_arg "sample_rate must be positive" ;
if n_fft <= 0 then invalid_arg "n_fft must be positive" ;
if n_mels <= 0 then invalid_arg "n_mels must be positive" ;
if f_min < 0.0 then invalid_arg "f_min must be non-negative" ;
if n_mels = 0 then Rune.empty device dtype [|0; (n_fft / 2) + 1|]
if n_mels = 0 then Nx.empty dtype [|0; (n_fft / 2) + 1|]
else
let f_max =
match f_max with
Expand All @@ -48,52 +47,46 @@ let mel_filterbank ?f_max ?(htk : bool = false) ?norm ~sample_rate ~n_fft
let freq_step = 1.0 /. (float_of_int n_fft *. d) in
let fftfreqs =
let indices = Array.init n_freqs (fun i -> float_of_int i *. freq_step) in
Rune.create device dtype [|n_freqs|] indices
Nx.create dtype [|n_freqs|] indices
in
let mel_freqs =
Utils.melfreqs ~n_mels:(n_mels + 2) ~f_min ~f_max ~htk device dtype
Utils.melfreqs ~n_mels:(n_mels + 2) ~f_min ~f_max ~htk dtype
in
let fdiff =
let n = Rune.size mel_freqs in
Rune.sub
(Rune.slice [R (1, n)] mel_freqs)
(Rune.slice [R (0, n - 1)] mel_freqs)
let n = Nx.numel mel_freqs in
Nx.sub (Nx.slice [R (1, n)] mel_freqs) (Nx.slice [R (0, n - 1)] mel_freqs)
in
let ramps = Utils.outer Rune.sub mel_freqs fftfreqs in
let ramps = Utils.outer Nx.sub mel_freqs fftfreqs in
let lower =
Rune.div
(Rune.neg (Rune.slice [R (0, n_mels)] ramps))
(Rune.reshape [|n_mels; 1|] (Rune.slice [R (0, n_mels)] fdiff))
Nx.div
(Nx.neg (Nx.slice [R (0, n_mels)] ramps))
(Nx.reshape [|n_mels; 1|] (Nx.slice [R (0, n_mels)] fdiff))
in
let upper =
Rune.div
(Rune.slice [R (2, n_mels + 2)] ramps)
(Rune.reshape [|n_mels; 1|] (Rune.slice [R (1, n_mels + 1)] fdiff))
Nx.div
(Nx.slice [R (2, n_mels + 2)] ramps)
(Nx.reshape [|n_mels; 1|] (Nx.slice [R (1, n_mels + 1)] fdiff))
in
(* Intersect slopes *)
let weights =
Rune.maximum (Rune.zeros_like lower) (Rune.minimum lower upper)
in
let weights = Nx.maximum (Nx.zeros_like lower) (Nx.minimum lower upper) in
let weights =
match norm with
| Some Slaney ->
let enorm =
Rune.div
(Rune.scalar device dtype 2.0)
(Rune.sub
(Rune.slice [R (2, n_mels + 2)] mel_freqs)
(Rune.slice [R (0, n_mels)] mel_freqs) )
Nx.div (Nx.scalar dtype 2.0)
(Nx.sub
(Nx.slice [R (2, n_mels + 2)] mel_freqs)
(Nx.slice [R (0, n_mels)] mel_freqs) )
in
let enorm = Rune.reshape [|n_mels; 1|] enorm in
Rune.mul weights enorm
let enorm = Nx.reshape [|n_mels; 1|] enorm in
Nx.mul weights enorm
| Some (Power_norm p) ->
let norm =
Rune.pow_s
(Rune.sum ~axes:[|-1|] ~keepdims:true
(Rune.pow_s (Rune.abs weights) p) )
Nx.pow_s
(Nx.sum ~axes:[-1] ~keepdims:true (Nx.pow_s (Nx.abs weights) p))
(1. /. p)
in
Rune.div weights (Rune.add_s norm 1e-8)
Nx.div weights (Nx.add_s norm 1e-8)
| None ->
weights
in
Expand Down
Loading
Loading