00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <iostream>
00012
00013 #include "wave-midi/midi_file.h"
00014
00015
00016
00017 typedef const char * cc_ptr_t;
00018
00019 struct stat_entry_t {
00020 const char *name;
00021 media::MidiEvent::eStatus status;
00022 };
00023
00024
00025 #define STAT_ENTRY(name,status) { #name , media::MidiEvent::status } ,
00026
00027 static const stat_entry_t s_statusTable[] = {
00028
00029
00030 STAT_ENTRY(note-on, eNoteOn)
00031 STAT_ENTRY(note-off, eNoteOff)
00032 STAT_ENTRY(program, eProgram)
00033
00034
00035 { 0, media::MidiEvent::eInvalid }
00036 };
00037
00038
00039
00040
00041
00042
00043
00044
00045 static const char *
00046 getNextToken
00047 (
00048 IO cc_ptr_t& p
00049 )
00050 {
00051 ASSERT(p, "null");
00052
00053 static const int s_max = 1024;
00054 static char s_buffer[s_max];
00055 const char * max = s_buffer + s_max;
00056
00057 char * q = s_buffer;
00058
00059
00060 while (isspace(*p)) {
00061
00062 ++p;
00063 }
00064
00065
00066 while (0 != *p && !isspace(*p) && '#' != *p) {
00067 ASSERT(q < max, "Ran out of room in buffer");
00068
00069
00070 *q = *p;
00071
00072
00073 ++q;
00074 ++p;
00075 }
00076
00077
00078 *q = 0;
00079 return s_buffer;
00080 }
00081
00082
00083
00084 static void
00085 addMeta
00086 (
00087 IN media::MidiFile * mf,
00088 IN const char * p
00089 )
00090 {
00091 ASSERT(mf, "null");
00092 ASSERT(p, "null");
00093
00094 const char * key = getNextToken(p);
00095 if (!strcmp("ppqn", key)) {
00096 int ppqn = atoi(getNextToken(p));
00097 mf->setPpqn(ppqn);
00098 } else if (!strcmp("bpm", key)) {
00099 float bpm = atof(getNextToken(p));
00100 mf->setTempo(bpm);
00101 } else {
00102 ASSERT(false, "unknown meta key: '%s'", key);
00103 }
00104 }
00105
00106
00107
00108 static media::MidiEvent::eStatus
00109 getStatus
00110 (
00111 IN const char * type
00112 )
00113 {
00114 ASSERT(type, "null");
00115
00116 const stat_entry_t * p = s_statusTable;
00117 while (p->name) {
00118 if (!strcmp(type, p->name)) {
00119 return p->status;
00120 }
00121 ++p;
00122 }
00123
00124 ASSERT(false, "unrecognized event type: '%s'", type);
00125 return p->status;
00126 }
00127
00128
00129
00130 static void
00131 addEvent
00132 (
00133 IN media::MidiFile * mf,
00134 IN const char * p
00135 )
00136 {
00137 ASSERT(mf, "null");
00138 ASSERT(p, "null");
00139
00140
00141 long tick = atol(getNextToken(p));
00142 ASSERT(tick >= 0, "Bad tick value: %ld", tick);
00143
00144 const char * type = getNextToken(p);
00145
00146
00147 media::MidiEvent me;
00148 me.SetStatus(getStatus(type));
00149
00150 int channel = atoi(getNextToken(p));
00151 ASSERT(channel >= 0 && channel < 16, "bad channel: %d", channel);
00152 int p1 = atoi(getNextToken(p));
00153 ASSERT(p1 >= 0 && p1 < 128, "bad parameter 1: %d", p1);
00154 int p2 = atoi(getNextToken(p));
00155 ASSERT(p2 >= 0 && p2 < 128, "bad parameter 2: %d", p2);
00156
00157 me.SetChannel(channel);
00158 me.SetByte0((byte_t) p1);
00159 me.SetByte1((byte_t) p2);
00160
00161 mf->addEvent(tick, me);
00162 }
00163
00164
00165
00166 static void
00167 addEvents
00168 (
00169 IN media::MidiFile * mf,
00170 IO std::istream& stream
00171 )
00172 {
00173 ASSERT(mf, "null");
00174
00175
00176 std::string line;
00177 while (stream.good()) {
00178 std::getline(stream, line);
00179 const char * p = line.c_str();
00180
00181
00182 const char * token = getNextToken(p);
00183 if (!*token) {
00184 continue;
00185 }
00186
00187
00188 if (!strcmp("meta", token)) {
00189 addMeta(mf, p);
00190 } else if (!strcmp("event", token)) {
00191 addEvent(mf, p);
00192 } else {
00193 ASSERT(false, "unknown token: '%s'", token);
00194 }
00195 }
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 int
00207 main
00208 (
00209 IN int argc,
00210 IN const char * argv[]
00211 )
00212 {
00213 ASSERT(2 == argc,
00214 "usage: midi-writer <filename>");
00215 const char * filename = argv[1];
00216
00217
00218 smart_ptr<media::MidiFile> mf = media::MidiFile::create();
00219 ASSERT(mf, "could not create midi file object?");
00220
00221
00222 addEvents(mf, std::cin);
00223
00224
00225 mf->write(filename);
00226
00227 return 0;
00228 }
00229