Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从振幅或FFT到dB_Python_Signal Processing_Fft_Wav_Decibel - Fatal编程技术网

Python 从振幅或FFT到dB

Python 从振幅或FFT到dB,python,signal-processing,fft,wav,decibel,Python,Signal Processing,Fft,Wav,Decibel,我有一个Python代码,它在wav文件上执行FFT,并绘制振幅-时间/振幅-频率图。我想从这些图中计算dB(它们是长数组)。我不想计算精确的dBA,我只想在计算后看到一个线性关系。我有分贝表,我会比较一下。这是我的密码: #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function import scipy.io.wavfile as wavfile import scipy impor

我有一个Python代码,它在wav文件上执行FFT,并绘制振幅-时间/振幅-频率图。我想从这些图中计算dB(它们是长数组)。我不想计算精确的dBA,我只想在计算后看到一个线性关系。我有分贝表,我会比较一下。这是我的密码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
import scipy.io.wavfile as wavfile
import scipy
import scipy.fftpack
import numpy as np
from matplotlib import pyplot as plt

fs_rate, signal = wavfile.read("output.wav")
print ("Frequency sampling", fs_rate)
l_audio = len(signal.shape)
print ("Channels", l_audio)
if l_audio == 2:
    signal = signal.sum(axis=1) / 2
N = signal.shape[0]
print ("Complete Samplings N", N)
secs = N / float(fs_rate)
print ("secs", secs)
Ts = 1.0/fs_rate # sampling interval in time
print ("Timestep between samples Ts", Ts)
t = scipy.arange(0, secs, Ts) # time vector as scipy arange field / numpy.ndarray
FFT = abs(scipy.fft(signal))
FFT_side = FFT[range(N//4)] # one side FFT range
freqs = scipy.fftpack.fftfreq(signal.size, t[1]-t[0])
fft_freqs = np.array(freqs)
freqs_side = freqs[range(N//4)] # one side frequency range
fft_freqs_side = np.array(freqs_side)

makespositive = signal[44100:]*(-1)
logal = np.log10(makespositive)

sn1 = np.mean(logal[1:44100])
sn2 = np.mean(logal[44100:88200])
sn3 = np.mean(logal[88200:132300])
sn4 = np.mean(logal[132300:176400])

print(sn1)
print(sn2)
print(sn3)
print(sn4)

abs(FFT_side)
for a in range(500):
    FFT_side[a] = 0

plt.subplot(311)
p1 = plt.plot(t[44100:], signal[44100:], "g") # plotting the signal
plt.xlabel('Time')
plt.ylabel('Amplitude')

plt.subplot(312)
p1 = plt.plot(t[44100:], logal, "r") # plotting the signal
plt.xlabel('Time')
plt.ylabel('Amplitude')

plt.subplot(313)
p3 = plt.plot(freqs_side, abs(FFT_side), "b") # plotting the positive fft spectrum
plt.xlabel('Frequency (Hz)')
plt.ylabel('Count single-sided')
plt.show()
第一个图是振幅与时间的关系,第二个图是上一个图的对数,最后一个图是FFT。 在sn1、sn2部分中,我尝试从信号中计算dB。首先我取对数,然后计算每秒钟的平均值。这并没有给我一个明确的关系。我也试过了,但没有成功

import numpy as np
import matplotlib.pyplot as plt
import scipy.io.wavfile as wf

fs, signal = wf.read('output.wav')  # Load the file
ref = 32768  # 0 dBFS is 32678 with an int16 signal

N = 8192
win = np.hamming(N)                                                       
x = signal[0:N] * win                             # Take a slice and multiply by a window
sp = np.fft.rfft(x)                               # Calculate real FFT
s_mag = np.abs(sp) * 2 / np.sum(win)              # Scale the magnitude of FFT by window and factor of 2,
                                                  # because we are using half of FFT spectrum
s_dbfs = 20 * np.log10(s_mag / ref)               # Convert to dBFS
freq = np.arange((N / 2) + 1) / (float(N) / fs)   # Frequency axis
plt.plot(freq, s_dbfs)
plt.grid(True)
那么我应该执行哪些步骤呢?(对所有频率振幅求和/平均值,然后取对数或倒数,或对信号等进行计算)

输出:

[4.6057844427695475e+17, 5.0025315250895744e+17, 5.028593412665193e+17, 4.910948397471887e+17]
[353.26607217 353.98379668 354.02893044 353.82330741]

分贝计测量信号的平均功率。因此,根据时间信号记录,您可以使用以下公式计算平均信号功率:

chunk_size = 44100
num_chunk  = len(signal) // chunk_size
sn = []
for chunk in range(0, num_chunk):
  sn.append(np.mean(signal[chunk*chunk_size:(chunk+1)*chunk_size]**2))
然后,相应的平均信号功率(单位:分贝)简单地由下式给出:

logsn = 10*np.log10(sn)
还可以使用获得频域信号的等效关系,但在您的情况下,将需要不必要的FFT计算(当您已经必须为其他目的计算FFT时,此关系最有用)


但是请注意,根据您的比较,可能会有一些差异(希望很小)。例如,使用非线性放大器会影响扬声器与放大器的关系。类似地,环境噪声会增加分贝计测得的功率。

我添加了第一张图的绘图。根据您的代码,序列号的第一部分和最后一部分为正,中间部分为负:
[16105357.619081633,-3698520.4044557824,-4771604.62320861748875571.17558957]
。第一秒和最后一秒是静音(约33分贝),它们之间是真空吸尘器(约55分贝)。我不明白为什么第一个值和最后一个值不相同或不接近。同样由于消极性,我面临着错误:
[16105357.619081633,-3698520.4044557824,-4771604.623208617,48875571.17558957]
sn
作为数量平方的平均值(因此为正)不应该为负。假设您完全按照原样使用了我的代码(即没有输入错误),那么可能是该信号包含整数值,在平方运算期间溢出。您可以尝试
(信号[…]。astype(float))**2
。您可以在第一个条目中检查编辑。我刚刚将
.astype(float)
添加到上一个。我仍然在同一个wav文件上执行它。结果太相似了,我无法区分沉默和吸尘器@另外,我们总是检查平均值。静音时Bu的振幅约为-0.5,噪声时Bu的振幅约为-0.25-0.75。所以沉默的平均值是-0.5,但是噪音的平均值也是-0.5,从(-0.25-0.75)/2。我知道你说的是RMS,但我的意思把我搞糊涂了@Sleutheye看起来你的输入信号有很大的偏差。我不确定它的确切来源,但典型的音频通常在0左右振荡。一旦你找出偏差的来源并消除它,你会得到更好的结果(否则你可以消除100毫秒小窗口上信号的平均值)。
logsn = 10*np.log10(sn)