double getMeasureSize(HumdrumFile& infile, int width) { int i; int bar = -100; int lastbar = -1000; int line = -100; int lastline = -1000; int number; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isMeasure()) { continue; } if (sscanf(infile[i][0], "=%d", &number)) { bar = number; line = i; if (bar == lastbar + 1) { return (infile[line].getAbsBeat() - infile[lastline].getAbsBeat()) / infile.getTotalDuration() * width; } else { lastbar = bar; lastline = line; } } } return 5; }
void getNotes(Array<NoteUnit>& 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<infile.getNumLines(); i++) { if (!infile[i].isData()) { continue; } for (j=0; j<infile[i].getFieldCount(); j++) { if (strcmp("**kern", infile[i].getExInterp(j)) != 0) { continue; } tokencount = infile[i].getTokenCount(j); track = infile[i].getPrimaryTrack(j); for (k=0; k<tokencount; k++) { infile[i].getToken(buffer, j, k); if (strcmp(buffer, ".") == 0) { continue; } if (strchr(buffer, '_') != NULL) { continue; } if (strchr(buffer, ']') != NULL) { continue; } tempnote.pitch = Convert::kernToBase40(buffer); if (restQ == 0 && tempnote.pitch < 0) { continue; } if (distQ) { dice = throwDice((double)infile[i].getAbsBeat()/ infile.getTotalDuration()); if (!dice) { continue; } } tempnote.line = i; tempnote.spine = j; tempnote.token = k; tempnote.track = track; notes.append(tempnote); } } } }
void loadHistograms(Array<Array<double> >& histograms, HumdrumFile& infile, int segments) { infile.analyzeRhythm("4"); double totalduration = infile.getTotalDuration(); double duration; int i; int j; int k; char buffer[10000] = {0}; int pitch; double start; int tokencount; for (i=0; i<infile.getNumLines(); i++) { if (infile[i].getType() != E_humrec_data) { continue; } start = infile[i].getAbsBeat(); for (j=0; j<infile[i].getFieldCount(); j++) { if (strcmp(infile[i].getExInterp(j), "**kern") != 0) { continue; } if (strcmp(infile[i][j], ".") == 0) { continue; // ignore null tokens } tokencount = infile[i].getTokenCount(j); for (k=0; k<tokencount; k++) { infile[i].getToken(buffer, j, k); if (strcmp(buffer, ".") == 0) { continue; // ignore illegal inline null tokens } pitch = Convert::kernToMidiNoteNumber(buffer); if (pitch < 0) { continue; // ignore rests or strange objects } pitch = pitch % 12; // convert to chromatic pitch-class duration = Convert::kernToDuration(buffer); if (duration <= 0.0) { continue; // ignore grace notes and strange objects } addToHistogramDouble(histograms, pitch, start, duration, totalduration, segments); } } } }
void getLocations(Array<double>& measures, HumdrumFile& infile, int segments) { infile.analyzeRhythm("4"); double totaldur = infile.getTotalDuration(); measures.setSize(segments); measures.allowGrowth(0); measures.setAll(-1); int barnum = 0; int index; int i; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isMeasure()) { continue; } if (sscanf(infile[i][0], "=%d", &barnum) == 1) { index = int(infile[i].getAbsBeat() / totaldur * segments); measures[index] = barnum; } } for (i=1; i<segments; i++) { if (measures[i] < 0) { measures[i] = measures[i-1]; } } index = -1; for (i=0; i<segments; i++) { if (measures[i] != -1) { index = i - 1; break; } } if (index < 0) { return; } if (index >= segments) { return; } for (i=index; i>=0; i--) { measures[i] = measures[index+1] - 1; } }
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 convertMeasureToXML(HumdrumFile& hfile, int line, int spine) { int measureno = -1; if (!musicstart) { return; } updateAccidentals(); const char *ptr; if (strcmp(hfile[line][spine], "==") == 0 || strcmp(hfile[line+1][0], "*-") == 0) { checkbackup(); lev++; pline(lev, "<barline>\n"); lev++; pline(lev, "<bar-style>light-heavy</bar-style>\n"); lev--; pline(lev, "</barline>\n"); lev--; pline(lev, "</measure>\n"); measurestate = 0; } else if ((ptr = strchr(hfile[line][spine], ':')) != NULL) { if ((ptr+1)[0] == '|' || (ptr+1)[0] == '!') { lev++; pline(lev, "<barline>\n"); lev++; if (strstr(hfile[line][spine], ":|!") != NULL) { pline(lev, "<bar-style>light-heavy</bar-style>\n"); } else if (strstr(hfile[line][spine], ":||") != NULL) { pline(lev, "<bar-style>light-light</bar-style>\n"); } else if (strstr(hfile[line][spine], ":!") != NULL) { pline(lev, "<bar-style>heavy</bar-style>\n"); } else if (strstr(hfile[line][spine], ":|") != NULL) { pline(lev, "<bar-style>light</bar-style>\n"); } pline(lev, "<repeat direction=\"backward\"/>\n"); lev--; pline(lev, "</barline>\n"); lev--; } } else if (strstr(hfile[line][spine], "||") != NULL) { checkbackup(); lev++; pline(lev, "<barline>\n"); lev++; pline(lev, "<bar-style>light-light</bar-style>\n"); lev--; pline(lev, "</barline>\n"); lev--; } if (strcmp(hfile[line+1][0], "*-") == 0) { return; } checkbackup(); if (minit != 0) { if (measurestate != 0) { pline(lev, "</measure>\n"); measurestate = 0; } } minit++; if (sscanf(hfile[line][spine], "=%d", &measureno)) { pline(lev, "<measure number=\""); cout << minit << "\">\n"; measurestate = 1; } else if (strncmp(hfile[line][spine], "=", 1) == 0) { if (hfile.getTotalDuration() > hfile[line].getAbsBeat()) { // don't start a new measure if we are at the end of the music pline(lev, "<measure number=\""); cout << minit << "\">\n"; measurestate = 1; } } if ((ptr = strchr(hfile[line][spine], ':')) != NULL) { if ((ptr-1)[0] == '|' || (ptr-1)[0] == '!') { lev++; pline(lev, "<barline>\n"); lev++; if (strstr(hfile[line][spine], ":|!") != NULL) { pline(lev, "<bar-style>light-heavy</bar-style>\n"); } else if (strstr(hfile[line][spine], ":||") != NULL) { pline(lev, "<bar-style>light-light</bar-style>\n"); } else if (strstr(hfile[line][spine], ":!") != NULL) { pline(lev, "<bar-style>heavy</bar-style>\n"); } else if (strstr(hfile[line][spine], ":|") != NULL) { pline(lev, "<bar-style>light</bar-style>\n"); } pline(lev, "<repeat direction=\"forward\"/>\n"); lev--; pline(lev, "</barline>\n"); lev--; } } }
void analyzeContinuously(HumdrumFile& infile, int windowsize, double stepsize, double* majorKey, double* minorKey) { Array<Array<double> > segments; infile.analyzeRhythm("4"); int segmentCount = int(infile.getTotalDuration() / stepsize + 0.5); if (segmentCount < windowsize) { cout << "Not enough data for requested analysis" << endl; return; } segments.setSize(segmentCount); segments.allowGrowth(0); int i; for (i=0; i<segments.getSize(); i++) { segments[i].setSize(12); segments[i].allowGrowth(0); segments[i].setAll(0); } loadHistograms(segments, infile, segmentCount); if (debugQ) { printHistogramTotals(segments); } Array<Array<double> > pitchhist; Array<Array<double> > correlations; pitchhist.setSize(segmentCount-windowsize); correlations.setSize(segmentCount-windowsize); pitchhist.allowGrowth(0); correlations.allowGrowth(0); for (i=0; i<segmentCount-windowsize; i++) { pitchhist[i].setSize(13); //last spot for best key pitchhist[i].allowGrowth(0); correlations[i].setSize(24); correlations[i].allowGrowth(0); } for (i=0; i<segmentCount - windowsize; i++) { createHistogram(pitchhist[i], i, windowsize, segments); identifyKeyDouble(pitchhist[i], correlations[i], majorKey, minorKey); } Array<double> measures; getLocations(measures, infile, segmentCount); cout << "**key\t**rval\t**conf\t**start\t**mid\t**end\n"; for (i=0; i<pitchhist.getSize(); i++) { printBestKey(int(pitchhist[i][12] + 0.5)); cout << "\t"; printCorrelation(correlations[i][int(pitchhist[i][12]+ 0.1)], roundQ); cout << "\t"; cout << getConfidence(correlations[i], int(pitchhist[i][12]+0.1)); cout << "\t"; cout << "=" << measures[i]; cout << "\t"; cout << "=" << int((measures[i] + measures[i+windowsize])/2+0.49); cout << "\t"; cout << "=" << measures[i+windowsize]; cout << endl; } cout << "*-\t*-\t*-\t*-\t*-\t*-\n"; }
void printBarlines(HumdrumFile& infile, int numberheight, int numberwidth) { int i, j; Array<Array<int> > xaxis; xaxis.setSize(numberheight-1); xaxis.allowGrowth(0); for (i=0; i<xaxis.getSize(); i++) { xaxis[i].setSize(numberwidth); xaxis[i].allowGrowth(0); xaxis[i].setAll(24); } // bar counter keeps track of multiple repeats of the same // music. Array<int> barcount(10000); barcount.allowGrowth(0); barcount.setAll(0); double measuresize = getMeasureSize(infile, numberwidth); int size; int style = 0; int position; int number; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isMeasure()) { continue; } size = 0; position = -1; if (sscanf(infile[i][0], "=%d", &number)) { if ((number >= 0) && (number < barcount.getSize())) { style = barcount[number]; barcount[number]++; } else { style = 0; } position = int(numberwidth * infile[i].getAbsBeat() / infile.getTotalDuration() + 0.5); if ((number % 100) == 0) { size = 10; } else if ((number % 50) == 0) { size = 8; } else if ((number % 10) == 0) { size = 6; } else if ((number % 5) == 0) { size = 4; } else { size = 2; if (measuresize < 3) { // don't display single measure ticks if they // are too closely spaced size = 0; } } } int color; if ((position >= 0) && (size > 0)) { for (j=0; j<size; j++) { if (style == 0) { color = 25; } else if (style == 1) { color = 4; // red (in default color) } else if (style == 2) { color = 2; // blue (in default color) } else if (style == 3) { color = 0; // green (in default color) } else { color = 11; // orange (in default color) } xaxis[j][position] = color; if (j==9) { if (position>0) { xaxis[j][position-1] = color; } if (position<xaxis[0].getSize()-1) { xaxis[j][position+1] = color; } } } } } // print a empty line so that small measure markers can be seen for (i=0; i<xaxis[0].getSize(); i++) { cout << ' ' << colorindex[24]; } cout << '\n'; for (i=0; i<xaxis.getSize(); i++) { for (j=0; j<xaxis[i].getSize(); j++) { cout << ' ' << colorindex[xaxis[i][j]]; } cout << '\n'; } }
void printTriadImage(HumdrumFile& infile, int rows, int cols) { Array<ChordQuality> cq; infile.analyzeSonorityQuality(cq); infile.analyzeRhythm("4"); Array<Array<int> > triads; triads.setSize(3); triads[0].setSize(cols); triads[0].setAll(24); triads[1].setSize(cols); triads[1].setAll(24); triads[2].setSize(cols); triads[2].setAll(24); colorindex[0] = "0 255 0"; // C major colorindex[1] = "38 255 140"; // C-sharp major colorindex[2] = "63 95 255"; // D major colorindex[3] = "228 19 83"; // E-flat major colorindex[4] = "255 0 0"; // E major colorindex[5] = "255 255 0"; // F major colorindex[6] = "192 255 0"; // F-sharp major colorindex[7] = "93 211 255"; // G major colorindex[8] = "129 50 255"; // A-flat major colorindex[9] = "205 41 255"; // A major colorindex[10] = "255 160 0"; // B-flat major colorindex[11] = "255 110 10"; // B major colorindex[12] = "0 161 0"; // C minor colorindex[13] = "15 191 90"; // C-sharp minor colorindex[14] = "37 61 181"; // D minor colorindex[15] = "184 27 75"; // E-flat minor colorindex[16] = "175 0 0"; // E minor colorindex[17] = "220 200 0"; // F minor colorindex[18] = "140 200 0"; // F-sharp minor colorindex[19] = "65 163 181"; // G minor colorindex[20] = "100 28 181"; // G-sharp minor colorindex[21] = "136 13 181"; // A minor colorindex[22] = "181 93 20"; // B-flat minor colorindex[23] = "211 107 0"; // B minor colorindex[24] = "255 255 255"; // background colorindex[25] = "0 0 0"; // silence double start; double end; int inversion; int starti; int endi; int minQ; int majQ; int i, m, j, ii; int rootindex; for (i=0; i<infile.getNumLines(); i++) { if (!infile[i].isData()) { continue; } if (strcmp(cq[i].getTypeName(), "min") == 0) { minQ = 1; } else { minQ = 0; } if (strcmp(cq[i].getTypeName(), "maj") == 0) { majQ = 1; } else { majQ = 0; } if (!(majQ || minQ)) { continue; } start = infile[i].getAbsBeat(); end = start + infile[i].getDuration(); starti = int(start / infile.getTotalDuration() * cols + 0.5); endi = int(end / infile.getTotalDuration() * cols + 0.5); if (starti < 0) { starti = 0; } if (endi < 0) { endi = 0; } if (starti >= cols) { starti = cols-1; } if (endi >= cols) { endi = cols-1; } rootindex = Convert::base40ToMidiNoteNumber(cq[i].getRoot()); if (minQ) { rootindex += 12; } inversion = cq[i].getInversion(); for (ii=starti; ii<=endi; ii++) { triads[inversion][ii] = rootindex; } } int barheight = 0; int barwidth = 0; if (barlinesQ) { barheight = 11; barwidth = cols; } int legendheight = 0; int legendwidth = 0; if (legendQ) { legendheight = 100; legendwidth = cols; } int value = 24; Matrix<int> image(rows*2, cols, value); for (i=triads.getSize()-1; i>=0; i--) { int start = int(i/2.0 * rows); for (m=0; m<rows; m++) { ii = (int)(m + start); if (ii >= image.getRowCount()) { ii = image.getRowCount() - 1; } for (j=0; j<triads[i].getSize(); j++) { if (triads[i][j] < 24) { image.cell(ii,j) = triads[i][j]; } // cout << colorindex[triads[i][j]] << " "; //cout << triads[i][j] << " "; } //cout << "\n"; } } // print Image: cout << "P3\n"; cout << cols << " " << rows*2 + barheight + legendheight << "\n"; cout << "255\n"; for (i=image.getRowCount()-1; i>=0; i--) { for (j=0; j<image.getColumnCount(); j++) { cout << colorindex[image.cell(i,j)] << ' '; } cout << "\n"; } if (barlinesQ) { printBarlines(infile, barheight, barwidth); } if (legendQ) { printLegend(legendheight, legendwidth); } }