140 lines
4.0 KiB
C++
140 lines
4.0 KiB
C++
/*
|
|
* Filename: SMF.h
|
|
*
|
|
* Description:
|
|
*
|
|
*
|
|
* Version:
|
|
* Created: Wed Mar 11 01:18:30 2020
|
|
* Revision: None
|
|
* Author: Rachel Fae Fox (foxiepaws),fox@foxiepa.ws
|
|
*
|
|
*/
|
|
|
|
#include "message.h"
|
|
namespace amalgam {
|
|
typedef std::basic_string<unsigned char> ByteString;
|
|
namespace midi {
|
|
static unsigned int vlv_length(unsigned char* bytes) {
|
|
int vlvLength = 1;
|
|
int i = 0;
|
|
while ((bytes[i] & 0x80) == 0x80) {
|
|
vlvLength++;
|
|
i++;
|
|
}
|
|
return vlvLength;
|
|
}
|
|
static unsigned int vlv_to_int(unsigned char* bytes) {
|
|
unsigned char* vlvBytes;
|
|
unsigned int real = 0;
|
|
int vlvLength = vlv_length(bytes);
|
|
vlvBytes = (unsigned char*) calloc(vlvLength, sizeof(unsigned char));
|
|
memcpy(vlvBytes,bytes, vlvLength);
|
|
int i = 0;
|
|
do {
|
|
vlvLength--;
|
|
real |= (vlvBytes[i] & 0x7f) << (7*vlvLength);
|
|
i++;
|
|
} while (vlvLength >= 0);
|
|
free(vlvBytes);
|
|
return real;
|
|
}
|
|
static unsigned int int_vlv_length(unsigned int i) {
|
|
int bytes = 0;
|
|
int temp = i;
|
|
while (temp > 127) {
|
|
bytes++;
|
|
temp >>= 7;
|
|
}
|
|
return bytes;
|
|
}
|
|
static void int_to_vlv(unsigned int i, ByteString ba) {
|
|
unsigned int bytes = int_vlv_length(i);
|
|
unsigned int temp = i;
|
|
for (int i = bytes; i >= 0; i--) {
|
|
int cv = temp & 0x7f;
|
|
temp >>= 7;
|
|
if (i < bytes)
|
|
cv |= 0x80;
|
|
|
|
ba.insert(ba.begin(),cv);
|
|
}
|
|
}
|
|
class Event {
|
|
protected:
|
|
unsigned int delta;
|
|
ByteString bytes;
|
|
};
|
|
class MidiEvent : Event {
|
|
Message midi;
|
|
|
|
ByteString toBytes() {
|
|
if (bytes.length() == 0) {
|
|
bytes += int_to_vlv(delta, bytes, length);
|
|
bytes += midi.raw;
|
|
}
|
|
return bytes
|
|
}
|
|
};
|
|
class SysexEvent : MidiEvent {
|
|
};
|
|
class MetaEvent : Event {
|
|
enum class MetaType : int { SequenceNumber = 0x00, Text, Copyright,
|
|
TrackName, InstrumentName, Lyric, Marker, Cue,
|
|
ChannelPrefix = 0x20, End = 0x2F, Tempo = 0x51,
|
|
SMPTEOffset = 0x54, SequencerSpecificEvent = 0x7f,
|
|
TimeSigniture = 0x58, KeySigniture = 0x59 };
|
|
MetaType mt;
|
|
unsigned int length;
|
|
ByteString bytes;
|
|
}
|
|
class Track {
|
|
uint32_t bytelength;
|
|
unsigned char* bytes;
|
|
std::list<Event> events;
|
|
|
|
ByteString toBytes() {
|
|
if (bytes.length() == 0) {
|
|
uint32_t length = 0;
|
|
for (auto e = events.begin(); e != events.end(); ++e) {
|
|
ByteString ebytes = e->toBytes();
|
|
length += ebytes.length();
|
|
bytes += ebytes;
|
|
}
|
|
ByteString len;
|
|
unsigned char* l = (unsigned char* &length);
|
|
len += l[3];
|
|
len += l[2];
|
|
len += l[1];
|
|
len += l[0];
|
|
|
|
bytes = "MTrk" + len + bytes;
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
Track(){}
|
|
Track(unsigned char* b) {
|
|
bytes = b;
|
|
fromBytes();
|
|
}
|
|
Track(std::list<event> e) {
|
|
events = e;
|
|
toBytes();
|
|
}
|
|
|
|
}
|
|
class SMF {
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Local Variables:
|
|
// mode: c++
|
|
// flycheck-clang-language-standard: "c++11"
|
|
// End:
|