annotate data/fileio/MIDIFileReader.h @ 1412:b7a9edee85e0 scale-ticks

Change loop to something that feels more correct, though it makes no difference to the tests here. More tests, one failing.
author Chris Cannam
date Thu, 04 May 2017 08:32:41 +0100
parents 1c9bbbb6116a
children 48e9f538e6e9
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 This is a modified version of a source file from the
Chris@148 17 Rosegarden MIDI and audio sequencer and notation editor.
Chris@148 18 This file copyright 2000-2006 Richard Bown and Chris Cannam.
Chris@148 19 */
Chris@148 20
Chris@1359 21 #ifndef SV_MIDI_FILE_READER_H
Chris@1359 22 #define SV_MIDI_FILE_READER_H
Chris@148 23
Chris@148 24 #include "DataFileReader.h"
Chris@148 25 #include "base/RealTime.h"
Chris@148 26
Chris@148 27 #include <map>
Chris@148 28 #include <set>
Chris@148 29 #include <vector>
Chris@148 30
Chris@148 31 #include <QObject>
Chris@148 32
Chris@148 33 class MIDIEvent;
Chris@148 34
Chris@301 35 typedef unsigned char MIDIByte;
Chris@301 36
Chris@392 37 class MIDIFileImportPreferenceAcquirer // welcome to our grand marble foyer
Chris@392 38 {
Chris@392 39 public:
Chris@392 40 enum TrackPreference {
Chris@392 41 ImportNothing,
Chris@392 42 ImportSingleTrack,
Chris@392 43 MergeAllTracks,
Chris@392 44 MergeAllNonPercussionTracks
Chris@392 45 };
Chris@392 46
Chris@392 47 virtual ~MIDIFileImportPreferenceAcquirer() { }
Chris@392 48
Chris@392 49 virtual TrackPreference getTrackImportPreference
Chris@392 50 (QStringList trackNames, bool haveSomePercussion,
Chris@392 51 QString &singleTrack) const = 0;
Chris@392 52
Chris@392 53 virtual void showError(QString error) = 0;
Chris@392 54 };
Chris@392 55
Chris@392 56
Chris@248 57 class MIDIFileReader : public DataFileReader
Chris@148 58 {
Chris@247 59 Q_OBJECT
Chris@247 60
Chris@148 61 public:
Chris@392 62 MIDIFileReader(QString path,
Chris@1359 63 MIDIFileImportPreferenceAcquirer *pref, // may be null
Chris@1047 64 sv_samplerate_t mainModelSampleRate);
Chris@148 65 virtual ~MIDIFileReader();
Chris@148 66
Chris@148 67 virtual bool isOK() const;
Chris@148 68 virtual QString getError() const;
Chris@148 69 virtual Model *load() const;
Chris@148 70
Chris@148 71 protected:
Chris@148 72 typedef std::vector<MIDIEvent *> MIDITrack;
Chris@148 73 typedef std::map<unsigned int, MIDITrack> MIDIComposition;
Chris@148 74 typedef std::pair<RealTime, double> TempoChange; // time, qpm
Chris@148 75 typedef std::map<unsigned long, TempoChange> TempoMap; // key is MIDI time
Chris@148 76
Chris@148 77 typedef enum {
Chris@148 78 MIDI_SINGLE_TRACK_FILE = 0x00,
Chris@148 79 MIDI_SIMULTANEOUS_TRACK_FILE = 0x01,
Chris@148 80 MIDI_SEQUENTIAL_TRACK_FILE = 0x02,
Chris@148 81 MIDI_FILE_BAD_FORMAT = 0xFF
Chris@148 82 } MIDIFileFormatType;
Chris@148 83
Chris@148 84 bool parseFile();
Chris@148 85 bool parseHeader(const std::string &midiHeader);
Chris@148 86 bool parseTrack(unsigned int &trackNum);
Chris@148 87
Chris@148 88 Model *loadTrack(unsigned int trackNum,
Chris@148 89 Model *existingModel = 0,
Chris@148 90 int minProgress = 0,
Chris@148 91 int progressAmount = 100) const;
Chris@148 92
Chris@148 93 bool consolidateNoteOffEvents(unsigned int track);
Chris@148 94 void updateTempoMap(unsigned int track);
Chris@148 95 void calculateTempoTimestamps();
Chris@148 96 RealTime getTimeForMIDITime(unsigned long midiTime) const;
Chris@148 97
Chris@148 98 // Internal convenience functions
Chris@148 99 //
Chris@148 100 int midiBytesToInt(const std::string &bytes);
Chris@148 101 long midiBytesToLong(const std::string &bytes);
Chris@148 102
Chris@148 103 long getNumberFromMIDIBytes(int firstByte = -1);
Chris@148 104
Chris@148 105 MIDIByte getMIDIByte();
Chris@148 106 std::string getMIDIBytes(unsigned long bytes);
Chris@148 107
Chris@148 108 bool skipToNextTrack();
Chris@148 109
Chris@613 110 bool m_smpte;
Chris@148 111 int m_timingDivision; // pulses per quarter note
Chris@613 112 int m_fps; // if smpte
Chris@613 113 int m_subframes; // if smpte
Chris@148 114 MIDIFileFormatType m_format;
Chris@148 115 unsigned int m_numberOfTracks;
Chris@148 116
Chris@148 117 long m_trackByteCount;
Chris@148 118 bool m_decrementCount;
Chris@148 119
Chris@148 120 std::map<int, QString> m_trackNames;
Chris@148 121 std::set<unsigned int> m_loadableTracks;
Chris@148 122 std::set<unsigned int> m_percussionTracks;
Chris@148 123 MIDIComposition m_midiComposition;
Chris@148 124 TempoMap m_tempoMap;
Chris@148 125
Chris@148 126 QString m_path;
Chris@148 127 std::ifstream *m_midiFile;
Chris@1038 128 size_t m_fileSize;
Chris@148 129 QString m_error;
Chris@1047 130 sv_samplerate_t m_mainModelSampleRate;
Chris@392 131
Chris@392 132 MIDIFileImportPreferenceAcquirer *m_acquirer;
Chris@148 133 };
Chris@148 134
Chris@148 135
Chris@148 136 #endif // _MIDI_FILE_READER_H_