//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Mon Apr 26 12:57:44 PDT 2004
// Last Modified: Wed Apr 28 00:32:30 PDT 2004
// Filename: ...sig/examples/all/phrasenum.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/phrasenum.cpp
// Syntax: C++; museinfo
//
// Description: Extracts the phrase locations in a monophonic song
// according to which note the phrases start on.
//
#include "humdrum.h"
#include <string.h>
#ifndef OLDCPP
#include <iostream>
using namespace std;
#else
#include <iostream.h>
#endif
// includes needed for file/directory processing:
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
// function declarations:
void checkOptions(Options& opts, int argc, char** argv);
void example(void);
void usage(const char* command);
void processFile(HumdrumFile& hfile, const char* filename);
void printAnalysis(Array<int>& phrase, Array<int>& phrasestart,
Array<int>& notes, const char* filename);
void processArgument(const char* path);
int is_file (const char* path);
int is_directory (const char* path);
// User interface variables:
Options options;
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
// process the command-line options
checkOptions(options, argc, argv);
int i;
int numinputs = options.getArgCount();
HumdrumFile hfile;
for (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);
processFile(hfile, "");
} else {
processArgument(options.getArg(i+1));
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// processArgument -- check if the argument is a file or a directory.
// if a directory, then process all files/subdirectories in it.
//
void processArgument(const char* path) {
HumdrumFile hfile;
DIR* dir = NULL;
char* fullname;
struct dirent* entry;
int namelen = 0;
int valid = 0;
if (is_file(path)) {
namelen = strlen(path);
valid = 0;
if (strcmp(&(path[namelen-4]), ".thm") == 0) {
valid = 1;
} else if (strcmp(&(path[namelen-4]), ".krn") == 0) {
valid = 1;
} else if (strcmp(&(path[namelen-4]), ".THM") == 0) {
valid = 1;
} else if (strcmp(&(path[namelen-4]), ".KRN") == 0) {
valid = 1;
}
if (!valid) {
return;
}
hfile.read(path);
processFile(hfile, path);
} else if (is_directory(path)) {
dir = opendir(path);
if (dir == NULL) {
return;
}
entry = readdir(dir);
while (entry != NULL) {
if (strncmp(entry->d_name, ".", 1) == 0) {
entry = readdir(dir);
continue;
}
fullname = new char[strlen(path) + 1 + strlen(entry->d_name) + 1];
strcpy(fullname, path);
strcat(fullname, "/");
strcat(fullname, entry->d_name);
processArgument(fullname);
entry = readdir(dir);
}
}
closedir(dir);
}
//////////////////////////////
//
// processFile -- print the analysis
//
void processFile(HumdrumFile& hfile, const char* filename) {
Array<int> notes;
Array<int> phrase;
Array<int> phrasestart;
notes.setSize(1000);
notes.setSize(0);
phrase.setSize(1000);
phrase.setSize(0);
phrasestart.setSize(1000);
phrasestart.setSize(0);
int pitch;
int counter = 0;
int i;
int start;
for (i=0; i<hfile.getNumLines(); i++) {
switch (hfile[i].getType()) {
case E_humrec_data:
if (strcmp(hfile[i][0], ".") == 0) {
break;
}
if (strchr(hfile[i][0], ']') != NULL) {
break;
}
if (strchr(hfile[i][0], 'r') != NULL) {
if (strchr(hfile[i][0], '{') != NULL) {
counter++;
start = notes.getSize()+1;
phrasestart.append(start);
}
break; // don't store rests
}
if (strchr(hfile[i][0], '_') != NULL) {
break;
}
pitch = Convert::kernToBase40(hfile[i][0]);
notes.append(pitch);
if (strchr(hfile[i][0], '{') != NULL) {
counter++;
start = notes.getSize();
phrasestart.append(start);
}
phrase.append(counter);
}
}
printAnalysis(phrase, phrasestart, notes, filename);
}
///////////////////////////////
//
// printAnalysis --
//
void printAnalysis(Array<int>& phrase, Array<int>& phrasestart,
Array<int>& notes, const char* filename) {
if ((filename != NULL) && (filename[0] != '\0')) {
cout << filename << "\t";
}
// cout << "There are " << phrasestart.getSize() << " phrases.\n";
// cout << "Starting on the note numbers (offset from 1):\n";
int i;
for (i=0; i<phrasestart.getSize(); i++) {
cout << phrasestart[i];
if (i<phrasestart.getSize()-1) {
cout << " ";
}
}
cout << "\t";
// print the note pitch classes.
// cout << "Notes\n";
char buffer[1024] = {0};
for (i=0; i<notes.getSize(); i++) {
cout << Convert::base40ToKern(buffer, notes[i] % 40 + 4 * 40);
if (i<notes.getSize()-1) {
cout << " ";
}
}
cout << "\n";
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char* argv[]) {
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 2004" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: April 2004" << 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);
}
}
//////////////////////////////
//
// example --
//
void example(void) {
}
//////////////////////////////
//
// usage --
//
void usage(const char* command) {
}
//////////////////////////////
//
// is_file -- returns true if the string is a file.
//
int is_file(const char* path) {
struct stat filestat;
stat(path, &filestat);
return S_ISREG(filestat.st_mode);
}
//////////////////////////////
//
// is_directory -- returns true if the string is a directory.
//
int is_directory(const char* path) {
struct stat filestat;
stat(path, &filestat);
return S_ISDIR(filestat.st_mode);
}
// md5sum: 737b0c1c8f2a18127e054dd6708ae096 phrasenum.cpp [20050403]