00001 #ifndef __CMidiFile__
00002 #define __CMidiFile__
00003
00004
00005
00006 #include <Collections/TCountedPointerArray.hpp>
00007 #include <Basics/CSystemString.hpp>
00008 #include <IO/CFileStream.hpp>
00009 #include "../Audio/TAudioBuffer.hpp"
00010 #include "CMidiEvent.hpp"
00011 #include "CMidiSequence.hpp"
00012 using Exponent::Midi::CMidiSequence;
00013 using Exponent::Midi::CMidiEvent;
00014 using Exponent::Audio::TAudioBuffer;
00015 using Exponent::IO::CFileStream;
00016 using Exponent::Basics::CSystemString;
00017 using Exponent::Collections::TCountedPointerArray;
00018
00019
00020
00021 namespace Exponent
00022 {
00023 namespace Midi
00024 {
00107 class CMidiFile : public CCountedObject
00108 {
00110 EXPONENT_CLASS_DECLARATION;
00113
00114
00115 public:
00116
00117
00118
00122 CMidiFile();
00123
00127 virtual ~CMidiFile();
00128
00129
00130
00137 bool openFile(CFileStream::EStreamMode mode, const CSystemString &filename);
00138
00143 bool closeFile();
00144
00145
00146
00152 bool readFile(CMidiSequence &sequence);
00153
00159 bool writeFile(const CMidiSequence &sequence);
00160
00161
00162
00167 static CString getFileExtension();
00168
00174 static bool isValidFormat(const CSystemString &filename);
00175
00176
00177
00178 protected:
00179
00180
00181
00186 struct SMTHDChunk
00187 {
00188 char m_mthdChunk[4];
00189 unsigned long m_mthdSize;
00191 unsigned short m_fileType;
00192 unsigned short m_numberOfTracks;
00193 unsigned short m_timeFormat;
00195 double m_samplesPerTick;
00196 };
00197
00202 struct SMTRKChunk
00203 {
00204
00205 char m_mtrkChunk[4];
00206 unsigned long m_mtrkSize;
00207 };
00208
00213 struct SMidiEvent
00214 {
00215 unsigned long m_delaySinceLast;
00216 unsigned char m_statusByte;
00217 unsigned char m_midiData[2];
00218 };
00219
00220
00221
00222
00223
00230 static bool readFileHeader(CFileStream &stream, SMTHDChunk &chunk);
00231
00239 static bool readTrackChunks(CFileStream &stream, SMTHDChunk &headChunk, CMidiSequence &sequence);
00240
00247 static unsigned long readVariableLengthUnsignedLong(CFileStream &stream, int &sizeRead);
00248
00249
00250
00251
00252
00259 static bool writeFileHeader(CFileStream &stream, const CMidiSequence &sequence);
00260
00266 static void writeMetaTrack(CFileStream &stream, const CMidiSequence &sequence);
00267
00273 static void writeTimeSignature(CFileStream &stream, const CTimeSignature ts);
00274
00282 static bool writeTrack(CFileStream &stream, const CMidiTrack &track, const double ticksPerSample);
00283
00289 static void writeTrackName(CFileStream &stream, const CString &name);
00290
00296 static void writeTrackMidiChannel(CFileStream &stream, const long channel);
00297
00302 static void writeTrackEnd(CFileStream &stream);
00303
00309 static void writeTempo(CFileStream &stream, const double bpm);
00310
00316 static void writeVariableLengthUnsignedLong(CFileStream &stream, const unsigned long value);
00317
00323 static bool isWritableEvent(const CMidiEvent &event);
00324
00325
00326
00327
00328
00334 static bool isValidMTHDChunk(const SMTHDChunk &chunk);
00335
00341 static bool isValidMTRKChunk(const SMTRKChunk &chunk);
00342
00349 static void computeSamplesPerTick(SMTHDChunk &headChunk, const double sampleRate, const double bpm);
00350
00357 static double computeTicksPerSample(const double sampleRate, const double bpm);
00358
00364 static void processMidiSequence(SMTHDChunk &headChunk, CMidiSequence &sequence);
00365
00366
00367
00368 const static char CMIDI_FILE_EVENT_SIZES[];
00369 const static unsigned short CMIDI_FILE_PPQ = 960;
00371
00372
00373 CFileStream m_stream;
00374 };
00375 }
00376 }
00377 #endif // End of CMidiFile.hpp