TrackAnalyzer(String[] args) throws Exception {

    JCommander jcommander = new JCommander(c, args);
    jcommander.setProgramName("TrackAnalyzer");
    if ((c.filenames.size() == 0 && Utils.isEmpty(c.filelist)) || c.help) {
      jcommander.usage();
      System.exit(-1);
    }
    if (c.debug) {
      Logger.getLogger(TrackAnalyzer.class.getName()).setLevel(Level.ALL);
    } else {
      Logger.getLogger(TrackAnalyzer.class.getName()).setLevel(Level.WARNING);
    }
    // we have a list, read all the filenames in the list and
    // collect them in 'filenames'
    if (!Utils.isEmpty(c.filelist)) {
      try {
        // use buffering, reading one line at a time
        // FileReader always assumes default encoding is OK!
        BufferedReader input = new BufferedReader(new FileReader(new File(c.filelist)));
        try {
          String line = null; // not declared within while loop
          /*
           * readLine is a bit quirky :
           * it returns the content of a line MINUS the newline.
           * it returns null only for the END of the stream.
           * it returns an empty String if two newlines appear in a row.
           */
          while ((line = input.readLine()) != null) {
            filenames.add(line);
          }
        } finally {
          input.close();
        }
      } catch (IOException ex) {
        ex.printStackTrace();
        System.exit(-1);
      }
    }
    // add filenames from command line
    filenames.addAll(c.filenames);

    if (!Utils.isEmpty(c.writeList)) {
      try {
        writeListWriter = new BufferedWriter(new FileWriter(c.writeList));
      } catch (IOException ex) {
        Logger.getLogger(TrackAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
      }
    }
    k = new KeyFinder();
    p = new Parameters();
    p.setHopSize(8192);
  }
  /**
   * runs key and bpm detector on
   *
   * @filename, optionally writes tags
   * @param filename
   * @return
   */
  public boolean analyzeTrack(String filename, boolean writeTags) {
    String wavfilename = "";
    AudioData data = new AudioData();
    File temp = null;
    File temp2 = null;
    try {
      temp = File.createTempFile("keyfinder", ".wav");
      temp2 = File.createTempFile("keyfinder2", ".wav");
      wavfilename = temp.getAbsolutePath();
      // Delete temp file when program exits.
      temp.deleteOnExit();
      temp2.deleteOnExit();
      decodeAudioFile(new File(filename), temp, 44100);
      decodeAudioFile(temp, temp2);
    } catch (Exception ex) {
      Logger.getLogger(TrackAnalyzer.class.getName())
          .log(Level.WARNING, "error while decoding" + filename + ".");
      if (temp.length() == 0) {
        logDetectionResult(filename, "-", "-", false);
        temp.delete();
        temp2.delete();
        return false;
      }
    }

    KeyDetectionResult r;
    try {
      data.loadFromAudioFile(temp2.getAbsolutePath());
      r = k.findKey(data, p);
      if (r.globalKeyEstimate == Parameters.key_t.SILENCE) {
        System.out.println("SILENCE");
      }
    } catch (Exception ex) {
      Logger.getLogger(TrackAnalyzer.class.getName()).log(Level.SEVERE, null, ex);
      logDetectionResult(filename, "-", "-", false);
      deleteTempFiles(temp, temp2);
      return false;
    }

    String formattedBpm = "0";
    if (!c.noBpm) {
      // get bpm
      if (c.hiQuality) {
        try {
          // decodeAudioFile(new File(filename), temp, 44100);
          // @todo hiquality stuff
        } catch (Exception ex) {
          Logger.getLogger(TrackAnalyzer.class.getName())
              .log(
                  Level.WARNING,
                  "couldn't decode " + filename + " for hiquality bpm detection.",
                  ex);
        }
      }
      double bpm = BeatRoot.getBPM(wavfilename);
      if (Double.isNaN(bpm) && !c.hiQuality) {
        try {
          // bpm couldn't be detected. try again with a higher quality wav.
          Logger.getLogger(TrackAnalyzer.class.getName())
              .log(Level.WARNING, "bpm couldn't be detected for " + filename + ". Trying again.");
          decodeAudioFile(new File(filename), temp, 44100);
          bpm = BeatRoot.getBPM(wavfilename);
          if (Double.isNaN(bpm)) {
            Logger.getLogger(TrackAnalyzer.class.getName())
                .log(Level.WARNING, "bpm still couldn't be detected for " + filename + ".");
          } else {
            Logger.getLogger(TrackAnalyzer.class.getName())
                .log(Level.INFO, "bpm now detected correctly for " + filename);
          }
        } catch (Exception ex) {
          logDetectionResult(filename, "-", "-", false);
        }
      } else if (Double.isNaN(bpm) && c.hiQuality) {
        Logger.getLogger(TrackAnalyzer.class.getName())
            .log(Level.WARNING, "bpm couldn't be detected for " + filename + ".");
      }
      if (!Double.isNaN(bpm)) {
        formattedBpm = new DecimalFormat("#.#").format(bpm).replaceAll(",", ".");
      }
    }
    System.out.printf(
        "%s key: %s BPM: %s\n", filename, Parameters.camelotKey(r.globalKeyEstimate), formattedBpm);

    boolean wroteTags = false;
    if (c.writeTags) {
      wroteTags = updateTags(filename, formattedBpm, Parameters.camelotKey(r.globalKeyEstimate));
    }
    logDetectionResult(
        filename, Parameters.camelotKey(r.globalKeyEstimate), formattedBpm, wroteTags);
    deleteTempFiles(temp, temp2);
    return true;
  }