//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Wed Dec 25 13:27:50 PST 2002
// Last Modified: Sun Dec 29 20:36:05 PST 2002
// Filename:      ...sig/examples/all/rootspectrum.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/humdrum/rootspectrum.cpp
// Syntax:        C++; museinfo
//
// Description:   Determine the root of a pitch set according to
//                different root-interval class sizes.
// 

#include "humdrum.h"

#include <stdio.h>


// function declarations
void        checkOptions(Options& opts, int argc, char* argv[]);
void        example(void);
void        usage(const char* command);

// global variables
Options     options;                  // database for command-line arguments
int         debugQ       = 0;         // used with --debug option
int         normQ        = 0;         // used to print norm scores (1.0 = best)
const char* label        = "";        // used for uniq MMA variable names
int         functionQ    = 1;         // used for MMA printing of functions
double      theta1       = 55.0;      // used for calculating interval weights
int         mmaQ         = 0;         // used with -m option
int         invQ         = 1;         // used with -I option
int         xfigQ        = 0;         // used with -x option
int         plotQ        = 0;         // used with -X option
int         displaytype  = 0;         // used with -5 and -b options
int         firstline    = -1;        // used with -r option
int         lastline     = -1;        // used with -r option
int         dataQ        = 0;         // used with --data option
double      dweight      = 0.25;      // duration weight from -d option
double      lweight      = 0.25;      // metric level weight from -l option
int         durationQ    = 1;         // used with -D option
int         levelQ       = 1;         // used with -M, -L option
int         melodyQ      = 1;         // used with -H option

const char* plottitle    = "Root Spectrum";  // used with -t option
IntervalWeight iweights;
RootSpectrum   spectrum;

///////////////////////////////////////////////////////////////////////////

int main(int argc, char* argv[]) {
   // process the command-line options
   checkOptions(options, argc, argv);

   HumdrumFile infile;
   // if no command-line arguments read data file from standard input
   if (options.getArgCount() < 1) {
      infile.read(cin);
   } else {
      infile.read(options.getArg(1));
   }

   if (firstline < 0) {
      firstline = 0;
   } else if (firstline > infile.getNumLines() - 1) {
      firstline = infile.getNumLines() - 1;
   }
   if ((lastline < 0) || (lastline > infile.getNumLines() - 1)) {
      lastline = infile.getNumLines() - 1;
   }

   spectrum.calculate(iweights, infile, firstline, lastline, debugQ);

   if (dataQ) {
      exit(0);
   }

   if (mmaQ) {
      spectrum.printMMA(label, cout, functionQ, normQ);
   } else if (xfigQ) {
      spectrum.printXfig(cout, plottitle, displaytype);
   } else if (plotQ) {
      spectrum.printPlot(cout, displaytype);
   } else {
      spectrum.printHumdrum(cout, displaytype, invQ, normQ);
   }
   return 0;
}


///////////////////////////////////////////////////////////////////////////


//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//

