1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __MIDIFILE_H__
14 #define __MIDIFILE_H__
15 
16 #include "libmscore/sig.h"
17 #include "event.h"
18 
19 namespace Ms {
20 
21 const int MIDI_CHANNEL = 16;
22 
23 //---------------------------------------------------------
24 //   MidiType
25 //---------------------------------------------------------
26 
27 enum class MidiType : char {
28       UNKNOWN = 0, GM = 1, GS = 2, XG = 4
29       };
30 
31 class MidiFile;
32 class Xml;
33 
34 //---------------------------------------------------------
35 //   MidiTrack
36 //---------------------------------------------------------
37 
38 class MidiTrack {
39       std::multimap<int, MidiEvent> _events;
40       int _outChannel;
41       int _outPort;
42       bool _drumTrack;
43 
44    protected:
45       void readXml(XmlReader&);
46 
47    public:
48       MidiTrack();
49       ~MidiTrack();
50 
51       bool empty() const;
events()52       const std::multimap<int, MidiEvent>& events() const { return _events; }
events()53       std::multimap<int, MidiEvent>&       events()       { return _events; }
54 
outChannel()55       int outChannel() const            { return _outChannel; }
56       void setOutChannel(int n);
outPort()57       int outPort() const               { return _outPort;    }
setOutPort(int n)58       void setOutPort(int n)            { _outPort = n;       }
59 
drumTrack()60       bool drumTrack() const            { return _drumTrack; }
61 
62       void insert(int tick, const MidiEvent&);
63       void mergeNoteOnOffAndFindMidiType(MidiType *mt);
64       };
65 
66 //---------------------------------------------------------
67 //   MidiFile
68 //---------------------------------------------------------
69 
70 class MidiFile {
71       QIODevice* fp;
72       QList<MidiTrack> _tracks;
73       int _division;
74       bool _isDivisionInTps;       ///< ticks per second, alternative - ticks per beat
75       int _format;               ///< midi file format (0-2)
76       bool _noRunningStatus;     ///< do not use running status on output
77       MidiType _midiType;
78 
79       // values used during read()
80       int status;                ///< running status
81       int sstatus;               ///< running status (not reset after meta or sysex events)
82       int click;                 ///< current tick position in file
83       qint64 curPos;             ///< current file byte position
84 
85       void writeEvent(const MidiEvent& event);
86 
87    protected:
88       // write
89       bool write(const void*, qint64);
90       void writeShort(int);
91       void writeLong(int);
92       bool writeTrack(const MidiTrack &);
93       void putvl(unsigned);
put(unsigned char c)94       void put(unsigned char c) { write(&c, 1); }
95       void writeStatus(int type, int channel);
96 
97       // read
98       void read(void*, qint64);
99       int getvl();
100       int readShort();
101       int readLong();
102       bool readEvent(MidiEvent*);
103       bool readTrack();
104       void skip(qint64);
105 
resetRunningStatus()106       void resetRunningStatus() { status = -1; }
107 
108    public:
109       MidiFile();
110       bool read(QIODevice*);
111       bool write(QIODevice*);
112       void readXml(XmlReader&);
113 
tracks()114       QList<MidiTrack>& tracks()             { return _tracks;  }
tracks()115       const QList<MidiTrack>& tracks() const { return _tracks;  }
116 
midiType()117       MidiType midiType() const     { return _midiType; }
setMidiType(MidiType mt)118       void setMidiType(MidiType mt) { _midiType = mt;   }
119 
format()120       int format() const            { return _format;   }
setFormat(int fmt)121       void setFormat(int fmt)       { _format = fmt;    }
122 
division()123       int division() const          { return _division; }
isDivisionInTps()124       bool isDivisionInTps() const  { return _isDivisionInTps; }
setDivision(int val)125       void setDivision(int val)     { _division = val;  }
126       void separateChannel();
127       };
128 }
129 #endif
130 
131