// // Programmer: Craig Stuart Sapp // Creation Date: Wed May 1 21:18:12 PDT 2002 // Last Modified: Wed May 1 21:18:16 PDT 2002 // Filename: ...sig/examples/all/pitchmix.cpp // Web Address: http://sig.sapp.org/examples/museinfo/humdrum/pitchmix.cpp // Syntax: C++; museinfo // // Description: Mix the ordering of pitches in a file, keeping the // durations in the same locations. // #include "humdrum.h" #include #include #include ////////////////////////////////////////////////////////////////////////// class NoteUnit { public: NoteUnit(void) { clear(); }; void clear(void) { track = random = newpitch = pitch = line = spine = token = -1; }; int track; int pitch; int line; int spine; int token; int random; int newpitch; }; ////////////////////////////////////////////////////////////////////////// // function declarations: void checkOptions (Options& opts, int argc, char** argv); void example (void); void usage (const char* command); void printNotes (Array& notes); void getNotes (Array& notes, HumdrumFile& infile); int compareNoteUnit (const void* A, const void* B); int compareNoteUnitTrack (const void* A, const void* B); int compareNoteSortTrack (const void* A, const void* B); void scrambleNotes (Array& notes); void replaceNotes (HumdrumFile& infile, Array& notes); void replaceNote (HumdrumFile& infile, int line, int spine, int token, int newpitch, int oldpitch = -1); void updateTiedNotes (HumdrumFile& infile, int line, int spine, int token, int newpitch, int oldpitch); int nearestNeighbor (int oldpitch, int newpitch); int throwDice (double piecefraction); // User interface variables: Options options; int debugQ = 0; // used with the --debug option int restQ = 0; // mix rests as well with -r option int seed = 0; // seed the random number generator int displaySeedQ = 0; // used with the -S option int transQ = 0; // display tranlation data only int trackQ = 0; // randomize by track int neighborQ = 0; // used with -n option int lowlimit = 40; // lowest note when tranposing EnvelopeString distring; // used with -d option int distQ = 0; // used with -d option ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { // process the command-line options checkOptions(options, argc, argv); HumdrumFile infile; infile.read(options.getArg(1)); if (distQ) { infile.analyzeRhythm(); } Array notes; getNotes(notes, infile); scrambleNotes(notes); if (transQ) { printNotes(notes); } else { replaceNotes(infile, notes); cout << infile; } if (displaySeedQ) { cout << "!!!seed: " << seed << endl; } return 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////// // // replaceNotes -- // void replaceNotes(HumdrumFile& infile, Array& notes) { int i; for (i=0; i& notes) { Array notes2; notes2 = notes; int i; for (i=0; i& notes, HumdrumFile& infile) { notes.setSize(100000); notes.setGrowth(100000); notes.setSize(0); NoteUnit tempnote; int tokencount; int track = 0; char buffer[1024] = {0}; int i, j, k; int dice = 0; for (i=0; i& notes) { int i; for (i=0; i b.random) { return 1; } else { return 0; } } ////////////////////////////// // // compareNoteUnitTrack -- sort by random number within each track // int compareNoteUnitTrack(const void* A, const void* B) { NoteUnit& a = *((NoteUnit*)A); NoteUnit& b = *((NoteUnit*)B); if (a.track < b.track) { return -1; } else if (a.track > b.track) { return 1; } if (a.random < b.random) { return -1; } else if (a.random > b.random) { return 1; } else { return 0; } } ////////////////////////////// // // compareNoteUnitTrack -- sort by random number within each track // int compareNoteSortTrack(const void* A, const void* B) { NoteUnit& a = *((NoteUnit*)A); NoteUnit& b = *((NoteUnit*)B); if (a.track < b.track) { return -1; } else if (a.track > b.track) { return 1; } else { return 0; } } ////////////////////////////// // // updatedTiedNotes -- change ending tied notes to the new random pitch // void updateTiedNotes(HumdrumFile& infile, int line, int spine, int token, int newpitch, int oldpitch) { // not quite perfect: if two primary tracks with common ties, will have prob: int m; int ptrack = infile[line].getPrimaryTrack(spine); int currentLine = line + 1; int length = infile.getNumLines(); int done = 0; // int matchpitch; while (!done && currentLine < length) { if (!infile[currentLine].isData()) { currentLine++; continue; } for (m=0; m 1.0) { piecefraction = 1.0; } // find the current point int i; int curr = distring.getNumPoints() - 1; for (i=0; i distring.getNumPoints() - 1) { fraction = distring.getValue(distring.getNumPoints()-1, 1); } else if (curr <= 0) { fraction = distring.getValue(0, 1); } else if (distring.getValue(curr, 0) == piecefraction) { fraction = distring.getValue(curr, 1); } else { x1 = distring.getValue(curr-1, 0); x2 = distring.getValue(curr, 0); y1 = distring.getValue(curr-1, 1); y2 = distring.getValue(curr, 1); slope = (y2-y1)/(x2-x1); fraction = slope * piecefraction + y2 - slope * x2; } #ifndef VISUAL if (drand48() > fraction) { return 0; } else { return 1; } #else if ((1.0*rand()/INT_MAX) > fraction) { return 0; } else { return 1; } #endif } // md5sum: 825362ac32bd38b19c76c8ef1d2bb416 pitchmix.cpp [20080518]