Example #1
0
void appendMidi(MidiFile& outfile, const char* filename,
      double seconds, int initQ) {
   MidiFile infile(filename);
   infile.joinTracks();
   infile.deltaTicks();
   int i;
   int tpq;
   int count;

   MidiEvent anevent;
   if (initQ == 0) {
      outfile.joinTracks();
      count = infile.getEventCount(0);
      // don't include end-of-track meta event
      count--;
      tpq = infile.getTicksPerQuarterNote();
      outfile.setTicksPerQuarterNote(tpq);
      for (i=0; i<count; i++) {
         anevent = infile.getEvent(0,i);
         // storing as a type-0 file, so remove track information
         anevent.track = 0;
         outfile.addEvent(anevent);
      }
      return;
   }

   // presuming constant tpq for different files.
   tpq = outfile.getTicksPerQuarterNote();

   if (seconds > 0.0) {
      // insert a tempo marking of 120, and then a pause related to how
      // long in second to wait until next MIDI file contents.
      // micro-seconds per quarter note is last three bytes of meta message
      // If quarter note is 120 bpm, that is 0.5 seconds or 500000 usec.
      // In hex 500000 is 07 a1 20
      // Tempo meta event:  ff 51 03 07 a1 20
      vector<uchar> bpm120;
      bpm120.resize(3);
      bpm120[0] = 0x07;
      bpm120[1] = 0xa1;
      bpm120[2] = 0x20;

      outfile.addMetaEvent(0, 0, 0x51, bpm120);
      infile.getEvent(0,0).tick = int(seconds * 2 * tpq + 0.5);
   }

   count = infile.getEventCount(0);
   // don't include end-of-track meta event
   count--;
   for (i=0; i<count; i++) {
      anevent = infile.getEvent(0,i);
      anevent.track = 0;
      outfile.addEvent(anevent);
   }
}
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();

}