//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Wed Apr 24 20:15:12 PDT 2002
// Last Modified: Sat Jan 24 09:27:33 PST 2004
// Filename: ...sig/examples/all/rism2kern2.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/rism2kern2.cpp
// Syntax: C++; museinfo
//
// Description: Converts RISM II/A Plaine and Easie Code into **kern data.
//
// Todo: interpret beam groupings (e.g.: 6{ABCD} -> aLL b c dJJ
// identify fermatas
// interpret trills
// handle tuplets
// measure repeat indicator
// repeat barlines
// i,F repetitions
// Figure out what ^! means (in RISM 1000117692)
// natural sign indicator
// clef changes (%F-4 )
// grace notes
// acciaccatura notes (q and qq..r types)
//
// Done: key signature
// ties
// beam groupings
// accidentals (except for naturals, and tied accidentals)
// full measure rests (single and multiple)
// time signature
//
// Fixed: initial octave (Sun Jan 25 10:46:10 PST 2004)
// Fixed: initial rhythm 6 (Sun Jan 25 10:46:10 PST 2004)
//
#include "humdrum.h"
#include <string.h>
#include <math.h>
#ifndef OLDCPP
#include <iostream>
#include <fstream>
using namespace std;
#else
#include <iostream.h>
#include <fstream.h>
#endif
typedef Array<char> ArrayChar;
//////////////////////////////////////////////////////////////////////////
class NoteObject {
public:
NoteObject(void) { clear(); };
void clear(void) {
pitch = tie = beam = clef = clefnum = 0;
wholerest = 0; measureduration = 0.0;
duration = 0.0;
};
int pitch;
double duration;
int tie;
int beam;
int clef;
int clefnum;
double measureduration;
int wholerest; // number of whole rests to process
};
//////////////////////////////////////////////////////////////////////////
// function declarations:
void checkOptions(Options& opts, int argc, char** argv);
void example(void);
void usage(const char* command);
void convertRism112ToKern(HumdrumFile& hfile, int incipitnum);
const char* getKeyInfo(Array<int>& key, HumdrumFile& hfile,
int incipitnum);
const char* getTimeInfo(Array<double>& timeinfo, HumdrumFile& hfile,
int incipitnum);
void printKeyInfo(ostream& out, Array<int>& key,
const char* keystring);
void printTimeInfo(ostream& out, const char* timestring);
void generateMusicData(Array<NoteObject>& notes, HumdrumFile& infile,
Array<int>& key, int incipitnum,
double measureduration);
void printPitches(ostream& out, Array<NoteObject>& notes);
int getLineIndex(Array<ArrayChar>& pieces, const char* string);
int getIncipitNumber(HumdrumFile& hfile);
const char* getField(const char* field, HumdrumFile& hfile,
int incipitnum);
double getMeasureDur(Array<double>& timeinfo);
int getIncipitCount(HumdrumFile& hfile);
const char* getKey(HumdrumFile& hfile, int incipitnum);
// User interface variables:
Options options;
int debugQ = 0; // used with the --debug option
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
// process the command-line options
checkOptions(options, argc, argv);
HumdrumFile hfile;
hfile.read(options.getArg(1));
int incipitnum = getIncipitNumber(hfile);
cout << hfile;
convertRism112ToKern(hfile, incipitnum);
return 0;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// getKey --
//
const char* getKey(HumdrumFile& hfile, int incipitnum) {
int i;
const char* keystring = NULL;
for (i=0; i<hfile.getNumLines(); i++) {
if (strncmp(hfile[i][0], "!!!RISM-026:", 12) == 0) {
keystring = hfile[i][1];
}
}
if (keystring == NULL) {
return "*X2:";
}
char buffer[4096] = {0};
strcpy(buffer, keystring);
char* ptr = strtok(buffer, " \t\n;");
char* first = ptr;
int count = 1;
while ((count < incipitnum) && (ptr != NULL)) {
ptr = strtok(NULL, " \t\n;");
count++;
if (count == 1) {
first = ptr;
}
}
if (ptr == NULL) {
ptr = first;
}
if (ptr == NULL) {
return "*X3:";
}
if (strcmp(ptr, "G") == 0) { // 5,690 cases
return "*G:";
} else if (strcmp(ptr, "C") == 0) { // 4,804 cases
return "*C:";
} else if (strcmp(ptr, "D") == 0) { // 4,594 cases
return "*D:";
} else if (strcmp(ptr, "F") == 0) { // 3,759 cases
return "*F:";
} else if (strcmp(ptr, "B>") == 0) { // 2,702 cases
return "*B-:";
} else if (strcmp(ptr, "A") == 0) { // 2,634 cases
return "*A:";
} else if (strcmp(ptr, "E>") == 0) { // 1,869 cases
return "*E-:";
} else if (strcmp(ptr, "g") == 0) { // 1,807 cases
return "*g:";
} else if (strcmp(ptr, "d") == 0) { // 1,711 cases
return "*d:";
} else if (strcmp(ptr, "a") == 0) { // 1,492 cases
return "*a:";
} else if (strcmp(ptr, "c") == 0) { // 797 cases
return "*c:";
} else if (strcmp(ptr, "e") == 0) { // 689 cases
return "*e:";
} else if (strcmp(ptr, "E") == 0) { // 598 cases
return "*E:";
} else if (strcmp(ptr, "f") == 0) { // 253 cases
return "*f:";
} else if (strcmp(ptr, "b") == 0) { // 206 cases
return "*b:";
} else if (strcmp(ptr, "A>") == 0) { // 78 cases
return "*A-:";
} else if (strcmp(ptr, "f#") == 0) { // 47 cases
return "*f#:";
} else if (strcmp(ptr, "B") == 0) { // 18 cases
return "*B:";
} else if (strcmp(ptr, "c#") == 0) { // 7 cases
return "*c#:";
} else if (strcmp(ptr, "Bb") == 0) { // 7 cases
return "*B-:";
} else if (strcmp(ptr, "Eb") == 0) { // 7 cases
return "*E-:";
} else if (strcmp(ptr, "D>") == 0) { // 5 cases
return "*D-:";
} else if (strcmp(ptr, "F#") == 0) { // 4 cases
return "*F#:";
} else if (strcmp(ptr, "e>") == 0) { // 4 cases
return "*e-:";
} else if (strcmp(ptr, "b>") == 0) { // 3 cases
return "*b-:";
} else if (strcmp(ptr, "g#") == 0) { // 1 case
return "*g#:";
} else if (strcmp(ptr, "G#") == 0) { // 1 case
return "*G#:";
} else if (strcmp(ptr, "G>") == 0) { // 1 case
return "*G-:";
}
return "*X4:";
}
//////////////////////////////
//
// getIncipitNumber --
//
int getIncipitNumber(HumdrumFile& hfile) {
int i;
int output = 0;
int count = 0;
const char* ptr = NULL;
for (i=0; i<hfile.getNumLines(); i++) {
if (strncmp(hfile[i][0], "!!!RISM-incipit:", 16) == 0) {
ptr = strrchr(hfile[i][1], '-');
if (ptr != NULL) {
sscanf(ptr, "-%d", &output);
}
} else if (strncmp(hfile[i][0], "!!!RISM-112F:", 13) == 0) {
count++;
}
}
if (count == 0) {
return 0;
} else if (output == 0) {
return 1;
} else {
return output;
}
}
//////////////////////////////
//
// getIncipitCount --
//
int getIncipitCount(HumdrumFile& hfile) {
int i;
int output = 0;
for (i=0; i<hfile.getNumLines(); i++) {
if (strncmp(hfile[i][0], "!!!RISM-112F:", 13) == 0) {
output++;
}
}
return output;
}
//////////////////////////////
//
// convertRism112ToKern --
//
void convertRism112ToKern(HumdrumFile& hfile, int incipitnum) {
Array<NoteObject> notes;
Array<int> key(7);
Array<double> timeinfo(2);
timeinfo.setAll(0);
key.setAll(0);
const char* keystring = getKeyInfo(key, hfile, incipitnum);
const char* timestring = getTimeInfo(timeinfo, hfile, incipitnum);
const char* a112 = getField("112A", hfile, incipitnum);
int incipitcount = getIncipitCount(hfile);
int length;
int jj;
if (incipitnum > 0) {
cout << "**kern\n";
if (incipitcount > 1) {
cout << "!! Incipit number: " << incipitnum << "/"
<< incipitcount << " (";
length = strlen(a112);
for (jj=0; jj<length-1; jj++) {
cout << a112[jj];
}
cout << ")" << endl;
}
printKeyInfo(cout, key, keystring);
cout << getKey(hfile, incipitnum) << "\n";
double measuredur = getMeasureDur(timeinfo);
printTimeInfo(cout, timestring);
generateMusicData(notes, hfile, key, incipitnum, measuredur);
printPitches(cout, notes);
cout << "*-\n\n";
}
}
//////////////////////////////
//
// getMeasureDur -- return the duration of the full measure
//
double getMeasureDur(Array& timeinfo) {
return timeinfo[0] * timeinfo[1];
}
//////////////////////////////
//
// generateMusicData --
//
void generateMusicData(Array<NoteObject>& notes, HumdrumFile& hfile,
Array<int>& key, int incipitnum, double measureduration) {
notes.setSize(0);
NoteObject tempnote;
const char* musicdata = getField("112F", hfile, incipitnum);
int length = strlen(musicdata);
// measure octave at each position in the data string
Array<int> octave;
octave.setSize(length);
octave.setAll(0);
int i;
if (musicdata[0] == '\'') {
octave[0] = 1;
} else if (musicdata[0] == ',') {
octave[0] = -1;
}
for (i=1; i<length; i++) {
switch (musicdata[i]) {
case '\'':
if (musicdata[i-1] == '\'') {
octave[i] = octave[i-1] + 1;
} else {
octave[i] = 1;
}
break;
case ',':
if (musicdata[i-1] == ',') {
octave[i] = octave[i-1] - 1;
} else {
octave[i] = -1;
}
break;
default:
octave[i] = octave[i-1];
break;
}
}
for (i=0; i<length; i++) {
switch (octave[i]) {
case 0: octave[i] = 4; break;
case 1: octave[i] = 4; break;
case 2: octave[i] = 5; break;
case 3: octave[i] = 6; break;
case 4: octave[i] = 7; break;
case 5: octave[i] = 8; break;
case 6: octave[i] = 9; break;
case -1: octave[i] = 3; break;
case -2: octave[i] = 2; break;
case -3: octave[i] = 1; break;
case -4: octave[i] = 0; break;
default: octave[i] = 4;
}
}
Array<int> acc;
acc.setSize(length);
acc.setAll(0);
// measure accidentals at each position in the data string
for (i=0; i<length; i++) {
switch (musicdata[i]) {
case 'x': acc[i] = acc[i-1] + 1; break;
case 'b': acc[i] = acc[i-1] - 1; break;
case 'n': acc[i] = 100; break;
}
}
int currentacc = 0;
for (i=1; i<length; i++) {
if (musicdata[i] == 'x' || musicdata[i] == 'b' ||
musicdata[i] == 'n') {
currentacc = acc[i];
} else if ((musicdata[i]-'A'>=0) && (musicdata[i]-'A'<7)) {
acc[i] = currentacc;
currentacc = 0;
}
}
// calculate slur information
Array<int> tempslur;
tempslur.setSize(length);
tempslur.setAll(0);
int lasti = 0;
int ii;
for (i=0; i<length; i++) {
if ((musicdata[i] - 'A' >= 0) && (musicdata[i] - 'A' < 7)) {
lasti = i;
} else if (musicdata[i] == '+') {
if (tempslur[lasti]) {
tempslur[lasti] = 3;
} else {
tempslur[lasti] = 1;
}
for (ii=i; ii<length; ii++) {
if ((musicdata[ii]-'A'>= 0) && (musicdata[ii]-'A'<7)) {
tempslur[ii] = 2;
i = ii;
break;
}
}
}
}
// calculate beam grouping information
Array<int> tempbeam;
tempbeam.setSize(length);
tempbeam.setAll(0);
lasti = 0;
for (i=0; i<length; i++) {
if ((musicdata[i] - 'A' >= 0) && (musicdata[i] - 'A' < 7)) {
lasti = i;
} else if (musicdata[i] == '}') {
tempbeam[lasti] = 2;
} else if (musicdata[i] == '{') {
for (ii=i; ii<length; ii++) {
if ((musicdata[ii]-'A'>= 0) && (musicdata[ii]-'A'<7)) {
tempbeam[ii] = 1;
i = ii;
lasti = i;
break;
}
}
}
}
// calculate durations for all positions in data string
Array<double> duration;
duration.setSize(length);
duration.setAll(0.0);
int dots = 0;
double basedur = 0.0;
for (i=0; i<length; i++) {
switch (musicdata[i]) {
case '0': duration[i] = 16.0; basedur = duration[i]; dots = 0;
break;
case '1': duration[i] = 4.0; basedur = duration[i]; dots = 0;
break;
case '2': duration[i] = 2.0; basedur = duration[i]; dots = 0;
break;
case '3': duration[i] = 4.0/32.0; basedur = duration[i]; dots = 0;
break;
case '4': duration[i] = 1.0; basedur = duration[i]; dots = 0;
break;
case '5': duration[i] = 4.0/64.0; basedur = duration[i]; dots = 0;
break;
case '6': duration[i] = 0.25; basedur = duration[i]; dots = 0;
break;
case '7': duration[i] = 4.0/128.0; basedur = duration[i]; dots = 0;
break;
case '8': duration[i] = 0.5; basedur = duration[i]; dots = 0;
break;
case '9': duration[i] = 8.0; basedur = duration[i]; dots = 0;
break;
case '.':
dots++;
if (i > 0) {
duration[i] = duration[i-1] + basedur * pow(2.0, -dots);
}
break;
default:
dots = 0;
if (i > 0) {
duration[i] = duration[i-1];
}
break;
}
}
// adjust for tuplet durations here...
Array<int> kkey;
kkey.setSize(key.getSize());
for (i=0; i<kkey.getSize(); i++) {
if (key[i] < 0) {
kkey[i] = -1;
} else if (key[i] > 0) {
kkey[i] = +1;
} else {
kkey[i] = 0;
}
}
int wholerestcount = 0;
int accidental;
Array<int> mkey(7);
mkey = kkey;
int natural = 0;
int pitch;
for (i=0; i<length; i++) {
wholerestcount = 0;
if (musicdata[i] == '/') {
mkey = kkey;
}
accidental = acc[i];
if (accidental > 5) {
// accidental = 0;
natural = 1;
}
pitch = 1000;
switch (musicdata[i]) {
case 'A':
if (accidental != 0) {
if (natural) {
pitch = 31 + 40 * octave[i];
mkey[4] = 0;
natural = 0;
} else {
pitch = 31 + 40 * octave[i] + accidental;
mkey[4] = accidental;
}
} else {
pitch = 31 + 40 * octave[i] + mkey[4];
}
break;
case 'B':
if (accidental != 0) {
if (natural) {
pitch = 37 + 40 * octave[i];
mkey[6] = 0;
natural = 0;
} else {
pitch = 37 + 40 * octave[i] + accidental;
mkey[6] = accidental;
}
} else {
pitch = 37 + 40 * octave[i] + mkey[6];
}
break;
case 'C':
if (accidental != 0) {
if (natural) {
pitch = 2 + 40 * octave[i];
mkey[1] = 0;
natural = 0;
} else {
pitch = 2 + 40 * octave[i] + accidental;
mkey[1] = accidental;
}
} else {
pitch = 2 + 40 * octave[i] + mkey[1];
}
break;
case 'D':
if (accidental != 0) {
if (natural) {
pitch = 8 + 40 * octave[i];
mkey[3] = 0;
natural = 0;
} else {
pitch = 8 + 40 * octave[i] + accidental;
mkey[3] = accidental;
}
} else {
pitch = 8 + 40 * octave[i] + mkey[3];
}
break;
case 'E':
if (accidental != 0) {
if (natural) {
pitch = 14 + 40 * octave[i];
mkey[5] = 0;
natural = 0;
} else {
pitch = 14 + 40 * octave[i] + accidental;
mkey[5] = accidental;
}
} else {
pitch = 14 + 40 * octave[i] + mkey[5];
}
break;
case 'F':
if (accidental != 0) {
if (natural) {
pitch = 19 + 40 * octave[i];
mkey[0] = 0;
natural = 0;
} else {
pitch = 19 + 40 * octave[i] + accidental;
mkey[0] = accidental;
}
} else {
pitch = 19 + 40 * octave[i] + mkey[0];
}
break;
case 'G':
if (accidental != 0) {
if (natural) {
pitch = 25 + 40 * octave[i];
mkey[2] = 0;
natural = 0;
} else {
pitch = 25 + 40 * octave[i] + accidental;
mkey[2] = accidental;
}
} else {
pitch = 25 + 40 * octave[i] + mkey[2];
}
break;
case '/': pitch = 0; break;
case '-': pitch = -1000; break;
case '=':
pitch = -1000;
wholerestcount = 1;
if (isdigit(musicdata[i+1])) {
sscanf(&(musicdata[i+1]), "%d", &wholerestcount);
// warning: possible error -- maybe need to increment
// pointer to the value after the whole rest count
// incase there is no rhythm marker before the next pitch.
}
break;
default:
break;
}
if (pitch < 1000) {
tempnote.pitch = pitch;
tempnote.duration = duration[i];
tempnote.tie = tempslur[i];
tempnote.beam = tempbeam[i];
tempnote.wholerest = wholerestcount;
tempnote.measureduration = measureduration;
notes.append(tempnote);
}
}
}
//////////////////////////////
//
// printPitches --
//
void printPitches(ostream& out, Array& notes) {
char buffer[1024] = {0};
int i, ii;
for (i=0; i<notes.getSize(); i++) {
if (notes[i].pitch < 0) {
if (notes[i].tie == 1) {
out << "[";
}
if (notes[i].wholerest == 0) {
out << Convert::durationToKernRhythm(buffer, notes[i].duration);
out << "r";
} else {
out << Convert::durationToKernRhythm(buffer,
notes[i].measureduration);
out << "rr\n";
for (ii=1; ii<notes[i].wholerest; ii++) {
out << "=\n";
out << Convert::durationToKernRhythm(buffer,
notes[i].measureduration);
out << "rr";
}
}
if (notes[i].beam == 1) {
out << "L";
} else if (notes[i].beam == 2) {
out << "J";
}
if (notes[i].tie == 2) {
out << "]";
} else if (notes[i].tie == 3) {
out << "_";
}
} else if (notes[i].pitch == 0) {
out << "=";
} else {
if (notes[i].tie == 1) {
out << "[";
}
out << Convert::durationToKernRhythm(buffer, notes[i].duration);
out << Convert::base40ToKern(buffer, notes[i].pitch);
if (notes[i].tie == 2) {
out << "]";
} else if (notes[i].tie == 3) {
out << "_";
}
if (notes[i].beam == 1) {
out << "L";
} else if (notes[i].beam == 2) {
out << "J";
}
}
out << "\n";
}
}
//////////////////////////////
//
// getField --
//
const char* getField(const char* field, HumdrumFile& hfile, int incipitnum) {
Array<int> endindex;
endindex.setSize(100);
endindex.setSize(0);
endindex.allowGrowth();
if (incipitnum == 0) {
return "";
}
int count = 0;
int i;
for (i=0; i<hfile.getNumLines(); i++) {
if (strncmp(hfile[i][0], "!!!RISM-112F:", 13) == 0) {
count++;
endindex.append(i);
}
}
char searchstring[1024] = {0};
strcpy(searchstring, "!!!RISM-");
strcat(searchstring, field);
strcat(searchstring, ":");
int length = strlen(searchstring);
const char* output = "";
for (i=endindex[incipitnum-1]; i>=0; i--) {
if (strncmp(hfile[i][0], "!!!RISM-112", 11) != 0) {
break;
} else if ((i < endindex[incipitnum-1]) &&
(strncmp(hfile[i][0], "!!!RISM-112F", 12) == 0)) {
break;
} else if (strncmp(hfile[i][0], searchstring, length) == 0) {
output = hfile[i][1];
break;
}
}
return output;
}
//////////////////////////////
//
// getTimeInfo -- read the key signature.
//
const char* getTimeInfo(Array<double>& timeinfo, HumdrumFile& hfile,
int incipitnum) {
const char* timeline = getField("112E", hfile, incipitnum);
const char* output = "*M4/4";
if (strcmp(timeline, "&C;") == 0) { // 19,511 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0;
output = "*M4/4\n*met(C)";
} else if (strcmp(timeline, "3/4;") == 0) { // 7,733 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/4.0;
output = "*M3/4";
} else if (strcmp(timeline, "2/4;") == 0) { // 6,873 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/4.0;
output = "*M2/4";
} else if (strcmp(timeline, "\"&alla\";") == 0) { // 6,865 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0;
output = "*M2/2\n*met(C|)";
} else if (strcmp(timeline, "\"&alla;\"") == 0) { // 6,865 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0;
output = "*M2/2\n*met(C|)";
} else if (strcmp(timeline, "\"&alla;\";") == 0) { // 6,865 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0;
output = "*M2/2\n*met(C|)";
} else if (strcmp(timeline, "6/8;") == 0) { // 3,855 cases
timeinfo[0] = 6.0; timeinfo[1] = 4.0/8.0;
output = "*M6/8";
} else if (strcmp(timeline, "3/8;") == 0) { // 2,789 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/8.0;
output = "*M3/8";
} else if (strcmp(timeline, "[3/4];") == 0) { // 1,742 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/4.0;
output = "*M3/4\n!! inferred meter";
} else if (strcmp(timeline, "[&C];") == 0) { // 824 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0;
output = "*M4/4\n*met(C)\n!! inferred meter";
} else if (strcmp(timeline, "[4/2];") == 0) { // 794 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/2.0;
output = "*M4/2\n!! inferred meter";
} else if (strcmp(timeline, "[2/2];") == 0) { // 778 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0;
output = "*M2/2\n!! inferred meter";
} else if (strcmp(timeline, "3/2;") == 0) { // 689 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/2.0;
output = "*M3/2";
} else if (strcmp(timeline, "12/8;") == 0) { // 482 cases
timeinfo[0] = 12.0; timeinfo[1] = 4.0/8.0;
output = "*M12/8";
} else if (strcmp(timeline, "\"[&alla;]\";") == 0) { // 417 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0;
output = "*M2/2\n*met(C|)\n!! inferred meter";
} else if (strcmp(timeline, "[3/2];") == 0) { // 374 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/2.0;
output = "*M3/2\n!! inferred meter";
} else if (strcmp(timeline, "[2/2];") == 0) { // 272 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/4.0;
output = "*M2/4\n!! inferred meter";
} else if (strcmp(timeline, "6/4;") == 0) { // 196 cases
timeinfo[0] = 6.0; timeinfo[1] = 4.0/4.0;
output = "*M6/4";
} else if (strcmp(timeline, "[6/8];") == 0) { // 169 cases
timeinfo[0] = 6.0; timeinfo[1] = 4.0/8.0;
output = "*M6/8\n!! inferred meter";
} else if (strcmp(timeline, "[6/4];") == 0) { // 157 cases
timeinfo[0] = 6.0; timeinfo[1] = 4.0/4.0;
output = "*M6/4\n!! inferred meter";
} else if (strcmp(timeline, "[3/8];") == 0) { // 123 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/8.0;
output = "*M3/8\n!! inferred meter";
} else if (strcmp(timeline, "9/8;") == 0) { // 82 cases
timeinfo[0] = 9.0; timeinfo[1] = 4.0/8.0;
output = "*M9/8";
} else if (strcmp(timeline, "2/2;") == 0) { // 80 cases
timeinfo[0] = 2.0; timeinfo[1] = 4.0/2.0;
output = "*M2/2";
} else if (strcmp(timeline, "[6/2];") == 0) { // 42 cases
timeinfo[0] = 6.0; timeinfo[1] = 4.0/2.0;
output = "*M6/2\n!! inferred meter";
} else if (strcmp(timeline, "[3/1];") == 0) { // 36 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/1.0;
output = "*M3/1\n!! inferred meter";
} else if (strcmp(timeline, "4/4;") == 0) { // 35 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0;
output = "*M4/4";
} else if (strcmp(timeline, "3/1;") == 0) { // 33 cases
timeinfo[0] = 3.0; timeinfo[1] = 4.0/1.0;
output = "*M3/1";
} else if (strcmp(timeline, "[4/4];") == 0) { // 18 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0;
output = "*M4/4\n!! inferred meter";
} else if (strcmp(timeline, "4/8;") == 0) { // 10 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/8.0;
output = "*M4/8";
} else if (strcmp(timeline, "4/2;") == 0) { // 7 cases
timeinfo[0] = 4.0; timeinfo[1] = 4.0/2.0;
output = "*M4/2";
} else if (strcmp(timeline, "12/16;") == 0) { // 7 cases
timeinfo[0] = 12.0; timeinfo[1] = 4.0/16.0;
output = "*M12/16";
} else if (strcmp(timeline, "[12/8];") == 0) { // 6 cases
timeinfo[0] = 12.0; timeinfo[1] = 4.0/8.0;
output = "*M12/8\n!! inferred meter";
} else if (strcmp(timeline, "8/8;") == 0) { // 5 cases
timeinfo[0] = 8.0; timeinfo[1] = 4.0/8.0;
output = "*M8/8";
}
else {
timeinfo[0] = 4.0; timeinfo[1] = 4.0/4.0;
output = "!! unknown meter";
}
/* Other time signature cases not yet processed
4 &c;
3 [9/8];
3 9/4;
3 6/16;
3 [4/8];
3 [12/4];
2 [&C/31];
2 &C 2/4;
2 "&alla; [2/2]";
2 9/16;
2 6/8-3/8;
2 [4/1];
2 2/8;
2 24/16;
2 0;
2 [?];
1 C6/8;
1 C6/4;
1 C/3/4;
1 &C,3/4;
1 C3/2;
1 &Alla.;
1 &alla.;
1 &alla;
1 &alla,;
1 "[&alla;?]";
1 [9/4];
1 [9/2];
1 [6/8;
1 [6/16];
1 5/4;
1 2/1;
1 [2/1];
1 11/4;
// weird time signatures
1 [?&C/3?];
1 bB;
1 "&alla;/3i";
1 2/3;
1 31;
1 [?3/1?];
1 !3/4!;
1 3/8 [6/8];
1 2 [2/4];
1 2/4[3/4];
8 &C 3/8;
3 &C/31;
3 [&C/3];
5 03;
128 3;
37 \;
36 2;
18 &C/3;
15 [3];
1 0/3;
*/
return output;
}
//////////////////////////////
//
// getKeyInfo -- read the key signature.
//
const char* getKeyInfo(Array& key, HumdrumFile& hfile, int incipitnum) {
const char* keyline = getField("112D", hfile, incipitnum);
// at the key information line, extract data
int type = 1; // 1 = sharps, 2 = flats
int paren = 1; // 1 = normal, 2 = inside of square brackets
int length = strlen(keyline);
int i = 0;
while (i < length) {
switch (keyline[i]) {
case 'b': type = -1; break;
case 'x': type = 1; break;
case '[': paren = 2; break;
case ']': paren = 1; break;
case 'F': key[0] = type * paren; break;
case 'C': key[1] = type * paren; break;
case 'G': key[2] = type * paren; break;
case 'D': key[3] = type * paren; break;
case 'A': key[4] = type * paren; break;
case 'E': key[5] = type * paren; break;
case 'B': key[6] = type * paren; break;
case ' ': break;
default:
if (debugQ) {
cout << "Error: unknown character: " << keyline[i]
<< endl;
exit(1);
}
break;
}
i++;
}
return keyline;
}
//////////////////////////////
//
// printTimeInfo --
//
void printTimeInfo(ostream& out, const char* timestring) {
out << timestring;
int length = strlen(timestring);
if (length > 0 && timestring[length-1] != '\n') {
out << "\n";
}
}
//////////////////////////////
//
// printKeyInfo -- not worrying about mixed sharp/flat key sigs
// for now...
//
void printKeyInfo(ostream& out, Array& key, const char* keystr) {
//if (keystr[0] != '\0') {
// out << "!! Key signature: " << keystr << "\n";
//}
out << "*k[";
if (key[0] > 0) {
if (key[0] > 0) out << "f#"; else if (key[0] < 0) out << "f-";
if (key[1] > 0) out << "c#"; else if (key[0] < 0) out << "c-";
if (key[2] > 0) out << "g#"; else if (key[0] < 0) out << "g-";
if (key[3] > 0) out << "d#"; else if (key[0] < 0) out << "d-";
if (key[4] > 0) out << "a#"; else if (key[0] < 0) out << "a-";
if (key[5] > 0) out << "e#"; else if (key[0] < 0) out << "e-";
if (key[6] > 0) out << "b#"; else if (key[0] < 0) out << "b-";
} else {
if (key[6] < 0) out << "b-"; else if (key[0] > 0) out << "b#";
if (key[5] < 0) out << "e-"; else if (key[0] > 0) out << "e#";
if (key[4] < 0) out << "a-"; else if (key[0] > 0) out << "a#";
if (key[3] < 0) out << "d-"; else if (key[0] > 0) out << "d#";
if (key[2] < 0) out << "g-"; else if (key[0] > 0) out << "g#";
if (key[1] < 0) out << "c-"; else if (key[0] > 0) out << "c#";
if (key[0] < 0) out << "f-"; else if (key[0] > 0) out << "g#";
}
out << "]" << endl;
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("debug=b", "print debug information");
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 2002" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 24 April 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");
}
//////////////////////////////
//
// example --
//
void example(void) {
}
//////////////////////////////
//
// usage --
//
void usage(const char* command) {
}
//////////////////////////////
//
// getLineIndex -- get the index location of the given string.
//
int getLineIndex(Array& pieces, const char* string) {
int index = -1;
int i;
for (i=0; i<pieces.getSize(); i++) {
if (strstr(pieces[i].getBase(), string) != NULL) {
index = i;
break;
}
}
return index;
}
// md5sum: 00d5e9dedeb47c815390eac97f8c9f42 rism2kern2.cpp [20050403]