// // Programmer: Craig Stuart Sapp // Creation Date: Thu Dec 6 23:09:26 PST 2001 // Last Modified: Sun Dec 9 17:32:12 PST 2001 // Filename: ...sig/examples/all/attacksum.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/attacksum.cpp // Syntax: C++; museinfo // // Description: Generate a rhythmic summary of each measure by // generating a binary number based on note attacks. // // This program could also be modified to handle doubles // for the summation, then non integer attack locations // could be linearly distributed between positions. // // Options: -f field numbers separated by dash for range and/or comma // Gives the fields to use for analysis. // -d Divisions per quarter note duration to provied analysis. // -b binary form only -- do not sum number of attacks. // -s sum all metric positions. // -r raw summation data only (rid -GLId applied). // -a append summation data to input data. // -c code table version // -C display code table // // Example analysis: 400321530043204 // #include "humdrum.h" #include #include #include typedef Array ArrayInt; typedef Array ArrayChar; // function declarations void checkOptions (Options& opts, int argc, char* argv[]); void example (void); void usage (const char* command); void ZeroArray (Array& array, int value = 0); void printAnalysis (HumdrumFile& infile, Array& analysis, Array& line, Array& beats, double divisions); void generateAnalysis (HumdrumFile& infile, Array& analysis, Array& line, Array& beats, double divisions); void addLineToSum (HumdrumFile& infile, int line, Array& sumarray, Array& fields, double divisions); void generateFieldList (Array& fieldList,const char* fieldstring); char printDigit (int number); void printSum (Array& analysis); void clearAnalysis (Array& array); int stringcompare (const void* a, const void* b); int findInList (Array& codeTable, Array searchstring); void switchArrays (Array& codeTable, int currentpos, int founditem); void replaceWithCode (Array& tableitem, int founditem); void generateCodeTable (Array& codeTable, Array& analysis); void printBase26 (int i); // global variables Options options; // database for command-line arguments int debugQ = 0; // used with the --debug option int int appendQ = 0; // used with the -a option int rawQ = 0; // used with the -r option int sumQ = 0; // used with the -s option int binaryQ = 0; // display only binary attacks double qdiv = 4.0; // number of divisions per quarter note int maxfield = 0; // for -f option int fieldsQ = 0; // for -f option Array fields; // **kern fields to decide attacks Array totalsum; // for -s option string CurrentFile = ""; // for -s option int codeQ = 0; // for -c option int codeTableQ = 0; // for -C option /////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { HumdrumFile infile; // process the command-line options checkOptions(options, argc, argv); // figure out the number of input files to process int numinputs = options.getArgCount(); Array analysis; Array beats; Array line; analysis.setGrowth(500); analysis.setSize(0); beats.setSize(500); beats.setGrowth(500); beats.setSize(0); line.setSize(500); line.setGrowth(500); line.setSize(0); int i; for (int i=0; i 1) { cout << "TOTAL:\t"; for (i=0; i& array) { int i; for (i=0; i& analysis, Array& line, Array& beats, double divisions) { line.setSize(infile.getNumLines()); line.setSize(0); line.allowGrowth(1); infile.analyzeRhythm("4"); Array measuresum; measuresum.setSize(5); ZeroArray(measuresum); int currentLine = -1; double meterbeats = 4.0; int top = 4; int bottom = 4; int newsize; int i; for (i=0; i& sumarray, Array& fields, double divisions) { int i, j, k; int tokencount; int pitch = 0; int position; char buffer[1024] = {0}; if (fieldsQ) { for (i=0; i 0) { sumarray[position]++; } // otherwise a rest } } } } } else { for (j=0; j 0) { sumarray[position]++; } // otherwise a rest } } } } ////////////////////////////// // // ZeroArray -- set all values in array to zero. // void ZeroArray(Array& array, int value) { for (int i=0; i& analysis, Array& line, Array& beats, double divisions) { int i, j; int curr = 0; Array codeTable; if (codeQ || codeTableQ) { generateCodeTable(codeTable, analysis); } if (appendQ) { for (i=0; i= line[curr]) { cout << infile[i] << "\t"; if (codeQ) { cout << codeTable[curr].getBase(); } else { printSum(analysis[curr]); } cout << "\n"; curr++; } else { cout << infile[i] << "\t.\n"; } break; default: cout << infile[i] << "\n"; break; } } } else if (rawQ) { for (i=0; i maxsize) { maxsize = analysis[i].getSize(); } } Array summation(maxsize); ZeroArray(summation); int j; for (i=0; i 1) { cout << CurrentFile << ":\t"; } for (i=0; i= line[curr]) { if (codeQ) { printSum(analysis[curr]); } else { cout << codeTable[curr].getBase(); } cout << "\n"; curr++; } else { // do nothing } break; case E_humrec_data_comment: case E_humrec_none: case E_humrec_empty: default: // do nothing break; } } } } ////////////////////////////// // // generateCodeTable -- convert analysis to a list of unique sequence codes. // void generateCodeTable(Array& codeTable, Array& analysis) { int i, j; char empty = '\0'; char element; Array temptable; temptable.setSize(analysis.getSize()); codeTable.setSize(analysis.getSize()); for (i=0; i 0) { count = 1; } for (i=1; i uniqtable; uniqtable.setSize(count); uniqtable.allowGrowth(0); int ncount = 0; if (temptable.getSize() > 0) { uniqtable[0] = temptable[0]; ncount = 1; } for (i=1; i currentpos) { switchArrays(uniqtable, currentpos, founditem); founditem = currentpos; currentpos++; } replaceWithCode(codeTable[i], founditem); } // print the uniq table if user requests it: if (codeTableQ) { for (i=0; i= 26*26*26) { digit = i/26*26*26; cout << (char)('A' + digit - 1); i -= digit * 26 * 26 * 26; } if (i >= 26*26) { digit = i/26*26; cout << (char)('A' + digit - 1); i -= digit * 26 * 26; } if (i >= 26) { digit = i/26; cout << (char)('A' + digit - 1); i -= digit * 26; } digit = i; cout << (char)('A' + digit); } ////////////////////////////// // // replaceWithCode -- // void replaceWithCode(Array& tableitem, int founditem) { char buffer[128] = {0}; int digit; char schar[2] = {0}; if (founditem >= 26*26*26) { digit = founditem/26*26*26; schar[0] = 'A' + digit - 1; strcat(buffer, schar); founditem -= digit * 26 * 26 * 26; } if (founditem >= 26*26) { digit = founditem/26*26; schar[0] = 'A' + digit - 1; strcat(buffer, schar); founditem -= digit * 26 * 26; } if (founditem >= 26) { digit = founditem/26; schar[0] = 'A' + digit - 1; strcat(buffer, schar); founditem -= digit * 26; } digit = founditem; schar[0] = 'A' + digit; strcat(buffer, schar); int length = strlen(buffer); tableitem.setSize(length+1); int i; for (i=0; i& codeTable, int currentpos, int founditem) { if (founditem < 0) { return; } ArrayChar temp = codeTable[currentpos]; codeTable[currentpos] = codeTable[founditem]; codeTable[founditem] = temp; } ////////////////////////////// // // findInList -- // int findInList(Array& codeTable, Array searchstring) { int i; for (i=0; i& analysis) { int i; for (i=0; i& fieldList, const char* fieldstring) { fieldList.setSize(100); fieldList.setGrowth(100); fieldList.setSize(0); maxfield = 0; int length = strlen(fieldstring); char* buffer = new char[length+1]; strcpy(buffer, fieldstring); int starti, stopi; int temp; int num; char* ptr = strtok(buffer, " ,;:"); while (ptr != NULL) { if (strchr(ptr, '-') != NULL) { sscanf(ptr, "%d-%d", &starti, &stopi); if (starti > stopi) { temp = starti; starti=stopi; stopi = temp; } for (num=starti; num<=stopi; num++) { fieldList.append(num); } if (num > maxfield) { maxfield = num; } } else { sscanf(ptr, "%d", &num); fieldList.append(num); if (num > maxfield) { maxfield = num; } } ptr = strtok(NULL, " ,;:"); } fieldList.allowGrowth(0); } ////////////////////////////// // // printDigit -- print digit in base 36 with cut off if too large // char printDigit(int number) { if (number <= 0) { return '0'; } if (binaryQ) { return '1'; } if (number < 10) { return '0' + number; } number = number - 10; if (number >= 25) { return 'Z'; } return 'A' + number; } ////////////////////////////// // // stringcompare -- // int stringcompare(const void* a, const void* b) { ArrayChar& A = *((ArrayChar*)a); ArrayChar& B = *((ArrayChar*)b); return strcmp(A.getBase(), B.getBase()); } // md5sum: 386ce099569c2b89648f58808328a4d1 attacksum.cpp [20160320]