//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Sun Feb 3 16:03:55 PST 2008
// Last Modified: Sun Feb 3 16:03:58 PST 2008
// Filename: ...sig/examples/all/nscale.cpp
// Web Address: http://sig.sapp.org/examples/museinfo/humdrum/nscale.cpp
// Syntax: C++; museinfo
//
// Description: Create Fast Keyscapes using MIDI file or Humdrum file.
//
#include "humdrum.h"
#include "MidiFile.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h> /* for qsort and bsearch functions */
#ifndef OLDCPP
#include <iostream>
#include <fstream>
#else
#include <iostream.h>
#include <fstream.h>
#endif
#define PHRASEBOUNDARY 0x8080
#define REST 0x8081
// function declarations:
void checkOptions(Options& opts, int argc, char** argv);
void example(void);
void usage(const char* command);
void printAnalysis(Array<double>& sequence);
void getSequence(Array<double>& sequence, HumdrumFile& infile,
int pspine = 1);
int getPspineIndex(HumdrumFile& infile, int line, int pspine);
void fillScaleArray(Array<double>& scaledegrees, int keychroma,
int keymode);
int getSubsequence(Array<double>& subsequence,
Array<double>& sequence, int start);
double getDegree(double value);
// User interface variables:
Options options;
int ccount = 5; // for -n option
int displaycountQ = 0; // for -c option
int repeatQ = 1; // for -R option
int keepphraseQ = 0; // for -P option
//////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
Array<double> sequence;
sequence.setSize(0);
HumdrumFile infile;
checkOptions(options, argc, argv);
int numinputs = options.getArgCount();
int i;
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);
} else {
infile.read(options.getArg(i+1));
}
getSequence(sequence, infile);
printAnalysis(sequence);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// getSequence --
//
void getSequence(Array& sequence, HumdrumFile& infile, int pspine) {
int keychroma = 0;
int keymode = 0; // 0 = major; 1 = minor
sequence.setSize(infile.getNumLines());
sequence.setSize(0);
Array<double> base40toScaleDegree(40);
base40toScaleDegree.zero();
fillScaleArray(base40toScaleDegree, 2, 0); // C major
int i;
int ii;
int octave;
double value;
int base40;
int length;
for (i=0; i<infile.getNumLines(); i++) {
switch (infile[i].getType()) {
case E_humrec_interpretation:
ii = getPspineIndex(infile, i, pspine);
if (strncmp("**kern", infile[i][ii], 2) == 0) {
if (strcmp("**kern", infile[i][ii]) != 0) {
cerr << "Error: input spine is not **kern: "
<< infile[i][ii] << endl;
exit(1);
}
}
// check for key signature marker
length = strlen(infile[i][ii]);
if (length >= 3 && length <= 4) {
if (infile[i][ii][length-1] == ':') {
keychroma = Convert::kernToBase40(infile[i][ii]);
octave = keychroma % 40;
if (octave >= 4) {
keymode = 0; // major
} else {
keymode = 1; // minor
}
keychroma = keychroma % 40;
}
// cout << "KEY = " << infile[i][ii] << endl;
fillScaleArray(base40toScaleDegree, keychroma, keymode);
}
break;
case E_humrec_data:
ii = getPspineIndex(infile, i, pspine);
if (strcmp(infile[i][ii], ".") == 0) {
break;
} else if (strchr(infile[i][ii], '_') != NULL) {
// ignore tied note mid notes
} else if (strchr(infile[i][ii], ']') != NULL) {
// ignore tied note end notes
} else if (strchr(infile[i][ii], 'r') != NULL) {
value = REST;
// sequence.append(value); don't store for now
} else {
if (keepphraseQ) {
if (strchr(infile[i][ii], '{') != NULL) {
value = PHRASEBOUNDARY;
sequence.append(value);
}
}
base40 = Convert::kernToBase40(infile[i][ii]);
if (base40 >= 0) {
octave = (base40 - keychroma + 40) / 40;
value = base40toScaleDegree[base40 % 40];
value = value + octave * 7;
if (repeatQ == 0) {
if (sequence[sequence.getSize()-1] != value) {
sequence.append(value);
}
} else {
sequence.append(value);
}
}
}
break;
case E_humrec_none:
case E_humrec_empty:
case E_humrec_global_comment:
case E_humrec_bibliography:
case E_humrec_data_comment:
case E_humrec_data_kern_measure:
default:
// don't do anything
break;
}
}
}
//////////////////////////////
//
// fillScaleArray --
//
void fillScaleArray(Array<double>& scaledegrees, int keychroma, int keymode) {
if (keymode == 1) {
scaledegrees[(38 + keychroma) % 40] = 7.0 - 1; // C--
scaledegrees[(39 + keychroma) % 40] = 7.5 - 1; // C-
scaledegrees[(0 + keychroma) % 40] = 1.0 - 1; // C
scaledegrees[(1 + keychroma) % 40] = 1.5 - 1; // C#
scaledegrees[(2 + keychroma) % 40] = 2.0 - 1; // C##
scaledegrees[(4 + keychroma) % 40] = 1.0 - 1; // D--
scaledegrees[(5 + keychroma) % 40] = 1.5 - 1; // D-
scaledegrees[(6 + keychroma) % 40] = 2.0 - 1; // D
scaledegrees[(7 + keychroma) % 40] = 3.0 - 1; // D#
scaledegrees[(8 + keychroma) % 40] = 3.5 - 1; // D##
scaledegrees[(10 + keychroma) % 40] = 2.0 - 1; // E--
scaledegrees[(11 + keychroma) % 40] = 3.0 - 1; // E-
scaledegrees[(12 + keychroma) % 40] = 3.5 - 1; // E
scaledegrees[(13 + keychroma) % 40] = 4.0 - 1; // E#
scaledegrees[(14 + keychroma) % 40] = 4.5 - 1; // E##
scaledegrees[(15 + keychroma) % 40] = 3.0 - 1; // F--
scaledegrees[(16 + keychroma) % 40] = 3.5 - 1; // F-
scaledegrees[(17 + keychroma) % 40] = 4.0 - 1; // F
scaledegrees[(18 + keychroma) % 40] = 4.5 - 1; // F#
scaledegrees[(19 + keychroma) % 40] = 5.0 - 1; // F##
scaledegrees[(21 + keychroma) % 40] = 4.0 - 1; // G--
scaledegrees[(22 + keychroma) % 40] = 4.5 - 1; // G-
scaledegrees[(23 + keychroma) % 40] = 5.0 - 1; // G
scaledegrees[(24 + keychroma) % 40] = 6.0 - 1; // G#
scaledegrees[(25 + keychroma) % 40] = 6.5 - 1; // G##
scaledegrees[(27 + keychroma) % 40] = 5.0 - 1; // A--
scaledegrees[(28 + keychroma) % 40] = 6.0 - 1; // A-
scaledegrees[(29 + keychroma) % 40] = 6.5 - 1; // A
scaledegrees[(30 + keychroma) % 40] = 7.0 - 1; // A#
scaledegrees[(31 + keychroma) % 40] = 7.5 - 1; // A##
scaledegrees[(33 + keychroma) % 40] = 6.5 - 1; // B--
scaledegrees[(34 + keychroma) % 40] = 7.0 - 1; // B-
scaledegrees[(35 + keychroma) % 40] = 7.5 - 1; // B
scaledegrees[(36 + keychroma) % 40] = 1.0 - 1; // B#
scaledegrees[(37 + keychroma) % 40] = 1.5 - 1; // B##
} else {
scaledegrees[(38 + keychroma) % 40] = 6.5 - 1; // C--
scaledegrees[(39 + keychroma) % 40] = 7.0 - 1; // C-
scaledegrees[(0 + keychroma) % 40] = 1.0 - 1; // C
scaledegrees[(1 + keychroma) % 40] = 1.5 - 1; // C#
scaledegrees[(2 + keychroma) % 40] = 2.0 - 1; // C##
scaledegrees[(4 + keychroma) % 40] = 1.0 - 1; // D--
scaledegrees[(5 + keychroma) % 40] = 1.5 - 1; // D-
scaledegrees[(6 + keychroma) % 40] = 2.0 - 1; // D
scaledegrees[(7 + keychroma) % 40] = 2.5 - 1; // D#
scaledegrees[(8 + keychroma) % 40] = 3.0 - 1; // D##
scaledegrees[(10 + keychroma) % 40] = 2.0 - 1; // E--
scaledegrees[(11 + keychroma) % 40] = 2.5 - 1; // E-
scaledegrees[(12 + keychroma) % 40] = 3.0 - 1; // E
scaledegrees[(13 + keychroma) % 40] = 4.0 - 1; // E#
scaledegrees[(14 + keychroma) % 40] = 4.5 - 1; // E##
scaledegrees[(15 + keychroma) % 40] = 2.5 - 1; // F--
scaledegrees[(16 + keychroma) % 40] = 3.0 - 1; // F-
scaledegrees[(17 + keychroma) % 40] = 4.0 - 1; // F
scaledegrees[(18 + keychroma) % 40] = 4.5 - 1; // F#
scaledegrees[(19 + keychroma) % 40] = 5.0 - 1; // F##
scaledegrees[(21 + keychroma) % 40] = 4.0 - 1; // G--
scaledegrees[(22 + keychroma) % 40] = 4.5 - 1; // G-
scaledegrees[(23 + keychroma) % 40] = 5.0 - 1; // G
scaledegrees[(24 + keychroma) % 40] = 5.5 - 1; // G#
scaledegrees[(25 + keychroma) % 40] = 6.0 - 1; // G##
scaledegrees[(27 + keychroma) % 40] = 5.0 - 1; // A--
scaledegrees[(28 + keychroma) % 40] = 5.5 - 1; // A-
scaledegrees[(29 + keychroma) % 40] = 6.0 - 1; // A
scaledegrees[(30 + keychroma) % 40] = 6.5 - 1; // A#
scaledegrees[(31 + keychroma) % 40] = 7.0 - 1; // A##
scaledegrees[(33 + keychroma) % 40] = 6.0 - 1; // B--
scaledegrees[(34 + keychroma) % 40] = 6.5 - 1; // B-
scaledegrees[(35 + keychroma) % 40] = 7.0 - 1; // B
scaledegrees[(36 + keychroma) % 40] = 1.0 - 1; // B#
scaledegrees[(37 + keychroma) % 40] = 1.5 - 1; // B##
}
}
//////////////////////////////
//
// getPspineIndex --
//
int getPspineIndex(HumdrumFile& infile, int line, int pspine) {
int i;
int output = 0;
for (i=0; i<infile[i].getFieldCount(); i++) {
if (infile[line].getPrimaryTrack(i) == pspine) {
output = i;
break;
}
}
return output;
}
//////////////////////////////
//
// printAnalysis --
//
void printAnalysis(Array<double>& sequence) {
int i,j;
Array<double> subsequence;
subsequence.setSize(ccount);
subsequence.allowGrowth(0);
subsequence.zero();
for (i=0; i<sequence.getSize(); i++) {
if (getSubsequence(subsequence, sequence, i)) {
if (displaycountQ) {
cout << subsequence.getSize() << "\t";
}
cout << getDegree(subsequence[0]);
for (j=1; j<subsequence.getSize(); j++) {
//cout << "\t:" << subsequence[j] << ":";
cout << "\t" << (subsequence[j] - subsequence[j-1]);
//cout << "\t" << getDegree(subsequence[j]);
}
cout << "\n";
}
}
}
//////////////////////////////
//
// getDegree --
//
double getDegree (double value) {
int octave = int(value / 7);
return (value - octave * 7) + 1;
}
//////////////////////////////
//
// getSubsequence --
//
int getSubsequence(Array<double>& subsequence, Array<double>& sequence,
int start) {
int status = 0;
int i;
int subi;
if (start + subsequence.getSize() >= sequence.getSize()) {
return status;
}
i = start;
subi = 0;
while (i < sequence.getSize() && subi < subsequence.getSize()) {
if (sequence[i] == PHRASEBOUNDARY) {
if (keepphraseQ) {
i++;
continue;
} else {
return status;
}
} else {
subsequence[subi++] = sequence[i++];
}
}
if (subi == subsequence.getSize()) {
status = 1;
}
return status;
}
//////////////////////////////
//
// checkOptions --
//
void checkOptions(Options& opts, int argc, char* argv[]) {
opts.define("n|length=i:5", "length of sequences");
opts.define("c|count=b", "display length of sequences");
opts.define("P|phrase=b", "ignore phrase information");
opts.define("R|repeat=b", "ignore repeated notes");
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, May 2008" << endl;
exit(0);
} else if (opts.getBoolean("version")) {
cout << argv[0] << ", version: 18 May 2008" << 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);
}
ccount = opts.getInteger("length");
displaycountQ = opts.getBoolean("count");
repeatQ = !opts.getBoolean("repeat");
keepphraseQ = opts.getBoolean("phrase");
}
//////////////////////////////
//
// example --
//
void example(void) {
}
//////////////////////////////
//
// usage --
//
void usage(const char* command) {
}
// md5sum: e212ecd364af401d89c93082f81af4f4 nscale.cpp [20080920]