void checkOptions(Options& opts, int argc, char* argv[]) {

   opts.define("n|norm=b",         "normalize root scores so that best is 1.0");
   opts.define("l|label=s",        "variable label");
   opts.define("t|theta=d:55.0",   "theta1 for interval weight calculations");
   opts.define("F|no-functions=b", "do not display MMA functions for plotting");
   opts.define("w|weightfile=s",   "interval weight file");
   opts.define("W|display-weights=b", "display interval weights and exit");
   opts.define("H|no-non-harmonic=b", "don't do non-harmonic note id");
   opts.define("mma=b",            "display spectrum as Mathematica plot");
   opts.define("x|xfig=b",         "display spectrum in xfig format");
   opts.define("X|plot=b",        "display spectrum in plot (pre-xfig) format");
   opts.define("5|fifths=b",       "display 2D plots by 5ths");
   opts.define("b|best=b",         "display 2D plots by best score ordering");
   opts.define("I|no-invert=b",    "don't invert root scores");
   opts.define("T|plot-title|title=s:Root Spectrum", "Title on plot outputs");
   opts.define("d|duration-weight=d:0.25", "duration weighting factor");
   opts.define("m|metric-weight=d:0.25",   "metric level weighting factor");
   opts.define("D|duration-weighting-off=b", "turn off duration weighting");
   opts.define("M|L|metric-weighting-off=b", "turn off metric weighting");
   opts.define("R|rhythm-weighting-off=b", "turn off duration and metric weighting");
   opts.define("r|range|lines=s:-1:-1", "range of lines offset from 1 to analyze in file");
   opts.define("debug=b",         "trace input parsing");   
   opts.define("data=b",          "trace input parsing");   

   opts.define("author=b",        "author of the program");   
   opts.define("version=b",       "compilation information"); 
   opts.define("example=b",       "example usage"); 
   opts.define("h|help=b",        "short description"); 
   opts.process(argc, argv);
   
   // handle basic options:
   if (opts.getBoolean("author")) {
      cout << "Written by Craig Stuart Sapp, "
           << "craig@ccrma.stanford.edu, December 2002" << endl;
      exit(0);
   } else if (opts.getBoolean("version")) {
      cout << argv[0] << ", version: 25 December 2002" << endl;
      cout << "compiled: " << __DATE__ << endl;
      cout << MUSEINFO_VERSION << endl;
      exit(0);
   } else if (opts.getBoolean("help")) {
      usage(opts.getCommand());
      exit(0);
   } else if (opts.getBoolean("example")) {
      example();
      exit(0);
   }

   debugQ     =  opts.getBoolean("debug");
   dataQ      =  opts.getBoolean("data");
   debugQ     =  debugQ | dataQ;
   normQ      =  opts.getBoolean("norm");
   functionQ  = !opts.getBoolean("no-functions");
   label      =  opts.getString("label");
   theta1     =  opts.getDouble("theta");
   mmaQ       =  opts.getBoolean("mma");
   plottitle  =  opts.getString("plot-title");
   invQ       = !opts.getBoolean("no-invert");
   xfigQ      =  opts.getBoolean("xfig");
   plotQ      =  opts.getBoolean("plot");
   lweight    =  opts.getDouble("metric-weight");
   dweight    =  opts.getDouble("duration-weight");
   durationQ  = !opts.getBoolean("duration-weighting-off");
   levelQ     = !opts.getBoolean("metric-weighting-off");
   melodyQ    = !opts.getBoolean("no-non-harmonic");
   if (opts.getBoolean("rhythm-weighting-off")) {
      durationQ = 0;
      levelQ    = 0;
   }


   // set the spectrum analysis values
   spectrum.setDuration(durationQ);
   spectrum.setMetricLevel(levelQ);
   spectrum.setDurationWeight(dweight);
   spectrum.setMetricLevelWeight(lweight);
   if (melodyQ) {
      spectrum.melodyOn();     // do non-harmonic tone estimation
   } else {
      spectrum.melodyOff();    // do not do non-harmonic tone estimation
   }


   if (opts.getBoolean("fifths")) {
      displaytype = DISPLAY_CHROMATIC;
   } else if (opts.getBoolean("best")) {
      displaytype = DISPLAY_BEST;
   } else {
      displaytype = DISPLAY_DIATONIC;
   }

   if (opts.getBoolean("weightfile")) {
      iweights.setFromFile(opts.getString("weightfile"));
   } else {
      iweights.setChromatic1(theta1);
   }
   
   if (opts.getBoolean("display-weights")) {
      cout << iweights;
      exit(0);
   }

   if (opts.getBoolean("range")) {
      sscanf(opts.getString("range"), "%d:%d", &firstline, &lastline);
      firstline -= 1;
      lastline -= 1;
   }
}



//////////////////////////////
//
// example -- example usage of the rootspectrum program
//

void example(void) {
   cout <<
   "                                                                        \n"
   << endl;
}



//////////////////////////////
//
// usage -- gives the usage statement for the rootspectrum program
//

void usage(const char* command) {
   cout <<
   "                                                                        \n"
   << endl;
}




// md5sum: e396096eac176accbe0d550abb22ad5c rootspectrum.cpp [20050403]