summaryrefslogtreecommitdiffabout
path: root/tools
Unidiff
Diffstat (limited to 'tools') (more/less context) (ignore whitespace changes)
-rw-r--r--tools/.gitignore11
-rw-r--r--tools/Makefile.am31
-rw-r--r--tools/enflesh_filters_list.sh20
-rw-r--r--tools/filters.list36
-rw-r--r--tools/midi2f0.cc151
-rw-r--r--tools/mididump.cc84
-rw-r--r--tools/midifilter.cc295
7 files changed, 628 insertions, 0 deletions
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 0000000..6d68099
--- a/dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,11 @@
1Makefile.in
2*.o
3midifilter
4midi2f0
5mididump
6.libs
7.deps
8Makefile
9COPYING.cc
10filters_enumeration.cc
11filters_definition.cc
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..811c4f8
--- a/dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,31 @@
1bin_PROGRAMS = midi2f0 midifilter mididump
2
3INCLUDES = -I${top_srcdir}/include ${KONFORKA_CFLAGS}
4LIBS += ${top_builddir}/lib/libmidillo.la ${KONFORKA_LIBS}
5
6midi2f0_SOURCES = midi2f0.cc \
7 COPYING.cc
8midi2f0_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la
9
10midifilter_SOURCES = midifilter.cc \
11 COPYING.cc \
12 filters.list \
13 enflesh_filters_list.sh
14midifilter_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la
15${srcdir}/midifilter.cc: filters_enumeration.cc filters_definition.cc
16filters_enumeration.cc filters_definition.cc: enflesh_filters_list.sh filters.list
17 sh $^ \
18 filters_enumeration.cc filters_definition.cc
19
20mididump_SOURCES = mididump.cc \
21 COPYING.cc
22mididump_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la
23
24clean-local:
25 rm -f filters_enumeration.cc filters_definition.cc
26
27
28COPYING.cc: ${top_srcdir}/COPYING
29 echo "const char * COPYING =" >$@ || (rm $@;exit 1)
30 sed 's/"/\\"/g' $< | sed 's/^/\"/' | sed 's/$$/\\n\"/' >>$@ || (rm $@;exit 1)
31 echo ";" >>$@ || (rm $@;exit 1)
diff --git a/tools/enflesh_filters_list.sh b/tools/enflesh_filters_list.sh
new file mode 100644
index 0000000..f1d8dfc
--- a/dev/null
+++ b/tools/enflesh_filters_list.sh
@@ -0,0 +1,20 @@
1#!/bin/sh
2srcfile="${1}"
3enumfile="${2}"
4deffile="${3}"
5IFS=':'
6exec 5>${enumfile}
7exec 6>${deffile}
8SEQN=0
9LN=0
10cat ${srcfile} \
11 | while read id ids help ; do
12 LN="`expr ${LN} + 1`"
13 test -z "${id}" && continue
14 test "${id}" != "${id# }" && continue
15 echo "#line ${LN} \"${srcfile}\"" >&5
16 echo " filter_${id} = ${SEQN}," >&5
17 echo "#line ${LN} \"${srcfile}\"" >&6
18 echo ' { { "'$(echo $ids|sed -e 's-/-", "-g')'", 0 }, "'"${help}"'", false },' >&6
19 SEQN="`expr ${SEQN} + 1`"
20 done
diff --git a/tools/filters.list b/tools/filters.list
new file mode 100644
index 0000000..c0fb951
--- a/dev/null
+++ b/tools/filters.list
@@ -0,0 +1,36 @@
1system:system:strip all system messages
2meta:meta:strip all meta events (except for EOT)
3
4sysex:sysex:strip sysex messages
5MTC_quarter_frame:MTC_quarter_frame/quarter_frame:strip 'MTC quarter frame' messages
6song_position_pointer:song_position_pointer:strip 'song position pointer' messages
7song_select:song_select:strip 'song select' messages
8tune_request:tune_request:strip 'tune request' messages
9
10midi_clock:midi_clock/timing_clock:strip 'midi clock' messages
11midi_tick:midi_tick:strip 'midi tick' messages
12midi_start:midi_start/start:strip 'midi start' messages
13midi_continue:midi_continue/continue:strip 'midi continue' messages
14midi_stop:midi_stop/stop:strip 'midi stop' messages
15active_sense:active_sense:strip 'active sense' messages
16
17meta_sequence_number:meta_sequence_number:strip 'sequence number' meta events
18meta_text:meta_text:strip 'text' meta events
19meta_copyright:meta_copyright:strip 'copyright' meta events
20meta_seq_track_name:meta_seq_track_name:strip 'sequence track name' meta events
21meta_instrument:meta_instrument:strip 'instrument' meta events
22meta_lyric:meta_lyric/meta_lyrics:strip 'lyric' meta events
23meta_marker:meta_marker:strip 'marker' meta events
24meta_cue_point:meta_cue_point:strip 'cue point' meta events
25meta_patch_name:meta_patch_name/meta_program_name:strip 'patch name' meta events
26meta_port_name:meta_port_name/meta_device_name:strip 'port name' meta events
27meta_tempo:meta_temp:strip 'tempo' meta events
28meta_SMPTE_offset:meta_SMPTE_offset:strip 'SMPTE offset' meta events
29meta_time_sig:meta_time_sig:strip 'time signature' meta events
30meta_key_sig:meta_key_sig:strip 'key signature' meta events
31meta_proprietary:meta_proprietary:strip 'proprietary' meta events
32
33meta_midi_channel:meta_midi_channel:strip 'midi channel' meta events
34meta_midi_port:meta_midi_port:strip 'midi port' meta events
35
36meta_unknown:meta_unknown:strip meta events not known by midillo
diff --git a/tools/midi2f0.cc b/tools/midi2f0.cc
new file mode 100644
index 0000000..dc95be6
--- a/dev/null
+++ b/tools/midi2f0.cc
@@ -0,0 +1,151 @@
1#include <getopt.h>
2#include <iostream>
3#include <algorithm>
4using namespace std;
5#include <konforka/exception.h>
6#include <midillo/SMF.h>
7using namespace midillo;
8
9#include "config.h"
10#define PHEADER PACKAGE " " VERSION " - midi2f0 - convert to midi format 0"
11#define PCOPY "Copyright (c) 2006 Klever Group"
12
13static void usage(const char *p) {
14 cerr << PHEADER << endl
15 << PCOPY << endl << endl
16 << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl
17 << " -h, --help" << endl
18 << " --usage display this text" << endl
19 << " -V, --version display version number" << endl
20 << " -L, --license show license" << endl;
21}
22
23static bool MTrk_is_empty(const MTrk_t& t) {
24 return
25 t.events.empty()
26 || t.events.front().message.is_meta(meta_EOT);
27}
28
29static bool MTrk_deltat_lt(const MTrk_t& a,const MTrk_t& b) {
30 // we assume tracks aren't empty
31 return a.events.front().deltat < b.events.front().deltat;
32}
33
34static bool event_has_nonzero_deltat_or_is_EOT(const event_t& e) {
35 return e.deltat!=0 || e.message.is_meta(meta_EOT);
36}
37
38main(int argc,char **argv) {
39 try {
40 while(true) {
41 static struct option opts[] = {
42 { "help", no_argument, 0, 'h' },
43 { "usage", no_argument, 0, 'h' },
44 { "version", no_argument, 0, 'V' },
45 { "license", no_argument, 0, 'L' },
46 { NULL, 0, 0, 0 }
47 };
48 int c = getopt_long(argc,argv,"hVL",opts,NULL);
49 if(c==-1)
50 break;
51 switch(c) {
52 case 'h':
53 usage(*argv);
54 exit(0);
55 break;
56 case 'V':
57 cerr << VERSION << endl;
58 exit(0);
59 break;
60 case 'L':
61 extern const char *COPYING;
62 cerr << COPYING << endl;
63 exit(0);
64 break;
65 default:
66 cerr << "Huh??" << endl;
67 break;
68 }
69 }
70 const char *infile = "-";
71 if(optind<argc)
72 infile = argv[optind++];
73 const char *oufile = "-";
74 if(optind<argc)
75 oufile = argv[optind++];
76 if(optind<argc) {
77 usage(*argv);
78 exit(1);
79 }
80 SMF_t in(infile);
81 if(in.mthd.fmt==MThd_t::fmt_0) {
82 cerr << "File is already SMF 0" << endl;
83 in.save(oufile);
84 }else if(in.mthd.fmt==MThd_t::fmt_1) {
85 cerr << "Converting from SMF 1 to SMF 0" << endl;
86 SMF_t ou;
87 ou.mthd = in.mthd;
88 ou.mthd.fmt = MThd_t::fmt_0; ou.mthd.ntracks = 1;
89 ou.tracks.resize(1);
90 MTrk_t& mtrk = ou.tracks.front();
91 events_t& evs = mtrk.events;
92 for(;;) {
93 // Cleaning up empty tracks
94 in.tracks.erase(
95 remove_if(
96 in.tracks.begin(),in.tracks.end(),
97 MTrk_is_empty),
98 in.tracks.end() );
99 if(in.tracks.empty())
100 break;
101 // Find the least deltat
102 unsigned long mindt = min_element(
103 in.tracks.begin(), in.tracks.end(),
104 MTrk_deltat_lt )->events.front().deltat;
105 int t=0;
106 bool reset = false;
107 for(SMF_t::tracks_t::iterator i=in.tracks.begin();i!=in.tracks.end();++i) {
108 if(i->events.front().deltat > mindt) {
109 i->events.front().deltat-=mindt;
110 }else{
111 do{
112 evs.splice(
113 evs.end(),
114 i->events,i->events.begin() );
115 if(reset)
116 evs.back().deltat = 0;
117 else
118 reset = true;
119 events_t::iterator lze=find_if(
120 i->events.begin(),i->events.end(),
121 event_has_nonzero_deltat_or_is_EOT );
122 evs.splice(
123 evs.end(),
124 i->events,i->events.begin(),lze );
125 }while( (!MTrk_is_empty(*i)) && i->events.front().deltat==0 );
126 }
127 }
128 }
129 event_t& eot = *evs.append_event();
130 eot.deltat=0;
131 eot.message.status = status_system_meta;
132 eot.message.meta_status = meta_EOT;
133 ou.save(oufile);
134 }else if(in.mthd.fmt==MThd_t::fmt_2) {
135 // TODO
136 cerr << "Not implemented" << endl;
137 }else{
138 cerr << "Unknown MIDI file format" << endl;
139 }
140 return 0;
141 }catch(konforka::exception& e) {
142 cerr << "Oops... Konforka exception:" << endl
143 << " what: " << e.what() << endl
144 << " where: " << e.where() << endl;
145 return 1;
146 }catch(exception& e) {
147 cerr << "Oops... Exception:" << endl
148 << " what: " << e.what() << endl;
149 return 1;
150 }
151}
diff --git a/tools/mididump.cc b/tools/mididump.cc
new file mode 100644
index 0000000..83b7086
--- a/dev/null
+++ b/tools/mididump.cc
@@ -0,0 +1,84 @@
1#include <getopt.h>
2#include <iostream>
3#include <fstream>
4#include <string>
5#include <algorithm>
6using namespace std;
7#include <konforka/exception.h>
8#include <midillo/SMF.h>
9using namespace midillo;
10
11#include "config.h"
12#define PHEADER PACKAGE " " VERSION " - mididump - dump midi files"
13#define PCOPY "Copyright (c) 2006 Klever Group"
14
15static void usage(const char *p) {
16 cerr << PHEADER << endl
17 << PCOPY << endl << endl
18 << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl
19 << " -h, --help" << endl
20 << " --usage display this text" << endl
21 << " -V, --version display version number" << endl
22 << " -L, --license show license" << endl;
23}
24
25main(int argc,char **argv) {
26 try {
27 while(true) {
28 static struct option opts[] = {
29 { "help", no_argument, 0, 'h' },
30 { "usage", no_argument, 0, 'h' },
31 { "version", no_argument, 0, 'V' },
32 { "license", no_argument, 0, 'L' },
33 { NULL, 0, 0, 0 }
34 };
35 int c = getopt_long(argc,argv,"f:hVLl",opts,NULL);
36 if(c==-1)
37 break;
38 switch(c) {
39 case 'h':
40 usage(*argv);
41 exit(0);
42 break;
43 case 'V':
44 cerr << VERSION << endl;
45 exit(0);
46 break;
47 case 'L':
48 extern const char *COPYING;
49 cerr << COPYING << endl;
50 exit(0);
51 break;
52 default:
53 cerr << "Huh??" << endl;
54 break;
55 }
56 }
57 const char *infile = "-";
58 if(optind<argc)
59 infile = argv[optind++];
60 const char *oufile = "-";
61 if(optind<argc)
62 oufile = argv[optind++];
63 if(optind<argc) {
64 usage(*argv);
65 exit(1);
66 }
67 SMF_t in(infile);
68 if(strcmp(oufile,"-")) {
69 ofstream s(oufile); s << in;
70 }else{
71 cout << in;
72 }
73 return 0;
74 }catch(konforka::exception& e) {
75 cerr << "Oops... Konforka exception:" << endl
76 << " what: " << e.what() << endl
77 << " where: " << e.where() << endl;
78 return 1;
79 }catch(exception& e) {
80 cerr << "Oops... Exception:" << endl
81 << " what: " << e.what() << endl;
82 return 1;
83 }
84}
diff --git a/tools/midifilter.cc b/tools/midifilter.cc
new file mode 100644
index 0000000..1c130de
--- a/dev/null
+++ b/tools/midifilter.cc
@@ -0,0 +1,295 @@
1#include <getopt.h>
2#include <iostream>
3#include <string>
4#include <algorithm>
5#include <iterator>
6using namespace std;
7#include <konforka/exception.h>
8#include <midillo/SMF.h>
9using namespace midillo;
10
11#include "config.h"
12#define PHEADER PACKAGE " " VERSION " - midifilter - midi filter tool"
13#define PCOPY "Copyright (c) 2006 Klever Group"
14
15enum {
16# include "filters_enumeration.cc"
17 total_filters
18};
19
20struct filter_t {
21 const char *ids[5];
22 const char *help;
23 bool filter;
24} filters[] = {
25# include "filters_definition.cc"
26 {0,0,0}
27};
28#define FILTER(f) filters[filter_##f].filter
29
30inline ostream& operator<<(ostream& s,const filter_t& f) {
31 ios::fmtflags ff = s.flags();
32 int w = s.width(25);
33 s.unsetf(ios::right); s.setf(ios::left);
34 s << *f.ids << " " << f.help;
35 s.width(w);
36 s.flags(ff);
37 return s;
38}
39
40static bool message_is_filtered(const message_t& m) {
41 if(m.is_meta(meta_EOT))
42 return false;
43
44 if(FILTER(sysex) && (m.status==status_system_sysex || m.status==status_system_end_of_sysex))
45 return true;
46 if(FILTER(MTC_quarter_frame) && m.status==status_system_MTC_quarter_frame)
47 return true;
48 if(FILTER(song_position_pointer) && m.status==status_system_song_position_pointer)
49 return true;
50 if(FILTER(song_select) && m.status==status_system_song_select)
51 return true;
52 if(FILTER(tune_request) && m.status==status_system_tune_request)
53 return true;
54 if(FILTER(midi_clock) && m.status==status_system_midi_clock)
55 return true;
56 if(FILTER(midi_tick) && m.status==status_system_midi_tick)
57 return true;
58 if(FILTER(midi_start) && m.status==status_system_midi_start)
59 return true;
60 if(FILTER(midi_continue) && m.status==status_system_midi_continue)
61 return true;
62 if(FILTER(midi_stop) && m.status==status_system_midi_stop)
63 return true;
64 if(FILTER(active_sense) && m.status==status_system_active_sense)
65 return true;
66
67 if(FILTER(meta_sequence_number) && m.is_meta(meta_sequence_number))
68 return true;
69 if(FILTER(meta_text) && m.is_meta(meta_text))
70 return true;
71 if(FILTER(meta_copyright) && m.is_meta(meta_copyright))
72 return true;
73 if(FILTER(meta_seq_track_name) && m.is_meta(meta_seq_track_name))
74 return true;
75 if(FILTER(meta_instrument) && m.is_meta(meta_instrument))
76 return true;
77 if(FILTER(meta_lyric) && m.is_meta(meta_lyric))
78 return true;
79 if(FILTER(meta_marker) && m.is_meta(meta_marker))
80 return true;
81 if(FILTER(meta_cue_point) && m.is_meta(meta_cue_point))
82 return true;
83 if(FILTER(meta_patch_name) && m.is_meta(meta_patch_name))
84 return true;
85 if(FILTER(meta_port_name) && m.is_meta(meta_port_name))
86 return true;
87 if(FILTER(meta_tempo) && m.is_meta(meta_tempo))
88 return true;
89 if(FILTER(meta_SMPTE_offset) && m.is_meta(meta_SMPTE_offset))
90 return true;
91 if(FILTER(meta_time_sig) && m.is_meta(meta_time_sig))
92 return true;
93 if(FILTER(meta_key_sig) && m.is_meta(meta_key_sig))
94 return true;
95 if(FILTER(meta_proprietary) && m.is_meta(meta_proprietary))
96 return true;
97
98 if(FILTER(meta_midi_channel) && m.is_meta(meta_midi_channel))
99 return true;
100 if(FILTER(meta_midi_port) && m.is_meta(meta_midi_port))
101 return true;
102
103 if(FILTER(meta_unknown) && m.is_meta()) {
104 const int known_metas[] = {
105 meta_sequence_number, meta_text, meta_copyright, meta_seq_track_name,
106 meta_instrument, meta_lyric, meta_marker, meta_cue_point,
107 meta_patch_name, meta_port_name, meta_EOT, meta_tempo,
108 meta_SMPTE_offset, meta_time_sig, meta_key_sig, meta_proprietary,
109 meta_midi_channel, meta_midi_port };
110 const int* lastknown = &known_metas[sizeof(known_metas)/sizeof(*known_metas)];
111 if( find(
112 known_metas, lastknown,
113 m.meta_status ) == lastknown ) {
114 return true;
115 }
116 }
117
118 if(FILTER(meta) && m.is_meta())
119 return true;
120
121 return false;
122}
123
124static bool event_is_filtered(const event_t& e) {
125 return message_is_filtered(e.message);
126}
127
128static bool MTrk_is_empty(const MTrk_t& t) {
129 return
130 t.events.empty()
131 || t.events.front().message.is_meta(meta_EOT);
132}
133
134struct filter_preset_t {
135 const char *id;
136 const char *help;
137 int filters[total_filters];
138} filter_presets[] = {
139 { "system_common", "strip system common messages",
140 { filter_sysex, filter_song_position_pointer, filter_song_select,
141 filter_tune_request, -1 } },
142 { "system_runtime", "strip system runtime messages",
143 { filter_midi_clock, filter_midi_tick, filter_midi_start,
144 filter_midi_continue, filter_midi_stop, filter_active_sense, -1 } },
145 { "meta_obsolete", "strip obsolete meta events",
146 { filter_meta_midi_channel, filter_meta_midi_port, -1 } },
147 { "meta_texts", "strip textual meta events",
148 { filter_meta_text, filter_meta_copyright,
149 filter_meta_seq_track_name, filter_meta_instrument,
150 filter_meta_lyric, filter_meta_marker, filter_meta_cue_point,
151 filter_meta_patch_name, filter_meta_port_name, -1 } }
152};
153
154inline ostream& operator<<(ostream& s,const filter_preset_t& fp) {
155 ios::fmtflags ff = s.flags();
156 int w = s.width(25);
157 s.unsetf(ios::right); s.setf(ios::left);
158 s << fp.id << " " << fp.help;
159 s.width(w);
160 s.flags(ff);
161 return s;
162}
163
164static void usage(const char *p) {
165 cerr << PHEADER << endl
166 << PCOPY << endl << endl
167 << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl
168 << " -h, --help" << endl
169 << " --usage display this text" << endl
170 << " -V, --version display version number" << endl
171 << " -L, --license show license" << endl
172 << " -f <filters>, --filter=<filters>"
173 << " specify the list of events (comma-separated) to" << endl
174 << " strip" << endl
175 << " -l, --list-filters" << endl
176 << " list available filters" << endl;
177}
178
179main(int argc,char **argv) {
180 try {
181 while(true) {
182 static struct option opts[] = {
183 { "help", no_argument, 0, 'h' },
184 { "usage", no_argument, 0, 'h' },
185 { "version", no_argument, 0, 'V' },
186 { "license", no_argument, 0, 'L' },
187 { "filter", no_argument, 0, 'f' },
188 { "list-filters", no_argument, 0, 'l' },
189 { NULL, 0, 0, 0 }
190 };
191 int c = getopt_long(argc,argv,"f:hVLl",opts,NULL);
192 if(c==-1)
193 break;
194 switch(c) {
195 case 'h':
196 usage(*argv);
197 exit(0);
198 break;
199 case 'V':
200 cerr << VERSION << endl;
201 exit(0);
202 break;
203 case 'L':
204 extern const char *COPYING;
205 cerr << COPYING << endl;
206 exit(0);
207 break;
208 case 'f':
209 {
210 string fs = optarg;
211 while(!fs.empty()) {
212 string::size_type ns = fs.find_first_not_of(" :/,;");
213 if(ns==string::npos)
214 break;
215 if(ns)
216 fs.erase(ns);
217 string::size_type s = fs.find_first_of(" :/,;");
218 string f;
219 if(s==string::npos) {
220 f = fs; fs.clear();
221 }else{
222 f = fs.substr(0,ns);
223 fs.erase(0,ns+1);
224 }
225 for(int fn=0;fn<total_filters;++fn) {
226 filter_t& filter = filters[fn];
227 for(int fid=0;fid<(sizeof(filter.ids)/sizeof(*filter.ids)) && filter.ids[fid];++fid) {
228 if(f == filter.ids[fid])
229 filter.filter = true;
230 }
231 }
232 }
233 }
234 break;
235 case 'l':
236 cerr << PHEADER << endl
237 << PCOPY << endl << endl;
238 copy(
239 filters, &filters[total_filters],
240 ostream_iterator<filter_t>(cerr,"\n") );
241 copy(
242 filter_presets, &filter_presets[sizeof(filter_presets)/sizeof(*filter_presets)],
243 ostream_iterator<filter_preset_t>(cerr,"\n") );
244 exit(0);
245 break;
246 default:
247 cerr << "Huh??" << endl;
248 break;
249 }
250 }
251 const char *infile = "-";
252 if(optind<argc)
253 infile = argv[optind++];
254 const char *oufile = "-";
255 if(optind<argc)
256 oufile = argv[optind++];
257 if(optind<argc) {
258 usage(*argv);
259 exit(1);
260 }
261 SMF_t in(infile);
262 for(SMF_t::tracks_t::iterator t=in.tracks.begin();t!=in.tracks.end();++t) {
263 for(events_t::iterator e=t->events.begin();e!=t->events.end();) {
264 if(event_is_filtered(*e)) {
265 events_t::iterator i = e++;
266 // we assume it is not the last event, since the last event
267 // (meta_EOT) is unfilterable
268 e->deltat += i->deltat;
269 t->events.erase(i);
270 }else
271 ++e;
272 }
273 }
274 in.tracks.erase(
275 remove_if(
276 in.tracks.begin(),in.tracks.end(),
277 MTrk_is_empty),
278 in.tracks.end() );
279 if(in.tracks.empty()) {
280 cerr << "We have no MIDI data in the output file";
281 }
282 in.mthd.ntracks = in.tracks.size();
283 in.save(oufile);
284 return 0;
285 }catch(konforka::exception& e) {
286 cerr << "Oops... Konforka exception:" << endl
287 << " what: " << e.what() << endl
288 << " where: " << e.where() << endl;
289 return 1;
290 }catch(exception& e) {
291 cerr << "Oops... Exception:" << endl
292 << " what: " << e.what() << endl;
293 return 1;
294 }
295}