Chris@148: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@148: 
Chris@148: /*
Chris@148:     Sonic Visualiser
Chris@148:     An audio file viewer and annotation editor.
Chris@148:     Centre for Digital Music, Queen Mary, University of London.
Chris@148:     
Chris@148:     This program is free software; you can redistribute it and/or
Chris@148:     modify it under the terms of the GNU General Public License as
Chris@148:     published by the Free Software Foundation; either version 2 of the
Chris@148:     License, or (at your option) any later version.  See the file
Chris@148:     COPYING included with this distribution for more information.
Chris@148: */
Chris@148: 
Chris@148: 
Chris@148: /*
Chris@148:    This is a modified version of a source file from the 
Chris@148:    Rosegarden MIDI and audio sequencer and notation editor.
Chris@148:    This file copyright 2000-2006 Richard Bown and Chris Cannam.
Chris@148: */
Chris@148: 
Chris@148: #ifndef _MIDI_FILE_READER_H_
Chris@148: #define _MIDI_FILE_READER_H_
Chris@148: 
Chris@148: #include "DataFileReader.h"
Chris@148: #include "base/RealTime.h"
Chris@148: 
Chris@148: #include <map>
Chris@148: #include <set>
Chris@148: #include <vector>
Chris@148: 
Chris@148: #include <QObject>
Chris@148: 
Chris@148: class MIDIEvent;
Chris@148: 
Chris@248: class MIDIFileReader : public DataFileReader
Chris@148: {
Chris@247:     Q_OBJECT
Chris@247: 
Chris@148: public:
Chris@148:     MIDIFileReader(QString path, size_t mainModelSampleRate);
Chris@148:     virtual ~MIDIFileReader();
Chris@148: 
Chris@148:     virtual bool isOK() const;
Chris@148:     virtual QString getError() const;
Chris@148:     virtual Model *load() const;
Chris@148: 
Chris@148:     typedef unsigned char MIDIByte;
Chris@148: 
Chris@148: protected:
Chris@148:     typedef std::vector<MIDIEvent *> MIDITrack;
Chris@148:     typedef std::map<unsigned int, MIDITrack> MIDIComposition;
Chris@148:     typedef std::pair<RealTime, double> TempoChange; // time, qpm
Chris@148:     typedef std::map<unsigned long, TempoChange> TempoMap; // key is MIDI time
Chris@148: 
Chris@148:     typedef enum {
Chris@148: 	MIDI_SINGLE_TRACK_FILE          = 0x00,
Chris@148: 	MIDI_SIMULTANEOUS_TRACK_FILE    = 0x01,
Chris@148: 	MIDI_SEQUENTIAL_TRACK_FILE      = 0x02,
Chris@148: 	MIDI_FILE_BAD_FORMAT            = 0xFF
Chris@148:     } MIDIFileFormatType;
Chris@148: 
Chris@148:     bool parseFile();
Chris@148:     bool parseHeader(const std::string &midiHeader);
Chris@148:     bool parseTrack(unsigned int &trackNum);
Chris@148: 
Chris@148:     Model *loadTrack(unsigned int trackNum,
Chris@148: 		     Model *existingModel = 0,
Chris@148: 		     int minProgress = 0,
Chris@148: 		     int progressAmount = 100) const;
Chris@148: 
Chris@148:     bool consolidateNoteOffEvents(unsigned int track);
Chris@148:     void updateTempoMap(unsigned int track);
Chris@148:     void calculateTempoTimestamps();
Chris@148:     RealTime getTimeForMIDITime(unsigned long midiTime) const;
Chris@148: 
Chris@148:     // Internal convenience functions
Chris@148:     //
Chris@148:     int  midiBytesToInt(const std::string &bytes);
Chris@148:     long midiBytesToLong(const std::string &bytes);
Chris@148: 
Chris@148:     long getNumberFromMIDIBytes(int firstByte = -1);
Chris@148: 
Chris@148:     MIDIByte getMIDIByte();
Chris@148:     std::string getMIDIBytes(unsigned long bytes);
Chris@148: 
Chris@148:     bool skipToNextTrack();
Chris@148: 
Chris@148:     int                    m_timingDivision;   // pulses per quarter note
Chris@148:     MIDIFileFormatType     m_format;
Chris@148:     unsigned int           m_numberOfTracks;
Chris@148: 
Chris@148:     long                   m_trackByteCount;
Chris@148:     bool                   m_decrementCount;
Chris@148: 
Chris@148:     std::map<int, QString> m_trackNames;
Chris@148:     std::set<unsigned int> m_loadableTracks;
Chris@148:     std::set<unsigned int> m_percussionTracks;
Chris@148:     MIDIComposition        m_midiComposition;
Chris@148:     TempoMap               m_tempoMap;
Chris@148: 
Chris@148:     QString                m_path;
Chris@148:     std::ifstream         *m_midiFile;
Chris@148:     size_t                 m_fileSize;
Chris@148:     QString                m_error;
Chris@148:     size_t                 m_mainModelSampleRate;
Chris@148: };
Chris@148: 
Chris@148: 
Chris@148: #endif // _MIDI_FILE_READER_H_