void extractDurationSequence(Array<double>& durations, HumdrumFile& hfile, int track) { durations.setSize(10000); durations.setSize(0); durations.allowGrowth(); double dur = 0; int i, j; int pitch; for (i=0; i<hfile.getNumLines(); i++) { switch (hfile[i].getType()) { case E_humrec_none: case E_humrec_empty: case E_humrec_bibliography: case E_humrec_global_comment: case E_humrec_data_comment: case E_humrec_interpretation: case E_humrec_data_kern_measure: break; case E_humrec_data: for (j=0; j<hfile[i].getFieldCount(); j++) { if (hfile[i].getPrimaryTrack(j) != track) { continue; } if (strcmp(hfile[i][j], ".") == 0) { // ignore null tokens break; } if (strchr(hfile[i][j], '_') != NULL) { // ignore continuing ties break; } if (strchr(hfile[i][j], ']') != NULL) { // ignore ending ties break; } if (strchr(hfile[i][j], 'r') != NULL) { // ignore rests break; } pitch = Convert::kernToBase40(hfile[i][j]); if ((pitch < 0) || (pitch > 10000)) { // ignore rests and other strange things break; } dur = hfile.getTiedDuration(i, j); durations.append(dur); if (limitQ) { if (durations.getSize() >= limit) { return; } } break; } break; default: break; } } }
void printOutput(HumdrumFile& hfile) { Array<double> tempo; hfile.analyzeTempoMarkings(tempo, tdefault); double currentmillisecond = 0.0; double lastduration = 0.0; double linestarttime = 0.0; double lineendtime = 0.0; int founddata = 0; int metlev; int i, j, k; char buffer1[1024] = {0}; char buffer2[1024] = {0}; double duration; for (i=0; i<hfile.getNumLines(); i++) { currentmillisecond = currentmillisecond + lastduration * 60000.0 / tempo[i]; lastduration = hfile[i].getDuration(); if (hfile[i].getType() == E_humrec_global_comment) { cout << "%% " << &(hfile[i].getLine()[3]) << endl; } if (hfile[i].getType() == E_humrec_bibliography) { cout << "%%%" << &(hfile[i].getLine()[3]) << endl; } if (hfile[i].getType() != E_humrec_data) { continue; } if (debugQ) { cout << "RECORD: " << hfile[i] << endl; } if (founddata == 0) { founddata = 1; comment(cout, 2, humdrumQ); cout << " Data column information:\n"; comment(cout, 3, humdrumQ); cout << "col01: abstime\t" << "(average absolute time in milliseconds of human " << "beats)\n"; comment(cout, 3, humdrumQ); cout << "col02: duration\t" << "(expected duration in ms based " << "on score duration)\n"; comment(cout, 3, humdrumQ); cout << "col03: note\t\t" << "(MIDI note number of pitch)\n"; comment(cout, 3, humdrumQ); cout << "col04: metlev\t" << "(metric level: 1 = downbeat; " << "0 = beat; -1 = offbeat)\n"; comment(cout, 3, humdrumQ); cout << "col05: measure\t" << "(measure number in which note occurs)\n"; comment(cout, 3, humdrumQ); cout << "col06: absbeat\t" << "(absolute beat from starting beat at 0)\n"; comment(cout, 3, humdrumQ); cout << "col07: trackno\t" << "(hand which plays the note: 1 = left; 2=right)\n"; if (!auxdataQ) { comment(cout, 3, humdrumQ); cout << "col08: mintime\t" << "(minimum absolute time of human beat for this note)\n"; comment(cout, 3, humdrumQ); cout << "col09: maxtime\t" << "(maximum absolute time of human beat for this note)\n"; comment(cout, 3, humdrumQ); cout << "col10: sd\t\t" << "(standard deviation of human beat time in ms.)\n"; } else { //comment(cout, 3, humdrumQ); //cout << "col08: paccid\t" << // "(printed accidental 0=none, -1=flat, +1=sharp, 10=nat)\n"; comment(cout, 3, humdrumQ); cout << "col08: saccid\t" << "(sounding accidental 0=natural, -1=flat, +1=sharp)\n"; } if (humdrumQ) { cout << "**start\t**dur\t**key\t**metr\t**meas\t**absb\t**track\t**saccid\n"; } } linestarttime = -1.0; // find current time value and save for (j=0; j<hfile[i].getFieldCount(); j++) { if (strcmp(hfile[i].getExInterp(j), "**time") == 0) { sscanf(hfile[i][j], "%lf", &linestarttime); break; } } for (j=0; j<hfile[i].getFieldCount(); j++) { if (hfile[i].getExInterpNum(j) != E_KERN_EXINT) { continue; } for (k=0; k<hfile[i].getTokenCount(j); k++) { if (strcmp(hfile[i][j], ".") == 0) { continue; } hfile[i].getToken(buffer1, j, k); if (strchr(buffer1, '_') != NULL) { // ignore notes which are tied continue; } if (strchr(buffer1, ']') != NULL) { // ignore notes which are tied continue; } preparePitch(buffer2, buffer1); duration = hfile.getTiedDuration(i, j, k); lineendtime = getEndTime(hfile, i, duration); int note = Convert::kernToMidiNoteNumber(buffer2); if (classQ) { note = note % 12; } if (note < 0) { // don't display rests. continue; } if (note < 0 || note > 127) { cerr << "Error reading MIDI pitch number from string: " << buffer2 << endl; exit(1); } //cout << "Note\t"; // cout << hfile.getAbsBeat(i) << "\t"; // cout << (int)(currentmillisecond+0.5) << "\t"; cout << linestarttime << "\t"; if (debugQ && (lineendtime - linestarttime < 0)) { cerr << "Error duration of note on line: " << hfile[i] << endl; cerr << "Starttime: " << linestarttime << endl; cerr << "Endtime: " << lineendtime << endl; cerr << "Line Index: " << i << endl; exit(1); } if (lineendtime != -1) { cout << lineendtime - linestarttime << "\t"; } else { cout << (int)(getTimeToEnd(hfile, linestarttime, i) + 0.5) << "\t"; } cout << note; cout << "\t"; metlev = getMetricLevel(hfile, i); cout << metlev; cout << "\t" << getMeasureNum(hfile, i); cout << "\t" << hfile[i].getAbsBeat(); // you must make sure that the spine order is // correct or this data will be bad cout << "\t" << hfile[i].getPrimaryTrack(j)-1; cout << "\t"; printSaccid(cout, buffer2); cout << "\n"; } } } if (humdrumQ) { cout << "*-\t*-\t*-\t*-\t*-\t*-\t*-\t*-\n"; } }
void processNotes(HumdrumRecord& record) { NoteEvent note; int pitch = 0; double duration = 0.0; int staccatoQ = 0; int accentQ = 0; int sforzandoQ = 0; int i, j; int notecount = 0; char buffer[128] = {0}; for (i=0; i<record.getFieldCount(); i++) { if ((record.getPrimaryTrack(i) < (int)trackmute.size()) && trackmute[record.getPrimaryTrack(i)]) { continue; } if (record.getExInterpNum(i) == E_KERN_EXINT) { notecount = record.getTokenCount(i); if (strcmp(record[i], ".") == 0) { continue; } for (j=0; j<notecount; j++) { record.getToken(buffer, i, j); if (strchr(buffer, '[')) { // total tied note durations duration = data.getTiedDuration(linenum, i, j); } else { duration = Convert::kernToDuration(buffer); } pitch = Convert::kernToMidiNoteNumber(buffer); // skip rests if (pitch < 0) { continue; } pitch += transpose; // don't play note which is transposed too extremely if (pitch < 0) { continue; } if (pitch > 127) { continue; } // skip tied notes if (strchr(buffer, '_') || strchr(buffer, ']')) { continue; } accentQ = strchr(buffer, '^') == NULL? 0 : 1; sforzandoQ = strchr(buffer, 'z') == NULL? 0 : 1; staccatoQ = strchr(buffer, '\'') == NULL? 0 : 1; note.setChannel(0); note.setKey(pitch); note.setOnTime(t_time); duration = duration * 60000 / tempo / tempoScale; if (shortenQ) { duration -= shortenamount; if (duration < mine) { duration = mine; } } note.setDur((int)duration); if (staccatoQ) { note.setDur((int)(0.5 * note.getDur())); } note.setKey(pitch); if (accentQ) { velocity *= 1.3; } if (sforzandoQ) { velocity *= 1.5; } if (velocity > 127) { velocity = 127; } note.setVelocity(velocity); note.activate(); note.action(eventBuffer); eventBuffer.insert(note); } } } }
int generatePicture(HumdrumFile& infile, Array<PixelRow>& picture, int style) { Array<char> marks; getMarkChars(marks, infile); PixelColor matchcolor(255,255,255); infile.analyzeRhythm("4"); int min = infile.getMinTimeBase(); double totaldur = infile.getTotalDuration(); int columns = (int)(totaldur * min / 4.0 + 0.5) + 5; if (columns > 50000) { cout << "Error: picture will be too big to generate" << endl; exit(1); } int factor = (int)(maxwidth / columns); if (factor <= 0) { factor = 1; } if (factor > maxfactor) { factor = maxfactor; } // set picture to black first. Black regions will be filled in // with the background later. picture.setSize(128); int i, j, k; PixelColor backcolor(bgcolor); for (i=0; i<picture.getSize(); i++) { picture[i].setSize(columns * factor); for (j=0; j<picture[i].getSize(); j++) { picture[i][j] = backcolor; // picture[i][j].setRed(0); // picture[i][j].setGreen(0); // picture[i][j].setBlue(0); } } // examine metric levels for metric coloration Array<int>rhylev; infile.analyzeMetricLevel(rhylev); for (i=0; i<rhylev.getSize(); i++) { // reverse sign so that long notes are positive. rhylev[i] = -rhylev[i]; } PixelColor color; int minpitch = 128; int maxpitch = -1; int pitch = 0; double duration = 0; double start = 0; char buffer[1024] = {0}; for (i=0; i<infile.getNumLines(); i++) { if (debugQ) { cout << "Processing input line " << i + 1 << '\t' << infile[i] << endl; } if (infile[i].isData()) { start = infile[i].getAbsBeat(); for (j=0; j<infile[i].getFieldCount(); j++) { if (strcmp(infile[i].getExInterp(j), "**kern") != 0) { continue; } // duration = Convert::kernToDuration(infile[i][j]); duration = infile.getTiedDuration(i, j); color = makeColor(infile, i, j, style, rhylev, infile[i].getPrimaryTrack(j)); for (k=0; k<infile[i].getTokenCount(j); k++) { infile[i].getToken(buffer, j, k); if (strchr(buffer, '_') != NULL) { continue; } if (strchr(buffer, ']') != NULL) { continue; } pitch = Convert::kernToMidiNoteNumber(buffer); if (pitch < 0) { // ignore rests continue; } if (pitch < minpitch) { minpitch = pitch; } if (pitch > maxpitch) { maxpitch = pitch; } if (isMatch(marks, buffer)) { placeNote(picture, pitch, start, duration, min, color, factor, 1); } else { placeNote(picture, pitch, start, duration, min, color, factor, 0); } } } } } gmaxpitch = maxpitch; gminpitch = minpitch; return factor; }
void printOutput(HumdrumFile& hfile) { Array<double> tempo; hfile.analyzeTempoMarkings(tempo, tdefault); double currentmillisecond = 0.0; double lastduration = 0.0; double endmillisecond; int i, j, k; char buffer1[1024] = {0}; char buffer2[1024] = {0}; double duration; for (i=0; i<hfile.getNumLines(); i++) { currentmillisecond = currentmillisecond + lastduration * 60000.0 / tempo[i]; lastduration = hfile[i].getDuration(); if (hfile[i].getType() == E_humrec_global_comment) { cout << "Comment\t" << &(hfile[i].getLine()[3]) << endl; } if (hfile[i].getType() == E_humrec_bibliography) { cout << "Reference " << &(hfile[i].getLine()[3]) << endl; } if (hfile[i].getType() == E_humrec_interpretation) { for (j=0; j<hfile[i].getFieldCount(); j++) { if (hfile[i].getExInterpNum(j) != E_KERN_EXINT) { continue; } int direction = 0; int acount = 0; if (strncmp(hfile[i][j], "*k[", 3) == 0) { if (strchr(hfile[i][j], '-') != NULL) { direction = -1; } else if (strchr(hfile[i][j], '#') != NULL) { direction = 1; } acount = (strlen(hfile[i][j]) - 4)/2; if (direction == 0) { cout << "Info keysig no accidentals" << endl; break; } else { cout << "Info keysig " << acount; if (acount < 0) { cout << " flat"; } else { cout << " sharp"; } if (acount > 1) { cout << "s"; } cout << endl; break; } } } } // look for key interpretations if (hfile[i].getType() == E_humrec_interpretation) { for (j=0; j<hfile[i].getFieldCount(); j++) { if (hfile[i].getExInterpNum(j) != E_KERN_EXINT) { continue; } int length = strlen(hfile[i][j]); if (length < 3 || length > 4) { continue; } if (hfile[i][j][length-1] == ':') { cout << "Info key "; cout << (char)toupper(hfile[i][j][1]); if (hfile[i][j][2] == '-') { cout << "-flat"; } if (hfile[i][j][2] == '#') { cout << "-sharp"; } if (std::islower(hfile[i][j][1])) { cout << " Minor"; } else { cout << " Major"; } cout << endl; break; } } } // look for tempo markings if (hfile[i].getType() == E_humrec_interpretation) { for (j=0; j<hfile[i].getFieldCount(); j++) { if (hfile[i].getExInterpNum(j) != E_KERN_EXINT) { continue; } double tempomark = 0.0; if (strncmp(hfile[i][j], "*MM", 3) == 0 && std::isdigit(hfile[i][j][3])) { sscanf(hfile[i][j], "*MM%lf", &tempomark); cout << "Info Tempo " << tempomark << " MM per quarter note" << endl; break; } } } if (hfile[i].getType() != E_humrec_data) { continue; } for (j=0; j<hfile[i].getFieldCount(); j++) { if (hfile[i].getExInterpNum(j) != E_KERN_EXINT) { continue; } for (k=0; k<hfile[i].getTokenCount(j); k++) { if (strcmp(hfile[i][j], ".") == 0) { continue; } hfile[i].getToken(buffer1, j, k); if (strchr(buffer1, '_') != NULL) { // ignore notes which are tied continue; } if (strchr(buffer1, ']') != NULL) { // ignore notes which are tied continue; } preparePitch(buffer2, buffer1); duration = hfile.getTiedDuration(i, j, k); int note = Convert::kernToMidiNoteNumber(buffer2); if (classQ) { note = note % 12; } if (note < 0) { // don't display rests. continue; } cout << "Note\t"; // cout << hfile.getAbsBeat(i) << "\t"; cout << (int)(currentmillisecond+0.5) << "\t"; // cout << duration << "\t"; endmillisecond = currentmillisecond + duration * 60000 / tempo[i]; if (int(endmillisecond+0.5) == int(currentmillisecond+0.5)) { // give grace notes 1 millisecond duration... cout << (int)(endmillisecond+0.5)+1 << "\t"; } else { cout << (int)(endmillisecond+0.5) << "\t"; } cout << note; cout << "\n"; } } } }