我正在尝试从20-30秒记录的心跳音频的.wav文件中提取单个心跳。每次心跳都以高强度声音(峰值)开始,称为" lub"然后另一个心跳从下一个峰值重复。
与使用的库类似,已有的任何算法,可用的教程等等。
答案 0 :(得分:1)
使用标准库波形模块加载音频。然后将数据转换为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])
现在您在阵列a上执行峰值检测。您可以使用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.