Start midi file processing.

This commit is contained in:
jmsgrogan 2020-05-03 07:56:27 +01:00
parent 59c6161fdb
commit 36826fa1d4
22 changed files with 528 additions and 44 deletions

View file

@ -0,0 +1,211 @@
#include "MidiReader.h"
#include <fstream>
#include <iostream>
#include <cstring>
#include <bitset>
#include "MidiDocument.h"
#include "ByteUtils.h"
#include "MidiTrack.h"
MidiReader::MidiReader()
{
}
bool GetBytes(std::ifstream& file, char* buffer, unsigned number)
{
char c;
for(unsigned idx=0; idx<number; idx++)
{
if(file.get(c))
{
buffer[idx] = c;
}
else
{
return false;
}
}
return true;
}
bool GetWord(std::ifstream& file, char* buffer)
{
return GetBytes(file, buffer, 2);
}
bool GetDWord(std::ifstream& file, char* buffer)
{
return GetBytes(file, buffer, 4);
}
bool MidiReader::ProcessHeader(std::ifstream& file)
{
char c;
unsigned bufferSize = ByteUtils::BYTES_PER_DWORD;
char buffer[bufferSize];
if(!GetDWord(file, buffer))
{
return false;
}
if(!ByteUtils::CompareDWords(buffer, HeaderLabel))
{
return false;
}
if(!GetDWord(file, buffer))
{
return false;
}
int length = ByteUtils::ToDWord(buffer);
if(!GetWord(file, buffer))
{
return false;
}
mDocument.mFormatType = ByteUtils::ToWord(buffer);
if(!GetWord(file, buffer))
{
return false;
}
mDocument.mExpectedTracks = ByteUtils::ToWord(buffer);
if(!GetWord(file, buffer))
{
return false;
}
int time_division;
std::memcpy(&time_division, buffer, sizeof(int));
const int TOP_7_BITS = 0x7F00; // 0111 1111 - 0000 0000
mDocument.mUseFps = ByteUtils::GetWordFirstBit(time_division);
mDocument.mFps = ((~time_division & TOP_7_BITS) >> 8) - 1; // Reverse 2complement of next 7 bits
mDocument.ticksPerFrame = ByteUtils::GetWordLastByte(time_division);
return true;
}
int MidiReader::ProcessTimeDelta(std::ifstream& file)
{
char c;
file.get(c);
bool needs_next = c & ByteUtils::BYTE_FIRST_BIT;
int time_offset = 0;
if(!needs_next)
{
time_offset = int(c);
mTrackByteCount ++;
}
std::cout << "Next " << needs_next <<std::endl;
std::cout << "Offset " << time_offset <<std::endl;
return time_offset;
}
bool MidiReader::ProcessMetaEvent(std::ifstream& file, MetaMidiEvent& event)
{
char c;
file.get(c);
mTrackByteCount ++;
if(MetaMidiEvent::IsTrackName(c))
{
event.mType = MetaMidiEvent::Type::TRACK_NAME;
file.get(c);
mTrackByteCount ++;
int length = int(c);
std::string name;
std::cout << "Track name: " << length <<std::endl;
for(unsigned idx=0; idx<length; idx++)
{
file.get(c);
mTrackByteCount ++;
name += c;
}
std::cout << name << std::endl;
event.mLabel = "Track name";
}
else
{
std::cout << "something else" << std::endl;
std::cout << "Next " << std::bitset<8>(c) << "|" <<std::endl;
}
return true;
}
bool MidiReader::ProcessEvent(std::ifstream& file)
{
char c;
int timeDelta = ProcessTimeDelta(file);
file.get(c);
mTrackByteCount ++;
if(MidiEvent::IsMetaEvent(c))
{
MetaMidiEvent event;
event.mTimeDelta = timeDelta;
std::cout << "Meta event " <<std::endl;
ProcessMetaEvent(file, event);
}
else
{
int first_byte = 0xF0;
int event_type = (c & first_byte) >> 4;
std::cout << "Next " << std::bitset<8>(c) << "|" << event_type <<std::endl;
std::cout << event_type << std::endl;
}
return true;
}
bool MidiReader::ProcessTrackChunk(std::ifstream& file)
{
char c;
unsigned bufferSize = ByteUtils::BYTES_PER_DWORD;
char buffer[bufferSize];
if(!GetDWord(file, buffer))
{
return false;
}
if(!ByteUtils::CompareDWords(buffer, TrackChunkLabel))
{
return false;
}
if(!GetDWord(file, buffer))
{
return false;
}
int chunkSize = ByteUtils::ToDWord(buffer);
std::cout << "Chunk size: "<< chunkSize << std::endl;
mTrackByteCount = 0;
MidiTrack track;
ProcessEvent(file);
std::cout << "Track byte count: "<< mTrackByteCount << std::endl;
ProcessEvent(file);
mDocument.mTracks.push_back(track);
return true;
}
void MidiReader::Read(const std::string& path)
{
std::ifstream file(path);
if(!ProcessHeader(file))
{
std::cout << "Problem processing header" << std::endl;
}
if(!ProcessTrackChunk(file))
{
std::cout << "Problem processing track chunk" << std::endl;
}
file.close();
}