2017-07-08 2 views
1

Ich versuche, einen einzigen Herzschlag aus einer. Wav-Datei von 20-30 Sekunden aufgezeichnet Heartbeat Audio.Jeder Herzschlag beginnt mit einem High-Intensity-Sound (Peak) namens "Iub" und dann ein weiterer Herzschlag wiederholt von der nächsten Spitze.Wie extrahiert man ein Segment der Audiodatei mit Python?

Wie, was Bibliotheken zu verwenden, werden alle Algorithmen bereits verfügbar, Tutorials usw.

Antwort

0

Verwenden Sie Standard-Bibliothek Wellen-Modul laden Audio. Dann wandeln Sie Daten in ein numpliges Array um und verwenden Sie dann den Peak-Detection-Algorithmus von scipy oder einigen Scikits.

Einige Code:

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]) 

Und jetzt führen Sie Spitzenerfassung auf Array ein. Sie können zum Beispiel einen Algorithmus von scikits talkbox verwenden (hier ist ein Kopieren-Einfügen der Funktion):



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. 

Verwandte Themen