//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Wed Mar 13 20:26:11 PST 2002
// Last Modified: Wed Mar 13 20:26:17 PST 2002
// Filename: ...sig/examples/all/esac2hum.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/esac2hum.cpp
// Syntax: C++; museinfo
//
// Description: Converts an EsAC file into Humdrum.
//
#include "humdrum.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
#ifndef OLDCPP
#include <iostream>
#include <fstream>
using namespace std;
#else
#include <iostream.h>
#include <fstream.h>
#endif
typedef Array<int> ArrayInt;
class char16 {
public:
char* getBase(void) { return buffer; }
char buffer[16];
};
// function declarations:
void checkOptions(Options& opts, int argc, char** argv);
void example(void);
void usage(const char* command);
void parseIndex(const char* filename, Array<char16>& ids,
Array<int>& startp,Array<ArrayInt>& intervals);
int generateScore(Array<int>& song1, Array<int>& song2,
int kernul);
void findBest(int index, Array<char16>& ids,
Array<ArrayInt>& intervals, int kernul,
double cutoff);
int comparePosition(Array<int>& song1, int i, Array<int>& song2,
int j, int kernul);
int scorecompare(const void* a, const void* b);
int generateScoreLinear(Array<int>& song1, Array<int>& song2,
int kernul);
int comparePositionContinuous(Array<int>& song1, int i, Array<int>& song2,
int j, int kernul);
int generateScoreLinearSum(Array<int>& song1, Array<int>& song2,
int kernul);
// User interface variables:
Options options;
int debugQ = 0; // used with the --debug option
int verboseQ = 0; // used with the -v option
int kernel = 4; // number of notes in sequence that are
// required to generate a match.
double cutoff = 0.1; // used with the -c option
int ncutoff = 0; // used with the -n option
int rawQ = 0; // used with the -r option
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
// process the command-line options
Array<ArrayInt> intervals;
Array<char16> ids;
Array<int> startp;
checkOptions(options, argc, argv);
parseIndex(options.getArg(1), ids, startp, intervals);
if (verboseQ) {
cout << "ids: " << ids.getSize()
<< "\tstartp: " << startp.getSize()
<< "\tintervals: " << intervals.getSize()
<< endl;
}
int i;
for (i=0; i<intervals.getSize(); i++) {
findBest(i, ids, intervals, kernel, cutoff);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
class scorepair {
public:
double score;
double score1;
double score2;
double score3;
int index;
};
//////////////////////////////
//
// findBest --
//
void findBest(int index, Array<char16>& ids, Array<ArrayInt>& intervals,
int kernul, double cutoff) {
double y0 = 0.0;
double y1 = 0.0;
double y2 = 0.0;
double sco;
int i;
Array<scorepair> scores;
scores.setSize(intervals.getSize());
for (i=0; i<intervals.getSize(); i++) {
scores[i].score1 = generateScoreLinear(intervals[index], intervals[i],
kernul+4);
scores[i].score2 = generateScoreLinear(intervals[index], intervals[i],
kernul+2);
scores[i].score3 = generateScoreLinear(intervals[index], intervals[i],
kernul+0);
scores[i].index = i;
scores[i].score = scores[i].score1;
}
// sort scores here.
qsort(scores.getBase(), scores.getSize(), sizeof(scorepair), scorecompare);
double basevalue1 = scores[0].score1;
double basevalue2 = scores[0].score2;
double basevalue3 = scores[0].score3;
for (i=0; i<scores.getSize(); i++) {
y0 = scores[i].score * 1.0 / basevalue1;
y1 = scores[i].score2 * 1.0 / basevalue2;
y2 = scores[i].score3 * 1.0 / basevalue3;
sco = 100 * (y0 + y1/2 + y2/4 - (y1-y0) - (y2-y0) - 0.75);
sco = (sco + 45.0) / 145.0 * 100.0;
scores[i].score = sco;
}
qsort(scores.getBase(), scores.getSize(), sizeof(scorepair), scorecompare);
cout << ids[index].getBase() << "\t";
if (ncutoff > 0) {
for (i=0; i<ncutoff; i++) {
cout << ids[scores[i].index].getBase()
<< "(" << scores[i].score << ")\t";
}
} else {
i = 0;
while (i < ids.getSize() && scores[i].score >= cutoff) {
cout << ids[scores[i].index].getBase() <<"("<< scores[i].score << ")\t";
i++;
}
}
cout << endl;
}
//////////////////////////////
//
// generateScore -- make a score for the two songs
//
int generateScore(Array& song1, Array& song2, int kernul) {
int score = 0;
int linescore = 0;
int tempscore = 0;
int i, j;
int seq = 0;
for (i=0; i<song1.getSize() - kernul; i++) {
j = 0;
linescore = 0;
while (j < song2.getSize() - kernul) {
tempscore = 0;
seq = 0;
while (j < song2.getSize() - kernul &&
i + seq + kernul < song1.getSize() &&
comparePosition(song1, i+seq, song2, j, kernul)) {
tempscore++;
j++;
seq++;
}
j++;
if (tempscore > linescore) {
linescore = tempscore;
}
}
score += linescore;
}
return score;
}
//////////////////////////////
//
// generateScoreLinear -- make a score for the two songs by finding
// every pattern in song1 anywhere in song2
//
int generateScoreLinear(Array& song1, Array& song2, int kernul) {
int score = 0;
int i, j;
for (i=0; i<song1.getSize() - kernul; i++) {
j = 0;
while (j < song2.getSize() - kernul) {
if (comparePosition(song1, i, song2, j, kernul)) {
score++;
}
j++;
}
}
return score;
}
//////////////////////////////
//
// generateScoreLinear -- make a score for the two songs by finding
// every pattern in song1 anywhere in song2
//
int generateScoreLinearSum(Array& song1, Array& song2, int kernul) {
int score = 0;
int tempscore = 0;
int maxscore = 0;
int i, j;
for (i=0; i<song1.getSize() - kernul; i++) {
j = 0;
maxscore = 0;
tempscore = 0;
while (j < song2.getSize() - kernul) {
tempscore = comparePositionContinuous(song1, i, song2, j, kernul);
if (tempscore == kernul) {
maxscore = tempscore;
break;
}
if (maxscore < tempscore) {
maxscore = tempscore;
}
j++;
}
score += tempscore;
}
return score;
}
//////////////////////////////
//
// comparePositionContinuous --
//
int comparePositionContinuous(Array<int>& song1, int i, Array<int>& song2,
int j, int kernul) {
int a;
int score = 0;
for (a=0; a<kernul; a++) {
if (song1[i+a] == song2[j+a]) {
score++;
}
}
return score;
}
//////////////////////////////
//
// comparePosition --
//
int comparePosition(Array<int>& song1, int i, Array<int>& song2, int j,
int kernul) {
int a;
for (a=0; a<kernul; a++) {
if (song1[i+a] != song2[j+a]) {
return 0;
}
}
return 1;
}
//////////////////////////////
//
// parseIndex --
//
void parseIndex(const char* filename, Array<char16>& ids, Array<int>& startp,
Array<ArrayInt>& intervals) {
#ifndef OLDCPP
ifstream infile(filename);
#else
ifstream infile(filename, ios::nocreate);
#endif
if (!infile.is_open()) {
cerr << "Error opening file: " << filename << endl;
exit(1);
}
char buffer[10001] = {0};
Array<int> templist;
templist.setSize(1000);
templist.setGrowth(1000);
templist.setSize(0);
ids.setSize(10000);
ids.setGrowth(10000);
ids.setSize(0);
char16 tempid;
startp.setSize(10000);
startp.setGrowth(10000);
startp.setSize(0);
int pitch;
intervals.setSize(10000);
intervals.setGrowth(10000);
intervals.setSize(0);
int inter;
Array<int> tempinter;
tempinter.setSize(1000);
tempinter.setGrowth(1000);
tempinter.setSize(0);
int lineno = 0;
infile.getline(buffer, 10000, '\n');
lineno++;
char* ptr;
while (!infile.eof()) {
// read id number
ptr = strtok(buffer, "\t\n: ");
if (ptr == NULL) {
break;
}
strcpy(tempid.getBase(), ptr);
ids.append(tempid);
// read starting pitch
ptr = strtok(NULL, "\t\n: ");
if (ptr == NULL) {
cerr << "Error on line: " << lineno << endl;
exit(1);
}
pitch = atoi(ptr);
startp.append(pitch);
tempinter.setSize(0);
ptr = strtok(NULL, "\t\n: ");
while (ptr != NULL) {
inter = atoi(ptr);
tempinter.append(inter);
ptr = strtok(NULL, "\t\n: ");
}
intervals.append(tempinter);
infile.getline(buffer, 10000, '\n');
lineno++;
}
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("debug=b", "print debug information");
opts.define("v|verbose=b", "verbose output");
opts.define("k|kernel=i:3", "matching sequence length");
opts.define("c|cutoff=d:0.5", "cut-off for matched displays");
opts.define("n|number=i:0", "number of best matches to display");
opts.define("r|raw=b", "print raw score with no scaling");
opts.define("author=b", "author of program");
opts.define("version=b", "compilation info");
opts.define("example=b", "example usages");
opts.define("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, March 2002" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 15 March 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");
verboseQ = opts.getBoolean("verbose");
kernel = opts.getInteger("kernel");
cutoff = opts.getDouble("cutoff");
ncutoff = opts.getInteger("number");
rawQ = opts.getBoolean("raw");
}
//////////////////////////////
//
// example --
//
void example(void) {
}
//////////////////////////////
//
// usage --
//
void usage(const char* command) {
}
//////////////////////////////
//
// scorecompare -- compare two integers for ordering
//
int scorecompare(const void* a, const void* b) {
scorepair& A = *((scorepair*)a);
scorepair& B = *((scorepair*)b);
if (A.score > B.score) {
return -1;
} else if (A.score < B.score) {
return 1;
} else {
return 0;
}
}
// md5sum: d0a542d39a5553960e187e9f5738d8e2 plmatch.cpp [20050403]