//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sat Jun 9 14:48:41 PDT 2001
// Last Modified: Wed Apr 27 22:40:12 PDT 2011 (adapted from parallel.cpp)
// Filename: ...museinfo/examples/all/dissonant.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/dissonant.cpp
// Syntax: C++; museinfo
//
// Description: calculates the minimum timebase which is the least common
// multiple of all rhythms in the file.
//
// Todo: some things to clean up in rhythmic representation due to conversions
// from ints to RationalNumber class for rhythms/durations...
#include "humdrum.h"
#include <stdlib.h>
#include "PerlRegularExpression.h"
#ifndef OLDCPP
#include <iostream>
#include <fstream>
#include <sstream>
#define SSTREAM stringstream
#define CSTRING str().c_str()
using namespace std;
#else
#include <iostream.h>
#include <fstream.h>
#ifdef VISUAL
#include <strstrea.h>
#else
#include <strstream.h>
#endif
#define SSTREAM strstream
#define CSTRING str()
#endif
class NoteNode {
public:
int b40; // base-40 pitch number or 0 if a rest, negative if tied0.
int line; // line number in original score of note
int spine; // spine number in original score of note
int lastint; // interval to last note (or 0 if no last or last is rest)
int nextint; // interval to next note (or 0 if no next or last is rest)
int serial; // notes serial number
int measure; // measure number of note
Array<int> hint; // harmonic intervals to other voices
Array<int> hvoice; // voice number of harmonic interval
NoteNode(void) { clear(); }
void clear(void) { serial = b40 = 0; line = spine = -1;
lastint = nextint = 0;
hvoice.setSize(0);
hint.setSize(0);
}
};
#define REST 0
#define RESTINT -1000000
///////////////////////////////////////////////////////////////////////////
// function declarations
void checkOptions(Options& opts, int argc, char* argv[]);
void example(void);
void usage(const char* command);
void processFile(HumdrumFile& infile, const char* filename);
void getKernTracks(Array<int>& ktracks, HumdrumFile& infile);
void calculateMelodicIntervals(Array<Array<NoteNode> >& notes);
void markParallels(Array<Array<NoteNode> >& notes,
HumdrumFile& infile, const char* filename,
Array<Array<char> >& names,
Array<int> reverselookup);
void addMark(HumdrumFile& infile, int line, int spine,
char marker);
void markParallel(HumdrumFile& infile,
Array<Array<NoteNode> >& notes,
int hint, int i, int j, int k);
int validateInterval(Array<Array<NoteNode> >& notes,
int i, int j, int k);
void markDissonances(Array<Array<NoteNode> >& notes,
HumdrumFile& infile, const char* filename,
Array<Array<char> >& names,
Array<int> reverselookup);
void printDissonanceOutput(HumdrumFile& infile,
Array<Array<NoteNode> >& notes,
Array<Array<char> >& names);
void printIntervalInfo(HumdrumFile& infile, int line, int spine,
Array<Array<NoteNode> >& notes, int noteline,
int noteindex, Array<Array<char> >& abbr);
void getAbbreviations(Array<Array<char> >& abbreviations,
Array<Array<char> >& names);
void getAbbreviation(Array<char>& abbr, Array<char>& name);
void markNote(HumdrumFile& infile, char mark, int line,
int spine);
int checkForFourth(Array<Array<NoteNode> >& notes, int j,
HumdrumFile& infile);
// global variables
Options options; // database for command-line arguments
int debugQ = 0; // used with --debug
int labelQ = 1; // used with -l option
int rawQ = 0; // used with -r option
int raw2Q = 0; // used with --r2 option
int fileQ = 0; // used with -f option
///////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
checkOptions(options, argc, argv);
HumdrumFile infile;
int i;
// figure out the number of input files to process
int numinputs = options.getArgCount();
const char* filename = "";
PerlRegularExpression pre;
for (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);
filename = "STDIN";
} else {
filename = options.getArg(i+1);
infile.read(filename);
pre.search(filename, "([^/.]+)(\\.[^\\.]+)$", "");
filename = pre.getSubmatch(1);
}
processFile(infile, filename);
}
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// getNames -- get the names of each column if they have one.
//
void getNames(Array<Array<char> >& names, Array<int>& reverselookup,
HumdrumFile& infile) {
names.setSize(reverselookup.getSize()-1);
names.allowGrowth(0);
char buffer[1024] = {0};
int value;
PerlRegularExpression pre;
int i;
int j;
int track;
for (i=0; i<names.getSize(); i++) {
value = reverselookup.getSize() - i;
sprintf(buffer, "%d", value);
names[i].setSize(strlen(buffer)+1);
strcpy(names[i].getBase(), buffer);
}
for (i=0; i<infile.getNumLines(); i++) {
if (infile[i].isData()) {
// stop looking for instrument name after the first data line
break;
}
if (!infile[i].isInterpretation()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
if (!infile[i].isExInterp(j, "**kern")) {
continue;
}
if (pre.search(infile[i][j], "^\\*I\"(.*)", "")) {
track = infile[i].getPrimaryTrack(j);
strcpy(buffer, pre.getSubmatch(1));
names[reverselookup[track]].setSize(strlen(buffer)+1);
strcpy(names[reverselookup[track]].getBase(), buffer);
}
}
}
if (debugQ) {
for (i=0; i<names.getSize(); i++) {
cout << i << ":\t" << names[i] << endl;
}
}
}
//////////////////////////////
//
// processFile --
//
void processFile(HumdrumFile& infile, const char* filename) {
int i, j;
Array<Array<NoteNode> > notes;
Array<Array<char> > names;
Array<int> ktracks;
Array<int> reverselookup;
int ii;
int jj;
getKernTracks(ktracks, infile);
notes.setSize(ktracks.getSize());
reverselookup.setSize(infile.getMaxTracks()+1);
reverselookup.setAll(-1);
for (i=0; i<ktracks.getSize(); i++) {
reverselookup[ktracks[i]] = i;
notes[i].setSize(infile.getNumLines());
notes[i].setSize(0);
}
getNames(names, reverselookup, infile);
PerlRegularExpression pre;
Array<NoteNode> current;
current.setSize(ktracks.getSize());
int sign;
int track;
int index;
int snum = 0;
int measurenumber = 0;
for (i=0; i<infile.getNumLines(); i++) {
if (debugQ) {
cout << "PROCESSING LINE: " << i << "\t" << infile[i] << endl;
}
if (infile[i].isMeasure()) {
if (pre.search(infile[i][0], "(\\d+)", "")) {
measurenumber = atoi(pre.getSubmatch(1));
}
}
for (j=0; j<current.getSize(); j++) {
current[j].clear();
current[j].measure = measurenumber;
}
if (infile[i].isMeasure() && (strstr(infile[i][0], "||") != NULL)) {
// double barline (terminal for Josquin project), so add a row
// of rests to prevent dissonant interval identification between
// adjacent notes in different sections.
for (j=0; j<notes.getSize(); j++) {
notes[j].append(current[j]);
}
}
if (!infile[i].isData()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
sign = 1;
if (!infile[i].isExInterp(j, "**kern")) {
continue;
}
track = infile[i].getPrimaryTrack(j);
index = reverselookup[track];
current[index].line = i;
current[index].spine = j;
if (strcmp(infile[i][j], ".") == 0) {
sign = -1;
ii = infile[i].getDotLine(j);
jj = infile[i].getDotSpine(j);
} else {
ii = i;
jj = j;
}
if (strchr(infile[ii][jj], 'r') != NULL) {
current[index].b40 = 0;
current[index].serial = ++snum;
continue;
}
if (strcmp(infile[ii][jj], ".") == 0) {
current[index].b40 = 0;
current[index].serial = snum;
}
current[index].b40 = Convert::kernToBase40(infile[ii][jj]);
if (strchr(infile[ii][jj], '_') != NULL) {
sign = -1;
current[index].serial = snum;
}
if (strchr(infile[ii][jj], ']') != NULL) {
sign = -1;
current[index].serial = snum;
}
current[index].b40 *= sign;
if (sign > 0) {
current[index].serial = ++snum;
}
}
for (j=0; j<notes.getSize(); j++) {
notes[j].append(current[j]);
}
}
if (rawQ) {
for (i=0; i<notes[0].getSize(); i++) {
for (j=0; j<notes.getSize(); j++) {
cout << notes[j][i].b40;
if (j < notes.getSize()-1) {
cout << "\t";
}
}
cout << endl;
}
exit(0);
}
// calculateMelodicIntervals(notes);
if (raw2Q) {
for (i=0; i<notes[0].getSize(); i++) {
for (j=0; j<notes.getSize(); j++) {
cout << notes[j][i].b40;
cout << "(";
cout << notes[j][i].lastint;
cout << ";";
cout << notes[j][i].nextint;
cout << ")";
if (j < notes.getSize()-1) {
cout << "\t";
}
}
cout << endl;
}
exit(0);
}
// markParallels(notes, infile, filename, names, reverselookup);
markDissonances(notes, infile, filename, names, reverselookup);
}
//////////////////////////////
//
// markDissonances -- search for parts which are dissonant fifth or octaves
//
// 0(REST;REST) 134(-5;REST) 162(11;-11) 174(6;28)
// 111(REST;-6) -134(-5;REST) -162(11;-11) 202(28;-5)
// -111(REST;-6) -134(-5;REST) 151(-11;6) -202(28;-5)
// 105(-6;6) -134(-5;REST) 157(6;5) 197(-5;-6)
// 111(6;23) -134(-5;REST) 162(5;-5) 191(-6;-6)
// 134(23;REST) -134(-5;REST) 157(-5;REST) 185(-6;REST)
//
void markDissonances(Array<Array<NoteNode> >& notes, HumdrumFile& infile,
const char* filename, Array<Array<char> >& names,
Array<int> reverselookup) {
int i;
int j;
int k;
int hint;
int hval;
int dhint; // diatonic harmonic interval
int highest;
int lowest;
int has2nd = 0;
int has7th = 0;
int has4th = 0;
for (j=0; j<notes[0].getSize(); j++) {
has4th |= checkForFourth(notes, j, infile);
}
for (i=0; i<notes.getSize(); i++) {
for (j=0; j<notes[i].getSize(); j++) {
if (notes[i][j].b40 == REST) {
// ignore rests
continue;
}
for (k=i+1; k<notes.getSize(); k++) {
if (notes[k][j].b40 == 0) {
// ignore rests
continue;
}
if ((notes[k][j].b40 < 0) && (notes[i][j].b40 < 0)) {
// ignore notes if both are tied.
continue;
}
// measure the interval from highest to lowest
if (abs(notes[k][j].b40) > abs(notes[i][j].b40)) {
highest = k;
lowest = i;
} else {
highest = i;
lowest = k;
}
hint = abs(notes[highest][j].b40) - abs(notes[lowest][j].b40);
dhint = Convert::base40IntervalToDiatonic(hint) % 7;
// store interval as positive for bottom voice's note and
// negative for top voice's note.
if (notes[lowest][j].b40 > 0) {
hval = hint % 40;
if (hval != 17) { // suppress 4ths since handled elsewhere
notes[lowest][j].hvoice.append(highest);
notes[lowest][j].hint.append(hval);
}
}
if (notes[highest][j].b40 > 0) {
hval = hint % 40;
if (hval != 17) { // suppress 4ths since handled elsewhere
hval = -hval;
notes[highest][j].hvoice.append(lowest);
notes[highest][j].hint.append(hval);
}
}
// markInterval(infile, notes, hint, highest, j, lowest);
if (dhint == 1) {
has2nd = 1;
if (notes[highest][j].b40 > 0) {
markNote(infile, '<', notes[highest][j].line,
notes[highest][j].spine);
}
if (notes[lowest][j].b40 > 0) {
markNote(infile, '<', notes[lowest][j].line,
notes[lowest][j].spine);
}
}
if (dhint == 6) {
has7th = 1;
if (notes[highest][j].b40 > 0) {
markNote(infile, '>', notes[highest][j].line,
notes[highest][j].spine);
}
if (notes[lowest][j].b40 > 0) {
markNote(infile, '>', notes[lowest][j].line,
notes[lowest][j].spine);
}
}
}
}
}
if (labelQ) {
printDissonanceOutput(infile, notes, names);
} else {
cout << infile;
}
if (has4th) {
cout << "!!!RDF**kern: | = marked note, color=\"#ff0000\", ";
cout << "fourth interval above lowest note" << endl;
}
if (has2nd) {
cout << "!!!RDF**kern: < = marked note, color=\"#00ff00\", ";
cout << "second interval" << endl;
}
if (has7th) {
cout << "!!!RDF**kern: > = marked note, color=\"#00ff00\", ";
cout << "seventh interval" << endl;
}
}
//////////////////////////////
//
// checkForFourth -- returns true if a 4th above the lowest note was found.
//
int checkForFourth(Array >& notes, int j, HumdrumFile& infile) {
int i;
int lowest = 100000;
int lowestindex = -1;
int notecount = 0;
int output = 0;
int hint;
for (i=0; i<notes.getSize(); i++) {
if (notes[i][j].b40 == REST) {
continue;
}
notecount++;
if (notecount == 1) {
lowest = abs(notes[i][j].b40);
lowestindex = i;
continue;
}
if (abs(notes[i][j].b40) < lowest) {
lowest = abs(notes[i][j].b40);
lowestindex = i;
}
}
if (notecount == 0) {
return output;
}
if (lowestindex < 0) {
return output;
}
int value;
for (i=0; i<notes.getSize(); i++) {
if (notes[i][j].b40 == REST) {
continue;
}
hint = abs(notes[i][j].b40) - abs(notes[lowestindex][j].b40);
if ((hint % 40) == 17) { // 17 = base-40 value for a perfect fourth
output = 1;
// found a fourth against the lowest note in the sonority.
value = -hint;
if (notes[i][j].b40 > 0) {
notes[i][j].hint.append(value);
notes[i][j].hvoice.append(lowestindex);
markNote(infile, '|', notes[i][j].line,
notes[i][j].spine);
}
value = hint;
if (notes[lowestindex][j].b40 > 0) {
notes[lowestindex][j].hint.append(value);
notes[lowestindex][j].hvoice.append(i);
markNote(infile, '|', notes[lowestindex][j].line,
notes[lowestindex][j].spine);
}
}
}
return output;
}
//////////////////////////////
//
// markNote --
//
void markNote(HumdrumFile& infile, char mark, int line, int spine) {
Array<char> token;
token.setSize(strlen(infile[line][spine])+2);
strcpy(token.getBase(), infile[line][spine]);
char buffer[2] = {0};
buffer[0] = mark;
strcat(token.getBase(), buffer);
infile[line].changeField(spine, token.getBase());
}
//////////////////////////////
//
// getAbbreviations --
//
void getAbbreviations(Array<Array<char> >& abbreviations,
Array<Array<char> >& names) {
abbreviations.setSize(names.getSize());
int i;
for (i=0; i<names.getSize(); i++) {
getAbbreviation(abbreviations[i], names[i]);
}
}
//////////////////////////////
//
// getAbbreviation --
//
void getAbbreviation(Array& abbr, Array& name) {
PerlRegularExpression pre;
abbr.setSize(strlen(name.getBase())+1);
strcpy(abbr.getBase(), name.getBase());
pre.sar(abbr, "(?<=[a-zA-Z])[a-zA-Z]*", "", "");
pre.tr(abbr, "123456789", "abcdefghi");
}
//////////////////////////////
//
// printDissonanceOutput --
//
void printDissonanceOutput(HumdrumFile& infile,
Array<Array<NoteNode> >& notes, Array<Array<char> >& names) {
Array<int> linemap;
linemap.setSize(infile.getNumLines());
linemap.setAll(-1);
int i, k;
for (k=0; k<notes.getSize(); k++) {
for (i=0; i<notes[k].getSize(); i++) {
if (notes[k][i].line >= 0) {
linemap[notes[k][i].line] = i;
}
}
}
Array<Array<char> > abbreviations;
getAbbreviations(abbreviations, names);
int j;
int n;
int value;
int track;
int nexttrack;
int noteindex;
PerlRegularExpression pre;
PerlRegularExpression pre2;
for (i=0; i<infile.getNumLines(); i++) {
if (debugQ) {
cout << "LINE = " << i << ":\t" << infile[i] << endl;
}
if (infile[i].isMeasure() || infile[i].isData()
|| infile[i].isInterpretation() || infile[i].isLocalComment()) {
noteindex = 0;
nexttrack = 0;
track = 0;
for (j=0; j<infile[i].getFieldCount(); j++) {
if (!infile[i].isExInterp(j, "**kern")) {
cout << infile[i][j];
if (j < infile[i].getFieldCount() - 1) {
cout << '\t';
}
continue;
}
// first print the **kern-related token:
cout << infile[i][j];
// then print extra data spines for interval descriptions
// if the **kern token is at the end of an adjacent subspine group:
if (j < infile[i].getFieldCount()-1) {
track = infile[i].getPrimaryTrack(j);
nexttrack = infile[i].getPrimaryTrack(j+1);
} else {
track = infile[i].getPrimaryTrack(j);
nexttrack = -1;
}
if (track != nexttrack) {
// the next track is different from the current one
// so print interval data spine here.
cout << "\t";
if (infile[i].isMeasure()) {
cout << infile[i][0];
} else if (infile[i].isLocalComment()) {
cout << "!";
} else if (infile[i].isInterpretation()) {
if (strncmp(infile[i][0], "**", 2) == 0) {
cout << "**text";
} else if (strcmp(infile[i][0], "*-") == 0) {
cout << "*-";
} else {
cout << "*";
}
} else if (infile[i].isData()) {
printIntervalInfo(infile, i, j, notes, linemap[i], noteindex,
abbreviations);
}
} else {
noteindex--;
}
if (j < infile[i].getFieldCount() - 1) {
cout << '\t';
}
noteindex++;
}
cout << '\n';
} else {
if (pre.search(infile[i][0], "^(!+muse2ps.*)v([\\d,]+)(.*)", "")) {
cout << pre.getSubmatch(1);
cout << "v";
Array<Array<char> > tokens;
pre2.getTokens(tokens, ",", pre.getSubmatch(2));
for (n=0; n<tokens.getSize(); n++) {
value = atoi(tokens[n].getBase());
value += 10;
cout << value;
if (n < tokens.getSize()-1) {
cout << ",";
}
}
cout << pre.getSubmatch(3);
cout << "\n";
} else {
cout << infile[i] << endl;
}
}
}
}
//////////////////////////////
//
// printIntervalInfo --
//
void printIntervalInfo(HumdrumFile& infile, int line, int spine,
Array<Array<NoteNode> >& notes, int noteline, int noteindex,
Array<Array<char> >& abbr) {
// [20120323] fixed spine split problem?
if (noteindex >= notes.getSize()) {
return;
}
if (notes[noteindex][noteline].hint.getSize() == 0) {
cout << ".";
return;
}
SSTREAM out;
int m;
int dhint;
int msize = notes[noteindex][noteline].hint.getSize();
int hint;
int pcount = 0;
for (m=0; m<msize; m++) {
hint = notes[noteindex][noteline].hint[m];
dhint = Convert::base40IntervalToDiatonic(abs(hint)) % 7 + 1;
if (dhint == 2) {
pcount++;
out << abbr[notes[noteindex][noteline].hvoice[m]];
if (hint < 0) {
out << "-";
}
out << "2";
out << ",";
}
if (dhint == 7) {
pcount++;
out << abbr[notes[noteindex][noteline].hvoice[m]];
if (hint < 0) {
out << "-";
}
out << "7";
out << ",";
}
if (abs(hint) % 40 == 17) {
pcount++;
out << abbr[notes[noteindex][noteline].hvoice[m]];
if (hint < 0) {
out << "-";
}
out << "4";
out << ",";
}
}
if (pcount == 0) {
out << ".";
}
out << ends;
Array<char> output;
output.setSize(strlen(out.CSTRING)+1);
strcpy(output.getBase(), out.CSTRING);
PerlRegularExpression pre;
pre.sar(output, ",$", "", "");
cout << output;
}
//////////////////////////////
//
// markParallel --
//
void markParallel(HumdrumFile& infile, Array<Array<NoteNode> >& notes,
int hint, int i, int j, int k) {
char marker = '<'; // dissonant octaves/unisons
if (hint == 23) {
marker = '>'; // dissonant fifths
}
int ii;
int jj;
// mark first note in dissonant motion
ii = notes[i][j].line;
jj = notes[i][j].spine;
if (strcmp(infile[ii][jj], ".") == 0) {
int ti;
int tj;
ti = infile[ii].getDotLine(jj);
tj = infile[ii].getDotSpine(jj);
ii = ti;
jj = tj;
}
if (strcmp(infile[ii][jj], ".") != 0) {
// if (strchr(infile[ii][jj], marker) == NULL) {
addMark(infile, ii, jj, marker);
// }
}
// mark second note in dissonant motion
ii = notes[k][j].line;
jj = notes[k][j].spine;
if (strcmp(infile[ii][jj], ".") == 0) {
int ti;
int tj;
ti = infile[ii].getDotLine(jj);
tj = infile[ii].getDotSpine(jj);
ii = ti;
jj = tj;
}
if (strcmp(infile[ii][jj], ".") != 0) {
// if (strchr(infile[ii][jj], marker) == NULL) {
addMark(infile, ii, jj, marker);
// }
}
int m;
// mark third note in dissonant motion
for (m=j+1; m<notes[i].getSize(); m++) {
if (notes[i][m].b40 < 0) {
continue;
}
ii = notes[i][m].line;
jj = notes[i][m].spine;
if (strcmp(infile[ii][jj], ".") == 0) {
int ti;
int tj;
ti = infile[ii].getDotLine(jj);
tj = infile[ii].getDotSpine(jj);
ii = ti;
jj = tj;
}
if (strcmp(infile[ii][jj], ".") != 0) {
// if (strchr(infile[ii][jj], marker) == NULL) {
addMark(infile, ii, jj, marker);
// }
}
break;
}
// mark third note in dissonant motion
for (m=j+1; m<notes[k].getSize(); m++) {
if (notes[i][m].b40 < 0) {
continue;
}
ii = notes[k][m].line;
jj = notes[k][m].spine;
if (strcmp(infile[ii][jj], ".") == 0) {
int ti;
int tj;
ti = infile[ii].getDotLine(jj);
tj = infile[ii].getDotSpine(jj);
ii = ti;
jj = tj;
}
if (strcmp(infile[ii][jj], ".") != 0) {
// if (strchr(infile[ii][jj], marker) == NULL) {
addMark(infile, ii, jj, marker);
// }
}
break;
}
}
//////////////////////////////
//
// addMark --
//
void addMark(HumdrumFile& infile, int line, int spine, char marker) {
char buffer[1024];
char mstring[2] = {0};
mstring[0] = marker;
strcpy(buffer, infile[line][spine]);
strcat(buffer, mstring);
infile[line].changeField(spine, buffer);
}
//////////////////////////////
//
// calculateMelodicIntervals --
//
void calculateMelodicIntervals(Array >& notes) {
int i, j;
int lastint = RESTINT;
int lastnote = 0;
// caluculate the intervals to previous notes:
for (i=0; i<notes.getSize(); i++) {
lastint = RESTINT;
lastnote = 0;
for (j=0; j<notes[i].getSize(); j++) {
if (notes[i][j].b40 < 0) {
// continuing note, just repeat previously calculate interval
notes[i][j].lastint = lastint;
continue;
}
if (notes[i][j].b40 == 0) {
// current note is a rest, to make the interval to the last
// note a RESTINT.
lastnote = 0;
notes[i][j].lastint = RESTINT;
lastint = RESTINT;
continue;
}
if (lastnote == 0) {
// if the last note was a rest, then the interval to it is a RESTINT
lastnote = abs(notes[i][j].b40); // update last note
notes[i][j].lastint = RESTINT;
lastint = RESTINT;
continue;
}
// have a note attack which does note follow a rest
lastint = notes[i][j].b40 - lastnote;
lastnote = notes[i][j].b40;
notes[i][j].lastint = lastint;
}
}
// caluculate the intervales in the other direction
//128(-6) -174(0) -185(5) -197(-5)
//122(-6) -174(0) -185(5) 191(-6)
//128(6) 168(-6) 180(-5) -191(-6)
//-128(6) 162(-6) -180(-5) -191(-6)
//105(-23) 157(-5) 168(-12) 185(-6)
int nextint = RESTINT;
int nextnote = 0;
// caluculate the intervals to next notes:
for (i=0; i<notes.getSize(); i++) {
nextint = RESTINT;
nextnote = 0;
for (j=notes[i].getSize()-1; j>=0; j--) {
notes[i][j].nextint = nextint;
if (notes[i][j].b40 >= 0) {
nextint = notes[i][j].lastint;
}
}
}
}
//////////////////////////////
//
// getKernTracks -- return a list of track number for **kern spines.
//
void getKernTracks(Array& ktracks, HumdrumFile& infile) {
int i, j;
ktracks.setSize(infile.getMaxTracks());
ktracks.setSize(0);
int track;
for (i=0; i<infile.getNumLines(); i++) {
if (!infile[i].isInterpretation()) {
continue;
}
for (j=0; j<infile[i].getFieldCount(); j++) {
if (infile[i].isExInterp(j, "**kern")) {
track = infile[i].getPrimaryTrack(j);
ktracks.append(track);
}
}
break;
}
}
//////////////////////////////
//
// checkOptions -- validate and process command-line options.
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("f|file=b", "display filenames with -l option");
//opts.define("l|location|loc=b", "print locations of dissonants");
opts.define("label=b", "print text labels");
opts.define("r|raw=b", "print raw data before analysis is done");
opts.define("raw2|r2=b", "print raw data 2 before analysis is done");
opts.define("debug=b"); // determine bad input line num
opts.define("author=b"); // author of program
opts.define("version=b"); // compilation info
opts.define("example=b"); // example usages
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, April 2011" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 22 April 2010" << 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");
rawQ = opts.getBoolean("raw");
labelQ =!opts.getBoolean("label");
raw2Q = opts.getBoolean("raw2");
fileQ = opts.getBoolean("file");
}
//////////////////////////////
//
// example -- example usage of the quality program
//
void example(void) {
cout <<
" \n"
<< endl;
}
//////////////////////////////
//
// usage -- gives the usage statement for the meter program
//
void usage(const char* command) {
cout <<
" \n"
<< endl;
}
// md5sum: 6dbbf454c8efaef3af52821368f51178 dissonant.cpp [20120404]