简体   繁体   中英

How to get list of amplitude values from a wave file in python

How could I get a list of the amplitudes of each frame in a wave file using python (in the dB unit)?

So far I have this:

samplerate, data = wavfile.read(patternPath)
print(max((data[:, 1]).tolist())))

but that prints out 0.7856917381286621 , which doesn't make much sense because I know that the wav file never surpasses 0 dB.

Assuming you are looking for the dBFS, the simple answer would be to use the definition:

20 log (P/P0) dB
  • P: measured power
  • P0: reference power

In Python terms:

import numpy as np

amps = [1, 0.1, 0.01] # that's the values you read from the file
dbs = 20 * np.log10(np.abs(amps)) # -> array([  0., -20., -40.])

The result is dBFS : Decibels relative to full scale (dBFS or dB FS) is a unit of measurement for amplitude levels in digital systems, such as pulse-code modulation (PCM), which have a defined maximum peak level.

Mind you, this has nothing to do with the absolute audio level, you cannot derive from it the dB SPL (Sound Pressure Level). The job of a microphone is to convert the change in air pressure (measured in dB SPL) into an analogous change in electrical voltage. This continuously changing voltage is sampled periodically and saved as a number (amplitude you read).

Since you loose the sound pressure information, to retrieve back the dB SPL you'd need to calibrate your system and know ADC range and microphone sensitivity.

AES17 defines 0 dBFS as 20*log10(FS) where 1.0 FS corresponds to the RMS level of a 997 Hz sine wave whose peak value reaches the positive digital full scale. It is normally considered that positive digital full scale is 1.0. If your data is represented otherwise, you'll need to scale first. Then it is worth nothing that the rms of a sine wave with a peak amplitude is 0.707 (sqrt(2)/2), but AES has defined this as 1.0 FS. Therefore you'll need to multiply the rms by a sqrt(2) to normalize to the AES standard.

# create a 1 kHz sine wave for 100 ms.
data = np.sin(2*np.pi*np.arange(0,480)*1000/48000)

# measure the rms of the sine wave and convert to fs
# via sqrt(2)
fs = np.sqrt(2) * np.sqrt(np.mean(data*data))

# final step convert to dBFS
dbfs = 20*np.log10(fs)

Presumably, you would like periodic readings of the amplitude. To do accomplish this you need to take your signal (data) and slice it into sections at the desired rate and run this process on each section. For a 1 second reading interval as an example, you take sample rate number of samples at a time.

It's also worth understanding one of this pitfalls of this technique. That is that chopping the signal up can result in a partial cycle of a waveform contaminating the rms computation (eg taking 1.25 ms of a 1kHz waveform). Taking a longer reading will diminish the error term as a part of the whole. In effect, the lower frequency the signal, the longer your reading interval needs to be.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM