annotate data/fileio/MIDIFileReader.h @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents 59e7fe1b1003
children cc27f35aa75c
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@929 65 int 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@613 111 bool m_smpte;
Chris@148 112 int m_timingDivision; // pulses per quarter note
Chris@613 113 int m_fps; // if smpte
Chris@613 114 int m_subframes; // if smpte
Chris@148 115 MIDIFileFormatType m_format;
Chris@148 116 unsigned int m_numberOfTracks;
Chris@148 117
Chris@148 118 long m_trackByteCount;
Chris@148 119 bool m_decrementCount;
Chris@148 120
Chris@148 121 std::map<int, QString> m_trackNames;
Chris@148 122 std::set<unsigned int> m_loadableTracks;
Chris@148 123 std::set<unsigned int> m_percussionTracks;
Chris@148 124 MIDIComposition m_midiComposition;
Chris@148 125 TempoMap m_tempoMap;
Chris@148 126
Chris@148 127 QString m_path;
Chris@148 128 std::ifstream *m_midiFile;
Chris@929 129 int m_fileSize;
Chris@148 130 QString m_error;
Chris@929 131 int m_mainModelSampleRate;
Chris@392 132
Chris@392 133 MIDIFileImportPreferenceAcquirer *m_acquirer;
Chris@148 134 };
Chris@148 135
Chris@148 136
Chris@148 137 #endif // _MIDI_FILE_READER_H_