scipy 如何使用python获取声音包络

m1m5dgzv  于 2022-11-09  发布在  Python
关注(0)|答案(2)|浏览(171)

你好,我是Python的新手,也是声音信号分析的新手。我正在尝试获取出生歌曲(斑马雀)的包络。它有一个非常快速的信号波动,我尝试了不同的方法。例如,我试图绘制信号,并根据我找到的其他示例(我在代码上添加了注解以理解它),使用以下代码获取包络:

  1. # Import the libraries
  2. from pylab import *
  3. import numpy
  4. import scipy.signal.signaltools as sigtool
  5. import scipy, pylab
  6. from scipy.io import wavfile
  7. import wave, struct
  8. import scipy.signal as signal
  9. # Open the txt file and read the wave file (also save it as txt file)
  10. f_out = open('mike_1_44100_.txt', 'w')
  11. w = scipy.io.wavfile.read("mike_1_44100_.wav") #here your sound file
  12. a=w[1]
  13. f_out.write('#time #z' + '\n')
  14. # I print to check
  15. print 'vector w'
  16. print w[0],w[1]
  17. print w
  18. i=w[1].size
  19. p=numpy.arange(i)*0.0000226 #to properly define the time signal with the sample rate
  20. print 'vector p:'
  21. print p
  22. x=numpy.dstack([p,a])
  23. print 'vector x:'
  24. print x[0]
  25. # saving file
  26. numpy.savetxt('mike_1_44100_.txt',x[0])
  27. f_out.close()
  28. print 'i:'
  29. print i
  30. # num is the number of samples in the resampled signal.
  31. num= np.ceil(float(i*0.0000226)/0.0015)
  32. print num
  33. y_resample, x_resample = scipy.signal.resample(numpy.abs(a),num, p,axis=0, window=('gaussian',150))
  34. # y_resample, x_resample = scipy.signal.resample(numpy.abs(a), num, p,axis=-1, window=0)
  35. # Aplaying a filter
  36. W1=float(5000)/(float(44100)/2) #the frequency for the cut over the sample frequency
  37. (b, a1) = signal.butter(4, W1, btype='lowpass')
  38. aaa=a
  39. slp =1* signal.filtfilt(b, a1, aaa)
  40. # Taking the abs value of the signal the resample and finaly aplying the hilbert transform
  41. y_resample2 =numpy.sqrt(numpy.abs(np.imag(sigtool.hilbert(slp, axis=-1)))**2+numpy.abs(np.real(sigtool.hilbert(slp, axis=-1)))**2)
  42. print 'x sampled'
  43. # print x_resample
  44. print 'y sampled'
  45. # print y_resample
  46. xx=x_resample #[0]
  47. yy=y_resample #[1]
  48. # ploting with some style
  49. plot(p,a,label='Time Signal') #to plot amplitud vs time
  50. # plot(p,numpy.abs(a),label='Time signal')
  51. plot(xx,yy,label='Resampled time signal Fourier technique Gauss window 1.5 ms ', linewidth=3)
  52. # plot(ww,label='Window', linewidth=3)
  53. # plot(p,y_resample2,label='Hilbert transformed sime signal', linewidth=3)
  54. grid(True)
  55. pylab.xlabel("time [s]")
  56. pylab.ylabel("Amplitde")
  57. legend()
  58. show()

这里我尝试了两种方法,第一种是使用scipy中的重采样函数来获得包络,但我对信号幅度有一些问题,我还不明白(我上传了使用傅立叶技术获得的图像,但系统不允许我上传):
第二种方法是使用希尔伯特变换来得到包络(现在我再次上传了希尔伯特变换的图像,系统不允许我)可以运行我的代码并获得两个图像。但我会把这个链接http://ceciliajarne.web.unq.edu.ar/?page_id=92&preview=true
现在“包络”又失败了。我试着过滤信号,就像我在一些例子中看到的那样,但是我的信号被衰减了,我无法获得包络。**有人能帮助我的代码吗?或者有更好的想法来获得包络吗?**可以使用任何鸟鸣作为例子(我可以给予你我的),但我需要看看发生了什么与复杂的声音,而不是简单的信号,因为它是非常不同的(与简单的声音两种技术都可以)。
我还尝试改编我在以下代码中找到的代码:http://nipy.org/nitime/examples/mtm_baseband_power.html
但是我不能得到适合我的信号的参数,我不明白调制部分。我已经问了代码开发者,直到等待答案。

