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: 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@1359: #ifndef SV_MIDI_FILE_READER_H Chris@1359: #define SV_MIDI_FILE_READER_H Chris@148: Chris@148: #include "DataFileReader.h" Chris@148: #include "base/RealTime.h" Chris@148: Chris@148: #include Chris@148: #include Chris@148: #include Chris@148: Chris@148: #include Chris@148: Chris@148: class MIDIEvent; Chris@1491: class ProgressReporter; Chris@148: Chris@301: typedef unsigned char MIDIByte; Chris@301: Chris@392: class MIDIFileImportPreferenceAcquirer // welcome to our grand marble foyer Chris@392: { Chris@392: public: Chris@392: enum TrackPreference { Chris@392: ImportNothing, Chris@392: ImportSingleTrack, Chris@392: MergeAllTracks, Chris@392: MergeAllNonPercussionTracks Chris@392: }; Chris@392: Chris@392: virtual ~MIDIFileImportPreferenceAcquirer() { } Chris@392: Chris@392: virtual TrackPreference getTrackImportPreference Chris@392: (QStringList trackNames, bool haveSomePercussion, Chris@392: QString &singleTrack) const = 0; Chris@392: Chris@392: virtual void showError(QString error) = 0; Chris@392: }; Chris@392: Chris@392: Chris@248: class MIDIFileReader : public DataFileReader Chris@148: { Chris@247: Q_OBJECT Chris@247: Chris@148: public: Chris@392: MIDIFileReader(QString path, Chris@1359: MIDIFileImportPreferenceAcquirer *pref, // may be null Chris@1491: sv_samplerate_t mainModelSampleRate, Chris@1491: ProgressReporter *reporter = 0); Chris@148: virtual ~MIDIFileReader(); Chris@148: Chris@1580: bool isOK() const override; Chris@1580: QString getError() const override; Chris@1580: Model *load() const override; Chris@148: Chris@148: protected: Chris@148: typedef std::vector MIDITrack; Chris@148: typedef std::map MIDIComposition; Chris@148: typedef std::pair TempoChange; // time, qpm Chris@148: typedef std::map TempoMap; // key is MIDI time Chris@148: Chris@148: typedef enum { Chris@1429: MIDI_SINGLE_TRACK_FILE = 0x00, Chris@1429: MIDI_SIMULTANEOUS_TRACK_FILE = 0x01, Chris@1429: MIDI_SEQUENTIAL_TRACK_FILE = 0x02, Chris@1429: 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@1429: Model *existingModel = 0, Chris@1429: int minProgress = 0, Chris@1429: 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@613: bool m_smpte; Chris@148: int m_timingDivision; // pulses per quarter note Chris@613: int m_fps; // if smpte Chris@613: int m_subframes; // if smpte 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 m_trackNames; Chris@148: std::set m_loadableTracks; Chris@148: std::set 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@1038: size_t m_fileSize; Chris@148: QString m_error; Chris@1047: sv_samplerate_t m_mainModelSampleRate; Chris@392: Chris@392: MIDIFileImportPreferenceAcquirer *m_acquirer; Chris@148: }; Chris@148: Chris@148: Chris@148: #endif // _MIDI_FILE_READER_H_