#!/usr/bin/python

import argparse

from features import mfcc
from features import logfbank
import scipy.io.wavfile as wav
import numpy as n
from pydub import AudioSegment

WINLEN = 0.025      # 25 ms
#WINLEN = 0.25      # 250 ms
WINSTEP = WINLEN    # Don't allow them to overlap

def find_nearest_frames(filename):
    # TODO convert everything to same samplerate
    (rate,sig) = wav.read(filename)
    nchannels = sig.shape[1]
    print "Read %s with sample rate %s, #channels = %d" % (filename, rate, sig.shape[1])

    # Mix to mono
    # TODO: Multi-channel
    sig = n.mean(sig, axis=1)

    # 30 seconds
    sig = sig[:1323000]
    
    mfcc_feat = mfcc(sig, rate, winlen=WINLEN, winstep=WINSTEP)
    print "Created MFCC with shape", mfcc_feat.shape
    nframes = mfcc_feat.shape[0]

    # For each frame, find the nearest frame
    near_frame_idxs = []
    for frame_idx in range(nframes):
        this_frame = mfcc_feat[frame_idx]
        
        # Sum of squared distances (euclidean) against every frame:
        frame_dist = n.sqrt(n.square(mfcc_feat - this_frame).sum(axis=1))
        # Remove the frame corresponding to this index
        dist_idx = [(dist, idx) for (idx, dist) in enumerate(frame_dist.tolist()) if idx != frame_idx]
#        dist_idx = [(dist, idx) for (idx, dist) in enumerate(frame_dist.tolist())]
        dist_idx.sort()
    
        near_frame_dist = dist_idx[0][0]
        near_frame_idx = dist_idx[0][1]
    
        print "Nearest frame to frame #%d is frame #%d (dist = %.3f)" % (frame_idx, near_frame_idx, near_frame_dist)
        near_frame_idxs.append(near_frame_idx)

    print near_frame_idxs
    frame_locations = []
    for idx in near_frame_idxs:
        frame_locations.append((WINSTEP * idx, WINSTEP * idx + WINLEN))
    return frame_locations

def redub(input_filename, frame_locations, output_filename):
    song = AudioSegment.from_wav(input_filename)
    print "Read audio from %s" % input_filename
    fragments = []
    for (start_sec, end_sec) in frame_locations:
        start_ms = int(start_sec * 1000 + 0.5)
        end_ms = int(end_sec * 1000 + 0.5)
        fragment = song[start_ms:end_ms]
        fragments.append(fragment)
    newsong = fragments[0]
    for f in fragments[1:]: newsong += f
    newsong.export(output_filename, format="mp3")
    print "Wrote new song to %s" % output_filename

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Aucode a sound.')
    parser.add_argument('--input', dest='input', help='Input audio signal to be covered')
    #parser.add_argument('--corpus', help='MP3 of audio to use as samples')

    args = parser.parse_args()
    frame_locations = find_nearest_frames(args.input)
    redub(args.input, frame_locations, "foo.mp3")

@@ -280,26 +280,30 @@
 %0A%0Adef fi
-nd_nearest
+lename_to_mfcc
 _frames(
@@ -592,16 +592,17 @@
 xis=1)%0A%0A
+#
     # 30
@@ -610,16 +610,17 @@
 seconds%0A
+#
     sig 
@@ -761,16 +761,17 @@
 ape%0A    
+#
 nframes 
@@ -791,16 +791,211 @@
 hape%5B0%5D%0A
+    return mfcc_feat%0A%0Adef find_nearest_frames(input_filename, corpus_filename):%0A    input_mfcc = filename_to_mfcc_frames(input_filename)%0A    corpus_mfcc = filename_to_mfcc_frames(corpus_filename)
 %0A    # F
@@ -1078,16 +1078,30 @@
 _idx in 
+range(1000): #
 range(nf
@@ -1129,25 +1129,26 @@
 frame = 
-mfcc_feat
+input_mfcc
 %5Bframe_i
@@ -1265,25 +1265,27 @@
 .square(
-mfcc_feat
+corpus_mfcc
  - this_
@@ -2757,16 +2757,21 @@
 ered
+ (wav)
 ')%0A    
-#
 pars
@@ -2808,20 +2808,18 @@
 lp='
-MP3 of audio
+Audio file
  to 
@@ -2832,16 +2832,103 @@
  samples
+ (wav)')%0A    parser.add_argument('--output', dest='output', help='Output filename (mp3)
 ')%0A%0A    
@@ -3006,16 +3006,29 @@
 gs.input
+, args.corpus
 )%0A    re
@@ -3036,21 +3036,22 @@
 ub(args.
-input
+corpus
 , frame_
@@ -3065,15 +3065,17 @@
 ns, 
-%22foo.mp3%22
+args.output
 )%0A

Read three files