patternpythonMinor
Comparing FFTs to deduplicate IVR recordings
Viewed 0 times
deduplicatecomparingrecordingsivrffts
Problem
I've got a Python script that traverses two file trees, checking all .wav files for duplication.
I'm still an undergrad, and have never worked with audio before. I'm not entirely sure this is going to be a valid comparison.
I lost the SO answer I was using as a guideline, but the general idea is to split the audio into chunks, FFT those chunks, then compare the results.
I also would appreciate any structure/style advice.
Note: All Olympus Recordings are valid, but I need to load them to have the ffts to compare.
```
import os
import os.path
import wave
import numpy
import struct
from shutil import copy
from subprocess import call, Popen, PIPE
oly_path = "/home/will/Desktop/soundfiles/Olympus Recordings"
titan_path = "/home/will/Desktop/soundfiles/TITAN Recordings"
wav_roots = [oly_path, titan_path]
destination_path = "/home/will/Desktop/soundfiles/output"
temp_wav_path = "/home/will/Desktop/soundfiles/temp.wav"
similarity_threshold = 95
validated_wavs = {}
bunk_wavs = {}
def get_fft_similarity(fft1, fft2):
hits = 0
len1 = len(fft1)
len2 = len(fft2)
limit = (len1 if len1= similarity_threshold:
bunk_wavs[key] = to_sort
return 0
while key in validated_wavs:
to_sort.generate_new_name()
key = to_sort.filename
for w in validated_wavs.values():
if get_fft_similarity(to_sort.fft, w.fft) >= similarity_threshold:
bunk_wavs[key] = to_sort
return 0
validated_wavs[key] = to_sort
return 1
def get_fft(fft_path):
return_list = []
frames_list = []
chunk_size = 36
start = 0
wav = wave.open(fft_path, 'r')
frames = wav.readframes(wav.getnframes())
wav.close()
while start+chunk_size fdddd", frames[start:start+chunk_size])
frames_list.append(data)
star
I'm still an undergrad, and have never worked with audio before. I'm not entirely sure this is going to be a valid comparison.
I lost the SO answer I was using as a guideline, but the general idea is to split the audio into chunks, FFT those chunks, then compare the results.
I also would appreciate any structure/style advice.
Note: All Olympus Recordings are valid, but I need to load them to have the ffts to compare.
```
import os
import os.path
import wave
import numpy
import struct
from shutil import copy
from subprocess import call, Popen, PIPE
oly_path = "/home/will/Desktop/soundfiles/Olympus Recordings"
titan_path = "/home/will/Desktop/soundfiles/TITAN Recordings"
wav_roots = [oly_path, titan_path]
destination_path = "/home/will/Desktop/soundfiles/output"
temp_wav_path = "/home/will/Desktop/soundfiles/temp.wav"
similarity_threshold = 95
validated_wavs = {}
bunk_wavs = {}
def get_fft_similarity(fft1, fft2):
hits = 0
len1 = len(fft1)
len2 = len(fft2)
limit = (len1 if len1= similarity_threshold:
bunk_wavs[key] = to_sort
return 0
while key in validated_wavs:
to_sort.generate_new_name()
key = to_sort.filename
for w in validated_wavs.values():
if get_fft_similarity(to_sort.fft, w.fft) >= similarity_threshold:
bunk_wavs[key] = to_sort
return 0
validated_wavs[key] = to_sort
return 1
def get_fft(fft_path):
return_list = []
frames_list = []
chunk_size = 36
start = 0
wav = wave.open(fft_path, 'r')
frames = wav.readframes(wav.getnframes())
wav.close()
while start+chunk_size fdddd", frames[start:start+chunk_size])
frames_list.append(data)
star
Solution
UPPERCASE for constants
As a convention, in Python constants are uppercase:
No need for temporary variables
Are useless because you use them only once, thus leading to no efficiency gain and code clutter.
Also about this function:
-
-
Down below:
You are using explicit indexing and a counter variable. Maybe
Use more constants
You already use some, and that is nice, but things like:
Should be in their own named constant.
Are you sure of your class?
Usually if a class has
Peculiar double effect
I noticed that
As a convention, in Python constants are uppercase:
OLY_PATH = "/home/will/Desktop/soundfiles/Olympus Recordings"
TITAN_PATH = "/home/will/Desktop/soundfiles/TITAN Recordings"
WAV_ROOTS = [oly_path, titan_path]
DESTINATION_PATH = "/home/will/Desktop/soundfiles/output"
TEEMP_WAV_PATH = "/home/will/Desktop/soundfiles/temp.wav"No need for temporary variables
len1 = len(fft1)
len2 = len(fft2)Are useless because you use them only once, thus leading to no efficiency gain and code clutter.
def get_fft_similarity(fft1, fft2):
hits = 0
limit = (len1 if len(fft1)<len(fft2) else len2)
if limit == 0:
return 0
for i in xrange(limit):
if (fft1[i] == fft2[i]).all():
hits += 1
ratio = float(hits)/limit
return int(ratio*100)Also about this function:
-
float(hits)/limit you can remove float if you from __future__ import division-
Down below:
for i in xrange(limit):
if (fft1[i] == fft2[i]).all():
hits += 1You are using explicit indexing and a counter variable. Maybe
zip is and sum will simplify your code.Use more constants
You already use some, and that is nice, but things like:
"Olympus"
".wav"
"Signed Integer PCM"
"soxi"
- ...
Should be in their own named constant.
Are you sure of your class?
Usually if a class has
init and only one other function, maybe you can use just a function for simplicity: I am looking at class IVR_WavPeculiar double effect
sort_wavI noticed that
sort_wav both modifies a global variable and returns 1 or 0. It is then called by validate. Maybe you could write a validator_helper to make the check and another function to update the dictionary.Code Snippets
OLY_PATH = "/home/will/Desktop/soundfiles/Olympus Recordings"
TITAN_PATH = "/home/will/Desktop/soundfiles/TITAN Recordings"
WAV_ROOTS = [oly_path, titan_path]
DESTINATION_PATH = "/home/will/Desktop/soundfiles/output"
TEEMP_WAV_PATH = "/home/will/Desktop/soundfiles/temp.wav"len1 = len(fft1)
len2 = len(fft2)def get_fft_similarity(fft1, fft2):
hits = 0
limit = (len1 if len(fft1)<len(fft2) else len2)
if limit == 0:
return 0
for i in xrange(limit):
if (fft1[i] == fft2[i]).all():
hits += 1
ratio = float(hits)/limit
return int(ratio*100)for i in xrange(limit):
if (fft1[i] == fft2[i]).all():
hits += 1Context
StackExchange Code Review Q#94672, answer score: 5
Revisions (0)
No revisions yet.