To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Revision:

root / main.cpp @ 6:467d1e3dc4cc

History | View | Annotate | Download (7.71 KB)

1
/*
2
    This file copyright 2010 Chris Cannam.
3
  
4
    Permission is hereby granted, free of charge, to any person
5
    obtaining a copy of this software and associated documentation
6
    files (the "Software"), to deal in the Software without
7
    restriction, including without limitation the rights to use, copy,
8
    modify, merge, publish, distribute, sublicense, and/or sell copies
9
    of the Software, and to permit persons to whom the Software is
10
    furnished to do so, subject to the following conditions:
11

12
    The above copyright notice and this permission notice shall be
13
    included in all copies or substantial portions of the Software.
14

15
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
19
    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22

23
    Except as contained in this notice, the names of the authors
24
    shall not be used in advertising or otherwise to promote the sale,
25
    use or other dealings in this Software without prior written
26
    authorization.
27
*/
28

    
29
#include "MIDIFileReader.h"
30

    
31
#include <iostream>
32

    
33
using namespace std;
34
using namespace MIDIConstants;
35

    
36
int main(int argc, char **argv)
37
{
38
    if (argc != 2) {
39
        cerr << "Usage: midifile <file.mid>" << endl;
40
        return 1;
41
    }
42

    
43
    std::string filename = argv[1];
44

    
45
    MIDIFileReader fr(filename);
46
    if (!fr.isOK()) {
47
        std::cerr << "Error: " << fr.getError().c_str() << std::endl;
48
        return 1;
49
    }
50

    
51
    MIDIComposition c = fr.load();
52

    
53
    switch (fr.getFormat()) {
54
    case MIDI_SINGLE_TRACK_FILE: cout << "Format: MIDI Single Track File" << endl; break;
55
    case MIDI_SIMULTANEOUS_TRACK_FILE: cout << "Format: MIDI Simultaneous Track File" << endl; break;
56
    case MIDI_SEQUENTIAL_TRACK_FILE: cout << "Format: MIDI Sequential Track File" << endl; break;
57
    default: cout << "Format: Unknown MIDI file format?" << endl; break;
58
    }
59

    
60
    cout << "Tracks: " << c.size() << endl;
61

    
62
    int td = fr.getTimingDivision();
63
    if (td < 32768) {
64
        cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl;
65
    } else {
66
        int frames = 256 - (td >> 8);
67
        int subframes = td & 0xff;
68
        cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl;
69
    }
70

    
71
    for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) {
72
        
73
        cout << "Start of track: " << i->first+1 << endl;
74

    
75
        for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
76

    
77
            unsigned int t = j->getTime();
78
            int ch = j->getChannelNumber();
79

    
80
            if (j->isMeta()) {
81
                int code = j->getMetaEventCode();
82
                string name;
83
                bool printable = true;
84
                switch (code) {
85

    
86
                case MIDI_END_OF_TRACK:
87
                    cout << t << ": End of track" << endl;
88
                    break;
89

    
90
                case MIDI_TEXT_EVENT: name = "Text"; break;
91
                case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break;
92
                case MIDI_TRACK_NAME: name = "Track name"; break;
93
                case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break;
94
                case MIDI_LYRIC: name = "Lyric"; break;
95
                case MIDI_TEXT_MARKER: name = "Text marker"; break;
96
                case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break;
97
                case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break;
98
                case MIDI_CUE_POINT: name = "Cue point"; break;
99
                case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break;
100
                case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break;
101
                case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break;
102

    
103
                case MIDI_SET_TEMPO:
104
                {
105
                    unsigned char m0 = j->getMetaMessage()[0];
106
                    unsigned char m1 = j->getMetaMessage()[1];
107
                    unsigned char m2 = j->getMetaMessage()[2];
108
                    long tempo = (((m0 << 8) + m1) << 8) + m2;
109
                    cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
110
                }
111
                    break;
112

    
113
                case MIDI_TIME_SIGNATURE:
114
                {
115
                    int numerator = j->getMetaMessage()[0];
116
                    int denominator = 1 << (int)j->getMetaMessage()[1];
117
                    
118
                    cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
119
                }
120

    
121
                case MIDI_KEY_SIGNATURE:
122
                {
123
                    int accidentals = j->getMetaMessage()[0];
124
                    int isMinor = j->getMetaMessage()[1];
125
                    bool isSharp = accidentals < 0 ? false : true;
126
                    accidentals = accidentals < 0 ? -accidentals : accidentals;
127
                    cout << t << ": Key signature: " << accidentals << " "
128
                         << (isSharp ?
129
                             (accidentals > 1 ? "sharps" : "sharp") :
130
                             (accidentals > 1 ? "flats" : "flat"))
131
                         << (isMinor ? ", minor" : ", major") << endl;
132
                }
133

    
134
                }
135
                
136

    
137
                if (name != "") {
138
                    if (printable) {
139
                        cout << t << ": File meta event: code " << code
140
                             << ": " << name << ": \"" << j->getMetaMessage()
141
                             << "\"" << endl;
142
                    } else {
143
                        cout << t << ": File meta event: code " << code
144
                             << ": " << name << ": ";
145
                        for (int k = 0; k < j->getMetaMessage().length(); ++k) {
146
                            cout << (int)j->getMetaMessage()[k] << " ";
147
                        }
148
                    }
149
                }
150
                continue;
151
            }
152

    
153
            switch (j->getMessageType()) {
154
                
155
            case MIDI_NOTE_ON:
156
                cout << t << ": Note: channel " << ch
157
                     << " duration " << j->getDuration()
158
                     << " pitch " << j->getPitch()
159
                     << " velocity " << j->getVelocity() << endl;
160
                break;
161

    
162
            case MIDI_POLY_AFTERTOUCH:
163
                cout << t << ": Polyphonic aftertouch: channel " << ch
164
                     << " pitch " << j->getPitch()
165
                     << " pressure " << j->getData2() << endl;
166
                break;
167
                
168
            case MIDI_CTRL_CHANGE:
169
            {
170
                int controller = j->getData1();
171
                string name;
172
                switch (controller) {
173
                case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
174
                case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
175
                case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
176
                case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
177
                case MIDI_CONTROLLER_PAN: name = "Pan"; break;
178
                case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
179
                case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
180
                case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
181
                case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
182
                case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
183
                case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
184
                case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
185
                case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
186
                case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
187
                case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
188
                case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
189
                case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
190
                case MIDI_CONTROLLER_RESET: name = "Reset"; break;
191
                case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
192
                case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
193
                }
194
                cout << t << ": Controller change: channel " << ch
195
                     << " controller " << j->getData1();
196
                if (name != "") cout << " (" << name << ")";
197
                cout << " value " << j->getData2() << endl;
198
            }
199
                break;
200

    
201
            case MIDI_PROG_CHANGE:
202
                cout << t << ": Program change: channel " << ch
203
                     << " program " << j->getData1() << endl;
204
                break;
205

    
206
            case MIDI_CHNL_AFTERTOUCH:
207
                cout << t << ": Channel aftertouch: channel " << ch
208
                     << " pressure " << j->getData1() << endl;
209
                break;
210

    
211
            case MIDI_PITCH_BEND:
212
                cout << t << ": Pitch bend: channel " << ch
213
                     << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
214
                break;
215

    
216
            case MIDI_SYSTEM_EXCLUSIVE:
217
                cout << t << ": System exclusive: code "
218
                     << (int)j->getMessageType() << " message length " <<
219
                    j->getMetaMessage().length() << endl;
220
                break;
221
                
222

    
223
            }
224

    
225
            
226
        }
227

    
228

    
229
    }
230

    
231
}
232

    
233