piztneat

piztneat1#

信号的包络可以使用相应analytic signal的绝对值来计算。Scipy实现函数scipy.signal.hilbert来计算分析信号。
从其文档中:
我们创建频率从20Hz增加到100Hz的啁啾,并应用幅度调制。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from scipy.signal import hilbert, chirp
  4. duration = 1.0
  5. fs = 400.0
  6. samples = int(fs*duration)
  7. t = np.arange(samples) / fs
  8. signal = chirp(t, 20.0, t[-1], 100.0)
  9. signal *= (1.0 + 0.5 * np.sin(2.0*np.pi*3.0*t))

振幅包络由分析信号的幅度给出。

  1. analytic_signal = hilbert(signal)
  2. amplitude_envelope = np.abs(analytic_signal)

看起来像是

  1. plt.plot(t, signal, label='signal')
  2. plt.plot(t, amplitude_envelope, label='envelope')
  3. plt.show()

它也可用于计算瞬时频率(参见文档)。

展开查看全部
cu6pst1q

cu6pst1q2#

由于鸟鸣声的“调制频率”可能远低于“载波频率”,即使振幅快速变化,也可以通过取信号的绝对值,然后应用长度为20 ms的移动平均滤波器来获得包络的近似值。
不过,你会不会对频率变化也感兴趣,以充分描述歌曲的特征?在这种情况下,在移动窗口上进行傅里叶变换会给予你更多的信息,即作为时间函数的近似频率内容。这是我们人类听到的,有助于我们区分鸟类物种。
如果您不希望衰减,则既不应应用巴特沃思滤波器,也不应采用移动平均值,而应应用峰值检测。
移动平均数:每个输出样值是例如50个先前输入样值的绝对值的平均值。
峰检测:每个输出样本是前面50个输入样本绝对值的最大值。输出不会被衰减。您可以在之后进行低通滤波,以去除剩余的阶梯“三重”。
你想知道为什么巴特沃思滤波器会衰减你的信号。如果你的截止频率足够高,它几乎不会衰减,但它看起来只是被强烈衰减了。你的输入信号不是载波的总和(口哨声)和调制滤波将限制频率成分,剩下的是频率分量(术语)而不是因子。您可以看到衰减调制(包络),因为该频率分量确实存在于信号中,比原始包络弱很多,因为它没有添加到载波中,而是与载波相乘。由于包络所乘以的载波正弦曲线,并不总是处于其最大值,包络将被调制过程而不是滤波分析“衰减”。
简而言之:如果您直接需要(乘法)包络,而不是由于包络调制(乘法)而产生的(加法)频率分量,请采用峰值检测方法。
峰值检测算法中的“Pythonish”伪代码,只是为了得到的想法。

  1. # Untested, but apart from typos this should work fine
  2. # No attention paid to speed, just to clarify the algorithm
  3. # Input signal and output signal are Python lists
  4. # Listcomprehensions will be a bit faster
  5. # Numpy will be a lot faster
  6. def getEnvelope (inputSignal):
  7. # Taking the absolute value
  8. absoluteSignal = []
  9. for sample in inputSignal:
  10. absoluteSignal.append (abs (sample))
  11. # Peak detection
  12. intervalLength = 50 # Experiment with this number, it depends on your sample frequency and highest "whistle" frequency
  13. outputSignal = []
  14. for baseIndex in range (intervalLength, len (absoluteSignal)):
  15. maximum = 0
  16. for lookbackIndex in range (intervalLength):
  17. maximum = max (absoluteSignal [baseIndex - lookbackIndex], maximum)
  18. outputSignal.append (maximum)
  19. return outputSignal
展开查看全部

相关问题