aboutsummaryrefslogtreecommitdiff
path: root/src/adlmidi_private.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/adlmidi_private.hpp')
-rw-r--r--src/adlmidi_private.hpp427
1 files changed, 231 insertions, 196 deletions
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index 622e9f2..7defa1e 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -194,6 +194,14 @@ public:
*/
struct MIDIEventHooks
{
+ MIDIEventHooks() :
+ onEvent(NULL),
+ onEvent_userData(NULL),
+ onNote(NULL),
+ onNote_userData(NULL),
+ onDebugMessage(NULL),
+ onDebugMessage_userData(NULL)
+ {}
//! Raw MIDI event hook
typedef void (*RawEventHook)(void *userdata, uint8_t type, uint8_t subtype, uint8_t channel, uint8_t *data, size_t len);
RawEventHook onEvent;
@@ -212,8 +220,165 @@ struct MIDIEventHooks
class MIDIplay
{
- std::map<std::string, uint64_t> devices;
- std::map<uint64_t /*track*/, uint64_t /*channel begin index*/> current_device;
+public:
+ MIDIplay();
+
+ ~MIDIplay()
+ {}
+
+ /**********************Internal structures and classes**********************/
+
+ /**
+ * @brief A little class gives able to read filedata from disk and also from a memory segment
+ */
+ class fileReader
+ {
+ public:
+ enum relTo
+ {
+ SET = 0,
+ CUR = 1,
+ END = 2
+ };
+
+ fileReader()
+ {
+ fp = NULL;
+ mp = NULL;
+ mp_size = 0;
+ mp_tell = 0;
+ }
+ ~fileReader()
+ {
+ close();
+ }
+
+ void openFile(const char *path)
+ {
+ #ifndef _WIN32
+ fp = std::fopen(path, "rb");
+ #else
+ wchar_t widePath[MAX_PATH];
+ int size = MultiByteToWideChar(CP_UTF8, 0, path, (int)std::strlen(path), widePath, MAX_PATH);
+ widePath[size] = '\0';
+ fp = _wfopen(widePath, L"rb");
+ #endif
+ _fileName = path;
+ mp = NULL;
+ mp_size = 0;
+ mp_tell = 0;
+ }
+
+ void openData(void *mem, size_t lenght)
+ {
+ fp = NULL;
+ mp = mem;
+ mp_size = lenght;
+ mp_tell = 0;
+ }
+
+ void seek(long pos, int rel_to)
+ {
+ if(fp)
+ std::fseek(fp, pos, rel_to);
+ else
+ {
+ switch(rel_to)
+ {
+ case SET:
+ mp_tell = static_cast<size_t>(pos);
+ break;
+
+ case END:
+ mp_tell = mp_size - static_cast<size_t>(pos);
+ break;
+
+ case CUR:
+ mp_tell = mp_tell + static_cast<size_t>(pos);
+ break;
+ }
+
+ if(mp_tell > mp_size)
+ mp_tell = mp_size;
+ }
+ }
+
+ inline void seeku(uint64_t pos, int rel_to)
+ {
+ seek(static_cast<long>(pos), rel_to);
+ }
+
+ size_t read(void *buf, size_t num, size_t size)
+ {
+ if(fp)
+ return std::fread(buf, num, size, fp);
+ else
+ {
+ size_t pos = 0;
+ size_t maxSize = static_cast<size_t>(size * num);
+
+ while((pos < maxSize) && (mp_tell < mp_size))
+ {
+ reinterpret_cast<unsigned char *>(buf)[pos] = reinterpret_cast<unsigned char *>(mp)[mp_tell];
+ mp_tell++;
+ pos++;
+ }
+
+ return pos;
+ }
+ }
+
+ int getc()
+ {
+ if(fp)
+ return std::getc(fp);
+ else
+ {
+ if(mp_tell >= mp_size)
+ return -1;
+
+ int x = reinterpret_cast<unsigned char *>(mp)[mp_tell];
+ mp_tell++;
+ return x;
+ }
+ }
+
+ size_t tell()
+ {
+ if(fp)
+ return static_cast<size_t>(std::ftell(fp));
+ else
+ return mp_tell;
+ }
+
+ void close()
+ {
+ if(fp) std::fclose(fp);
+
+ fp = NULL;
+ mp = NULL;
+ mp_size = 0;
+ mp_tell = 0;
+ }
+
+ bool isValid()
+ {
+ return (fp) || (mp);
+ }
+
+ bool eof()
+ {
+ if(fp)
+ return std::feof(fp);
+ else
+ return mp_tell >= mp_size;
+ }
+ std::string _fileName;
+ std::FILE *fp;
+ void *mp;
+ size_t mp_size;
+ size_t mp_tell;
+ };
// Persistent settings for each MIDI channel
struct MIDIchannel
@@ -261,8 +426,6 @@ class MIDIplay
lastlrpn(0), lastmrpn(0), nrpn(false),
activenotes() { }
};
- std::vector<MIDIchannel> Ch;
- bool cmf_percussion_mode;
// Additional information about AdLib channels
struct AdlChannel
@@ -301,12 +464,6 @@ class MIDIplay
void AddAge(int64_t ms);
};
- //Padding to fix CLanc code model's warning
- char ____padding[7];
-
- std::vector<AdlChannel> ch;
- std::vector<std::vector<uint8_t> > TrackData;
-
/**
* @brief MIDI Event utility container
*/
@@ -430,7 +587,62 @@ class MIDIplay
std::vector<TrackInfo> track;
PositionNew(): began(false), wait(0.0), absTimePosition(0.0), track()
{}
- } CurrentPositionNew, LoopBeginPositionNew, trackBeginPositionNew;
+ };
+
+ struct Setup
+ {
+ unsigned int AdlBank;
+ unsigned int NumFourOps;
+ unsigned int NumCards;
+ bool HighTremoloMode;
+ bool HighVibratoMode;
+ bool AdlPercussionMode;
+ bool LogarithmicVolumes;
+ int VolumeModel;
+ unsigned int SkipForward;
+ bool loopingIsEnabled;
+ bool ScaleModulators;
+
+ double delay;
+ double carry;
+
+ /* The lag between visual content and audio content equals */
+ /* the sum of these two buffers. */
+ double mindelay;
+ double maxdelay;
+
+ /* For internal usage */
+ ssize_t stored_samples; /* num of collected samples */
+ short backup_samples[1024]; /* Backup sample storage. */
+ ssize_t backup_samples_size; /* Backup sample storage. */
+ /* For internal usage */
+
+ unsigned long PCM_RATE;
+ };
+
+ struct MIDI_MarkerEntry
+ {
+ std::string label;
+ double pos_time;
+ unsigned long pos_ticks;
+ };
+
+ std::vector<MIDIchannel> Ch;
+ bool cmf_percussion_mode;
+
+ MIDIEventHooks hooks;
+
+private:
+ std::map<std::string, uint64_t> devices;
+ std::map<uint64_t /*track*/, uint64_t /*channel begin index*/> current_device;
+
+ //Padding to fix CLanc code model's warning
+ char ____padding[7];
+
+ std::vector<AdlChannel> ch;
+ std::vector<std::vector<uint8_t> > TrackData;
+
+ PositionNew CurrentPositionNew, LoopBeginPositionNew, trackBeginPositionNew;
//! Full song length in seconds
double fullSongTimeLength;
@@ -447,6 +659,9 @@ class MIDIplay
//! Pre-processed track data storage
std::vector<MidiTrackQueue > trackDataNew;
+ //! Missing instruments catches
+ std::set<uint8_t> caugh_missing_instruments;
+
/**
* @brief Build MIDI track data from the raw track data storage
* @return true if everything successfully processed, or false on any error
@@ -463,11 +678,12 @@ class MIDIplay
MidiEvent parseEvent(uint8_t **ptr, uint8_t *end, int &status);
public:
- MIDIplay();
- ~MIDIplay()
- {}
std::string musTitle;
+ std::string musCopyright;
+ std::vector<std::string> musTrackTitles;
+ std::vector<MIDI_MarkerEntry> musMarkers;
+
fraction<uint64_t> InvDeltaTicks, Tempo;
//! Tempo multiplier
double tempoMultiplier;
@@ -481,36 +697,7 @@ public:
int16_t outBuf[1024];
- struct Setup
- {
- unsigned int AdlBank;
- unsigned int NumFourOps;
- unsigned int NumCards;
- bool HighTremoloMode;
- bool HighVibratoMode;
- bool AdlPercussionMode;
- bool LogarithmicVolumes;
- int VolumeModel;
- unsigned int SkipForward;
- bool loopingIsEnabled;
- bool ScaleModulators;
-
- double delay;
- double carry;
-
- /* The lag between visual content and audio content equals */
- /* the sum of these two buffers. */
- double mindelay;
- double maxdelay;
-
- /* For internal usage */
- ssize_t stored_samples; /* num of collected samples */
- short backup_samples[1024]; /* Backup sample storage. */
- ssize_t backup_samples_size; /* Backup sample storage. */
- /* For internal usage */
-
- unsigned long PCM_RATE;
- } m_setup;
+ Setup m_setup;
static uint64_t ReadBEint(const void *buffer, size_t nbytes);
static uint64_t ReadLEint(const void *buffer, size_t nbytes);
@@ -530,158 +717,6 @@ public:
*/
uint64_t ReadVarLenEx(uint8_t **ptr, uint8_t *end, bool &ok);
- /*
- * A little class gives able to read filedata from disk and also from a memory segment
- */
- class fileReader
- {
- public:
- enum relTo
- {
- SET = 0,
- CUR = 1,
- END = 2
- };
-
- fileReader()
- {
- fp = NULL;
- mp = NULL;
- mp_size = 0;
- mp_tell = 0;
- }
- ~fileReader()
- {
- close();
- }
-
- void openFile(const char *path)
- {
- #ifndef _WIN32
- fp = std::fopen(path, "rb");
- #else
- wchar_t widePath[MAX_PATH];
- int size = MultiByteToWideChar(CP_UTF8, 0, path, (int)std::strlen(path), widePath, MAX_PATH);
- widePath[size] = '\0';
- fp = _wfopen(widePath, L"rb");
- #endif
- _fileName = path;
- mp = NULL;
- mp_size = 0;
- mp_tell = 0;
- }
-
- void openData(void *mem, size_t lenght)
- {
- fp = NULL;
- mp = mem;
- mp_size = lenght;
- mp_tell = 0;
- }
-
- void seek(long pos, int rel_to)
- {
- if(fp)
- std::fseek(fp, pos, rel_to);
- else
- {
- switch(rel_to)
- {
- case SET:
- mp_tell = static_cast<size_t>(pos);
- break;
-
- case END:
- mp_tell = mp_size - static_cast<size_t>(pos);
- break;
-
- case CUR:
- mp_tell = mp_tell + static_cast<size_t>(pos);
- break;
- }
-
- if(mp_tell > mp_size)
- mp_tell = mp_size;
- }
- }
-
- inline void seeku(uint64_t pos, int rel_to)
- {
- seek(static_cast<long>(pos), rel_to);
- }
-
- size_t read(void *buf, size_t num, size_t size)
- {
- if(fp)
- return std::fread(buf, num, size, fp);
- else
- {
- size_t pos = 0;
- size_t maxSize = static_cast<size_t>(size * num);
-
- while((pos < maxSize) && (mp_tell < mp_size))
- {
- reinterpret_cast<unsigned char *>(buf)[pos] = reinterpret_cast<unsigned char *>(mp)[mp_tell];
- mp_tell++;
- pos++;
- }
-
- return pos;
- }
- }
-
- int getc()
- {
- if(fp)
- return std::getc(fp);
- else
- {
- if(mp_tell >= mp_size)
- return -1;
-
- int x = reinterpret_cast<unsigned char *>(mp)[mp_tell];
- mp_tell++;
- return x;
- }
- }
-
- size_t tell()
- {
- if(fp)
- return static_cast<size_t>(std::ftell(fp));
- else
- return mp_tell;
- }
-
- void close()
- {
- if(fp) std::fclose(fp);
-
- fp = NULL;
- mp = NULL;
- mp_size = 0;
- mp_tell = 0;
- }
-
- bool isValid()
- {
- return (fp) || (mp);
- }
-
- bool eof()
- {
- if(fp)
- return std::feof(fp);
- else
- return mp_tell >= mp_size;
- }
- std::string _fileName;
- std::FILE *fp;
- void *mp;
- size_t mp_size;
- size_t mp_tell;
- };
-
bool LoadBank(const std::string &filename);
bool LoadBank(void *data, unsigned long size);
bool LoadBank(fileReader &fr);