Currently I am using this code:
import sys
import soundfile as sf
import pyloudnorm as pyln
f = open( "c:\\temp\\wav_analysis.txt", "w" )
data, rate = sf.read(sys.argv[1]) # load audio (with shape (samples, channels))
meter = pyln.Meter( rate ) # create BS.1770 meter
loudness = meter.integrated_loudness(data) # measure loudness
'''output analysis data'''
for i in range(1, len(data)):
if abs(data[i]) > 0.4:
f.write(str( i / rate ) + "," + str(abs(data[ i ])) + "\n")
The WAV file is passed in as an argument, it's read in and then analyzed for loudness across all of "data".
I don't want that. I want to analyze 100ms windows of data (i.e. 4410 samples at a time, while shifting my window by 50 milliseconds, thus creating lots of loudness values.
Is there a way to call meter.integrated_loundess() in such a way that it does that?
Or do I need to somehow create a bunch of 4410-value long data arrays derived from "data" and then feed each one of those to meter.integrated_loudness() one by one?
(The stuff below '''output analysis data''' is just a place holder. I want to replace it with what I need.)
EDIT: See the "slicing" answer below. Also, keep in mind that through trial and error I discovered that integrated_loudness requires the data to be at least 17640 samples long (i.e. 400ms at 44100).
EDIT2: During random searching for something else, I came across this site:https://pysoundfile.readthedocs.io/en/0.8.0/
There, this code snippet was exactly what I was initially looking for for quickly getting the RMS values of the WAV file:
import numpy as np
import soundfile as sf
rms = [np.sqrt(np.mean(block**2)) for block in
sf.blocks('myfile.wav', blocksize=1024, overlap=512)]
Not only is it much faster, but it is also not limited by the "0.4second" window limit that I ran into with meter.integrated_loudness.
If I understand your question correctly, perhaps you can slice the data doing something like the following:
import sys
import soundfile as sf
import pyloudnorm as pyln
with open("c:\\temp\\wav_analysis.txt", "w") as f:
data, rate = sf.read(sys.argv[1]) # load audio (with shape (samples, channels))
meter = pyln.Meter(rate) # create BS.1770 meter
window_size = int(rate * 0.1) # window size of 100ms in samples
hop_size = int(rate * 0.05) # hop size of 50ms in samples
for i in range(0, len(data)-window_size, hop_size):
window = data[i:i+window_size] # extract a 100ms window of data
loudness = meter.integrated_loudness(window) # measure loudness of the window
f.write(f"{str(i / rate)},{str(loudness)}" + "\n")