aboutsummaryrefslogtreecommitdiff
path: root/src/adlmidi_load.cpp
diff options
context:
space:
mode:
authorWohlstand <admin@wohlnet.ru>2017-02-15 16:19:08 +0300
committerWohlstand <admin@wohlnet.ru>2017-02-15 16:19:08 +0300
commit9cd892706bf782c8a0e47731bd71e629d505c5cf (patch)
tree5d83247581e0b9a513be0ea38135afa3c94b440f /src/adlmidi_load.cpp
parentba0b0c4d5c1e8c8926c6838dddb0f6abdbccd9f2 (diff)
downloadlibADLMIDI-9cd892706bf782c8a0e47731bd71e629d505c5cf.tar.gz
libADLMIDI-9cd892706bf782c8a0e47731bd71e629d505c5cf.tar.bz2
libADLMIDI-9cd892706bf782c8a0e47731bd71e629d505c5cf.zip
Fixed logarithmic volumes flag and added support for XMI and MUS formats
MUS playing was totally invalid: the MUS data are completely different from regular MIDI data. Now is added a right converter which results a MIDI data which can be played correctly.
Diffstat (limited to 'src/adlmidi_load.cpp')
-rw-r--r--src/adlmidi_load.cpp136
1 files changed, 105 insertions, 31 deletions
diff --git a/src/adlmidi_load.cpp b/src/adlmidi_load.cpp
index af7cf0d..1ef355d 100644
--- a/src/adlmidi_load.cpp
+++ b/src/adlmidi_load.cpp
@@ -23,6 +23,10 @@
#include "adlmidi_private.hpp"
+#include "adlmidi_mus2mid.h"
+#include "adlmidi_xmi2mid.h"
+
+#include <memory>
uint64_t MIDIplay::ReadBEint(const void *buffer, size_t nbytes)
{
@@ -97,9 +101,11 @@ bool MIDIplay::LoadMIDI(void *data, unsigned long size)
bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr)
{
-#define qqq(x) (void)x
+ #define qqq(x) (void)x
size_t fsize;
qqq(fsize);
+ //! Temp buffer for conversion
+ std::shared_ptr<uint8_t> cvt_buf;
//std::FILE* fr = std::fopen(filename.c_str(), "rb");
if(!fr.isValid())
@@ -108,19 +114,8 @@ bool MIDIplay::LoadMIDI(MIDIplay::fileReader &fr)
return false;
}
- const size_t HeaderSize = 4 + 4 + 2 + 2 + 2; // 14
- char HeaderBuf[HeaderSize] = "";
-riffskip:
- ;
- fsize = fr.read(HeaderBuf, 1, HeaderSize);
-
- if(std::memcmp(HeaderBuf, "RIFF", 4) == 0)
- {
- fr.seek(6l, SEEK_CUR);
- goto riffskip;
- }
+ /**** Set all properties BEFORE starting of actial file reading! ****/
- size_t DeltaTicks = 192, TrackCount = 1;
config->stored_samples = 0;
config->backup_samples_size = 0;
opl.AdlPercussionMode = config->AdlPercussionMode;
@@ -165,16 +160,30 @@ riffskip:
opl.NumFourOps = config->NumFourOps;
cmf_percussion_mode = false;
opl.Reset();
- trackStart = true;
- loopStart = true;
+
+ trackStart = true;
+ loopStart = true;
loopStart_passed = false;
- invalidLoop = false;
- loopStart_hit = false;
+ invalidLoop = false;
+ loopStart_hit = false;
+
bool is_GMF = false; // GMD/MUS files (ScummVM)
- bool is_MUS = false; // MUS/DMX files (Doom)
+ //bool is_MUS = false; // MUS/DMX files (Doom)
bool is_IMF = false; // IMF
bool is_CMF = false; // Creative Music format (CMF/CTMF)
- //std::vector<unsigned char> MUS_instrumentList;
+
+ const size_t HeaderSize = 4 + 4 + 2 + 2 + 2; // 14
+ char HeaderBuf[HeaderSize] = "";
+ size_t DeltaTicks = 192, TrackCount = 1;
+
+riffskip:
+ fsize = fr.read(HeaderBuf, 1, HeaderSize);
+
+ if(std::memcmp(HeaderBuf, "RIFF", 4) == 0)
+ {
+ fr.seek(6l, SEEK_CUR);
+ goto riffskip;
+ }
if(std::memcmp(HeaderBuf, "GMF\x1", 4) == 0)
{
@@ -185,9 +194,74 @@ riffskip:
else if(std::memcmp(HeaderBuf, "MUS\x1A", 4) == 0)
{
// MUS/DMX files (Doom)
- uint64_t start = ReadLEint(HeaderBuf + 6, 2);
- is_MUS = true;
- fr.seek(static_cast<long>(start), SEEK_SET);
+ //uint64_t start = ReadLEint(HeaderBuf + 6, 2);
+ //is_MUS = true;
+ fr.seek(0, SEEK_END);
+ size_t mus_len = fr.tell();
+ fr.seek(0, SEEK_SET);
+ uint8_t *mus = (uint8_t*)malloc(mus_len);
+ if(!mus)
+ {
+ ADLMIDI_ErrorString = "Out of memory!";
+ return false;
+ }
+ fr.read(mus, 1, mus_len);
+ //Close source stream
+ fr.close();
+
+ uint8_t *mid = NULL;
+ uint32_t mid_len = 0;
+ int m2mret = AdlMidi_mus2midi(mus, static_cast<uint32_t>(mus_len),
+ &mid, &mid_len, 0);
+ if(mus) free(mus);
+ if(m2mret < 0)
+ {
+ ADLMIDI_ErrorString = "Invalid MUS/DMX data format!";
+ return false;
+ }
+ cvt_buf.reset(mid, ::free);
+ //Open converted MIDI file
+ fr.openData(mid, static_cast<size_t>(mid_len));
+ //Re-Read header again!
+ goto riffskip;
+ }
+ else if(std::memcmp(HeaderBuf, "FORM", 4) == 0)
+ {
+ if(std::memcmp(HeaderBuf + 8, "XDIR", 4) != 0)
+ {
+ fr.close();
+ ADLMIDI_ErrorString = fr._fileName + ": Invalid format\n";
+ return false;
+ }
+
+ fr.seek(0, SEEK_END);
+ size_t mus_len = fr.tell();
+ fr.seek(0, SEEK_SET);
+ uint8_t *mus = (uint8_t*)malloc(mus_len);
+ if(!mus)
+ {
+ ADLMIDI_ErrorString = "Out of memory!";
+ return false;
+ }
+ fr.read(mus, 1, mus_len);
+ //Close source stream
+ fr.close();
+
+ uint8_t *mid = NULL;
+ uint32_t mid_len = 0;
+ int m2mret = AdlMidi_xmi2midi(mus, static_cast<uint32_t>(mus_len),
+ &mid, &mid_len, XMIDI_CONVERT_NOCONVERSION);
+ if(mus) free(mus);
+ if(m2mret < 0)
+ {
+ ADLMIDI_ErrorString = "Invalid XMI data format!";
+ return false;
+ }
+ cvt_buf.reset(mid, ::free);
+ //Open converted MIDI file
+ fr.openData(mid, static_cast<size_t>(mid_len));
+ //Re-Read header again!
+ goto riffskip;
}
else if(std::memcmp(HeaderBuf, "CTMF", 4) == 0)
{
@@ -375,14 +449,14 @@ InvFmt:
TrackLength = fr.tell() - pos;
fr.seek(static_cast<long>(pos), SEEK_SET);
}
- else if(is_MUS) // Read TrackLength from file position 4
- {
- size_t pos = fr.tell();
- fr.seek(4, SEEK_SET);
- TrackLength = static_cast<size_t>(fr.getc());
- TrackLength += static_cast<size_t>(fr.getc() << 8);
- fr.seek(static_cast<long>(pos), SEEK_SET);
- }
+ //else if(is_MUS) // Read TrackLength from file position 4
+ //{
+ // size_t pos = fr.tell();
+ // fr.seek(4, SEEK_SET);
+ // TrackLength = static_cast<size_t>(fr.getc());
+ // TrackLength += static_cast<size_t>(fr.getc() << 8);
+ // fr.seek(static_cast<long>(pos), SEEK_SET);
+ //}
else
{
fsize = fr.read(HeaderBuf, 1, 8);
@@ -398,7 +472,7 @@ InvFmt:
fsize = fr.read(&TrackData[tk][0], 1, TrackLength);
totalGotten += fsize;
- if(is_GMF || is_MUS) // Note: CMF does include the track end tag.
+ if(is_GMF /*|| is_MUS*/) // Note: CMF does include the track end tag.
TrackData[tk].insert(TrackData[tk].end(), EndTag + 0, EndTag + 4);
bool ok = false;