예제 #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);
   }
}
예제 #2
0
int main(int argc, char** argv) {
   MidiFile outputfile;        // create an empty MIDI file with one track
   outputfile.absoluteTicks();  // time information stored as absolute time
                               // (will be coverted to delta time when written)
   outputfile.addTrack(2);     // Add another two tracks to the MIDI file
   vector<uchar> midievent;     // temporary storage for MIDI events
   midievent.resize(3);        // set the size of the array to 3 bytes
   int tpq = 120;              // default value in MIDI file is 48
   outputfile.setTicksPerQuarterNote(tpq);

   // data to write to MIDI file: (60 = middle C)
   // C5 C  G G A A G-  F F  E  E  D D C-
   int melody[50]  = {72,72,79,79,81,81,79,77,77,76,76,74,74,72,-1};
   int mrhythm[50] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2,-1};

   // C3 C4 E C F C E C D B3 C4 A3 F G C-
   int bass[50] =   {48,60,64,60,65,60,64,60,62,59,60,57,53,55,48,-1};
   int brhythm[50]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,-1};


   // store a melody line in track 1 (track 0 left empty for conductor info)
   int i=0;
   int actiontime = 0;      // temporary storage for MIDI event time
   midievent[2] = 64;       // store attack/release velocity for note command
   while (melody[i] >= 0) {
      midievent[0] = 0x90;     // store a note on command (MIDI channel 1)
      midievent[1] = melody[i];
      outputfile.addEvent(1, actiontime, midievent);
      actiontime += tpq * mrhythm[i];
      midievent[0] = 0x80;     // store a note on command (MIDI channel 1)
      outputfile.addEvent(1, actiontime, midievent);
      i++;
   }

   // store a base line in track 2
   i=0;
   actiontime = 0;          // reset time for beginning of file
   midievent[2] = 64;
   while (bass[i] >= 0) {
      midievent[0] = 0x90;
      midievent[1] = bass[i];
      outputfile.addEvent(2, actiontime, midievent);
      actiontime += tpq * brhythm[i];
      midievent[0] = 0x80;
      outputfile.addEvent(2, actiontime, midievent);
      i++;
   }

   outputfile.sortTracks();         // make sure data is in correct order
   outputfile.write("twinkle.mid"); // write Standard MIDI File twinkle.mid
   return 0;
}
예제 #3
0
void createMidiFile(const char* filename, vector<vector<int> >& sequence) {
   MidiFile midifile;
   midifile.absoluteTicks();
   midifile.addTrack(1);
   int tpq = 120;
   double beat = 0.0;
   midifile.setTicksPerQuarterNote(tpq);


   MidiEvent tempo;
   tempo.setMetaTempo(60.0);
   tempo.track = 0;
   tempo.tick = 0;
   midifile.addEvent(tempo);

   int maxlen = 0;
   int i, j;
   for (i=0; i<(int)sequence.size(); i++) {
      if ((int)sequence[i].size() > maxlen) {
         maxlen = sequence[i].size();
      }
   }

   vector<int> notelist;
   MidiEvent noteon(0x90, 0, 64);
   MidiEvent noteoff(0x80, 0, 64);
   noteon.track  = 1;
   noteoff.track = 1;

   for (i=0; i<maxlen; i++) {
      notelist.clear();
      for (j=0; j<(int)sequence.size(); j++) {
         if (i<(int)sequence[j].size()) {
            notelist.push_back(sequence[j][i]);
         }
      }
      for (j=0; j<(int)notelist.size(); j++) {
         noteon[1]  = 0x7f & notelist[j];
         noteoff[1] = 0x7f & notelist[j];
         noteon.tick  = (int)(beat * tpq + 0.5);
         noteoff.tick = (int)(beat * tpq + 1 * tpq + 0.5);
         midifile.addEvent(noteon);
         midifile.addEvent(noteoff);
      }
      beat += 1.0;
   }

   midifile.sortTracks();
   midifile.write(filename);
}
예제 #4
0
void AddDrumTrack(MidiFile& midifile, int* data, int instrument, int ticks) {
   vector<uchar> midievent;   // temporary storage for MIDI events
   midievent.resize(3);       // set the size of the array to 3 bytes
   midievent[2] = 64;         // set the loudness to a constant value
   int notestate = 0;         // 0 = off, 1 = on
   int i         = 0;
   int actiontime;
   int track = midifile.addTrack();      // Add a track to the MIDI file

   while (data[i] >= 0) {
      switch (data[i]) {
         case 'x': case 'X':
            if (notestate) {
               // turn off previous note
               midievent[0] = 0x89;
               midievent[1] = instrument;
               actiontime = ticks * i - 1;
               midifile.addEvent(track, actiontime, midievent);
            }
            // turn on current note
            midievent[0] = 0x99;
            midievent[1] = instrument;
            actiontime = ticks * i;
            midifile.addEvent(track, actiontime, midievent);
            notestate = 1;
            break;
         case '0': case 'o': case 'O':
            // turn off previous note
            if (notestate) {
               midievent[0] = 0x89;
               midievent[1] = instrument;
               actiontime = ticks * i - 1;
               midifile.addEvent(track, actiontime, midievent);
               notestate = 0;
            }
         break;
      }
      i++;
   }

   if (notestate) {
      // turn off last note
      midievent[0] = 0x89;
      midievent[1] = instrument;
      actiontime = ticks * i;
      midifile.addEvent(track, actiontime, midievent);
   }

}
예제 #5
0
int main(int argc, char* argv[]) {
   checkOptions(options, argc, argv);
   MidiFile outfile;
   outfile.joinTracks();
   outfile.deltaTicks();

   int i;
   int initQ = 0;
   for (i=1; i<=options.getArgCount(); i++) {
      appendMidi(outfile, options.getArg(i).data(), seconds, initQ++);
   }

   // insert an end-of track Meta Event
   int tpq = outfile.getTicksPerQuarterNote();
   MidiEvent mfevent;
   mfevent.tick = tpq;
   mfevent.track = 0;
   mfevent.resize(3);
   mfevent[0] = 0xff;
   mfevent[1] = 0x2f;
   mfevent[2] = 0;
   outfile.addEvent(mfevent);

   if (binaryQ) {
      outfile.write(cout);
   } else {
      cout << outfile;
   }

   return 0;
}
void midiProcessing::generateMidiFile(const char *filePath, int size)
{
    srand (time(NULL));
    MidiFile outputFile;
    outputFile.absoluteTime();
    outputFile.addTrack(1);
    outputFile.setTicksPerQuarterNote(tpq);
    Array<uchar> midiEvent;
    midiEvent.setSize(3);
    int actionTime = 0;
    int tempVectorIndex = 0;
    std::vector<note> tempNote;
    int tempIndex;
    
    for (int i = 0; i < size; i++)
    {
        tempNote = midiProcessing::markovList.at(tempVectorIndex);
        tempIndex = (rand() % (midiProcessing::markovList.at(tempVectorIndex).size()-1)) + 1;
        midiEvent[0] = 0x90;
        midiEvent[1] = tempNote.at(tempIndex).getNumber();
        midiEvent[2] = tempNote.at(tempIndex).getVelocity();
        outputFile.addEvent(1, actionTime, midiEvent);
        midiEvent[0] = 0x80;
        outputFile.addEvent(1, (tempNote.at(tempIndex).getDuration())+actionTime, midiEvent);
        
        actionTime += tempNote.at(tempIndex).getRest();
        
        for (int j = 0; j < midiProcessing::markovList.size(); j++)
        {
            if (midiProcessing::markovList.at(j).at(0).getNumber() == tempNote.at(tempIndex).getNumber())
            {
                tempVectorIndex = j;
                break;
            }
        }
    }
    outputFile.sortTracks();
    outputFile.write(filePath);
}
예제 #7
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();

}