Chris@148
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@148
|
2
|
Chris@148
|
3 /*
|
Chris@148
|
4 Sonic Visualiser
|
Chris@148
|
5 An audio file viewer and annotation editor.
|
Chris@148
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@148
|
7
|
Chris@148
|
8 This program is free software; you can redistribute it and/or
|
Chris@148
|
9 modify it under the terms of the GNU General Public License as
|
Chris@148
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@148
|
11 License, or (at your option) any later version. See the file
|
Chris@148
|
12 COPYING included with this distribution for more information.
|
Chris@148
|
13 */
|
Chris@148
|
14
|
Chris@148
|
15 /*
|
Chris@148
|
16 This is a modified version of a source file from the
|
Chris@148
|
17 Rosegarden MIDI and audio sequencer and notation editor.
|
Chris@148
|
18 This file copyright 2000-2006 Richard Bown and Chris Cannam.
|
Chris@148
|
19 */
|
Chris@148
|
20
|
Chris@1359
|
21 #ifndef SV_MIDI_FILE_READER_H
|
Chris@1359
|
22 #define SV_MIDI_FILE_READER_H
|
Chris@148
|
23
|
Chris@148
|
24 #include "DataFileReader.h"
|
Chris@148
|
25 #include "base/RealTime.h"
|
Chris@148
|
26
|
Chris@148
|
27 #include <map>
|
Chris@148
|
28 #include <set>
|
Chris@148
|
29 #include <vector>
|
Chris@148
|
30
|
Chris@148
|
31 #include <QObject>
|
Chris@148
|
32
|
Chris@148
|
33 class MIDIEvent;
|
Chris@1491
|
34 class ProgressReporter;
|
Chris@148
|
35
|
Chris@301
|
36 typedef unsigned char MIDIByte;
|
Chris@301
|
37
|
Chris@392
|
38 class MIDIFileImportPreferenceAcquirer // welcome to our grand marble foyer
|
Chris@392
|
39 {
|
Chris@392
|
40 public:
|
Chris@392
|
41 enum TrackPreference {
|
Chris@392
|
42 ImportNothing,
|
Chris@392
|
43 ImportSingleTrack,
|
Chris@392
|
44 MergeAllTracks,
|
Chris@392
|
45 MergeAllNonPercussionTracks
|
Chris@392
|
46 };
|
Chris@392
|
47
|
Chris@392
|
48 virtual ~MIDIFileImportPreferenceAcquirer() { }
|
Chris@392
|
49
|
Chris@392
|
50 virtual TrackPreference getTrackImportPreference
|
Chris@392
|
51 (QStringList trackNames, bool haveSomePercussion,
|
Chris@392
|
52 QString &singleTrack) const = 0;
|
Chris@392
|
53
|
Chris@392
|
54 virtual void showError(QString error) = 0;
|
Chris@392
|
55 };
|
Chris@392
|
56
|
Chris@392
|
57
|
Chris@248
|
58 class MIDIFileReader : public DataFileReader
|
Chris@148
|
59 {
|
Chris@247
|
60 Q_OBJECT
|
Chris@247
|
61
|
Chris@148
|
62 public:
|
Chris@392
|
63 MIDIFileReader(QString path,
|
Chris@1359
|
64 MIDIFileImportPreferenceAcquirer *pref, // may be null
|
Chris@1491
|
65 sv_samplerate_t mainModelSampleRate,
|
Chris@1491
|
66 ProgressReporter *reporter = 0);
|
Chris@148
|
67 virtual ~MIDIFileReader();
|
Chris@148
|
68
|
Chris@1580
|
69 bool isOK() const override;
|
Chris@1580
|
70 QString getError() const override;
|
Chris@1580
|
71 Model *load() const override;
|
Chris@148
|
72
|
Chris@148
|
73 protected:
|
Chris@148
|
74 typedef std::vector<MIDIEvent *> MIDITrack;
|
Chris@148
|
75 typedef std::map<unsigned int, MIDITrack> MIDIComposition;
|
Chris@148
|
76 typedef std::pair<RealTime, double> TempoChange; // time, qpm
|
Chris@148
|
77 typedef std::map<unsigned long, TempoChange> TempoMap; // key is MIDI time
|
Chris@148
|
78
|
Chris@148
|
79 typedef enum {
|
Chris@1429
|
80 MIDI_SINGLE_TRACK_FILE = 0x00,
|
Chris@1429
|
81 MIDI_SIMULTANEOUS_TRACK_FILE = 0x01,
|
Chris@1429
|
82 MIDI_SEQUENTIAL_TRACK_FILE = 0x02,
|
Chris@1429
|
83 MIDI_FILE_BAD_FORMAT = 0xFF
|
Chris@148
|
84 } MIDIFileFormatType;
|
Chris@148
|
85
|
Chris@148
|
86 bool parseFile();
|
Chris@148
|
87 bool parseHeader(const std::string &midiHeader);
|
Chris@148
|
88 bool parseTrack(unsigned int &trackNum);
|
Chris@148
|
89
|
Chris@148
|
90 Model *loadTrack(unsigned int trackNum,
|
Chris@1429
|
91 Model *existingModel = 0,
|
Chris@1429
|
92 int minProgress = 0,
|
Chris@1429
|
93 int progressAmount = 100) const;
|
Chris@148
|
94
|
Chris@148
|
95 bool consolidateNoteOffEvents(unsigned int track);
|
Chris@148
|
96 void updateTempoMap(unsigned int track);
|
Chris@148
|
97 void calculateTempoTimestamps();
|
Chris@148
|
98 RealTime getTimeForMIDITime(unsigned long midiTime) const;
|
Chris@148
|
99
|
Chris@148
|
100 // Internal convenience functions
|
Chris@148
|
101 //
|
Chris@148
|
102 int midiBytesToInt(const std::string &bytes);
|
Chris@148
|
103 long midiBytesToLong(const std::string &bytes);
|
Chris@148
|
104
|
Chris@148
|
105 long getNumberFromMIDIBytes(int firstByte = -1);
|
Chris@148
|
106
|
Chris@148
|
107 MIDIByte getMIDIByte();
|
Chris@148
|
108 std::string getMIDIBytes(unsigned long bytes);
|
Chris@148
|
109
|
Chris@148
|
110 bool skipToNextTrack();
|
Chris@148
|
111
|
Chris@613
|
112 bool m_smpte;
|
Chris@148
|
113 int m_timingDivision; // pulses per quarter note
|
Chris@613
|
114 int m_fps; // if smpte
|
Chris@613
|
115 int m_subframes; // if smpte
|
Chris@148
|
116 MIDIFileFormatType m_format;
|
Chris@148
|
117 unsigned int m_numberOfTracks;
|
Chris@148
|
118
|
Chris@148
|
119 long m_trackByteCount;
|
Chris@148
|
120 bool m_decrementCount;
|
Chris@148
|
121
|
Chris@148
|
122 std::map<int, QString> m_trackNames;
|
Chris@148
|
123 std::set<unsigned int> m_loadableTracks;
|
Chris@148
|
124 std::set<unsigned int> m_percussionTracks;
|
Chris@148
|
125 MIDIComposition m_midiComposition;
|
Chris@148
|
126 TempoMap m_tempoMap;
|
Chris@148
|
127
|
Chris@148
|
128 QString m_path;
|
Chris@148
|
129 std::ifstream *m_midiFile;
|
Chris@1038
|
130 size_t m_fileSize;
|
Chris@148
|
131 QString m_error;
|
Chris@1047
|
132 sv_samplerate_t m_mainModelSampleRate;
|
Chris@392
|
133
|
Chris@392
|
134 MIDIFileImportPreferenceAcquirer *m_acquirer;
|
Chris@148
|
135 };
|
Chris@148
|
136
|
Chris@148
|
137
|
Chris@148
|
138 #endif // _MIDI_FILE_READER_H_
|