text: from __future__ import division
  from pydub import AudioSegment
  from dejavu.decoder import path_to_songname
  from dejavu import Dejavu
  from dejavu.fingerprint import *
  import traceback
  import fnmatch
  import os, re, ast
  import subprocess
  import random
  import logging
  
  def set_seed(seed=None):
      """
      `seed` as None means that the sampling will be random. 
  
      Setting your own seed means that you can produce the 
      same experiment over and over. 
      """
      if seed != None:
          random.seed(seed)
  
  def get_files_recursive(src, fmt):
      """
      `src` is the source directory. 
      `fmt` is the extension, ie ".mp3" or "mp3", etc.
      """
      for root, dirnames, filenames in os.walk(src):
          for filename in fnmatch.filter(filenames, '*' + fmt):
              yield os.path.join(root, filename)
  
  def get_length_audio(audiopath, extension):
      """
      Returns length of audio in seconds. 
      Returns None if format isn't supported or in case of error. 
      """
      try:
          audio = AudioSegment.from_file(audiopath, extension.replace(".", ""))
      except:
          print "Error in get_length_audio(): %s" % traceback.format_exc()
          return None
      return int(len(audio) / 1000.0)
  
  def get_starttime(length, nseconds, padding):
      """
      `length` is total audio length in seconds
      `nseconds` is amount of time to sample in seconds
      `padding` is off-limits seconds at beginning and ending
      """
      maximum = length - padding - nseconds
      if padding > maximum:
          return 0
      return random.randint(padding, maximum)
  
  def generate_test_files(src, dest, nseconds, fmts=[".mp3", ".wav"], padding=10):
      """
      Generates a test file for each file recursively in `src` directory
      of given format using `nseconds` sampled from the audio file. 
  
      Results are written to `dest` directory.
  
      `padding` is the number of off-limit seconds and the beginning and
      end of a track that won't be sampled in testing. Often you want to 
      avoid silence, etc. 
      """
      # create directories if necessary
      for directory in [src, dest]:
          try:
              os.stat(directory)
          except:
              os.mkdir(directory)
  
      # find files recursively of a given file format
      for fmt in fmts:
          testsources = get_files_recursive(src, fmt) 
          for audiosource in testsources:
  
              print "audiosource:", audiosource
              
              filename, extension = os.path.splitext(os.path.basename(audiosource))
              length = get_length_audio(audiosource, extension) 
              starttime = get_starttime(length, nseconds, padding)
  
              test_file_name = "%s_%s_%ssec.%s" % (
                  os.path.join(dest, filename), starttime, 
                  nseconds, extension.replace(".", ""))
              
              subprocess.check_output([
                  "ffmpeg", "-y",
                  "-ss", "%d" % starttime, 
                  '-t' , "%d" % nseconds, 
                  "-i", audiosource,
                  test_file_name])
  
  def log_msg(msg, log=True, silent=False):
      if log:
          logging.debug(msg)
      if not silent:
          print msg
  
  def autolabel(rects, ax):
      # attach some text labels
      for rect in rects:
          height = rect.get_height()
          ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height, 
              '%d' % int(height), ha='center', va='bottom')
  
  def autolabeldoubles(rects, ax):
      # attach some text labels
      for rect in rects:
          height = rect.get_height()
          ax.text(rect.get_x() + rect.get_width() / 2., 1.05 * height, 
              '%s' % round(float(height), 3), ha='center', va='bottom')
  
  class DejavuTest(object):
      def __init__(self, folder, seconds):
          super(DejavuTest, self).__init__()
  
          self.test_folder = folder
          self.test_seconds = seconds
          self.test_songs = []
  
          print "test_seconds", self.test_seconds
  
          self.test_files = [
              f for f in os.listdir(self.test_folder) 
              if os.path.isfile(os.path.join(self.test_folder, f)) 
              and re.findall("[0-9]*sec", f)[0] in self.test_seconds]
  
          print "test_files", self.test_files
  
          self.n_columns = len(self.test_seconds)
          self.n_lines = int(len(self.test_files) / self.n_columns)
  
          print "columns:", self.n_columns
          print "length of test files:", len(self.test_files)
          print "lines:", self.n_lines
  
          # variable match results (yes, no, invalid)
          self.result_match = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)] 
  
          print "result_match matrix:", self.result_match 
  
          # variable match precision (if matched in the corrected time)
          self.result_matching_times = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)] 
  
          # variable mahing time (query time) 
          self.result_query_duration = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)] 
  
          # variable confidence
          self.result_match_confidence = [[0 for x in xrange(self.n_columns)] for x in xrange(self.n_lines)] 
  
          self.begin()
  
      def get_column_id (self, secs):
          for i, sec in enumerate(self.test_seconds):
              if secs == sec:
                  return i
  
      def get_line_id (self, song):
          for i, s in enumerate(self.test_songs):
              if song == s:
                  return i
          self.test_songs.append(song)
          return len(self.test_songs) - 1
  
      def create_plots(self, name, results, results_folder):
          for sec in range(0, len(self.test_seconds)):
              ind = np.arange(self.n_lines) #
              width = 0.25       # the width of the bars
  
              fig = plt.figure()
              ax = fig.add_subplot(111)
              ax.set_xlim([-1 * width, 2 * width])
  
              means_dvj = [x[0] for x in results[sec]]
              rects1 = ax.bar(ind, means_dvj, width, color='r')
  
              # add some
              ax.set_ylabel(name)
              ax.set_title("%s %s Results" % (self.test_seconds[sec], name)) 
              ax.set_xticks(ind + width)
  
              labels = [0 for x in range(0, self.n_lines)]
              for x in range(0, self.n_lines):
                  labels[x] = "song %s" % (x+1)
              ax.set_xticklabels(labels)
  
              box = ax.get_position()
              ax.set_position([box.x0, box.y0, box.width * 0.75, box.height])
  
              #ax.legend( (rects1[0]), ('Dejavu'), loc='center left', bbox_to_anchor=(1, 0.5))
  
              if name == 'Confidence':
                  autolabel(rects1, ax)
              else:
                  autolabeldoubles(rects1, ax)
  
              plt.grid()
  
              fig_name = os.path.join(results_folder, "%s_%s.png" % (name, self.test_seconds[sec]))
              fig.savefig(fig_name)
  
      def begin(self):
          for f in self.test_files:
              log_msg('--------------------------------------------------')
              log_msg('file: %s' % f)
  
              # get column 
              col = self.get_column_id(re.findall("[0-9]*sec", f)[0])
              # format: XXXX_offset_length.mp3
              song = path_to_songname(f).split("_")[0]  
              line = self.get_line_id(song)
              result = subprocess.check_output([
                  "python", 
                  "dejavu.py",
                  '-r',
                  'file', 
                  self.test_folder + "/" + f])
  
              if result.strip() == "None":
                  log_msg('No match')
                  self.result_match[line][col] = 'no'
                  self.result_matching_times[line][col] = 0
                  self.result_query_duration[line][col] = 0
                  self.result_match_confidence[line][col] = 0
              
              else:
                  result = result.strip()
                  result = result.replace(" \'", ' "')
                  result = result.replace("{\'", '{"')
                  result = result.replace("\':", '":')
                  result = result.replace("\',", '",')
  
                  # which song did we predict?
                  result = ast.literal_eval(result)
                  song_result = result["song_name"]
                  log_msg('song: %s' % song)
                  log_msg('song_result: %s' % song_result)
  
                  if song_result != song:
                      log_msg('invalid match')
                      self.result_match[line][col] = 'invalid'
                      self.result_matching_times[line][col] = 0
                      self.result_query_duration[line][col] = 0
                      self.result_match_confidence[line][col] = 0
                  else:
                      log_msg('correct match')
                      print self.result_match
                      self.result_match[line][col] = 'yes'
                      self.result_query_duration[line][col] = round(result[Dejavu.MATCH_TIME],3)
                      self.result_match_confidence[line][col] = result[Dejavu.CONFIDENCE]
  
                      song_start_time = re.findall("\_[^\_]+",f)
                      song_start_time = song_start_time[0].lstrip("_ ")
  
                      result_start_time = round((result[Dejavu.OFFSET] * DEFAULT_WINDOW_SIZE * 
                          DEFAULT_OVERLAP_RATIO) / (DEFAULT_FS), 0)
  
                      self.result_matching_times[line][col] = int(result_start_time) - int(song_start_time)
                      if (abs(self.result_matching_times[line][col]) == 1):
                          self.result_matching_times[line][col] = 0
  
                      log_msg('query duration: %s' % round(result[Dejavu.MATCH_TIME],3))
                      log_msg('confidence: %s' % result[Dejavu.CONFIDENCE])
                      log_msg('song start_time: %s' % song_start_time)
                      log_msg('result start time: %s' % result_start_time)
                      if (self.result_matching_times[line][col] == 0):
                          log_msg('accurate match')
                      else:
                          log_msg('inaccurate match')
              log_msg('--------------------------------------------------\n')
  
  
  
  
  