pianobooster/src/MidiTrack.h

175 lines
4.5 KiB
C++

/*********************************************************************************/
/*!
@file MidiTrack.h
@brief xxxx.
@author L. J. Barman
Copyright (c) 2008-2013, L. J. Barman, all rights reserved
This file is part of the PianoBooster application
PianoBooster is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PianoBooster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PianoBooster. If not, see <http://www.gnu.org/licenses/>.
*/
/*********************************************************************************/
#ifndef __MIDITRACK_H__
#define __MIDITRACK_H__
#include <QString>
#include <string>
#include <fstream>
#include "Queue.h"
#include "MidiEvent.h"
typedef enum
{
SMF_NO_ERROR,
SMF_CANNOT_OPEN_FILE,
SMF_CORRUPTED_MIDI_FILE,
SMF_UNKNOW_EVENT,
SMF_ERROR_TOO_MANY_TRACK,
SMF_END_OF_FILE
} midiErrors_t;
typedef unsigned char byte_t;
typedef unsigned short word_t;
typedef unsigned long dword_t;
// Reads data from a standard MIDI file
class CMidiTrack
{
public:
CMidiTrack(std::fstream& file, int no);
~CMidiTrack()
{
delete m_trackEventQueue;
for ( int chan =0; chan <MAX_MIDI_CHANNELS; chan++ )
{
delete [] m_noteOnEventPtr[chan];
}
}
int readDeltaTime()
{
int deltaTime = m_deltaTime;
m_deltaTime = 0;
return deltaTime;
}
dword_t getTrackLength() {return m_trackLength;}
void decodeTrack();
bool failed() { return m_midiError != SMF_NO_ERROR;}
midiErrors_t getMidiError() { return m_midiError;}
int length() {return m_trackEventQueue->length();}
CMidiEvent pop(int trackNo) {
CMidiEvent m = m_trackEventQueue->pop();
m.setTrack(trackNo);
m.printDetails();
return m;
}
QString getTrackName() {return m_trackName;}
static void setLogLevel(int level){m_logLevel = level;}
private:
void errorFail(midiErrors_t error)
{
if (m_midiError != SMF_NO_ERROR || error != SMF_NO_ERROR)
{
m_midiError = error;
if (m_midiError != SMF_NO_ERROR)
ppLogError("MIDI error %d", m_midiError);
}
}
void midiFailReset() { m_midiError = SMF_NO_ERROR;}
void ppDebugTrack(int level, const char *msg, ...);
byte_t readByte(void)
{
auto c = byte_t();
if (m_trackLengthCounter != 0 )
{
c = static_cast<byte_t>(m_file.get());
if (m_file.fail())
errorFail(SMF_END_OF_FILE);
m_trackLengthCounter--;
}
else
c = 0;
return c;
}
word_t readWord(void)
{
word_t value = readByte() << 8;
value |= readByte();
return value;
}
dword_t readDWord(void)
{
dword_t value = readWord() << 16;
value |= readWord();
return value;
}
void decodeMidiEvent();
dword_t readVarLen();
std::string readTextEvent();
dword_t readDataEvent(int expectedLength);
void readMetaEvent(byte_t type);
void ignoreSysexEvent(byte_t data);
void readTimeSignatureEvent();
void readKeySignatureEvent();
void decodeSystemMessage( byte_t status, byte_t data1 );
void noteOffEvent(CMidiEvent &event, int deltaTime, int channel, int pitch, int velocity);
void createNoteEventPtr(int channel)
{
if (m_noteOnEventPtr[channel] == 0)
{
m_noteOnEventPtr[channel] = new CMidiEvent*[MAX_MIDI_NOTES];
for (int pitch = 0; pitch < MAX_MIDI_NOTES; pitch++)
m_noteOnEventPtr[channel][pitch] = 0;
}
}
std::fstream& m_file;
int m_trackNumber;
std::streampos m_filePos;
dword_t m_trackLength;
dword_t m_trackLengthCounter;
CQueue<CMidiEvent>* m_trackEventQueue;
byte_t m_savedRunningStatus;
int m_deltaTime;
int m_currentTime; // The current time (all the delta times added up)
midiErrors_t m_midiError;
QString m_trackName;
static int m_logLevel;
CMidiEvent** m_noteOnEventPtr[MAX_MIDI_CHANNELS];
};
#endif // __MIDITRACK_H__