csteinmetz1 / pyloudnorm

Flexible audio loudness meter in Python with implementation of ITU-R BS.1770-4 loudness algorithm
https://www.christiansteinmetz.com/projects-blog/pyloudnorm
MIT License
639 stars 56 forks source link

Overflow, 2473.459531146733 #42

Open PetrochukM opened 2 years ago

PetrochukM commented 2 years ago

Hello!

I ran a quiet sine wave through the implementation and I believe it overflowed, I received the output: loudness 2473.459531146733

import numpy as np
import pyloudnorm

frequency = 997
sample_rate = 1000
block_size = 0.4

# NOTE: Generate sine wave
# https://stackoverflow.com/questions/22566692/python-how-to-plot-graph-sine-wave/34442729
signal = np.arange(sample_rate * block_size, dtype=np.float32)
signal = np.sin(2 * np.pi * frequency * (signal / sample_rate)).astype(np.float32)
signal = signal / 100000
meter = pyloudnorm.Meter(rate=sample_rate, block_size=block_size, filter_class="DeMan")
print("loudness", meter.integrated_loudness(signal))

I think it would be best to adjust the computation so that this does not overflow and return negative infinity like other quiet signals.

csteinmetz1 commented 1 year ago

Hi @PetrochukM,

Thanks for checking out pyloudnorm.

This is an interesting issue. The first thing is that a sample rate of 1000 for most audio signals is not very realsitic, and in those cases I do not think the loudness algorithm will produce meaningful results. However, I agree with you that pyloudnorm should not produce a value like 2473.459531146733.

I noticed something else from your example. You are using a sample rate of 1000, but trying to construct a sine wave with a frequency of 997 Hz. According to Nyquist we can only represent properly a signal of fs/2 which would be 500 Hz in this case. I found that pyloudnorm gives -inf correctly in the case where you increase the sample rate to 2000 Hz. However, whenever a sample rate of 1000 Hz or less is used I find this overflow issue. It is not clear yet what causes this, but I have a hypothesis that it is related to how the filters are constructed. They likely do not make sense with such low cutoff frequencies and hence cause an overflow.

I do not think it is worth reworking the computation to fix this edge case as it might have implications for performance at normal sample rates. Instead I propose that we add an error message when users supply audio with a sample rate less than 8000 Hz. This seems like a valid solution since the original algorithm was not intended to operate at samples rates lower than this anyway. What do you think?