Skip to main content

Implementation of ITU-R BS.1770-4 loudness algorithm in JAX

Project description

Docs below are from the original repo for the most part.

jaxloudnorm Zenodo

Flexible audio loudness meter in Python.

Implementation of ITU-R BS.1770-4.
Allows control over gating block size and frequency weighting filters for additional control.

For full details on the implementation see our paper with a summary in our AES presentation video.

Installation

Install from PyPI:

pip install jaxloudnorm

Usage

Find the loudness of an audio file

It's easy to measure the loudness of a wav file. Here we use PySoundFile to read a .wav file as an ndarray.

import soundfile as sf
import jaxloudnorm as jln

data, rate = sf.read("test.wav") # load audio (with shape (samples, channels))
data = data.T # convert to (channels, samples) for jaxloudnorm
meter = jln.Meter(rate) # create BS.1770 meter
loudness = meter.integrated_loudness(data) # measure loudness

Loudness normalize and peak normalize audio files

Methods are included to normalize audio files to desired peak values or desired loudness.

import soundfile as sf
import jaxloudnorm as jln

data, rate = sf.read("test.wav") # load audio
data = data.T # convert to (channels, samples) for jaxloudnorm
# peak normalize audio to -1 dB
peak_normalized_audio = jln.normalize.peak(data, -1.0)

# measure the loudness first 
meter = jln.Meter(rate) # create BS.1770 meter
loudness = meter.integrated_loudness(data)

# loudness normalize audio to -12 dB LUFS
loudness_normalized_audio = jln.normalize.loudness(data, loudness, -12.0)

Advanced operation

A number of alternate weighting filters are available, as well as the ability to adjust the analysis block size. Examples are shown below.

import soundfile as sf
import jaxloudnorm as jln
from jaxloudnorm import IIRfilter

data, rate = sf.read("test.wav") # load audio (with shape (samples, channels))
data = data.T # convert to (channels, samples) for jaxloudnorm

# block size
meter1 = jln.Meter(rate)                               # 400ms block size
meter2 = jln.Meter(rate, block_size=0.200)             # 200ms block size

# filter classes
meter3 = jln.Meter(rate)                               # BS.1770 meter
meter4 = jln.Meter(rate, filter_class="DeMan")         # fully compliant filters  
meter5 = jln.Meter(rate, filter_class="Fenton/Lee 1")  # low complexity improvement by Fenton and Lee
meter6 = jln.Meter(rate, filter_class="Fenton/Lee 2")  # higher complexity improvement by Fenton and Lee
meter7 = jln.Meter(rate, filter_class="Dash et al.")   # early modification option

# create your own IIR filters
my_high_pass  = IIRfilter(0.0, 0.5, 20.0, rate, 'high_pass')
my_high_shelf = IIRfilter(2.0, 0.7, 1525.0, rate, 'high_shelf')

# create a meter initialized without filters
meter8 = jln.Meter(rate, filter_class="custom")

# load your filters into the meter
meter8._filters = [my_high_pass, my_high_shelf]

# Use FIR approximation for faster speed on GPU.
# This idea is from AudioTools:
# https://github.com/descriptinc/audiotools/blob/master/audiotools/core/loudness.py
# We can set the FIR length with the `zeros` keyword.
meter9 = jln.Meter(rate, use_fir=True, zeros=2048)

Batched operation

Using jax allows us to calculate loudness and normalize across a batch dimension using vmap (or pmap across devices). Examples from tests:

def test_batched_integrated_loudness():
    data, rate = sf.read("tests/data/sine_1000.wav")
    data = data.T # convert to (channels, samples) for jaxloudnorm
    meter = pyln.Meter(rate)
    loudness = jax.vmap(meter.integrated_loudness)(jnp.stack([data, data, data]))

    assert jnp.allclose(loudness, jnp.full(loudness.shape, -3.0523438444331137))

def test_batched_loudness_normalize():
    data, rate = sf.read("tests/data/sine_1000.wav")
    data = data.T # convert to (channels, samples) for jaxloudnorm
    data = jnp.stack([data, data, data, data])
    meter = pyln.Meter(rate)
    loudness = jax.vmap(meter.integrated_loudness)(data)
    norm = jax.vmap(pyln.normalize.loudness, in_axes=(0, 0, None))(data, loudness, -6.0)
    loudness = jax.vmap(meter.integrated_loudness)(norm)

    assert jnp.allclose(loudness, jnp.full(loudness.shape, -6.0))

`

Dependencies

References

Ian Dash, Luis Miranda, and Densil Cabrera, "Multichannel Loudness Listening Test," 124th International Convention of the Audio Engineering Society, May 2008

Pedro D. Pestana and Álvaro Barbosa, "Accuracy of ITU-R BS.1770 Algorithm in Evaluating Multitrack Material," 133rd International Convention of the Audio Engineering Society, October 2012

Pedro D. Pestana, Josh D. Reiss, and Álvaro Barbosa, "Loudness Measurement of Multitrack Audio Content Using Modifications of ITU-R BS.1770," 134th International Convention of the Audio Engineering Society, May 2013

Steven Fenton and Hyunkook Lee, "Alternative Weighting Filters for Multi-Track Program Loudness Measurement," 143rd International Convention of the Audio Engineering Society, October 2017

Brecht De Man, "Evaluation of Implementations of the EBU R128 Loudness Measurement," 145th International Convention of the Audio Engineering Society, October 2018.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jaxloudnorm-0.3.1.tar.gz (15.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jaxloudnorm-0.3.1-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file jaxloudnorm-0.3.1.tar.gz.

File metadata

  • Download URL: jaxloudnorm-0.3.1.tar.gz
  • Upload date:
  • Size: 15.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for jaxloudnorm-0.3.1.tar.gz
Algorithm Hash digest
SHA256 a69a16600adfb849f6153aae3a302446d3910b36184beb62a986b7281fc88703
MD5 c10ad47214641c5ab6936ea27b4a5ce6
BLAKE2b-256 2708b5af7ce45c0836679c1e987b05f120de2160adae4ef76e86c4a9f7385a75

See more details on using hashes here.

File details

Details for the file jaxloudnorm-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: jaxloudnorm-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for jaxloudnorm-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ea7d2a8f8ef96e36e92159c41d90756380000c2265c07a8f9e816996cca42a03
MD5 eb650a6a2bbf9059e3bfacb20b213581
BLAKE2b-256 1008ccf3f794fe43984ebc664b5272f19b151d484723c078ab76dc80d3afae2e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page