diff src/program_options.cpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/program_options.cpp	Thu Aug 25 11:05:55 2011 +0100
@@ -0,0 +1,180 @@
+//  Copyright 2011, Ian Hobson.
+//
+//  This file is part of gpsynth.
+//
+//  gpsynth is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  gpsynth is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with gpsynth in the file COPYING. 
+//  If not, see http://www.gnu.org/licenses/.
+
+#include "program_options.hpp"
+
+#include "boost/filesystem.hpp"
+#include "boost/program_options.hpp"
+
+#include <ctime>
+
+namespace bf = boost::filesystem;
+namespace bo = boost::program_options;
+
+namespace {
+
+const std::string g_default_sc_app_path = "/Applications/SuperCollider";
+
+void PrintHelpAndQuit(const bo::options_description& options,
+                      int exit_code = 0) {
+  bo::arg = "value";
+  std::cout << '\n' << options << std::endl;
+  exit(exit_code);
+}
+
+std::string GetTimeString() {
+  std::time_t raw_time;
+  time(&raw_time);
+  tm* time_info = localtime(&raw_time);
+  char buffer[20];
+  strftime(buffer, 20, "%Y-%m-%d_%H:%M:%S", time_info);
+  return buffer;
+}
+
+  
+} // namespace
+
+
+void ParseCommandLine(int argument_count,
+                      const char* arguments[],
+                      ProgramOptions* options) {
+  bo::options_description description;
+  description.add_options()
+  ("help,?", "Displays this message")
+  ("target,t",
+   bo::value<std::string>(&options->target_path_)->required(),
+   "Target sound file path")
+  ("grammar,g",
+   bo::value<std::string>(&options->grammar_path_),
+   "Grammar file path")
+  ("scpath,s", 
+   bo::value<std::string>(&options->sc_app_path_),
+   "Path to SuperCollider application folder")
+  ("workfolder,w", 
+   bo::value<std::string>(&options->work_folder_),
+   "Path of folder to place files in")
+  ("population,p",
+   bo::value<std::size_t>(&options->population_size_)->default_value(500),
+   "Population size")
+  ("generations,G",
+   bo::value<std::size_t>(&options->generations_)->default_value(20),
+   "Number of Generations")
+  ("fitness,f",
+   bo::value<double>(&options->fitness_threshold_)->default_value(0),
+   "Fitness threshold")
+  ("tournament,T",
+   bo::value<std::size_t>(&options->tournament_size_)->default_value(7),
+   "Tournament selection size")
+  ("crossover,c",
+   bo::value<double>(&options->crossover_rate_)->default_value(0.6, "0.6"),
+   "Crossover rate")
+  ("mutation,m",
+   bo::value<double>(&options->mutation_rate_)->default_value(0.35, "0.35"),
+   "Mutation rate")
+  ("reproducebest,r",
+   bo::value<bool>(&options->reproduce_best_individual_)->default_value(false),
+   "Automatically reproduce best individual when populating next generation.")
+  ("features,F",
+   bo::value<std::string>(&options->fitness_features_),
+   "Set of features that the fitness function will measure when comparing files."
+   " Must be a comma separated list of feature names, which can be any of the following:"
+   " pitch, energy, mfccs, dmfccs, ddmfccs, mag, logmag, centroid, spread, flux."
+   " Default value is 'mfccs,dmfccs,ddmfccs'.")
+  ("windowsize,w",
+   bo::value<std::size_t>(&options->analysis_window_size_)->default_value(1024),
+   "Analysis Window Size")
+  ("hopsize,h",
+   bo::value<std::size_t>(&options->analysis_hop_size_)->default_value(256),
+   "Analysis Hop Size")
+  ("maxtreedepth,M",
+   bo::value<std::size_t>(&options->maximum_tree_depth_)->default_value(3),
+   "Maximum generated tree depth (can grow bigger through mutation).")
+  ("keepfolders,k",
+   bo::value<bool>(&options->keep_temp_folders_)->default_value(false),
+   "When set to 1 the temporary generation folders won't be deleted")
+  ("corelimit,C",
+   bo::value<std::size_t>(&options->core_limit_)->default_value(0),
+   "Limits the number of cores gpsynth will use simultaneously, 0=unlimited.")
+  ;
+  
+  bo::command_line_parser parser(argument_count, arguments);
+  parser.options(description);
+  bo::variables_map config;
+  try {
+    bo::store(parser.run(), config);
+    bo::notify(config);
+  } catch (std::exception& e) {
+    std::cout << "Error parsing options: " << e.what() << ".\n";
+    PrintHelpAndQuit(description, -1);
+  }
+  
+  if (config.count("help")) {
+    PrintHelpAndQuit(description);
+  }
+  
+  if (config.count("workfolder") == 0) {
+    options->work_folder_ = bf::current_path().string();
+  }
+  // validate the work folder path
+  if (!bf::is_directory(options->work_folder_)) {
+    std::cout << "Work folder path '" << options->work_folder_ 
+              << "' doesn't exist.\n";
+    exit(-1);
+  }
+  options->work_folder_ += "/gpsynth_" + GetTimeString() + "/";
+  
+  if (config.count("scpath") == 0) {
+    options->sc_app_path_ = g_default_sc_app_path;
+  }
+  if (!bf::is_directory(options->sc_app_path_)) {
+    std::cout << "SC App path '" << options->sc_app_path_ 
+              << "' doesn't exist.\n";
+    exit(-1);
+  }
+  
+  if (options->tournament_size_ < 1) {
+    std::cout << "Tournament size must be greater than zero.\n";
+    exit(-1);
+  }
+  
+  if (options->tournament_size_ > options->population_size_) {
+    std::cout << "Tournament size can not be larger than population size.\n";
+    exit(-1);
+  }
+  
+  if (options->crossover_rate_ < 0 || options->crossover_rate_ > 1) {
+    std::cout << "The crossover rate should be between 0-1.\n";
+    exit(-1);
+  }
+  
+  if (options->mutation_rate_ < 0 || options->mutation_rate_ > 1) {
+    std::cout << "The mutation rate should be between 0-1.\n";
+    exit(-1);
+  }
+  
+  if (options->maximum_tree_depth_ < 1) {
+    std::cout << "Maximum tree depth must be greater than zero.\n";
+    exit(-1);
+  }
+  
+  if (options->fitness_features_.empty()) {
+    options->fitness_features_ = "mfccs,dmfccs,ddmfccs";
+  }
+}
+
+