summaryrefslogtreecommitdiffabout
path: root/tools/midi2f0.cc
Unidiff
Diffstat (limited to 'tools/midi2f0.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--tools/midi2f0.cc151
1 files changed, 151 insertions, 0 deletions
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}