svcore  1.9
MIDIFileReader.h
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     
00008     This program is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU General Public License as
00010     published by the Free Software Foundation; either version 2 of the
00011     License, or (at your option) any later version.  See the file
00012     COPYING included with this distribution for more information.
00013 */
00014 
00015 
00016 /*
00017    This is a modified version of a source file from the 
00018    Rosegarden MIDI and audio sequencer and notation editor.
00019    This file copyright 2000-2006 Richard Bown and Chris Cannam.
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 MIDIFileImportPreferenceAcquirer // welcome to our grand marble foyer
00039 {
00040 public:
00041     enum TrackPreference {
00042         ImportNothing,
00043         ImportSingleTrack,
00044         MergeAllTracks,
00045         MergeAllNonPercussionTracks
00046     };
00047 
00048     virtual ~MIDIFileImportPreferenceAcquirer() { }
00049 
00050     virtual TrackPreference getTrackImportPreference
00051     (QStringList trackNames, bool haveSomePercussion,
00052      QString &singleTrack) const = 0;
00053 
00054     virtual void showError(QString error) = 0;
00055 };
00056 
00057 
00058 class MIDIFileReader : public DataFileReader
00059 {
00060     Q_OBJECT
00061 
00062 public:
00063     MIDIFileReader(QString path,
00064                    MIDIFileImportPreferenceAcquirer *pref,
00065                    int mainModelSampleRate);
00066     virtual ~MIDIFileReader();
00067 
00068     virtual bool isOK() const;
00069     virtual QString getError() const;
00070     virtual Model *load() const;
00071 
00072 protected:
00073     typedef std::vector<MIDIEvent *> MIDITrack;
00074     typedef std::map<unsigned int, MIDITrack> MIDIComposition;
00075     typedef std::pair<RealTime, double> TempoChange; // time, qpm
00076     typedef std::map<unsigned long, TempoChange> TempoMap; // key is MIDI time
00077 
00078     typedef enum {
00079         MIDI_SINGLE_TRACK_FILE          = 0x00,
00080         MIDI_SIMULTANEOUS_TRACK_FILE    = 0x01,
00081         MIDI_SEQUENTIAL_TRACK_FILE      = 0x02,
00082         MIDI_FILE_BAD_FORMAT            = 0xFF
00083     } MIDIFileFormatType;
00084 
00085     bool parseFile();
00086     bool parseHeader(const std::string &midiHeader);
00087     bool parseTrack(unsigned int &trackNum);
00088 
00089     Model *loadTrack(unsigned int trackNum,
00090                      Model *existingModel = 0,
00091                      int minProgress = 0,
00092                      int progressAmount = 100) const;
00093 
00094     bool consolidateNoteOffEvents(unsigned int track);
00095     void updateTempoMap(unsigned int track);
00096     void calculateTempoTimestamps();
00097     RealTime getTimeForMIDITime(unsigned long midiTime) const;
00098 
00099     // Internal convenience functions
00100     //
00101     int  midiBytesToInt(const std::string &bytes);
00102     long midiBytesToLong(const std::string &bytes);
00103 
00104     long getNumberFromMIDIBytes(int firstByte = -1);
00105 
00106     MIDIByte getMIDIByte();
00107     std::string getMIDIBytes(unsigned long bytes);
00108 
00109     bool skipToNextTrack();
00110 
00111     bool                   m_smpte;
00112     int                    m_timingDivision;   // pulses per quarter note
00113     int                    m_fps;              // if smpte
00114     int                    m_subframes;        // if smpte
00115     MIDIFileFormatType     m_format;
00116     unsigned int           m_numberOfTracks;
00117 
00118     long                   m_trackByteCount;
00119     bool                   m_decrementCount;
00120 
00121     std::map<int, QString> m_trackNames;
00122     std::set<unsigned int> m_loadableTracks;
00123     std::set<unsigned int> m_percussionTracks;
00124     MIDIComposition        m_midiComposition;
00125     TempoMap               m_tempoMap;
00126 
00127     QString                m_path;
00128     std::ifstream         *m_midiFile;
00129     int                    m_fileSize;
00130     QString                m_error;
00131     int                    m_mainModelSampleRate;
00132 
00133     MIDIFileImportPreferenceAcquirer *m_acquirer;
00134 };
00135 
00136 
00137 #endif // _MIDI_FILE_READER_H_