1
我試圖從20-30秒錄製的心跳音頻的.wav文件中提取單個心跳。每次心跳都從一個名爲「lub」的高強度聲音(峯值)開始,然後另一個心跳從下一個高峯重複。如何使用python提取一段音頻文件?
像什麼庫使用,任何可用的算法,可輔導等
我試圖從20-30秒錄製的心跳音頻的.wav文件中提取單個心跳。每次心跳都從一個名爲「lub」的高強度聲音(峯值)開始,然後另一個心跳從下一個高峯重複。如何使用python提取一段音頻文件?
像什麼庫使用,任何可用的算法,可輔導等
使用標準庫波模塊加載音頻。然後將數據轉換爲numpy數組,然後使用scipy或scikits的峯值檢測算法。
一些代碼:
import wave
wf = wave.open("file.wav", "r")
fs = wf.getframerate()
nc = wf.getnchannels()
sw = wf.getsampwidth()
nf = wf.getnframes()
data = wf.readframes(nf)
wf.close()
import numpy as np
dt = {1: np.int8, 2: np.int16, 4: np.int32}
a = np.fromstring(data, dtype=dt[sw])
現在你陣列上執行峯值檢測。您可以使用例如scikits talkbox的算法(這裏是該功能的複製粘貼):
def findpeaks (x, neighbours=50):
"""
Peak seeking algorithm from scikits talkbox.
Returns indexes of peaks in the x curve.
"""
peaks = []
nx = x.size
assert 2 * neighbours + 1 <= nx
if nx == 1:
return [0]
elif nx == 2:
if x[0] > x[1]:
peaks.append(0)
else:
peaks.append(1)
return peaks
# Handle points which have less than neighs samples on their left
for i in xrange(neighbours):
cur = x[i]
m = x[i+1]
# look at the left of the current position
for j in xrange(i):
if m < x[j]:
m = x[j]
# look at the right of the current position
for j in xrange(i+1, i+neighbours):
if m < x[j]:
m = x[j]
if cur > m:
peaks.append(i)
#assert(pkcnt <= (nx/neighbours + 1))
# Handle points which have at least neighs samples on both their left
# and right
for i in xrange(neighbours, nx - neighbours):
cur = x[i]
m = x[i+1]
# look at the left
for j in xrange(i - neighbours, i):
if m < x[j]:
m = x[j]
# look at the right
for j in xrange(i+1, i+neighbours):
if m < x[j]:
m = x[j]
if cur > m:
peaks.append(i)
#assert(pkcnt <= (nx/neighbours + 1))
# Handle points which have less than neighs samples on their right
for i in xrange(nx - neighbours, nx):
cur = x[i]
m = x[i-1]
# look at the left
for j in xrange(i - neighbours, i):
if m < x[j]:
m = x[j]
# look at the right
for j in xrange(i+1, nx):
if m < x[j]:
m = x[j]
if cur > m:
peaks.append(i)
#assert(pkcnt <= (nx/neighbours + 1))
return peaks
peaks = findpeaks(a)
# And now you get the segment of a signal by slicing it:
# For example (assuming you checked what peaks you want and if they were found at all):
s = a[peaks[0]:peaks[1]] # Let say you want first two peaks regardless the sign
# As you can see, this concrete algo is not strictly numpy dependant. You just have to change line nx = x.size into nx = len(x) to avoid it completely.
# So you can "throw" numpy away by loading wave data into a list like this:
import struct
dt = {1: "c", 2: "h", 4: "l"}
a = struct.unpack("<"+dt[sw], data)
# And then you use a as demonstrated above i.e. as an array. But numpy will give you more flexibility, speed and options to work on.