00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _MIDI_FILE_READER_H_
00023 #define _MIDI_FILE_READER_H_
00024
00025 #include "DataFileReader.h"
00026 #include "base/RealTime.h"
00027
00028 #include <map>
00029 #include <set>
00030 #include <vector>
00031
00032 #include <QObject>
00033
00034 class MIDIEvent;
00035
00036 typedef unsigned char MIDIByte;
00037
00038 class MIDIFileReader : public DataFileReader
00039 {
00040 Q_OBJECT
00041
00042 public:
00043 MIDIFileReader(QString path, size_t mainModelSampleRate);
00044 virtual ~MIDIFileReader();
00045
00046 virtual bool isOK() const;
00047 virtual QString getError() const;
00048 virtual Model *load() const;
00049
00050 protected:
00051 typedef std::vector<MIDIEvent *> MIDITrack;
00052 typedef std::map<unsigned int, MIDITrack> MIDIComposition;
00053 typedef std::pair<RealTime, double> TempoChange;
00054 typedef std::map<unsigned long, TempoChange> TempoMap;
00055
00056 typedef enum {
00057 MIDI_SINGLE_TRACK_FILE = 0x00,
00058 MIDI_SIMULTANEOUS_TRACK_FILE = 0x01,
00059 MIDI_SEQUENTIAL_TRACK_FILE = 0x02,
00060 MIDI_FILE_BAD_FORMAT = 0xFF
00061 } MIDIFileFormatType;
00062
00063 bool parseFile();
00064 bool parseHeader(const std::string &midiHeader);
00065 bool parseTrack(unsigned int &trackNum);
00066
00067 Model *loadTrack(unsigned int trackNum,
00068 Model *existingModel = 0,
00069 int minProgress = 0,
00070 int progressAmount = 100) const;
00071
00072 bool consolidateNoteOffEvents(unsigned int track);
00073 void updateTempoMap(unsigned int track);
00074 void calculateTempoTimestamps();
00075 RealTime getTimeForMIDITime(unsigned long midiTime) const;
00076
00077
00078
00079 int midiBytesToInt(const std::string &bytes);
00080 long midiBytesToLong(const std::string &bytes);
00081
00082 long getNumberFromMIDIBytes(int firstByte = -1);
00083
00084 MIDIByte getMIDIByte();
00085 std::string getMIDIBytes(unsigned long bytes);
00086
00087 bool skipToNextTrack();
00088
00089 int m_timingDivision;
00090 MIDIFileFormatType m_format;
00091 unsigned int m_numberOfTracks;
00092
00093 long m_trackByteCount;
00094 bool m_decrementCount;
00095
00096 std::map<int, QString> m_trackNames;
00097 std::set<unsigned int> m_loadableTracks;
00098 std::set<unsigned int> m_percussionTracks;
00099 MIDIComposition m_midiComposition;
00100 TempoMap m_tempoMap;
00101
00102 QString m_path;
00103 std::ifstream *m_midiFile;
00104 size_t m_fileSize;
00105 QString m_error;
00106 size_t m_mainModelSampleRate;
00107 };
00108
00109
00110 #endif // _MIDI_FILE_READER_H_