annotate data/fileio/MIDIFileReader.h @ 1881:b504df98c3be

Ensure completion on output model is started at zero, so if it's checked before the input model has become ready and the transform has begun, it is not accidentally reported as complete (affected re-aligning models in Sonic Lineup when replacing the session)
author Chris Cannam
date Fri, 26 Jun 2020 11:45:39 +0100
parents c01cbe41aeb5
children
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@1491 34 class ProgressReporter;
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@1359 64 MIDIFileImportPreferenceAcquirer *pref, // may be null
Chris@1491 65 sv_samplerate_t mainModelSampleRate,
Chris@1491 66 ProgressReporter *reporter = 0);
Chris@148 67 virtual ~MIDIFileReader();
Chris@148 68
Chris@1580 69 bool isOK() const override;
Chris@1580 70 QString getError() const override;
Chris@1580 71 Model *load() const override;
Chris@148 72
Chris@148 73 protected:
Chris@148 74 typedef std::vector<MIDIEvent *> MIDITrack;
Chris@148 75 typedef std::map<unsigned int, MIDITrack> MIDIComposition;
Chris@148 76 typedef std::pair<RealTime, double> TempoChange; // time, qpm
Chris@148 77 typedef std::map<unsigned long, TempoChange> TempoMap; // key is MIDI time
Chris@148 78
Chris@148 79 typedef enum {
Chris@1429 80 MIDI_SINGLE_TRACK_FILE = 0x00,
Chris@1429 81 MIDI_SIMULTANEOUS_TRACK_FILE = 0x01,
Chris@1429 82 MIDI_SEQUENTIAL_TRACK_FILE = 0x02,
Chris@1429 83 MIDI_FILE_BAD_FORMAT = 0xFF
Chris@148 84 } MIDIFileFormatType;
Chris@148 85
Chris@148 86 bool parseFile();
Chris@148 87 bool parseHeader(const std::string &midiHeader);
Chris@148 88 bool parseTrack(unsigned int &trackNum);
Chris@148 89
Chris@148 90 Model *loadTrack(unsigned int trackNum,
Chris@1429 91 Model *existingModel = 0,
Chris@1429 92 int minProgress = 0,
Chris@1429 93 int progressAmount = 100) const;
Chris@148 94
Chris@148 95 bool consolidateNoteOffEvents(unsigned int track);
Chris@148 96 void updateTempoMap(unsigned int track);
Chris@148 97 void calculateTempoTimestamps();
Chris@148 98 RealTime getTimeForMIDITime(unsigned long midiTime) const;
Chris@148 99
Chris@148 100 // Internal convenience functions
Chris@148 101 //
Chris@148 102 int midiBytesToInt(const std::string &bytes);
Chris@148 103 long midiBytesToLong(const std::string &bytes);
Chris@148 104
Chris@148 105 long getNumberFromMIDIBytes(int firstByte = -1);
Chris@148 106
Chris@148 107 MIDIByte getMIDIByte();
Chris@148 108 std::string getMIDIBytes(unsigned long bytes);
Chris@148 109
Chris@148 110 bool skipToNextTrack();
Chris@148 111
Chris@613 112 bool m_smpte;
Chris@148 113 int m_timingDivision; // pulses per quarter note
Chris@613 114 int m_fps; // if smpte
Chris@613 115 int m_subframes; // if smpte
Chris@148 116 MIDIFileFormatType m_format;
Chris@148 117 unsigned int m_numberOfTracks;
Chris@148 118
Chris@148 119 long m_trackByteCount;
Chris@148 120 bool m_decrementCount;
Chris@148 121
Chris@148 122 std::map<int, QString> m_trackNames;
Chris@148 123 std::set<unsigned int> m_loadableTracks;
Chris@148 124 std::set<unsigned int> m_percussionTracks;
Chris@148 125 MIDIComposition m_midiComposition;
Chris@148 126 TempoMap m_tempoMap;
Chris@148 127
Chris@148 128 QString m_path;
Chris@148 129 std::ifstream *m_midiFile;
Chris@1038 130 size_t m_fileSize;
Chris@148 131 QString m_error;
Chris@1047 132 sv_samplerate_t m_mainModelSampleRate;
Chris@392 133
Chris@392 134 MIDIFileImportPreferenceAcquirer *m_acquirer;
Chris@148 135 };
Chris@148 136
Chris@148 137
Chris@148 138 #endif // _MIDI_FILE_READER_H_