Exemplo n.º 1
0
void printKernOutput(HumdrumFile& infile) {
	int i, j;
	infile.analyzeRhythm("4");
	infile.printNonemptySegmentLabel(cout);
	for (i=0; i<infile.getNumLines(); i++) {
		if (!infile[i].isData()) {
			cout << infile[i].getLine() << "\n";
			continue;
		}
		for (j=0; j<infile[i].getFieldCount(); j++) {
			if (!infile[i].isExInterp(j, "**kern")) {
				if (strcmp(infile[i][j], ".") == 0) {
					if (parensQ) {
						cout << "(";
					}
					cout << infile.getDotValue(i, j);
					if (parensQ) {
						cout << ")";
					}
				} else {
					cout << infile[i][j];
				}
			} else {
				// this is **kern data, so create tied notes if note duration
				// is longer than the current line's duration
				printKernTokenLineDuration(infile, i, j);
			}
			if (j < infile[i].getFieldCount() - 1) {
				cout << "\t";
			}
		}
		cout << "\n";
	}
}
Exemplo n.º 2
0
void analyzeTiming(HumdrumFile& infile, Array<double>& timings,
      Array<double>& tempo) {
   infile.analyzeRhythm("4");

   timings.setSize(infile.getNumLines());
   timings.setAll(0.0);
   tempo.setSize(infile.getNumLines());
   tempo.setAll(dtempo);
   tempo[0] = dtempo;
   double currtempo = dtempo;
   double input = 0.0;
   int count;

   int i;
   for (i=1; i<infile.getNumLines(); i++) {
      // check for new tempo...
      if (strncmp(infile[i][0], "*MM", 3) == 0) {
         count = sscanf(infile[i][0], "*MM%lf", &input);
         if (count == 1) {
            currtempo = input;
            if (i > 0) {
               tempo[i-1] = currtempo;
            }
            tempo[i] = currtempo;
         }
      }

      tempo[i] = currtempo;
      timings[i] = timings[i-1] + (infile[i].getAbsBeat() - 
            infile[i-1].getAbsBeat()) * 60.0/currtempo;

   }

}
Exemplo n.º 3
0
int main(int argc, char* argv[]) {
    HumdrumFile infile;

    // process the command-line options
    checkOptions(options, argc, argv);

    // figure out the number of input files to process
    int numinputs = options.getArgCount();

    Array<double> absbeat;
    Array<int> pitch;
    Array<int> testset;
    Array<double> duration;
    Array<double> level;
    Array<double> coef;

    for (int i=0; i<numinputs || i==0; i++) {
        infile.clear();

        // if no command-line arguments read data file from standard input
        if (numinputs < 1) {
            infile.read(cin);
        } else {
            infile.read(options.getArg(i+1));
        }
        infile.analyzeRhythm();
        cout << "(cmn\n";
        convertToCMN(infile);
        cout << ")\n";
    }

    return 0;
}
Exemplo n.º 4
0
void analyzeTiming(HumdrumFile& infile, vector<double>& timings,
      vector<double>& tempo) {

   infile.analyzeRhythm();
   timings.resize(infile.getNumLines());
   fill(timings.begin(), timings.end(), 0.0);
   tempo.resize(infile.getNumLines());
   fill(tempo.begin(), tempo.end(), dtempo);
   double currtempo = dtempo;
   double input = 0.0;
   int count;

   int i;
   for (i=1; i<infile.getNumLines(); i++) {
      // check for new tempo...
      if (strncmp(infile[i][0], "*MM", 3) == 0) {
         count = sscanf(infile[i][0], "*MM%lf", &input);
         if (count == 1) {
            currtempo = input;
            if (i > 0) {
               tempo[i-1] = currtempo;
            }
            tempo[i] = currtempo;
         }
      }

      tempo[i] = currtempo;
      timings[i] = timings[i-1] + (infile[i].getAbsBeat() - 
            infile[i-1].getAbsBeat()) * 60.0/currtempo;

   }

}
Exemplo n.º 5
0
int main(int argc, char** argv) {
   HumdrumFile hfile;

   // process the command-line options
   checkOptions(options, argc, argv);

   // figure out the number of input files to process
   numinputs = options.getArgCount();
 
   const char* filename = "";

   for (int i=0; i<numinputs || i==0; i++) {
      hfile.clear();

      // if no command-line arguments read data file from standard input
      if (numinputs < 1) {
         filename = "";
         hfile.read(cin);
      } else {
         filename = options.getArg(i+1).data();
         hfile.read(filename);
      }
     
      hfile.analyzeRhythm();
      displayResults(hfile, numinputs, filename);
   }

   return 0;
}
Exemplo n.º 6
0
int main(int argc, char** argv) {
   // process the command-line options
   checkOptions(options, argc, argv);

   HumdrumFile infile;
   infile.read(options.getArg(1));
   if (distQ) {
      infile.analyzeRhythm();
   }
   Array<NoteUnit> notes;
   getNotes(notes, infile);
   scrambleNotes(notes);
   if (transQ) {
      printNotes(notes);
   } else {
      replaceNotes(infile, notes);
      cout << infile;
   }

   if (displaySeedQ) {
      cout << "!!!seed: " << seed << endl;
   }

   return 0;
}
Exemplo n.º 7
0
int main(int argc, char** argv) {
   if (argc > 2) {
      cout << "Usage: " << argv[0] << " input-file" << endl;
      exit(1);
   }

   HumdrumFile hfile;
   if (argc == 2) {
      hfile.read(argv[1]);
   } else if (argc == 1) {
      hfile.read(cin);
   }
   
   hfile.analyzeRhythm("4", DEBUG);

   int measure = 0;

   cout << "absbeat\tdur\tbeat\tmeasure\t::\tdata\n";
   cout << ":::::::::::::::::::::::::::::::::::::::::::::::::::::\n";
   for (int i=0; i<hfile.getNumLines(); i++) {
      if (hfile[i].isMeasure()) {
         sscanf(hfile[i][0], "=%d", &measure);
      }
      cout << hfile.getAbsBeat(i) << '\t'
           << hfile.getDuration(i) << '\t'
           << measure << '\t'
           << hfile.getBeat(i) << "\t::\t"
           << hfile.getLine(i) << endl;
   }

   return 0;
}
Exemplo n.º 8
0
int main(int argc, char** argv) {
   // process the command-line options
   checkOptions(options, argc, argv);

   // figure out the number of input files to process
   int numinputs = options.getArgCount();

   HumdrumFile hfile;
   for (int i=0; i<numinputs || i==0; i++) {
      hfile.clear();

      // if no command-line arguments read data file from standard input
      if (numinputs < 1) {
         hfile.read(cin);
      } else {
         hfile.read(options.getArg(i+1));
      }

      hfile.analyzeRhythm();
      divisions = hfile.getMinTimeBase();
      if (divisions % 4 == 0) {
         divisions = divisions/4;
      } else {
         // don't know what this case may be
      }
      convertToMusicXML(hfile);

   }

   return 0;
}
Exemplo n.º 9
0
int main(int argc, char** argv) {
   // process the command-line options
   checkOptions(options, argc, argv);
   HumdrumStream streamer(options);
   HumdrumFile hfile;
   if (!streamer.read(hfile)) {
      // no data could be read
      exit(1);
   }
   hfile.analyzeRhythm("4");
   printOutput(hfile);
   return 0;
}
Exemplo n.º 10
0
int main(int argc, char** argv) {
   checkOptions(options, argc, argv);
   HumdrumStream streamer(options);
   HumdrumFile infile;

   while (streamer.read(infile)) {
      if (beatQ || absQ) {
         infile.analyzeRhythm();
      }
      processFile(infile);
   }
  
   return 0;
}
Exemplo n.º 11
0
void inputNewFile(void) {
	data.clear();
	linenum = 0;
	if (!streamer.read(data)) {
		finishup();
		exit(0);
	}

	data.analyzeRhythm("4");

	if (fileNumber > 1) {
		millisleep((float)(1000 * options.getDouble("pause")));
	}
	fileNumber++;
}
Exemplo n.º 12
0
void getLocations(Array<double>& measures, HumdrumFile& infile, int segments) {
   infile.analyzeRhythm("4");
   double totaldur = infile.getTotalDuration();

   measures.setSize(segments);
   measures.allowGrowth(0);
   measures.setAll(-1);

   int barnum = 0;
   int index;

   int i;
   for (i=0; i<infile.getNumLines(); i++) {
      if (!infile[i].isMeasure()) {
         continue;
      }
      if (sscanf(infile[i][0], "=%d", &barnum) == 1) {
         index = int(infile[i].getAbsBeat() / totaldur * segments);
         measures[index] = barnum;
      }
   }

   for (i=1; i<segments; i++) {
      if (measures[i] < 0) {
         measures[i] = measures[i-1];
      } 
   }

   index = -1;
   for (i=0; i<segments; i++) {
      if (measures[i] != -1) {
         index = i - 1;
         break;
      }
   }

   if (index < 0) {
      return;
   }
   if (index >= segments) {
      return;
   }

   for (i=index; i>=0; i--) {
      measures[i] = measures[index+1] - 1;
   }

}
Exemplo n.º 13
0
void loadHistograms(Array<Array<double> >& histograms,
   HumdrumFile& infile, int segments) {

   infile.analyzeRhythm("4");
   double totalduration = infile.getTotalDuration();

   double duration;
   int i;
   int j;
   int k;
   char buffer[10000] = {0};
   int pitch;
   double start;
   int tokencount;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() !=  E_humrec_data) {
         continue;
      }
      start = infile[i].getAbsBeat();
      for (j=0; j<infile[i].getFieldCount(); j++) {
         if (strcmp(infile[i].getExInterp(j), "**kern") != 0) {
            continue;
         }
         if (strcmp(infile[i][j], ".") == 0) {
            continue; // ignore null tokens
         }
         tokencount = infile[i].getTokenCount(j);
         for (k=0; k<tokencount; k++) {
            infile[i].getToken(buffer, j, k);
            if (strcmp(buffer, ".") == 0) {
               continue;  // ignore illegal inline null tokens
            }
            pitch = Convert::kernToMidiNoteNumber(buffer);
            if (pitch < 0) {
               continue;  // ignore rests or strange objects
            }
            pitch = pitch % 12;  // convert to chromatic pitch-class
            duration = Convert::kernToDuration(buffer);
            if (duration <= 0.0) {
               continue;   // ignore grace notes and strange objects
            }
            
            addToHistogramDouble(histograms, pitch,
                  start, duration, totalduration, segments);
         }
      }
   }
}
Exemplo n.º 14
0
void processFileAuto(HumdrumFile& infile) {
   infile.analyzeRhythm("4");
   PerlRegularExpression pre;
   RationalNumber fraction = 1;
   int barcounter = 0;
   RationalNumber barstarttime;
   RationalNumber barduration;
   RationalNumber nextbarmessage;
   int dashQ = 0;

   for (int i=0; i<infile.getNumLines(); i++) {

      if ((nextbarmessage > 0) && (infile[i].getAbsBeatR() >= nextbarmessage)) {
         cout << "!!barline: absbeat=" << nextbarmessage;
         if (dashQ) {
            cout << " dash";
         }
         cout << endl;
         if (infile[i].getAbsBeatR() > nextbarmessage) {
            cout << "!!barline: dataline" << endl;
         } 
         barcounter++;
         if (barcounter+1 == fraction.getDenominator()) {
            nextbarmessage = -1;
         } else {
            nextbarmessage = barstarttime + barduration * 
                  fraction * (barcounter + 1);
         }
      }

      if (infile[i].isGlobalComment()) {
         if (pre.search(infile[i][0], "!!BARLINES:\\s*(\\d+)/(\\d+)")) {
            fraction  = atoi(pre.getSubmatch(1));
            fraction /= atoi(pre.getSubmatch(2));
            if (pre.search(infile[i][0], "dash", "i")) {
               dashQ = 1;
            } else {
               dashQ = 0;
            }
            continue;
         }
      }
      if (fraction == 1) {
         cout << infile[i] << endl;
         continue;
      }
      if (infile[i].isBarline()) {
         barcounter = 0;
         barstarttime = infile[i].getAbsBeatR();
         barduration  = infile[i].getMeasureDuration();
         if (barduration <= 0) {
            nextbarmessage = -1;
         } else {
            nextbarmessage = barstarttime + barduration * fraction;
         }
         cout << infile[i] << endl;
         continue;
      }

      cout << infile[i] << endl;
   }
}
Exemplo n.º 15
0
void processFile(HumdrumFile& infile) {
   infile.analyzeRhythm("4");

   Array<int>    measureline;   // line number in the file where measure occur
   Array<double> measurebeats;  // duration of measure
   Array<double> timesigbeats;  // duration according to timesignature
   Array<int>    control;       // control = numbered measure
   Array<int>    measurenums;   // output measure numbers

   measureline.setSize(infile.getNumLines());
   measureline.setSize(0);
   measurebeats.setSize(infile.getNumLines());
   measurebeats.setSize(0);
   timesigbeats.setSize(infile.getNumLines());
   timesigbeats.setSize(0);

   int i, j;
   double timesigdur = 0.0;
   double timetop = 4;
   double timebot = 1;
   double value   = 1;
   double lastvalue = 1;
   for (i=0; i<infile.getNumLines(); i++) {
      if (debugQ) {
         cout << "LINE " << i+1 << "\t" << infile[i] << endl;
      }
      if (infile[i].getType() == E_humrec_interpretation) {
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if ((strncmp(infile[i][j], "*M", 2) == 0) 
                  && (strchr(infile[i][j], '/') != NULL)) {
               timetop = Convert::kernTimeSignatureTop(infile[i][j]);
               timebot = Convert::kernTimeSignatureBottomToDuration(infile[i][j]);
               timesigdur = timetop * timebot;
               // fix last timesigbeats value
               if (timesigbeats.getSize() > 0) {
                  timesigbeats[timesigbeats.getSize()-1] = timesigdur;
                  measurebeats[measurebeats.getSize()-1] = lastvalue * timebot;
               }
            }
         }
      } else if (infile[i].getType() == E_humrec_data_measure) {
         measureline.append(i);
         lastvalue = infile[i].getBeat();
         // shouldn't use timebot (now analyzing rhythm by "4")
         // value = lastvalue * timebot;
         value = lastvalue;
         measurebeats.append(value);
         timesigbeats.append(timesigdur);
      }
   }

   if (debugQ) {
      cout << "measure beats / timesig beats" << endl;
      for (i=0; i<measurebeats.getSize(); i++) {
         cout << measurebeats[i] << "\t" << timesigbeats[i] << endl;
      }
   }

   if (measurebeats.getSize() == 0) {
      // no barlines, nothing to do...
      cout << infile;
      return;
   }

   // Identify controlling/non-controlling barlines
   // at each measure line determine one of three cases:
   // 
   // (1) all ok -- the summation of durations in the measure
   //     matches the current time sign
   // (2) a partial measure -- the measure durations do not
   //     add up to the time signature, but the measure is
   //     at the start/end of a musical section such as the
   //     beginning of a piece, end of a piece, or between
   //     repeat bar dividing a full measure.
   // (3) the sum of the durations does not match the 
   //     time signature because the durations are incorrectly
   //     given.
   //

   control.setSize(measureline.getSize());
   measurenums.setSize(measureline.getSize());
   control.setAll(-1);
   measurenums.setAll(-1);

   // If the time signature and the number of beats in a measure
   // agree, then the bar is worth numbering:
   for (i=0; i<control.getSize(); i++) {
      if (measurebeats[i] == timesigbeats[i]) {
         control[i] = 1;
      }
   }

   // Determine first bar (which is marked with a negative value
   // if there is a pickup bar)
   if (measurebeats[0] < 0) {
      if (-measurebeats[0] == timesigbeats[0]) {
         control[0] = 1;
      }
   }

   // Check for intermediate barlines which split one measure
   for (i=0; i<control.getSize()-2; i++) {
      if ((control[i] == 1) || (control[i+1] == 1)) {
         continue;
      }
      if (timesigbeats[i] != timesigbeats[i+1]) {
         continue;
      }
      if ((measurebeats[i]+measurebeats[i+1]) == timesigbeats[i]) {
         // found a barline which splits a complete measure
         // into two pieces.
         control[i] = 1;
         control[i+1] = 0;
         i++;
      }
   }

   // if two (or more) non-controlling bars occur in a row, then
   // make them controlling:
   //for (i=0; i<control.getSize()-1; i++) {
   //   if ((control[i] < 1) && (control[i+1] < 1)) {
   //      while ((i < control.getSize()) && (control[i] < 1)) {
   //         control[i++] = 1;
   //      }
   //   }
   //}

   for (i=0; i<control.getSize()-1; i++) {
      if ((control[i] == 0) && (control[i+1] < 0)) {
         control[i+1] = 1;
      }
   }

   // if a measure contains no beats, then it is not a controlling barline
   for (i=0; i<control.getSize(); i++) {
      if (measurebeats[i] == 0) {
         control[i] = 0;
      }
   }

   // if the first bar is not a pickup measure, but there is no
   // starting measure, then subtract one from the starting barline
   // count;
   int offset = 0;
   int dataq = 0;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].isData()) {
         dataq = 1;
         continue;
      }
      if (infile[i].getType() == E_humrec_data_measure) {
         if ((measurebeats[0] > 0) && dataq) {
            offset = 1;
         }
         break;
      }
   }

   // if the last bar is incomplete, but the bar before it
   // is not incomplete, then allow barline on last measure,
   // excluding any ending barlines with no data after them.
   for (i=control.getSize()-1; i>=0; i--) {
      if (control[i] == 0) {
         continue;
      }
      if ((control[i] < 0) && (i > 0) && (control[i-1] > 0)) {
         control[i] = 1;
      }
      break;
   }

   if (allQ) {
      control.setAll(1);
      offset = 0;
   }

   // if there is no time data, just label each barline
   // as a new measure. 
   if (infile[infile.getNumLines()-1].getAbsBeat() == 0.0) {
      for (i=0; i<control.getSize(); i++) {
         control[i] = 1;
      }
      // don't mark the last barline if there is no data
      // line after it.
      for (i=infile.getNumLines()-1; i>=0; i--) {
         if (infile[i].isData()) {
            break;
         }
         if (infile[i].isBarline()) {
            control.last() = -1;
            break;
         }
      }
   }

   // assign the measure numbers;
   int mnum = startnum + offset;
   for (i=0; i<measurenums.getSize(); i++) {
      if (control[i] == 1) {
         measurenums[i] = mnum++;
      }
   }

   if (debugQ) {
      cout << "cont\tnum\tbeats" << endl;
      for (i=0; i<control.getSize(); i++) {
         cout << control[i] << "\t" << measurenums[i] << "\t"
              << measurebeats[i] << "\t" << timesigbeats[i] << endl;
      }
   }

   int endingbarline = getEndingBarline(infile);

   // ready to print the new barline numbers
   int mindex = 0;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() != E_humrec_data_measure) {
         cout << infile[i] << "\n";
         continue;
      }

      if (endingbarline == i) {
         printWithoutBarNumbers(infile[i]);
      } else if (measurenums[mindex] < 0) {
         printWithoutBarNumbers(infile[i]);
      } else {
         printWithBarNumbers(infile[i], measurenums[mindex]);
      }

      mindex++;
   }

}
Exemplo n.º 16
0
void convertHumdrumToEnp(ostream& out, HumdrumFile& infile) {
   infile.analyzeRhythm("4");
   Array<int> kerntracks;
   getKernTracks(kerntracks, infile);

   Array<int> subtracks;
   getSubspines(subtracks, infile, kerntracks);

   Array<Array<char> > partnames;
   getPartNames(infile, partnames);
   Array<int> barlines;
   getBarlines(barlines, infile);

   checkMarks(infile, marks, markcolors);

   if (commentQ) {
      printHeaderComments(out, infile);
   }

   LEVEL = 0;

   // Print the outer score parentheses
   plineStart(out, LEVEL++, "(");
   if (labelQ) {
      out << ":begin :score";
   }
   out << endl;
   printScoreInformation(out, infile);

   int i, j;
   int partnum = 0;
   for (i=kerntracks.getSize()-1; i>=0; i--) {
      partnum++;
      indent(out, LEVEL++);

      // print part-level parenthesis
      out << "(";
      if (labelQ) {
         out << ":begin :part" << partnum;
      }
      out << endl;

      int initialclef = CLEF_UNKNOWN;
      printInitialStaff(out, infile, kerntracks[i], initialclef);
      int initialkeysig = printKeySignature(out, infile, kerntracks[i], 0);
      printTimeSignature(out, infile, kerntracks[i], 0);
      printPart(out, infile, kerntracks[i], 0, barlines, initialkeysig, initialclef);
      // print voices/layers after the first one:
      for (j=1; j<subtracks[i]; j++) {
         printPart(out, infile, kerntracks[i], j, barlines, initialkeysig, initialclef);
      }

      plineStart(out, --LEVEL, ")"); // part-level parenthesis
      if (labelQ) {
         out << " ; end :part" << partnum;
      }
      out << endl;
   }
   plineStart(out, --LEVEL, ")");
   if (labelQ) {
      out << " ; end :score";  // score level parenthesis
   }
   out << endl;

   if (commentQ) {
      printTrailerComments(out, infile);
   }
}
Exemplo n.º 17
0
void getTimings(HumdrumFile& infile, Array<double>& timings,
      Array<double>& tempo) {
   infile.analyzeRhythm("4");

   int i;
   int j;

   timings.setSize(infile.getNumLines());
   tempo.setSize(infile.getNumLines());

   timings.setAll(-1.0);
   tempo.setAll(-1.0);

   double atime;
   int secondsQ = 0;

   // get the timing values from the **time spine.
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() == E_humrec_interpretation) {
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if (strcmp(infile[i].getExInterp(j), "**time") == 0) {
               if (strcmp(infile[i][j], "*u=sec") == 0) {
                  // measuring time in seconds.
                  secondsQ = 1;
               } else if (strcmp(infile[i][j], "*u=msec") == 0) {
                  secondsQ = 0;
               }
               break;
            }
         }
      }
      if (infile[i].getType() != E_humrec_data) {
         continue; 
      }

      for (j=0; j<infile[i].getFieldCount(); j++) {
         // just looking for the first **time spine for now...
         if (strcmp(infile[i].getExInterp(j), "**time") != 0) {
            continue;
         }
         if (strcmp(infile[i][j], ".") == 0) {
            timings[i] = -1.0;
         } else {
            if (sscanf(infile[i][j], "%lf", &atime) == 1) {
               timings[i] = atime;
               if (secondsQ) {
                  // convert seconds measurements into milliseconds
                  timings[i] *= 1000.0;
               }
            } else {
               timings[i] = -1.0;
            }
         }
         break;
      }
   }

   // the times have been extracted from the Humdrum data, so now
   // convert them into tempo markings.  

   int lastindex = 0;
   double beatdur;
   double timedur;
   double atempo;
   
   for (i=0; i<infile.getNumLines(); i++) {
      if (timings[i] < 0.0) {
         continue;
      }
      beatdur = infile[i].getAbsBeat() - infile[lastindex].getAbsBeat();
      timedur = (timings[i] - timings[lastindex])/1000.0;
      atempo  = 60.0 * beatdur / timedur;
      tempo[lastindex] = atempo;
      if (roundQ) {
         tempo[lastindex] = (int)(tempo[lastindex] + 0.5);
      }
      lastindex = i;
   }

   // set all zero tempos to be the same as the previous
   // tempo marking.
   if (fillQ) {
      for (i=1; i<infile.getNumLines(); i++) {
         if (tempo[i] <= 0.0) {
            tempo[i] = tempo[i-1];
         }
      }
   }

}
Exemplo n.º 18
0
void processRecords(HumdrumFile& infile, HumdrumFile& outfile) {
   infile.analyzeRhythm();
   char buffer[10000] = {0};

   int style;
   double duration;
   style = styles.extract();
   duration = durations.extract();

   double currbeat = 0;

   double targetbeat = 0;
   int lastline = 0;
   double currdur;
   int state = 0;

   for (int i=0; i<infile.getNumLines(); i++) {
      if (options.getBoolean("debug")) {
         cout << "processing line " << (i+1) << " of input ..." << endl;
      }

      if (infile[i].getType() != E_humrec_data) {
         outfile.appendLine(infile[i]);
         continue;
      }
 
      state = 0;
      currbeat = infile[i].getAbsBeat();
      currdur = infile[i].getDuration();
      while ((currbeat+currdur > targetbeat) || 
            (fabs(currbeat-targetbeat) < 0.001)) {

         if (fabs(currbeat - targetbeat) < 0.0001) {
            createDataLine(buffer, infile, i, duration, style);
            outfile.appendLine(buffer);
            styles.insert(style);
            durations.insert(duration);
            style = styles.extract();
            duration = durations.extract();
            targetbeat += duration;
         } else if (currbeat+currdur > targetbeat) {
            if (state == 1) {
               createDataLine(buffer, infile, lastline, duration, style);
            } else {
               createDataLine(buffer, infile, i, duration, style);
            }
            outfile.appendLine(buffer);
            styles.insert(style);
            durations.insert(duration);
            style = styles.extract();
            duration = durations.extract();
            targetbeat += duration;
         } else {
            break;
         }
      }

      lastline = i;

   }
}
Exemplo n.º 19
0
void analyzeContinuously(HumdrumFile& infile, int windowsize,
      double stepsize, double* majorKey, double* minorKey) {

   Array<Array<double> > segments;
   infile.analyzeRhythm("4");
   int segmentCount = int(infile.getTotalDuration() / stepsize + 0.5);

   if (segmentCount < windowsize) {
      cout << "Not enough data for requested analysis" << endl;
      return;
   }

   segments.setSize(segmentCount);
   segments.allowGrowth(0);
   int i;
   for (i=0; i<segments.getSize(); i++) {
      segments[i].setSize(12);
      segments[i].allowGrowth(0);
      segments[i].setAll(0);
   }
	    
   loadHistograms(segments, infile, segmentCount);

   if (debugQ) {
      printHistogramTotals(segments);
   }

   Array<Array<double> > pitchhist; 
   Array<Array<double> > correlations;

   pitchhist.setSize(segmentCount-windowsize);
   correlations.setSize(segmentCount-windowsize);
   pitchhist.allowGrowth(0);
   correlations.allowGrowth(0);
   for (i=0; i<segmentCount-windowsize; i++) {
      pitchhist[i].setSize(13);  //last spot for best key
      pitchhist[i].allowGrowth(0);
      correlations[i].setSize(24);
      correlations[i].allowGrowth(0);
   }

   for (i=0; i<segmentCount - windowsize; i++) {
      createHistogram(pitchhist[i], i, windowsize, segments);
      identifyKeyDouble(pitchhist[i], correlations[i], majorKey, minorKey);
   }


   Array<double> measures;
   getLocations(measures, infile, segmentCount);

   cout << "**key\t**rval\t**conf\t**start\t**mid\t**end\n";
   for (i=0; i<pitchhist.getSize(); i++) {
      printBestKey(int(pitchhist[i][12] + 0.5));
      cout << "\t";
      printCorrelation(correlations[i][int(pitchhist[i][12]+ 0.1)], roundQ);
      cout << "\t";
      cout << getConfidence(correlations[i], int(pitchhist[i][12]+0.1));
      cout << "\t";
      cout << "=" << measures[i];
      cout << "\t";
      cout << "=" << int((measures[i] + measures[i+windowsize])/2+0.49);
      cout << "\t";
      cout << "=" << measures[i+windowsize];
      cout << endl;
   }
   cout << "*-\t*-\t*-\t*-\t*-\t*-\n";

}
Exemplo n.º 20
0
int generatePicture(HumdrumFile& infile, Array<PixelRow>& picture, int
      style) {

   Array<char> marks;
   getMarkChars(marks, infile);
   PixelColor matchcolor(255,255,255);

   infile.analyzeRhythm("4");
   int min = infile.getMinTimeBase();
   double totaldur = infile.getTotalDuration();
   
   int columns = (int)(totaldur * min / 4.0 + 0.5) + 5;
   if (columns > 50000) {
      cout << "Error: picture will be too big to generate" << endl;
      exit(1);
   }
   int factor = (int)(maxwidth / columns);
   if (factor <= 0) {
      factor = 1;
   }
   if (factor > maxfactor) {
      factor = maxfactor;
   }

   // set picture to black first.  Black regions will be filled in
   // with the background later.
   picture.setSize(128);
   int i, j, k;
   PixelColor backcolor(bgcolor);
   for (i=0; i<picture.getSize(); i++) {
      picture[i].setSize(columns * factor);
      for (j=0; j<picture[i].getSize(); j++) {
         picture[i][j] = backcolor;
         // picture[i][j].setRed(0);
         // picture[i][j].setGreen(0);
         // picture[i][j].setBlue(0);
      }
   }

   // examine metric levels for metric coloration
   Array<int>rhylev;
   infile.analyzeMetricLevel(rhylev);
   for (i=0; i<rhylev.getSize(); i++) {
      // reverse sign so that long notes are positive.
      rhylev[i] = -rhylev[i];
   }
   
   PixelColor color;
   int minpitch = 128;
   int maxpitch = -1;
   int pitch = 0;
   double duration = 0;
   double start = 0;
   char buffer[1024] = {0};
   for (i=0; i<infile.getNumLines(); i++) {
      if (debugQ) {
         cout << "Processing input line " << i + 1 << '\t' << infile[i] << endl;
      }
      if (infile[i].isData()) {
         start = infile[i].getAbsBeat();
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if (strcmp(infile[i].getExInterp(j), "**kern") != 0) {
               continue;
            }
            // duration = Convert::kernToDuration(infile[i][j]);
            duration = infile.getTiedDuration(i, j);
            color = makeColor(infile, i, j, style, rhylev, 
                  infile[i].getPrimaryTrack(j));
            for (k=0; k<infile[i].getTokenCount(j); k++) {
               infile[i].getToken(buffer, j, k);
               if (strchr(buffer, '_') != NULL) {
                  continue;
               }
               if (strchr(buffer, ']') != NULL) {
                  continue;
               }

               pitch = Convert::kernToMidiNoteNumber(buffer);
               if (pitch < 0) {
                  // ignore rests
                  continue;
               }
               if (pitch < minpitch) {
                  minpitch = pitch;
               }
               if (pitch > maxpitch) {
                  maxpitch = pitch;
               }
               if (isMatch(marks, buffer)) {
                  placeNote(picture, pitch, start, duration, min, 
                        color, factor, 1);
               } else {
                  placeNote(picture, pitch, start, duration, min, 
                        color, factor, 0);
               }
            }
         }
      }

   }

   gmaxpitch = maxpitch;
   gminpitch = minpitch;
   return factor;
}
Exemplo n.º 21
0
void analyzeTiming(HumdrumFile& infile, Array<double>& timings,
      Array<double>& tempo) {
   infile.analyzeRhythm("4");

   timings.setSize(infile.getNumLines());
   timings.setAll(0.0);
   tempo.setSize(infile.getNumLines());
   tempo.setAll(dtempo);
   tempo[0] = dtempo;
   double currtempo = dtempo;
   double input = 0.0;
   int count;
   Array<double> tempoindicators;
   Array<int>    tempoindex;

   tempoindicators.setSize(1000);
   tempoindicators.setSize(0);
   tempoindicators.setGrowth(1000);
   tempoindex.setSize(1000);
   tempoindex.setSize(0);
   tempoindex.setGrowth(1000);

   double ritard = -1.0;
   double accel  = -2.0;

   int i;
   int j;
   for (i=1; i<infile.getNumLines(); i++) {
      // check for new tempo...
      if (infile[i].getType() == E_humrec_interpretation) {
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if (strcmp(infile[i].getExInterp(j), "**kern") != 0) {
               continue;
            }
            if (strncmp(infile[i][j], "*MM", 3) == 0) {
               count = sscanf(infile[i][j], "*MM%lf", &input);
               if (count == 1) {
                  currtempo = input;
                  tempoindicators.append(currtempo);
                  tempoindex.append(i);
                  if (i > 0) {
                     tempo[i-1] = currtempo;
                  }
                  tempo[i] = currtempo;
               }
            } else if (strcmp(infile[i][j], "*accel") == 0) {
               tempoindicators.append(accel);
               tempoindex.append(i);
            } else if (strcmp(infile[i][j], "*rit") == 0) {
               tempoindicators.append(ritard);
               tempoindex.append(i);
            }
            break;
         }
      }

      tempo[i] = currtempo;
      timings[i] = timings[i-1] + (infile[i].getAbsBeat() - 
            infile[i-1].getAbsBeat()) * 60.0/currtempo;

   }

   if (!changeQ) {
      // do not adjust for *rit and *accel markers
      return;
   }

   // go back and geometrically interpolate the tempo markings
   // when there are *accel and *rit markers in the data.

   for (i=1; i<tempoindicators.getSize()-1; i++) {
      if ((tempoindicators[i] < 0) && (tempoindicators[i+1] > 0)) {
         interpolateGeometric(infile, tempo, tempoindex[i], tempoindex[i+1]);
      }
   }


   // the following code will have to be debugged (mostly for off-by-one
   // errors).

   // adjust the timing values
   double beatdiff;
   double increment = 1.0/32.0;
   double starttempo;
   double stoptempo;
   double timesum;
   double logtem1;
   double logtem2;
   double tfraction;
   double ftempo;
   double beatduration;
   int    ntindex;
   double startbeat;
   double stopbeat;

   for (i=1; i<infile.getNumLines(); i++) {
      starttempo   = tempo[i];
      ntindex      = getNextTempoIndex(infile, i);
      stoptempo    = tempo[ntindex];
      
      startbeat    = infile[i-1].getAbsBeat();
      stopbeat     = infile[i].getAbsBeat();
      beatduration = stopbeat - startbeat;
      beatdiff     = beatduration;

      if (starttempo == stoptempo) {
         timings[i] = timings[i-1] + beatduration * 60/tempo[i];
      } else {
         // calculate the time as the tempo changes
         logtem1      = log10(starttempo);
         logtem2      = log10(stoptempo);

         timesum = 0.0;
         while (beatdiff >= increment) {
            tfraction = ((beatduration - beatdiff) / beatduration);
            ftempo = pow(10.0, logtem1 + (logtem2 - logtem1) * tfraction);
            timesum += increment * 60/ftempo;
            beatdiff -= increment;
         }

         if (beatduration > 0.0) {
            tfraction = ((beatduration - beatdiff) / beatduration);
            ftempo = pow(10.0, logtem1 + (logtem2 - logtem1) * tfraction);
            timesum += beatdiff * 60/ftempo;
         } else {
            timesum = 0.0;
         }

         timings[i] = timings[i-1] + timesum;
      }
      
   }
}
Exemplo n.º 22
0
void processFile(HumdrumFile& infile, const string& filename) {
   int i;
   if (SEGMENTS && !summaryQ) {
      cout << "!!!!SEGMENT: " << infile.getFileName() << endl;
   }

   if (debugQ) {
      cout << "!! file: " << infile.getFileName() << endl;
   }
   if (validQ && !isValidFile(infile)) {
      return;
   }

   if (kernQ) {
      Array<int> ktracks;
      infile.getTracksByExInterp(ktracks, "**kern");
      cout << ktracks.getSize() << endl;
      return;
   }

   if (mdurQ || summaryQ || nograceQ) {
      infile.analyzeRhythm("4");
   }

   Array<int> analysis(infile.getNumLines());
   analysis.setAll(0);
   analysis.allowGrowth(0);
   for (i=0; i<infile.getNumLines(); i++) {
      if (!infile[i].isData()) {
         continue;
      }
      analysis[i] = doAnalysis(infile, i);
   }

   if (summaryQ) {
      return;
   }

   // print analysis:

   int firstdata = 1;
   PerlRegularExpression pre;
   for (i=0; i<infile.getNumLines(); i++) {
      if (appendQ) { cout << infile[i]; }
      if (infile[i].isData()) {
         if (appendQ)  { cout << '\t'; }
         if (measureQ && firstdata) {
            printMeasureData(analysis, infile, i);
            firstdata = 0;
         } else if (measureQ) {
            cout << ".";
         } else {
            if (nograceQ && (infile[i].getDuration() == 0)) {
               cout << ".";
            } else {
               cout << analysis[i];
            }
         }
         if (prependQ) { cout << '\t'; }
         if (appendQ)  { cout << '\n'; }
      } else if (infile[i].isInterpretation()) {
         if (appendQ)  { cout << '\t'; }
         if (strcmp(infile[i][0], "*-") == 0) {
            cout << "*-";
         } else if (strncmp(infile[i][0], "**", 2) == 0) {
            printExclusiveInterpretation();
         } else {
            cout << "*";
         }
         if (prependQ) { cout << '\t'; }
         if (appendQ)  { cout << '\n'; }
      } else if (infile[i].isBarline()) {
         if (pre.search(infile[i][0], "\\d")) {
            firstdata = 1;
         } 
         if (appendQ)  { cout << '\t'; }
         cout << infile[i][0];
         if (prependQ) { cout << '\t'; }
         if (appendQ)  { cout << '\n'; }
      } else if (infile[i].isLocalComment()) {
         if (appendQ)  { cout << '\t'; }
         cout << "!";
         if (prependQ) { cout << '\t'; }
         if (appendQ)  { cout << '\n'; }
      } else {
         if (!(appendQ || prependQ)) { cout << infile[i]; }
         if (appendQ)  { cout << '\n'; }
      }
      if (prependQ) { cout << infile[i]; }
      if (!appendQ) { cout << '\n'; }
   }
}
Exemplo n.º 23
0
void printTriadImage(HumdrumFile& infile, int rows, int cols) {

   Array<ChordQuality> cq;
   infile.analyzeSonorityQuality(cq);
   infile.analyzeRhythm("4");

   Array<Array<int> > triads;

   triads.setSize(3);

   triads[0].setSize(cols);
   triads[0].setAll(24);
   triads[1].setSize(cols);
   triads[1].setAll(24);
   triads[2].setSize(cols);
   triads[2].setAll(24);


   colorindex[0]  = "0 255 0";		// C major
   colorindex[1]  = "38 255 140";	// C-sharp major
   colorindex[2]  = "63 95 255";	// D major
   colorindex[3]  = "228 19 83";	// E-flat major
   colorindex[4]  = "255 0 0";		// E major
   colorindex[5]  = "255 255 0";	// F major
   colorindex[6]  = "192 255 0";	// F-sharp major
   colorindex[7]  = "93 211 255";	// G major
   colorindex[8]  = "129 50 255";	// A-flat major
   colorindex[9]  = "205 41 255";	// A major
   colorindex[10] = "255 160 0";	// B-flat major
   colorindex[11] = "255 110 10";	// B major
   colorindex[12] = "0 161 0";		// C minor
   colorindex[13] = "15 191 90";	// C-sharp minor
   colorindex[14] = "37 61 181";	// D minor
   colorindex[15] = "184 27 75";	// E-flat minor
   colorindex[16] = "175 0 0";		// E minor
   colorindex[17] = "220 200 0";	// F minor
   colorindex[18] = "140 200 0";	// F-sharp minor
   colorindex[19] = "65 163 181";	// G minor
   colorindex[20] = "100 28 181";	// G-sharp minor
   colorindex[21] = "136 13 181";	// A minor
   colorindex[22] = "181 93 20";	// B-flat minor
   colorindex[23] = "211 107 0";	// B minor
   colorindex[24] = "255 255 255";	// background
   colorindex[25] = "0 0 0";		// silence


   double start;
   double end;
   int    inversion;
   int    starti;
   int    endi;
   int    minQ;
   int    majQ;
   int    i, m, j, ii;
   int    rootindex;
   for (i=0; i<infile.getNumLines(); i++) {
      if (!infile[i].isData()) {
         continue;
      }
      if (strcmp(cq[i].getTypeName(), "min") == 0) {
         minQ = 1;
      } else {
         minQ = 0;
      }
      if (strcmp(cq[i].getTypeName(), "maj") == 0) {
         majQ = 1;
      } else {
         majQ = 0;
      }

      if (!(majQ || minQ)) {
         continue;
      }
      start = infile[i].getAbsBeat();
      end   = start + infile[i].getDuration();
      starti = int(start / infile.getTotalDuration() * cols + 0.5);
      endi   = int(end   / infile.getTotalDuration() * cols + 0.5);
      if (starti < 0) { starti = 0; }
      if (endi   < 0) { endi   = 0; }
      if (starti >= cols) { starti = cols-1; }
      if (endi   >= cols) { endi   = cols-1; }
      rootindex = Convert::base40ToMidiNoteNumber(cq[i].getRoot());
      if (minQ) {
         rootindex += 12;
      }
      inversion = cq[i].getInversion();
      for (ii=starti; ii<=endi; ii++) {
         triads[inversion][ii] = rootindex;
      }
   }

   int barheight = 0;
   int barwidth  = 0;
   if (barlinesQ) {
      barheight = 11;
      barwidth  = cols;
   }

   int legendheight = 0;
   int legendwidth  = 0;
   if (legendQ) {
      legendheight = 100;
      legendwidth  = cols;
   }


   int value = 24;
   Matrix<int> image(rows*2, cols, value);

   for (i=triads.getSize()-1; i>=0; i--) {
      int start = int(i/2.0 * rows);
      for (m=0; m<rows; m++) {
         ii = (int)(m + start);
         if (ii >= image.getRowCount()) {
            ii = image.getRowCount() - 1;
         }
         for (j=0; j<triads[i].getSize(); j++) {
            if (triads[i][j] < 24) {
               image.cell(ii,j) = triads[i][j];
            }
            // cout << colorindex[triads[i][j]] << " ";
            //cout << triads[i][j] << " ";
         }
         //cout << "\n";
      }
   }

   // print Image:
   cout << "P3\n";
   cout << cols  << " " << rows*2 + barheight + legendheight << "\n";
   cout << "255\n";

   for (i=image.getRowCount()-1; i>=0; i--) {
      for (j=0; j<image.getColumnCount(); j++) {
         cout << colorindex[image.cell(i,j)] << ' ';
      }
      cout << "\n";
   }

   if (barlinesQ) {
      printBarlines(infile, barheight, barwidth);
   }

   if (legendQ) {
      printLegend(legendheight, legendwidth);
   }

}
Exemplo n.º 24
0
void doLinearInterpolation(HumdrumFile& infile) {
   infile.analyzeRhythm("4");

   // extract the timing data using -1 for undefined

   Array<double> timings;
   Array<double> absbeat;

   timings.setSize(infile.getNumLines());
   timings.setAll(INVALIDTIME);
   double atime;

   int i, j;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() != E_humrec_data) {
         continue;
      }
      for (j=0; j<infile[i].getFieldCount(); j++) {
         if (strcmp("**time", infile[i].getExInterp(j)) == 0) {
            if (strcmp(infile[i][j], ".") == 0) {
               timings[i] = UNKNOWNTIME;
            } else {
               sscanf(infile[i][j], "%lf", &atime);
               timings[i] = atime;
            }
            break;
         }

      }

   }

   int lasttimeindex = -1;
   for (i=0; i<timings.getSize(); i++) {
      if (timings[i] < 0) {
         continue;
      }

      if (lasttimeindex < 0) {
         lasttimeindex = i;
         continue;
      }

      interpolateTimings(timings, infile, lasttimeindex, i);

      lasttimeindex = i;

   }

   fixendingtimes(timings, infile);

   // now insert the interpolated timings back into the score.
   int tfound = 0;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() == E_humrec_data) {
         tfound = 0;
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if ((tfound == 0) && 
                (strcmp(infile[i].getExInterp(j), "**time") == 0)) {
               tfound = 1;
               if (timings[i] < 0) { 
                  cout << "0.0";
               } else {
                  cout << timings[i];
               }
            } else {
               cout << infile[i][j];
            }
            if (j < infile[i].getFieldCount() - 1) {
               cout << "\t";
            }
         }
         cout << "\n";
      } else {
         cout << infile[i] << "\n";
      }
   }

}
Exemplo n.º 25
0
void processFileConvert(HumdrumFile& infile) {
   infile.analyzeRhythm("4");
   PerlRegularExpression pre;
   RationalNumber absbeat;
   int fieldcount = 0;
   int i, j;
   char buffer[1024] = {0};
   int trackline = 0;
   int dashQ = 0;

   for (i=0; i<infile.getNumLines(); i++) {

      if (infile[i].isData()) {
         fieldcount = infile[i].getFieldCount();
         trackline = i;
         continue;
      }

      if (infile[i].isInterpretation()) {
         fieldcount = infile[i].getFieldCount();
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if (strcmp(infile[i][j], "*") == 0) {
               continue;
            } else if (strcmp(infile[i][j], "*^") == 0) {
               fieldcount++;
               trackline = i;
            } else if ((j > 0) && (strcmp(infile[i][j], "*v") == 0)) {
               if (strcmp(infile[i][j-1], "*v") == 0) {
                  fieldcount--;
                  trackline = i;
               }
            }
            // should check for *+, but not very common.
         }
         continue;
      }
      if (!infile[i].isGlobalComment()) {
         continue;
      }

      if (pre.search(infile[i][0], 
            "^!!barline:.*absbeat\\s*=\\s*(\\d+)/(\\d+)")) {
         absbeat = atoi(pre.getSubmatch(1));
         absbeat /= atoi(pre.getSubmatch(2));
         if (pre.search(infile[i][0], "dash", "i")) {
            dashQ = 1;
         } else {
            dashQ = 0;
         }
      } else if (pre.search(infile[i][0], 
            "^!!barline:.*absbeat\\s*=\\s*(\\d+)")) {
         absbeat = atoi(pre.getSubmatch(1));
         if (pre.search(infile[i][0], "dash", "i")) {
            dashQ = 1;
         } else {
            dashQ = 0;
         }
      } else {
         continue;
      }

      buffer[0] = '\0';
      for (j=0; j<fieldcount; j++) {
         strcat(buffer, "=");
         if (dashQ) {
            strcat(buffer, ".");
         }
         if (j < fieldcount - 1) {
            strcat(buffer, "\t");
         }
      }
      infile[i].setLine(buffer);
      infile[i].setAbsBeatR(absbeat);
      cutNotesAcrossBarline(infile, i, trackline, fieldcount, absbeat);
   }

   cout << infile;
}
Exemplo n.º 26
0
void createJsonProll(HumdrumFile& infile) {
   infile.analyzeRhythm("4");
   Array<int> ktracks;
   infile.getTracksByExInterp(ktracks, "**kern");
   Array<int> rktracks(infile.getMaxTracks()+1);
   rktracks.allowGrowth(0);
   rktracks.setAll(-1);
   int i, j, k;
   for (i=0; i<ktracks.getSize(); i++) {
      rktracks[ktracks[i]] = i;
   }

   int ksize = ktracks.getSize();
   stringstream* staves;
   staves = new stringstream[ksize];

   char buffer[1024] = {0};
   int b40;
   RationalNumber duration;
   int track;
   int tcount;

   Array<Array<char> > partnames(ktracks.getSize());

   Array<int> partmax(ktracks.getSize());
   Array<int> partmin(ktracks.getSize());
   partmax.setAll(-10000);
   partmin.setAll(+10000);

   Array<int> noteinit(ktracks.getSize());
   noteinit.setAll(0);

   for (i=0; i<infile.getNumLines(); i++) {
      if (!infile[i].isData()) {
         continue;
      }
      for (j=0; j<infile[i].getFieldCount(); j++) {
         if (!infile[i].isExInterp(j, "**kern")) {
            continue;
         }
         if (strcmp(infile[i][j], ".") == 0) {
            continue;
         }
         tcount = infile[i].getTokenCount(j);
         track = infile[i].getPrimaryTrack(j);
         for (k=0; k<tcount; k++) {
            infile[i].getToken(buffer, j, k);
            if (strchr(buffer, 'r') != NULL) {
               continue;
            }
            if (strchr(buffer, ']') != NULL) {
               continue;
            }
            if (strchr(buffer, '_') != NULL) {
               continue;
            }
            if (strcmp(buffer, ".") == 0) {
               continue;
            }
            b40 = Convert::kernToBase40(buffer);
            duration = infile.getTiedDurationR(i, j, k);
            if (noteinit[rktracks[track]] == 0) {
               noteinit[rktracks[track]] = 1;
               pi(staves[rktracks[track]], 4);
               staves[rktracks[track]] << "{\n";
            } else {
               pi(staves[rktracks[track]], 4);
               staves[rktracks[track]] << "},\n";
               pi(staves[rktracks[track]], 4);
               staves[rktracks[track]] << "{\n";
            }
            printJsonNote(staves[rktracks[track]], b40, duration, buffer, 
                  infile, i, j, k);

            if (b40 > partmax[rktracks[track]]) {
               partmax[rktracks[track]] = b40;
            }
            if (b40 < partmin[rktracks[track]]) {
               partmin[rktracks[track]] = b40;
            }
         }
      }
   }

   printJsonHeader(infile, 0, ktracks, partmin, partmax);

   pi(cout, 2);
   cout << "[\n";

   pi(cout, 2);
   cout << "{\n";

   int pindex = 0;
   for (i=ktracks.getSize()-1; i>=0; i--) {
      pi(cout, 3);
      cout << "\"partindex\"\t:\t" << pindex++ << ",\n";

      pi(cout, 3);
      cout << "\"notedata\"\t:\t" << "\n";

      pi(cout, 4);
      cout << "[\n";
     
      cout << staves[i].str();

      pi(cout, 4);
      cout << "}\n";

      pi(cout, 4);
      cout << "]\n";
  
      if (i > 0) {
         pi(cout, 2);
         cout << "},\n";
         pi(cout, 2);
         cout << "{\n";
      } else {
         pi(cout, 2);
         cout << "}\n";
      }
   }

   pi(cout, 2);
   cout << "]\n";

   pi(cout, 0);
   cout << "}\n";

   delete [] staves;
}