Example #1
0
void prepareChordSet(Array<Array<char> >& names, Array<Array<int> >& chordset) {
   SSTREAM stream;
   stream << "!! Column 1: Root of the chord\n";
   stream << "!! Column 2: Other notes in the chord\n";
   stream << "!! Column 3: Notated chord symbol\n";
   stream << "!! Column 4: Full chord name\n";
   stream << "!!  substitutes with pitch in first column\n";
   stream << "**kern\t**kern\t**label\t**name\n";
   stream << "!root\t!others\t!\t!\n";
   stream << "4C\t4e 4g\t.\tMajor\n";
   stream << "4C\t4e- 4g\tm\tMinor\n";
   stream << "4C\t4e 4g#\t+\tAugmented Triad\n";
   stream << "4C\t4f 4g\tsus4\tSuspended 4th\n";
   stream << "4C\t4e- 4g-\to\tDiminished Triad\n";
   stream << "4C\t4e 4g 4a\t6\tMajor 6th\n";
   stream << "4C\t4e- 4g 4a\tm6\tMinor 6th\n";
   stream << "4C\t4e 4g 4b\tmaj7\tMajor 7th\n";
   stream << "4C\t4e- 4g 4b-\tm7\tMinor 7th\n";
   stream << "4C\t4e 4g 4b-\t7\tDominant 7th\n";
   stream << "4C\t4f 4g 4b-\t7sus4\tDominant 7th sus4\n";
   stream << "4C\t4e 4g# 4b-\t7+5\tDominant 7th Augmented 5th\n";
   stream << "4C\t4e 4g- 4b-\t7-5\tDominant 7th Flattened 5th\n";
   stream << "4C\t4e- 4g- 4b--\tdim7\tDiminished 7th\n";
   stream << "4C\t4e- 4g- 4b-\tm7-5\tMinor 7th Flattened 5th\n";
   stream << "4C\t4e- 4g 4b\tmmaj7\tMinor-Major 7th\n";
   stream << "4C\t4e 4g 4b 4dd\tmaj9\tMajor 9th\n";
   stream << "4C\t4e- 4g 4b- 4dd\tm9\tMinor 9th\n";
   stream << "4C\t4e 4g 4b- 4dd\t9\tDominant 9th\n";
   stream << "4C\t4e 4g# 4b- 4dd\t9+5\t9th Augmented 5th\n";
   stream << "4C\t4e 4g- 4b- 4dd\t9-5\t9th Flattened 5th\n";
   stream << "4C\t4e 4g 4a 4b- 4dd\t9/6\t9th Add 6th\n";
   stream << "4C\t4e 4g 4b 4dd 4ff\tmaj11\tMajor 11th\n";
   stream << "4C\t4e- 4g 4b- 4dd 4ff\tm11\tMinor 11th\n";
   stream << "4C\t4e 4g 4b- 4dd 4ff\t11\tDominant 11th\n";
   stream << "4C\t4e 4g 4b- 4dd- 4ff\t11-9\t11th Flattened 9th\n";
   stream << "4C\t4e 4g 4b 4dd 4ff 4aa\tmaj13\tMajor 13th\n";
   stream << "4C\t4e- 4g 4b- 4dd 4ff 4aa\tm13\tMinor 13th\n";
   stream << "4C\t4e 4g 4b- 4dd 4ff 4aa\t13\tDominant 13th\n";
   stream << "4C\t4e 4g 4b- 4dd- 4ff 4aa\t13-9\t13th Flattened 9th\n";
   stream << "*-\t*-\t*-\t*-\n";

   stream << ends;

   HumdrumFile infile;
   infile.read(stream);
   chordset.setSize(infile.getNumLines());
   chordset.setSize(0);

   names.setSize(infile.getNumLines());
   names.setSize(0);

   int index;
   int length;
   int i;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() != E_humrec_data) {
         continue;
      }
      index = chordset.getSize();
      chordset.setSize(chordset.getSize() + 1);
      names.setSize(names.getSize() + 1);
      length = strlen(infile[i][2]);
      names[index].setSize(length+1);
      strcpy(names[index].getBase(), infile[i][2]);
      if (names[index][0] == '.') {
         names[index][0] = '\0';	        
      }
      storeChordData(chordset[index], infile, i);
      

   }
   chordset.allowGrowth(0);
}
Example #2
0
void createMidiFile(MidiFile& midifile, HumdrumFile& infile) {

   Array<int>    millitimes;
   Array<double> velocities;
   Array<int>    keynum;
   Array<int>    track;

   millitimes.setSize(infile.getNumLines());
   velocities.setSize(infile.getNumLines());
   keynum.setSize(infile.getNumLines());
   track.setSize(infile.getNumLines());

   millitimes.setSize(0);
   velocities.setSize(0);
   keynum.setSize(0);
   track.setSize(0);

   int    intval;
   double floatval;
   double dmax = -100000;
   double dmin = +100000;

   int i;
   for (i=0; i<infile.getNumLines(); i++) {
      if (!infile[i].isData()) {
         continue;
      }
      sscanf(infile[i][0], "%lf", &floatval);
      intval = int(floatval * 1000.0 + 0.5);
      millitimes.append(intval);

      sscanf(infile[i][1], "%lf", &floatval);
      velocities.append(floatval);
      if (floatval < dmin) { dmin = floatval; }
      if (floatval > dmax) { dmax = floatval; }

      intval = getMIDIKeyNum(infile[i][2]);
      keynum.append(intval);

      intval = getTrackNumber(infile[i][2]);
      track.append(intval);
   }
   millitimes.allowGrowth(0);
   velocities.allowGrowth(0);
   keynum.allowGrowth(0);
   track.allowGrowth(0);

   // normalize the dynamics data into the range from 0 to 1
   double diff = dmax - dmin;
   for (i=0; i<velocities.getSize(); i++) {
      if (diff > 0.0) {
         velocities[i] = (velocities[i] - dmin) / diff;
      } else {
         velocities[i] = 0.5;
      }
   }


   // now ready to write the data to the MIDI file:

   midifile.setMillisecondDelta();   // SMPTE 25 frames & 40 subframes
   midifile.absoluteTime();          // Time values inserted are absolute
   midifile.addTrack(2);             // Right and Left hands

   Array<uchar> event;
   event.setSize(3);

   int intdur  = int(duration * 1000.0 + 0.5);
   int lasttime = 0;
   int dyndiff = maxdyn - mindyn;
   int vel;
   for (i=0; i<millitimes.getSize(); i++) {
      if ((keynum[i] <= 10) || (keynum[i] > 127)) {
         continue;
      }
      vel = int(velocities[i] * dyndiff + mindyn + 0.5);
      if (vel < 1) { vel = 1; }
      if (vel > 127) { vel = 127; }

      event[0] = 0x90; // note-on
      event[1] = keynum[i];
      event[2] = vel;
      midifile.addEvent(track[i], millitimes[i], event);
      event[2] = 0;
      lasttime = millitimes[i] + intdur;
      midifile.addEvent(track[i], lasttime, event);
   }

   // write the end of track marker
   event[0] = 0xff;
   event[1] = 0x2f;
   event[2] = 0;
   for (i=0; i<midifile.getTrackCount(); i++) {
	
      if (i>0) {
         // have to lengthen the last note in track due to bugs
         // in various MIDI playback programs which clip
         // the last chord of a file
         midifile.getEvent(i, midifile.getNumEvents(i)-1).time += 1500;
      }
      midifile.addEvent(i, lasttime+2000, event);
   }

   // add comments from header
   for (i=0; i<infile.getNumLines() && i<lasttime; i++) {
      if (infile[i].isBibliographic() || infile[i].isGlobalComment()) {
         // 0x01 is a text event
         midifile.addMetaEvent(0, i, 0x01, infile[i].getLine());
      }
   }

   // sort the ontimes and offtimes so they are in correct time order:
   midifile.sortTracks();

}
Example #3
0
void processDynamicSpine(HumdrumFile& infile, int track) {
   Array<Array<Coord> > data;
   storeDynamSpine(data, infile, track);
   int i;
   int ii, jj;
   int crescX       = 0;  // interpreted crescendo (cresc. word)
   int decrescX     = 0;  // interpreted decrescendo (decresc. word)
   int crescy       = 0;  // hidden crescendo
   int decrescy     = 0;  // hidden decrescendo
   int crescState   = 0;  // active crescendo
   int decrescState = 0;  // active decrescendo
   char buffer[1024] = {0};
   Array<char> buf;
   PerlRegularExpression pre;

   int xx, yy;

   if (debugQ) {
      cerr << "DATA SIZE = " << data.getSize() << endl;
   }

   for (i=0; i<data.getSize(); i++) {
      ii = data[i][0].i;
      jj = data[i][0].j;

      if (debugQ) {
         cerr << "PROCESSING I = " << i << " " << infile[ii][jj] << endl;
      }
      if (crescState) {
         if (debugQ) {
            cerr << "\tACTIVE CRESC" << endl;
         }
         // if currently a crescendo, then either continue or end
         if (strcmp(infile[ii][jj], ".") == 0) {
            // convert "." to "(" to continue the crescendo
            if (debugQ) {
               cerr << "\tChanging . to (" << endl;
            }
            strcpy(buffer, "(");
            if (crescX) {
               strcat(buffer, "X");
            }
            if (crescy) {
               strcat(buffer, "yy");
            }
            infile[ii].changeField(jj, buffer);
         } else {
            // end the crescendo
            xx = data[i-1][0].i;
            yy = data[i-1][0].j;
            if (debugQ) {
               cerr << "GOT HERE " << infile[xx][yy] << endl;
            }
            if ((xx < 0) || (yy < 0)) {
               continue;
            }
            // this is a dynamic object of some sort so terminate
            // the crescendo on the previous item
            if (strchr(infile[xx][yy], '(') != NULL) {
               if (debugQ) {
                  cerr << "GOT HERE " << infile[xx][yy] << endl;
               }
               // replace the '(' found on the previous data line
               buf.setSize(strlen(infile[xx][yy])+1);
               strcpy(buf.getBase(), infile[xx][yy]);
               pre.sar(buf, "\\(", "[", "");  // should only apply to last 
               if (crescX) {
                  pre.sar(buf, "\\[", "[", "");
                  crescX = 0;
               }
               if (crescy) {
                  pre.sar(buf, "\\[", "[", "");
                  crescy = 0;
               }
               infile[xx].changeField(yy, buf.getBase());
               crescState = 0;
               if (debugQ) {
                  cerr << "DEACTIVATING CRESC 1" << endl;
               }
            } else {
               // there is something other than ( on the last line:
               // append " ["
               strcpy(buffer, infile[xx][yy]);
               strcat(buffer, " [");
               //if (crescy) { 
               //   strcat(buffer, "yy");
               //   crescy = 0;
               //} if (crescX) { 
               //   strcat(buffer, "X");
               //   crescX = 0;
               //}
               infile[xx].changeField(yy, buffer);
               crescState = 0;
               if (debugQ) {
                  cerr << "DEACTIVATING CRESC 2" << endl;
               }
            }
         }

      } else if (decrescState) {

         // if currently a decrescendo, then either continue or end
         if (strcmp(infile[ii][jj], ".") == 0) {
            // convert "." to "(" to continue the decrescendo
            strcpy(buffer, ")");
            if (decrescX) {
               strcat(buffer, "X");
            }
            if (decrescy) {
               strcat(buffer, "yy");
            }
            infile[ii].changeField(jj, buffer);
         } else {
            // end the decrescendo
            xx = data[i-1][0].i;
            yy = data[i-1][0].j;
            if ((xx < 0) || (yy < 0)) {
               continue;
            }
            // this is a dynamic object of some sort so terminate
            // the decrescendo on the previous item
            if (strchr(infile[xx][yy], ')') != NULL) {
               // replace the '(' found on the previous data line
               buf.setSize(strlen(infile[xx][yy])+1);
               strcpy(buf.getBase(), infile[xx][yy]);
               pre.sar(buf, "\\)", "]", "");  // should only apply to last 
               //if (decrescX) {
               //   pre.sar(buf, "\\]", "]X", "");
               //   decrescX = 0;
               //}
               //if (decrescy) {
               //   pre.sar(buf, "\\]", "]y", "");
               //   decrescy = 0;
               //}
               infile[xx].changeField(yy, buf.getBase());
               decrescState = 0;
            } else {
               // there is something other than ( on the last line:
               // append " ["
               strcpy(buffer, infile[xx][yy]);
               strcat(buffer, " ]");
               if (decrescy) { 
                  strcat(buffer, "yy");
                  decrescy = 0;
               } if (decrescX) { 
                  strcat(buffer, "X");
                  decrescX = 0;
               }
               infile[xx].changeField(yy, buffer);
               decrescState = 0;
            }
         }

      } 

      // search for < or > marker to initiate de/cresc.
      if (strchr(infile[ii][jj], '<')  != NULL) { crescState   = 1; }
      if (strchr(infile[ii][jj], '>')  != NULL) { decrescState = 1; }
      if (strstr(infile[ii][jj], "<X") != NULL) { crescX       = 1; }
      if (strstr(infile[ii][jj], ">X") != NULL) { decrescX     = 1; }
      if (strstr(infile[ii][jj], "<yy") != NULL) { crescy      = 1; }
      if (strstr(infile[ii][jj], ">yy") != NULL) { decrescy    = 1; }
   }


   // handle case where cresc/decresc ends data with nothing after it.
   if (crescState) {

      // end the crescendo
      xx = data.last()[0].i;
      yy = data.last()[0].j;
      if (debugQ) {
         cerr << "GOT HERE " << infile[xx][yy] << endl;
      }
      if ((xx < 0) || (yy < 0)) {
         return;
      }
      // this is a dynamic object of some sort so terminate
      // the crescendo on the previous item
      if (strchr(infile[xx][yy], '(') != NULL) {
         if (debugQ) {
            cerr << "GOT HERE " << infile[xx][yy] << endl;
         }
         // replace the '(' found on the previous data line
         buf.setSize(strlen(infile[xx][yy])+1);
         strcpy(buf.getBase(), infile[xx][yy]);
         pre.sar(buf, "\\(", "[", "");  // should only apply to last 
         if (crescX) {
            pre.sar(buf, "\\[", "[", "");
            crescX = 0;
         }
         if (crescy) {
            pre.sar(buf, "\\[", "[", "");
            crescy = 0;
         }
         infile[xx].changeField(yy, buf.getBase());
         crescState = 0;
         if (debugQ) {
            cerr << "DEACTIVATING CRESC 1" << endl;
         }
      }

   } else if (decrescState) {

      // end the decrescendo
      xx = data.last()[0].i;
      yy = data.last()[0].j;
      if (debugQ) {
         cerr << "GOT HERE " << infile[xx][yy] << endl;
      }
      if ((xx < 0) || (yy < 0)) {
         return;
      }
      // this is a dynamic object of some sort so terminate
      // the decrescendo on the previous item
      if (strchr(infile[xx][yy], ')') != NULL) {
         if (debugQ) {
            cerr << "GOT HERE " << infile[xx][yy] << endl;
         }
         // replace the '(' found on the previous data line
         buf.setSize(strlen(infile[xx][yy])+1);
         strcpy(buf.getBase(), infile[xx][yy]);
         pre.sar(buf, "\\)", "]", "");  // should only apply to last 
         if (decrescX) {
            pre.sar(buf, "\\]", "]", "");
            decrescX = 0;
         }
         if (decrescy) {
            pre.sar(buf, "\\]", "]", "");
            decrescy = 0;
         }
         infile[xx].changeField(yy, buf.getBase());
         decrescState = 0;
         if (debugQ) {
            cerr << "DEACTIVATING DECRESC 1" << endl;
         }
      }

   }

}
Example #4
0
void doLinearInterpolation(HumdrumFile& infile) {
   infile.analyzeRhythm("4");

   // extract the timing data using -1 for undefined

   Array<double> timings;
   Array<double> absbeat;

   timings.setSize(infile.getNumLines());
   timings.setAll(INVALIDTIME);
   double atime;

   int i, j;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() != E_humrec_data) {
         continue;
      }
      for (j=0; j<infile[i].getFieldCount(); j++) {
         if (strcmp("**time", infile[i].getExInterp(j)) == 0) {
            if (strcmp(infile[i][j], ".") == 0) {
               timings[i] = UNKNOWNTIME;
            } else {
               sscanf(infile[i][j], "%lf", &atime);
               timings[i] = atime;
            }
            break;
         }

      }

   }

   int lasttimeindex = -1;
   for (i=0; i<timings.getSize(); i++) {
      if (timings[i] < 0) {
         continue;
      }

      if (lasttimeindex < 0) {
         lasttimeindex = i;
         continue;
      }

      interpolateTimings(timings, infile, lasttimeindex, i);

      lasttimeindex = i;

   }

   fixendingtimes(timings, infile);

   // now insert the interpolated timings back into the score.
   int tfound = 0;
   for (i=0; i<infile.getNumLines(); i++) {
      if (infile[i].getType() == E_humrec_data) {
         tfound = 0;
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if ((tfound == 0) && 
                (strcmp(infile[i].getExInterp(j), "**time") == 0)) {
               tfound = 1;
               if (timings[i] < 0) { 
                  cout << "0.0";
               } else {
                  cout << timings[i];
               }
            } else {
               cout << infile[i][j];
            }
            if (j < infile[i].getFieldCount() - 1) {
               cout << "\t";
            }
         }
         cout << "\n";
      } else {
         cout << infile[i] << "\n";
      }
   }

}
Example #5
0
void analyzeTiming(HumdrumFile& infile, Array<double>& timings,
      Array<double>& tempo) {
   infile.analyzeRhythm("4");

   timings.setSize(infile.getNumLines());
   timings.setAll(0.0);
   tempo.setSize(infile.getNumLines());
   tempo.setAll(dtempo);
   tempo[0] = dtempo;
   double currtempo = dtempo;
   double input = 0.0;
   int count;
   Array<double> tempoindicators;
   Array<int>    tempoindex;

   tempoindicators.setSize(1000);
   tempoindicators.setSize(0);
   tempoindicators.setGrowth(1000);
   tempoindex.setSize(1000);
   tempoindex.setSize(0);
   tempoindex.setGrowth(1000);

   double ritard = -1.0;
   double accel  = -2.0;

   int i;
   int j;
   for (i=1; i<infile.getNumLines(); i++) {
      // check for new tempo...
      if (infile[i].getType() == E_humrec_interpretation) {
         for (j=0; j<infile[i].getFieldCount(); j++) {
            if (strcmp(infile[i].getExInterp(j), "**kern") != 0) {
               continue;
            }
            if (strncmp(infile[i][j], "*MM", 3) == 0) {
               count = sscanf(infile[i][j], "*MM%lf", &input);
               if (count == 1) {
                  currtempo = input;
                  tempoindicators.append(currtempo);
                  tempoindex.append(i);
                  if (i > 0) {
                     tempo[i-1] = currtempo;
                  }
                  tempo[i] = currtempo;
               }
            } else if (strcmp(infile[i][j], "*accel") == 0) {
               tempoindicators.append(accel);
               tempoindex.append(i);
            } else if (strcmp(infile[i][j], "*rit") == 0) {
               tempoindicators.append(ritard);
               tempoindex.append(i);
            }
            break;
         }
      }

      tempo[i] = currtempo;
      timings[i] = timings[i-1] + (infile[i].getAbsBeat() - 
            infile[i-1].getAbsBeat()) * 60.0/currtempo;

   }

   if (!changeQ) {
      // do not adjust for *rit and *accel markers
      return;
   }

   // go back and geometrically interpolate the tempo markings
   // when there are *accel and *rit markers in the data.

   for (i=1; i<tempoindicators.getSize()-1; i++) {
      if ((tempoindicators[i] < 0) && (tempoindicators[i+1] > 0)) {
         interpolateGeometric(infile, tempo, tempoindex[i], tempoindex[i+1]);
      }
   }


   // the following code will have to be debugged (mostly for off-by-one
   // errors).

   // adjust the timing values
   double beatdiff;
   double increment = 1.0/32.0;
   double starttempo;
   double stoptempo;
   double timesum;
   double logtem1;
   double logtem2;
   double tfraction;
   double ftempo;
   double beatduration;
   int    ntindex;
   double startbeat;
   double stopbeat;

   for (i=1; i<infile.getNumLines(); i++) {
      starttempo   = tempo[i];
      ntindex      = getNextTempoIndex(infile, i);
      stoptempo    = tempo[ntindex];
      
      startbeat    = infile[i-1].getAbsBeat();
      stopbeat     = infile[i].getAbsBeat();
      beatduration = stopbeat - startbeat;
      beatdiff     = beatduration;

      if (starttempo == stoptempo) {
         timings[i] = timings[i-1] + beatduration * 60/tempo[i];
      } else {
         // calculate the time as the tempo changes
         logtem1      = log10(starttempo);
         logtem2      = log10(stoptempo);

         timesum = 0.0;
         while (beatdiff >= increment) {
            tfraction = ((beatduration - beatdiff) / beatduration);
            ftempo = pow(10.0, logtem1 + (logtem2 - logtem1) * tfraction);
            timesum += increment * 60/ftempo;
            beatdiff -= increment;
         }

         if (beatduration > 0.0) {
            tfraction = ((beatduration - beatdiff) / beatduration);
            ftempo = pow(10.0, logtem1 + (logtem2 - logtem1) * tfraction);
            timesum += beatdiff * 60/ftempo;
         } else {
            timesum = 0.0;
         }

         timings[i] = timings[i-1] + timesum;
      }
      
   }
}
Example #6
0
int identifyBassNote(SigCollection<int>& notes, HumdrumFile& infile, 
      int line, Array<int>& sounding) {
   int j, k;
   int output = -1;
   int minval = 1000000;
   int value;
   int tcount;
   char buffer[128] = {0};

   Array<int> soundQ(40);
   soundQ.setAll(0);

   sounding.setSize(notes.getSize());
   sounding.setAll(0);

   int pline;
   int pspine;

   int dotQ = 0;

   if (notes.getSize() == 0) {
      return -1;
   }

   for (j=0; j<infile[line].getFieldCount(); j++) {
      if (!infile[line].isExInterp(j, "**kern")) {
         continue;
      }
      dotQ = 0;
      if (strcmp(infile[line][j], ".") == 0) {
         pline  = infile[line].getDotLine(j);
         pspine = infile[line].getDotSpine(j);
         dotQ = 1;
      } else {
         pline = line;
         pspine = j;
      }
      tcount = infile[pline].getTokenCount(pspine);
      for (k=0; k<tcount; k++) {
         infile[pline].getToken(buffer, pspine, k);
         if (strchr(buffer, 'r') != NULL) {
            continue;
         }
	 if (strcmp(buffer, ".") == 0) {
            // shouldn't get here...
            continue;
         }
	 value = Convert::kernToMidiNoteNumber(buffer);
         if (value < 0) {
            continue;
         }
         if (value < minval) {
            minval = value;
         }
         if (dotQ) {
            continue;
         }
         if (strchr(buffer, '_') != NULL) {
            continue;
         }
         if (strchr(buffer, ']') != NULL) {
            continue;
         }
	 value = Convert::kernToBase40(buffer);
         if (value < 0) {
            continue;
         }
         soundQ[value % 40] = 1;
      }
   }

   if (minval > 100000) {
      return -1;
   }

   minval = minval % 12;
   int i;
   int tval;
   for (i=0; i<notes.getSize(); i++) {
      if (notes[i] >= 0) {
         if (soundQ[notes[i]%40]) {
            sounding[i] = 1;
         }
      }
      tval = Convert::base40ToMidiNoteNumber(notes[i]);
      if (tval < 0) {
         continue;
      }
      tval = tval % 12;
      if (tval == minval) {
         output = i;
         // break;  need to supress this because of sounding tests
      }
   }
   return output;
}
Example #7
0
void printLegend(int legendheight, int legendwidth) {
   Array<Array<int> > legend;
   legend.setSize(legendheight);
   legend.allowGrowth(0);
   int i, j;
   for (i=0; i<legend.getSize(); i++) {
      legend[i].setSize(legendwidth);
      legend[i].allowGrowth(0);
      legend[i].setAll(24);  // set to background color
   }


   int startrow = legendheight / 5;
   int endrow   = legendheight - 1;
   int startcol = legendwidth / 5;
   int endcol   = legendwidth - startcol - 1;

   int dooutline = outlineQ;
   if (legendwidth < 100) {   // don't print outline on a small legend
      dooutline = 0;
   }

   Array<int> diatonic(8);
   diatonic.allowGrowth(0);
   diatonic[0] = 0;
   diatonic[1] = 2;
   diatonic[2] = 4;
   diatonic[3] = 5;
   diatonic[4] = 7;
   diatonic[5] = 9;
   diatonic[6] = 11;

   int v, lastv = -1;
   for (i=startrow; i<=endrow; i++) {
      for (j=startcol; j<=endcol; j++) {
         v = diatonic[int((double)(j-startcol)/(endcol-startcol+1)*7)]; 
         if (dooutline && ((v != lastv) || 
               (j == endcol) || (i==startrow) || (i==endrow))) {
            legend[i][j] = 25;
         } else if (i > (endrow + startrow)/2) {  // major keys
            legend[i][j] = v;
         } else {                          // minor keys
            legend[i][j] = v+12;
         }
         lastv = v;
      }
   }

   int blackkeyheight = 2 * (endrow - startrow) / 3;
   int blackend = startrow + blackkeyheight;

   int blackstartcol = startcol;
   int blackendcol   = endcol;
   blackstartcol = blackstartcol + (endcol - startcol) / 96;

   lastv = 0;
   for (i=startrow; i<=blackend; i++) {
      for (j=blackstartcol; j<=blackendcol; j++) {
	 v = int((double)(j-blackstartcol)/(blackendcol-blackstartcol+1)*12);
	 if ((v != lastv) || (i==startrow)) {
            if ((v != 0) && (v != 5)) {
               legend[i][j] = 25;
            }
	    lastv = v;
	    continue;
         }
	 if (!((v==1)||(v==3)||(v==6)||(v==8)||(v==10))) {
            continue;
         }
	 if ((i==blackend)) {
            legend[i][j] = 25;
         } else if (i > (blackend + startrow)/2) {  // major keys
            legend[i][j] = v;
         } else {                          // minor keys
            legend[i][j] = v+12;
         }
	 lastv = v;
      }
   }

   Array<const char*> transcolor;
   transcolor.setSize(26);
   transcolor.setAll(0);
   transcolor[24] = colorindex[24];
   transcolor[25] = colorindex[25];
   int transpose = 0;
   int rrotate   = 0;
   for (i=0; i<12; i++) {
      transcolor[i] = colorindex[(i+transpose+rrotate) % 12];
      transcolor[i+12] = colorindex[((i+transpose+rrotate) % 12)+12];
   }

   for (i=0; i<legend.getSize(); i++) {
      for (j=0; j<legend[i].getSize(); j++) {
         cout << ' ' << transcolor[legend[i][j]];
      }
      cout << "\n";
   }
}
Example #8
0
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';
   }


}
Example #9
0
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);
   }

}
Example #10
0
void processNote(MidiMessage message, int seqLength, int direction) {
   static Array<char>         notes;
   static Array<char>         velocities;
   static Array<int>          durations;
   static Array<int>          iois;
   static Array<int>          ontimes;
   static CircularBuffer<int> attacktimes;
   static int                 init = 0;
   static TumbleParameters    temparam;
   char vel;

   if (!init) {
      attacktimes.setSize(256);
      attacktimes.reset();
      notes.setSize(0);
      velocities.setSize(0);
      durations.setSize(0);
      iois.setSize(0);
      ontimes.setSize(128);
      ontimes.zero();
      init = 1;
   }

   char note;
   int deltatime;
   int ioi0;
   int ioix;
   if (message.is_note_on()) {
      attacktimes.insert(message.time);

      // check to see if the ioi is in the correct range
      if (notes.getSize() == 0) {
         // no notes yet, so don't know the first ioi
      } else {
         deltatime = attacktimes[0] - attacktimes[1];
         iois.append(deltatime);
      }
      if (iois.getSize() > 1) {
         ioi0 = iois[0];
         ioix = iois[iois.getSize()-1];
         if ((ioix < ioi0 * tolerance) || (ioix > ioi0 / tolerance)) {
            goto resettrigger;
         }
      }

      // at this point the note can be added to the sequence
      if (notes.getSize() + 1 >= seqLength) {
         // time to trigger an algorithm
         if (durations.getSize() < notes.getSize()) {
            // if the last note has not yet been turned off, approximate dur.
            deltatime = iois[iois.getSize()-1];
            durations.append(deltatime);
         }

         int i;
         for (i=0; i<seqLength; i++) {
            temparam.v[i] = velocities[i];
            temparam.i[i] = iois[i];
            temparam.d[i] = durations[i];
            temparam.n[i] = notes[i] - notes[0];
         }
         temparam.n[0]    = message.p1() - notes[0];
         temparam.current = message.p1();
         temparam.pos     = 1;
         temparam.max     = seqLength;
         temparam.active  = 1;
         
         startAlgorithm(temparam);
         goto resettrigger;
      } else {
         // add the note info to the algorithm pile
         note = message.p1();
         notes.append(note);
         vel = message.p2();
         velocities.append(vel);
         attacktimes[message.p1()] = message.time;
      }
   } else if (message.is_note_off()) {
      if (notes.getSize() > 0) {
         if (notes[notes.getSize()-1] == message.p1()) {
         deltatime = message.time - ontimes[message.p1()];
         durations.append(deltatime);
      } else {
         cout << "A funny error ocurred" << endl;
      }
   }

   return;

resettrigger:
   attacktimes.setSize(0);
   notes.setSize(0);
   velocities.setSize(0);
   durations.setSize(0);
   iois.setSize(0);

   if (message.is_note_on()) {
      note = message.p1();
      notes.append(note);
      ontimes[message.p1()] = message.time;
      vel = message.p2();
      velocities.append(vel);
   }
}



//////////////////////////////
//
// startAlgorithm -- start playing the tumble algorithm.  Inserts a
//     FunctionEvent into the eventBuffer which plays the tumble
//     algorithm sequence.  The algorithm will die after the notes
//     fall off of the 88-note keyboard.
//

}