//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Thu Dec 2 12:45:43 PST 1999
// Last Modified: Thu Dec 2 13:53:31 PST 1999
// Filename: midimixup.cpp
// Syntax: C++
//
// Description: Reads a standard MIDI file, adjusts the timing of
// the events in a random manner, then writes the file
// back out to a standard MIDI file.
//
#include "MidiFile.h"
#include "Options.h"
#ifndef OLDCPP
#include <iostream>
#else
#include <iostream.h>
#endif
// function declarations:
void adjustTime(int deviation, int& aTime);
void checkOptions(Options& opts);
void example(void);
void usage(const char* command);
// Global variables:
MidiFile midifile; // performance interface
// command-line variables
int maxdev = 10; // maximum unit deviation
///////////////////////////////////////////////////////////////////////////
int main(int argc, char** argv) {
Options options(argc, argv);
checkOptions(options);
MidiFile midifile;
midifile.read(options.getArg(1));
// note: when a MIDI file is read in by the read() function,
// the delta timings are converted to absolute timings.
// The next piece of code will add random timing shifts
// to all events in the file according to the -m command line
// option.
int track, event;
for (track=0; track<midifile.getNumTracks(); track++) {
for (event=0; event<midifile.getNumEvents(track); event++) {
adjustTime(maxdev, midifile.getEvent(track, event).time);
}
}
// the timing values are not sorted any longer, so they
// have to be resorted in time.
midifile.sortTracks();
// you can view an ASCII version of the MIDI file with the
// following code:
// cout << midifile;
// now ready to write out the new midi file to the second argument
midifile.write(options.getArg(2));
return 0;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////
//
// adjustTime -- adjust an absolute MIDI time. If the time
// becomes negative, then the time will be set to zero.
//
void adjustTime(int deviation, int& aTime) {
// if you are using a UNIX computer, you might want to try
// the lrand48() function which gives more random values.
int sign = rand() % 2 ? 1 : -1;
aTime += sign * (rand() % deviation + 1);
}
//////////////////////////////
//
// checkOptions -- handle command-line options.
//
void checkOptions(Options& opts) {
opts.define("m|max|max-deviation=i:10");
opts.define("author=b");
opts.define("version=b");
opts.define("example=b");
opts.define("help=b");
opts.process();
if (opts.getBoolean("author")) {
cout << "Written by Craig Stuart Sapp, "
<< "craig@ccrma.stanford.edu, 2 December 1999" << endl;
exit(0);
}
if (opts.getBoolean("version")) {
cout << "midimixup version 1.0" << endl;
cout << "compiled: " << __DATE__ << endl;
}
if (opts.getBoolean("help")) {
usage(opts.getCommand());
exit(0);
}
if (opts.getBoolean("example")) {
example();
exit(0);
}
// must have two filenames on the command-line
if (opts.getArgCount() == 1) {
cout << "Need an output file specified." << endl;
usage(opts.getCommand());
exit(1);
}
if (opts.getArgCount() != 2) {
cout << "Error: need one input and one output MIDI filename." << endl;
usage(opts.getCommand());
exit(1);
}
maxdev = opts.getInteger("max-deviation");
}
//////////////////////////////
//
// example -- gives example calls to the midiplay program.
//
void example(void) {
cout <<
"# midimixup examples: \n"
" midimixup -m 10 fileinput.mid fileoutput.mid \n"
<< endl;
}
//////////////////////////////
//
// usage -- how to run the textmidi program on the command line.
//
void usage(const char* command) {
cout <<
" \n"
"Applies a random variation to the timing of notes in a MIDI file. \n"
" \n"
"Usage: " << command << " [-m amt] input-midifile output-midifile \n"
" \n"
"Options: \n"
" -m amt = adjust each timing value randomly up to +/- amt \n"
" --options = list of all options, aliases and default values. \n"
" \n"
" \n"
<< endl;
}
// md5sum: cf2e5559e7e3e8b36b93c0f569425bf9 midimixup.cpp [20050403]