//
// Programmer:    Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Tue Mar 26 09:12:54 PST 2002
// Last Modified: Tue Mar 26 09:12:58 PST 2002
// Filename:      ...sig/examples/all/scorepitch.cpp
// Web Address:   http://sig.sapp.org/examples/museinfo/score/scorepitch.cpp
// Syntax:        C++; museinfo
//
// Description:   Extract pitch information from a SCORE data file.
//

#include "museinfo.h"
#include "ScorePage.h"

#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#ifndef OLDCPP
   #include <fstream>
#else
   #include <fstream.h>
#endif


// function declarations:
void extractPitches(ScorePage& score);
void printItem(ScoreRecord& record, int& clef, int& key);
void printKey(int key);
void printClef(int clef);


// interface variables:
Options options;
int     verboseQ  = 0;    // Display debugging information
int     rhythmQ   = 1;    // use with the -r option


int main(int argc, char** argv) {
   options.define("v|verbose=b",      "print debugging information");
   options.define("R|no-rhythm=b",    "don't display rhythm information");
   options.process(argc, argv);
   verboseQ  =  options.getBoolean("verbose");
   rhythmQ   = !options.getBoolean("no-rhythm");

   if (options.getArgCount() == 0) {
      cout << "Usage: " << argv[0] << " input.mus " << endl;
      exit(1);
   }

   ScorePage score;
   for (int i=1; i<=options.getArgCount(); i++) {
      score.clear();
      score.readFile(options.getArg(i), verboseQ); 
      extractPitches(score);
   }

   cout << flush;
   return 0;
}


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


//////////////////////////////
//
// extractPitches --
//

void extractPitches(ScorePage& score) {
   score.analyzePitch();
   int i, j;
   int clef = -1000;
   int key  = -1000;
   for (i=score.getMaxStaff(); i>=0; i--) {
      if (verboseQ) {
         cout << "Staff: " << i << "\titems: " << score.getStaffSize(i) << endl;
      }
      for (j=0; j<score.getStaffSize(i); j++) {
         printItem(score.getStaff(i, j), clef, key);
      }
      if (score.getStaffSize(i) > 0) {
         cout << "\n";
      }
   }

}



//////////////////////////////
//
// printItem -- print the given score item.
//

void printItem(ScoreRecord& record, int& clef, int& key) {
   char pbuffer[32] = {0};
   char dbuffer[32] = {0};
   int tempkey;
   int tempclef;
   switch ((int)record.getPValue(1)) {
      case S_Note:
         cout << " ";
         if (rhythmQ) {
            if (record.getPValue(7) == 0.0 || record.getPValue(7) > 64.0) {
               cout << "8";
            } else {
               cout << Convert::durationToKernRhythm(dbuffer, record.getPValue(7));
            }
         }
         cout << Convert::base40ToKern(pbuffer, record.getPitch());
         if (rhythmQ) {
            if (record.getPValue(7) == 0.0 || record.getPValue(7) > 64.0) {
               cout << "q";
            }
         }
         break;
      case S_Rest:
         cout << " ";
         if (rhythmQ) {
            cout << Convert::durationToKernRhythm(dbuffer, record.getPValue(7));
         }
         cout << "r";
         break;
      case S_Barline:
         cout << " =";
         switch ((int)record.getPValue(5)) {
            case 1: cout << "||"; break;
            case 2: cout << "="; break;
            case 3: cout << ":|!"; break;
            case 4: cout << "!|:"; break;
            case 5: cout << ":|!|:"; break;
            case 6: cout << ":!!:"; break;
         }
         break;
      case S_MeterSignature:
         cout << " *M" << (int)record.getPValue(5) 
              << "/" << (int)record.getPValue(6);
         break;
      case S_KeySignature:
         tempkey = (int)record.getPValue(5);
         if (key < -10 || key != tempkey) {
            key = tempkey;
            cout << " ";
            printKey(key);
         } 
         break;
      case S_Clef:
         tempclef = (int)record.getPValue(5);
         if (clef < -10 || clef != tempclef) {
            clef = tempclef;
            cout << " ";
            printClef(clef);
         }
   }
}



//////////////////////////////
//
// printClef -- print the **kern clef token.
//   Ignoring Soprano, Baritone, and Mezzo-soprano clefs for now.
//

void printClef(int clef) {
   switch (clef) {
      case  0:  cout << "*clefG2";    break;   // treble
      case  1:  cout << "*clefF4";    break;   // bass
      case  2:  cout << "*clefC3";    break;   // alto
      case  3:  cout << "*clefC4";    break;   // tenor
      case  4:  cout << "*clefX";     break;   // percussion
   }
}



//////////////////////////////
//
// printKey -- print the **kern key token.
//

void printKey(int key) {
   switch (key) {
      case -7:  cout << "*k[b-e-a-d-g-c-f-]";  break;
      case -6:  cout << "*k[b-e-a-d-g-c-]";    break;
      case -5:  cout << "*k[b-e-a-d-g-]";      break;
      case -4:  cout << "*k[b-e-a-d-]";        break;
      case -3:  cout << "*k[b-e-a-]";          break;
      case -2:  cout << "*k[b-e-]";            break;
      case -1:  cout << "*k[b-]";              break;
      case  0:  cout << "*k[]";                break;
      case  1:  cout << "*k[f#]";              break;
      case  2:  cout << "*k[f#c#]";            break;
      case  3:  cout << "*k[f#c#g#]";          break;
      case  4:  cout << "*k[f#c#g#d#]";        break;
      case  5:  cout << "*k[f#c#g#d#a#]";      break;
      case  6:  cout << "*k[f#c#g#d#a#e#]";    break;
      case  7:  cout << "*k[f#c#g#d#a#e#b#]";  break;
   }
}



// md5sum: 0429012f5b318ced9f67d5daa934c96e scorepitch.cpp [20050403]