annotate data/fileio/MIDIFileReader.h @ 490:c3fb8258e34d

* Make it possible to import an entire session from an RDF document. However, at the moment the timings of events appear to be constrained by how far the audio decoder has got through its audio file at the time the event is queried -- need to investigate.
author Chris Cannam
date Fri, 21 Nov 2008 18:03:14 +0000
parents 183ee2a55fc7
children eb1b517f5eeb
rev   line source
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 /*
Chris@148 17 This is a modified version of a source file from the
Chris@148 18 Rosegarden MIDI and audio sequencer and notation editor.
Chris@148 19 This file copyright 2000-2006 Richard Bown and Chris Cannam.
Chris@148 20 */
Chris@148 21
Chris@148 22 #ifndef _MIDI_FILE_READER_H_
Chris@148 23 #define _MIDI_FILE_READER_H_
Chris@148 24
Chris@148 25 #include "DataFileReader.h"
Chris@148 26 #include "base/RealTime.h"
Chris@148 27
Chris@148 28 #include <map>
Chris@148 29 #include <set>
Chris@148 30 #include <vector>
Chris@148 31
Chris@148 32 #include <QObject>
Chris@148 33
Chris@148 34 class MIDIEvent;
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@392 64 MIDIFileImportPreferenceAcquirer *pref,
Chris@392 65 size_t mainModelSampleRate);
Chris@148 66 virtual ~MIDIFileReader();
Chris@148 67
Chris@148 68 virtual bool isOK() const;
Chris@148 69 virtual QString getError() const;
Chris@148 70 virtual Model *load() const;
Chris@148 71
Chris@148 72 protected:
Chris@148 73 typedef std::vector<MIDIEvent *> MIDITrack;
Chris@148 74 typedef std::map<unsigned int, MIDITrack> MIDIComposition;
Chris@148 75 typedef std::pair<RealTime, double> TempoChange; // time, qpm
Chris@148 76 typedef std::map<unsigned long, TempoChange> TempoMap; // key is MIDI time
Chris@148 77
Chris@148 78 typedef enum {
Chris@148 79 MIDI_SINGLE_TRACK_FILE = 0x00,
Chris@148 80 MIDI_SIMULTANEOUS_TRACK_FILE = 0x01,
Chris@148 81 MIDI_SEQUENTIAL_TRACK_FILE = 0x02,
Chris@148 82 MIDI_FILE_BAD_FORMAT = 0xFF
Chris@148 83 } MIDIFileFormatType;
Chris@148 84
Chris@148 85 bool parseFile();
Chris@148 86 bool parseHeader(const std::string &midiHeader);
Chris@148 87 bool parseTrack(unsigned int &trackNum);
Chris@148 88
Chris@148 89 Model *loadTrack(unsigned int trackNum,
Chris@148 90 Model *existingModel = 0,
Chris@148 91 int minProgress = 0,
Chris@148 92 int progressAmount = 100) const;
Chris@148 93
Chris@148 94 bool consolidateNoteOffEvents(unsigned int track);
Chris@148 95 void updateTempoMap(unsigned int track);
Chris@148 96 void calculateTempoTimestamps();
Chris@148 97 RealTime getTimeForMIDITime(unsigned long midiTime) const;
Chris@148 98
Chris@148 99 // Internal convenience functions
Chris@148 100 //
Chris@148 101 int midiBytesToInt(const std::string &bytes);
Chris@148 102 long midiBytesToLong(const std::string &bytes);
Chris@148 103
Chris@148 104 long getNumberFromMIDIBytes(int firstByte = -1);
Chris@148 105
Chris@148 106 MIDIByte getMIDIByte();
Chris@148 107 std::string getMIDIBytes(unsigned long bytes);
Chris@148 108
Chris@148 109 bool skipToNextTrack();
Chris@148 110
Chris@148 111 int m_timingDivision; // pulses per quarter note
Chris@148 112 MIDIFileFormatType m_format;
Chris@148 113 unsigned int m_numberOfTracks;
Chris@148 114
Chris@148 115 long m_trackByteCount;
Chris@148 116 bool m_decrementCount;
Chris@148 117
Chris@148 118 std::map<int, QString> m_trackNames;
Chris@148 119 std::set<unsigned int> m_loadableTracks;
Chris@148 120 std::set<unsigned int> m_percussionTracks;
Chris@148 121 MIDIComposition m_midiComposition;
Chris@148 122 TempoMap m_tempoMap;
Chris@148 123
Chris@148 124 QString m_path;
Chris@148 125 std::ifstream *m_midiFile;
Chris@148 126 size_t m_fileSize;
Chris@148 127 QString m_error;
Chris@148 128 size_t m_mainModelSampleRate;
Chris@392 129
Chris@392 130 MIDIFileImportPreferenceAcquirer *m_acquirer;
Chris@148 131 };
Chris@148 132
Chris@148 133
Chris@148 134 #endif // _MIDI_FILE_READER_H_