2016-08-01 17 views
2

`Was ist der beste Weg, um eine 2 GB WAV-Datei (1 kHz Ton) für Audio-Aussetzer mit Wave-Modul zu analysieren? Ich habe versucht, das Skript untersuchen Sie eine 2GB WAV-Datei für Aussetzer mit Wave-Modul

import wave 
file1 = wave.open("testdropout.wav", "r") 
file2 = open("silence.log", "w") 
for i in xrange(file1.getnframes()): 
    frame = file1.readframes(i) 

    zero = True 

    for j in xrange(len(frame)): 
     # check if amplitude is greater than 0 
     # the ord() function converts the hex values to integers 
    if ord(frame[j]) > 0: 
     zero = False 
     break 

    if zero: 
     print >> file2, 'dropout at second %s' % (file1.tell()/file1.getframerate()) 
file1.close() 
file2.close() 
+0

Auf keinen Fall haben Sie eine Beispieldatei online? –

+0

Welche Version von Python? in 2.x Verwenden Sie 'xrange()' anstelle von 'range()' für einen Start. – TessellatingHeckler

Antwort

1

Ich denke, eine einfache Lösung für dieses wäre zu berücksichtigen, dass die Framerate auf Audiodateien ziemlich hoch ist. Eine Beispieldatei auf meinem Computer hat eine Bildrate von 8.000. Das bedeutet für jede Sekunde Audio, ich habe 8.000 Samples. Wenn Sie Audio verpassen, bin ich mir sicher, dass es in mehreren Frames innerhalb einer Sekunde existiert, so dass Sie Ihre Vergleiche so drastisch reduzieren können, wie es Ihre Standards erlauben würden. Wenn ich Sie wäre, würde ich versuchen, über jedes tausendste Sample statt jedes einzelne Sample in der Audiodatei zu iterieren. Das heißt im Grunde, dass es jede 1/8 Sekunde Audio überprüft, um zu sehen, ob es tot ist. Nicht so präzise, ​​aber hoffentlich wird es die Arbeit erledigen.

import wave 

file1 = wave.open("testdropout.wav", "r") 
file2 = open("silence.log", "w") 
for i in range(file1.getnframes()): 
    frame = file1.readframes(i) 

    zero = True 

    for j in range(0, len(frame), 1000): 
     # check if amplitude is greater than 0 
     # the ord() function converts the hex values to integers 
    if ord(frame[j]) > 0: 
     zero = False 
     break 

    if zero: 
     print >> file2, 'dropout at second %s' % (file1.tell()/file1.getframerate()) 

file1.close() 
file2.close() 
1

Im Moment lesen Sie die gesamte Datei in den Speicher, was nicht ideal ist. Wenn Sie sich die verfügbaren Methoden für ein "Wave_read" -Objekt ansehen, ist eines davon setpos(pos), das die Position des Dateizeigers auf pos setzt. Wenn Sie diese Position aktualisieren, sollten Sie nur den gewünschten Frame im Speicher behalten können, um Fehler zu vermeiden. Unten ist eine grobe Skizze:

import wave 

file1 = wave.open("testdropout.wav", "r") 
file2 = open("silence.log", "w") 

def scan_frame(frame): 
    for j in range(len(frame)): 
     # check if amplitude is less than 0 
     # It makes more sense here to check for the desired case (low amplitude) 
     # rather than breaking at higher amplitudes 
     if ord(frame[j]) <= 0: 
      return True 

for i in range(file1.getnframes()): 
    frame = file1.readframes(1) # only read the frame at the current file position 

    zero = scan_frame(frame) 

    if zero: 
     print >> file2, 'dropout at second %s' % (file1.tell()/file1.getframerate()) 

    pos = file1.tell() # States current file position 
    file1.setpos(pos + len(frame)) # or pos + 1, or whatever a single unit in a wave 
            # file is, I'm not entirely sure 

file1.close() 
file2.close() 

Hoffe, das kann helfen!

1

Ich habe das Modul wave vorher noch nicht benutzt, aber file1.readframes(i) sieht aus, als würde es 1 Frame lesen, wenn Sie im ersten Frame sind, 2 Frames im zweiten Frame, 10 Frames in der zehnten Frame, und eine 2-GB-CD-Qualität-Datei möglicherweise eine Million Frames - bis Sie bei Frame 100.000 100.000 Frames lesen ... immer langsamer durch die Schleife auch?

Und von meinem Kommentar, in Python 2 range() erzeugt ein In-Memory-Array der vollen Größe zuerst, und xrange() nicht, aber nicht mit Bereich überhaupt hilft noch mehr.

und drücken Sie den Looping nach unten in die unteren Schichten mit any() der Code kürzer zu machen und möglicherweise schneller:

import wave 

file1 = wave.open("testdropout.wav", "r") 
file2 = open("silence.log", "w") 

chunksize = file1.getframerate() 
chunk = file1.readframes(chunksize) 

while chunk: 
    if not any(ord(sample) for sample in chunk): 
    print >> file2, 'dropout at second %s' % (file1.tell()/chunksize) 

    chunk = file1.readframes(chunksize) 

file1.close() 
file2.close() 

Dies sollte die Datei in 1-Sekunden-Stücke lesen.

+0

wo überprüfe ich, ob die Amplitude größer als 0 ist? – sam

+0

@sam Ich habe gestern Ihren Kommentar gesehen, dass dies nicht funktioniert, ich habe hier eine zufällige .wav-Datei getestet, ohne dass ich sicher war, dass es sich um dieselbe Art von Aussetzer handelt. Der Test ist 'any (ord (sample) für sample in chunk)' - ein Generator, der alle von der Platte gelesenen Werte mit 'ord()' in Zahlen umwandelt und die Zahlen in Python wie folgt auf True/False setzen: 0-> Falsch, alles andere -> Wahr. Also gibt 'any()' True zurück, wenn einer der Samples größer als 0 ist. False, wenn sie alle 0 sind. Das könnte das Problem sein - es wird nur gedruckt, wenn die * ganze Sekunde * still ist. Vielleicht 'any (nicht ord (Probe) ...)'? – TessellatingHeckler