diff options
Diffstat (limited to 'src/adlmidi_private.hpp')
-rw-r--r-- | src/adlmidi_private.hpp | 427 |
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); |