From dff692fff4a9908094312cda6e4c16d98431babf Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 19 Jun 2018 16:34:52 +0200 Subject: polyphonic portamento --- src/adlmidi_private.hpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 0e63b5a..93817cd 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -334,7 +334,7 @@ class MIDIplay { friend void adl_reset(struct ADL_MIDIPlayer*); public: - MIDIplay(unsigned long sampleRate = 22050); + explicit MIDIplay(unsigned long sampleRate = 22050); ~MIDIplay() {} @@ -496,11 +496,14 @@ public: // Persistent settings for each MIDI channel struct MIDIchannel { - uint16_t portamento; uint8_t bank_lsb, bank_msb; uint8_t patch; uint8_t volume, expression; uint8_t panning, vibrato, aftertouch, sustain; + uint16_t portamento; + bool portamentoEnable; + int8_t portamentoSource; // note number or -1 + double portamentoRate; //! Per note Aftertouch values uint8_t noteAftertouch[128]; //! Is note aftertouch has any non-zero value @@ -524,8 +527,11 @@ public: // Note vibrato (a part of Note Aftertouch feature) uint8_t vibrato; // Tone selected on noteon: - int16_t tone; - char ____padding2[4]; + int16_t noteTone; + // Current tone (!= noteTone if gliding note) + double currentTone; + // Gliding rate + double glideRate; // Patch selected on noteon; index to bank.ins[] size_t midiins; // Patch selected @@ -717,6 +723,9 @@ public: vibdelay = 0; panning = OPL_PANNING_BOTH; portamento = 0; + portamentoEnable = false; + portamentoSource = -1; + portamentoRate = HUGE_VAL; brightness = 127; } bool hasVibrato() @@ -1228,7 +1237,7 @@ private: void Panic(); void KillSustainingNotes(int32_t MidCh = -1, int32_t this_adlchn = -1); void SetRPN(unsigned MidCh, unsigned value, bool MSB); - //void UpdatePortamento(unsigned MidCh) + void UpdatePortamento(unsigned MidCh); void NoteUpdate_All(uint16_t MidCh, unsigned props_mask); void NoteOff(uint16_t MidCh, uint8_t note); -- cgit v1.2.3 From 2f26855c27aaffee0472edf43dbc5ac5ca1a5162 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 19 Jun 2018 21:15:45 +0200 Subject: allow portamento to be updated by MIDI::Tick --- src/adlmidi_private.hpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 93817cd..7aad63b 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -996,8 +996,10 @@ private: //! Counter of arpeggio processing size_t m_arpeggioCounter; +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) //! Audio tick counter uint32_t m_audioTickCounter; +#endif #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER std::vector > TrackData; @@ -1196,8 +1198,10 @@ public: void realTime_panic(); +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) // Audio rate tick handler void AudioTick(uint32_t chipId, uint32_t rate); +#endif private: enum @@ -1243,6 +1247,7 @@ private: void UpdateVibrato(double amount); void UpdateArpeggio(double /*amount*/); + void UpdateGlide(double amount); public: uint64_t ChooseDevice(const std::string &name); @@ -1267,7 +1272,9 @@ struct FourChars }; */ +#if defined(ADLMIDI_AUDIO_TICK_HANDLER) extern void adl_audioTickHandler(void *instance, uint32_t chipId, uint32_t rate); +#endif extern int adlRefreshNumCards(ADL_MIDIPlayer *device); -- cgit v1.2.3 From 6586740caacfb17210a26e9618c31c54ec0da703 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Tue, 19 Jun 2018 22:13:40 +0200 Subject: avoid portamento work when no notes have it on channel --- src/adlmidi_private.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 7aad63b..fda629d 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -610,6 +610,7 @@ public: } }; char ____padding2[5]; + unsigned gliding_note_count; NoteInfo activenotes[128]; struct activenoteiterator @@ -740,6 +741,7 @@ public: MIDIchannel() { activenotes_clear(); + gliding_note_count = 0; reset(); } }; -- cgit v1.2.3 From 8326a355c45d1d038934264be5f00c7dc5ac33c7 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Wed, 20 Jun 2018 19:11:51 +0300 Subject: Move file reader into the separated header file --- src/adlmidi_private.hpp | 155 +----------------------------------------------- 1 file changed, 3 insertions(+), 152 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index fda629d..13160b2 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -131,6 +131,7 @@ typedef int32_t ssize_t; #define INT32_MAX 0x7fffffff #endif +#include "file_reader.hpp" #include "fraction.hpp" #ifndef ADLMIDI_HW_OPL #include "chips/opl_chip_base.h" @@ -343,156 +344,6 @@ public: /**********************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) - { - #if !defined(_WIN32) || defined(__WATCOMC__) - 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(const 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(pos); - break; - - case END: - mp_tell = mp_size - static_cast(pos); - break; - - case CUR: - mp_tell = mp_tell + static_cast(pos); - break; - } - - if(mp_tell > mp_size) - mp_tell = mp_size; - } - } - - inline void seeku(uint64_t pos, int rel_to) - { - seek(static_cast(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 * num); - - while((pos < maxSize) && (mp_tell < mp_size)) - { - reinterpret_cast(buf)[pos] = reinterpret_cast(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(mp)[mp_tell]; - mp_tell++; - return x; - } - } - - size_t tell() - { - if(fp) - return static_cast(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) != 0); - else - return mp_tell >= mp_size; - } - std::string _fileName; - std::FILE *fp; - const void *mp; - size_t mp_size; - size_t mp_tell; - }; - // Persistent settings for each MIDI channel struct MIDIchannel { @@ -1113,12 +964,12 @@ public: bool LoadBank(const std::string &filename); bool LoadBank(const void *data, size_t size); - bool LoadBank(fileReader &fr); + bool LoadBank(FileAndMemReader &fr); #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER bool LoadMIDI(const std::string &filename); bool LoadMIDI(const void *data, size_t size); - bool LoadMIDI(fileReader &fr); + bool LoadMIDI(FileAndMemReader &fr); /** * @brief Periodic tick handler. -- cgit v1.2.3 From 252e65097e9b8a815485fc03e4358698803f1a73 Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Wed, 20 Jun 2018 21:45:54 +0200 Subject: basic framework of sysex handling and sequencer support --- src/adlmidi_private.hpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index fda629d..4b3ab10 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -108,6 +108,7 @@ typedef int32_t ssize_t; #include #include +#include /* * Workaround for some compilers are has no those macros in their headers! @@ -984,6 +985,7 @@ public: std::vector Ch; bool cmf_percussion_mode; + uint8_t m_sysExDeviceId; MIDIEventHooks hooks; @@ -1198,6 +1200,9 @@ public: void realTime_BankChangeMSB(uint8_t channel, uint8_t msb); void realTime_BankChange(uint8_t channel, uint16_t bank); + void setDeviceId(uint8_t id); + bool realTime_SysEx(const uint8_t *msg, unsigned size); + void realTime_panic(); #if defined(ADLMIDI_AUDIO_TICK_HANDLER) @@ -1205,6 +1210,30 @@ public: void AudioTick(uint32_t chipId, uint32_t rate); #endif +private: + enum + { + Manufacturer_Roland = 0x41, + Manufacturer_Yamaha = 0x43, + Manufacturer_UniversalNonRealtime = 0x7E, + Manufacturer_UniversalRealtime = 0x7F + }; + enum + { + RolandMode_Request = 0x11, + RolandMode_Send = 0x12 + }; + enum + { + RolandModel_GS = 0x42, + RolandModel_SC55 = 0x45, + YamahaModel_XG = 0x4C + }; + + bool doUniversalSysEx(unsigned dev, bool realtime, const uint8_t *data, unsigned size); + bool doRolandSysEx(unsigned dev, const uint8_t *data, unsigned size); + bool doYamahaSysEx(unsigned dev, const uint8_t *data, unsigned size); + private: enum { -- cgit v1.2.3 From 9f0f9e4e374798851da39335406ac4bafad81297 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Thu, 21 Jun 2018 04:23:14 +0300 Subject: Move MIDI sequencer into completely separated class TODO: - implement C bindings for most of class functions - test it in work on any different synthesizer --- src/adlmidi_private.hpp | 370 ++++++++++++++++-------------------------------- 1 file changed, 121 insertions(+), 249 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 13160b2..446bae0 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -132,7 +132,14 @@ typedef int32_t ssize_t; #endif #include "file_reader.hpp" -#include "fraction.hpp" + +#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER +// Rename class to avoid ABI conflicts +#define BW_MidiSequencer AdlMidiSequencer +#include "midi_sequencer.hpp" +typedef BW_MidiSequencer MidiSequencer; +#endif//ADLMIDI_DISABLE_MIDI_SEQUENCER + #ifndef ADLMIDI_HW_OPL #include "chips/opl_chip_base.h" #endif @@ -307,17 +314,11 @@ 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, const uint8_t *data, size_t len); - RawEventHook onEvent; - void *onEvent_userData; //! Note on/off hooks typedef void (*NoteHook)(void *userdata, int adlchn, int note, int ins, int pressure, double bend); @@ -669,130 +670,20 @@ public: #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER /** - * @brief MIDI Event utility container + * @brief MIDI files player sequencer */ - class MidiEvent - { - public: - MidiEvent(); - - enum Types - { - T_UNKNOWN = 0x00, - T_NOTEOFF = 0x08,//size == 2 - T_NOTEON = 0x09,//size == 2 - T_NOTETOUCH = 0x0A,//size == 2 - T_CTRLCHANGE = 0x0B,//size == 2 - T_PATCHCHANGE = 0x0C,//size == 1 - T_CHANAFTTOUCH = 0x0D,//size == 1 - T_WHEEL = 0x0E,//size == 2 - - T_SYSEX = 0xF0,//size == len - T_SYSCOMSPOSPTR = 0xF2,//size == 2 - T_SYSCOMSNGSEL = 0xF3,//size == 1 - T_SYSEX2 = 0xF7,//size == len - T_SPECIAL = 0xFF - }; - enum SubTypes - { - ST_SEQNUMBER = 0x00,//size == 2 - ST_TEXT = 0x01,//size == len - ST_COPYRIGHT = 0x02,//size == len - ST_SQTRKTITLE = 0x03,//size == len - ST_INSTRTITLE = 0x04,//size == len - ST_LYRICS = 0x05,//size == len - ST_MARKER = 0x06,//size == len - ST_CUEPOINT = 0x07,//size == len - ST_DEVICESWITCH = 0x09,//size == len - ST_MIDICHPREFIX = 0x20,//size == 1 - - ST_ENDTRACK = 0x2F,//size == 0 - ST_TEMPOCHANGE = 0x51,//size == 3 - ST_SMPTEOFFSET = 0x54,//size == 5 - ST_TIMESIGNATURE = 0x55, //size == 4 - ST_KEYSIGNATURE = 0x59,//size == 2 - ST_SEQUENCERSPEC = 0x7F, //size == len - - /* Non-standard, internal ADLMIDI usage only */ - ST_LOOPSTART = 0xE1,//size == 0 - ST_LOOPEND = 0xE2,//size == 0 - ST_RAWOPL = 0xE3//size == 0 - }; - //! Main type of event - uint8_t type; - //! Sub-type of the event - uint8_t subtype; - //! Targeted MIDI channel - uint8_t channel; - //! Is valid event - uint8_t isValid; - //! Reserved 5 bytes padding - uint8_t __padding[4]; - //! Absolute tick position (Used for the tempo calculation only) - uint64_t absPosition; - //! Raw data of this event - std::vector data; - }; + MidiSequencer m_sequencer; /** - * @brief A track position event contains a chain of MIDI events until next delay value - * - * Created with purpose to sort events by type in the same position - * (for example, to keep controllers always first than note on events or lower than note-off events) + * @brief Interface between MIDI sequencer and this library */ - class MidiTrackRow - { - public: - MidiTrackRow(); - void reset(); - //! Absolute time position in seconds - double time; - //! Delay to next event in ticks - uint64_t delay; - //! Absolute position in ticks - uint64_t absPos; - //! Delay to next event in seconds - double timeDelay; - std::vector events; - /** - * @brief Sort events in this position - */ - void sortEvents(bool *noteStates = NULL); - }; + BW_MidiRtInterface m_sequencerInterface; /** - * @brief Tempo change point entry. Used in the MIDI data building function only. + * @brief Initialize MIDI sequencer interface */ - struct TempoChangePoint - { - uint64_t absPos; - fraction tempo; - }; - //P.S. I declared it here instead of local in-function because C++99 can't process templates with locally-declared structures - - typedef std::list MidiTrackQueue; - - // Information about each track - struct PositionNew - { - bool began; - char padding[7]; - double wait; - double absTimePosition; - struct TrackInfo - { - size_t ptr; - uint64_t delay; - int status; - char padding2[4]; - MidiTrackQueue::iterator pos; - TrackInfo(): ptr(0), delay(0), status(0) {} - }; - std::vector track; - PositionNew(): began(false), wait(0.0), absTimePosition(0.0), track() - {} - }; -#endif//ADLMIDI_DISABLE_MIDI_SEQUENCER + void initSequencerInterface(); +#endif //ADLMIDI_DISABLE_MIDI_SEQUENCER struct Setup { @@ -807,7 +698,6 @@ public: bool LogarithmicVolumes; int VolumeModel; //unsigned int SkipForward; - bool loopingIsEnabled; int ScaleModulators; bool fullRangeBrightnessCC74; @@ -854,31 +744,9 @@ private: uint32_t m_audioTickCounter; #endif -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER - std::vector > TrackData; - - PositionNew CurrentPositionNew, LoopBeginPositionNew, trackBeginPositionNew; - - //! Full song length in seconds - double fullSongTimeLength; - //! Delay after song playd before rejecting the output stream requests - double postSongWaitDelay; - - //! Loop start time - double loopStartTime; - //! Loop end time - double loopEndTime; -#endif - //! Local error string - std::string errorString; //! Local error string std::string errorStringOut; -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER - //! Pre-processed track data storage - std::vector trackDataNew; -#endif - //! Missing instruments catches std::set caugh_missing_instruments; //! Missing melodic banks catches @@ -886,90 +754,49 @@ private: //! Missing percussion banks catches std::set caugh_missing_banks_percussion; -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER - /** - * @brief Build MIDI track data from the raw track data storage - * @return true if everything successfully processed, or false on any error - */ - bool buildTrackData(); - - /** - * @brief Parse one event from raw MIDI track stream - * @param [_inout] ptr pointer to pointer to current position on the raw data track - * @param [_in] end address to end of raw track data, needed to validate position and size - * @param [_inout] status status of the track processing - * @return Parsed MIDI event entry - */ - MidiEvent parseEvent(uint8_t **ptr, uint8_t *end, int &status); -#endif//ADLMIDI_DISABLE_MIDI_SEQUENCER - public: const std::string &getErrorString(); void setErrorString(const std::string &err); -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER - std::string musTitle; - std::string musCopyright; - std::vector musTrackTitles; - std::vector musMarkers; - - fraction InvDeltaTicks, Tempo; - //! Tempo multiplier - double tempoMultiplier; - bool atEnd, - loopStart, - loopEnd, - invalidLoop; /*Loop points are invalid (loopStart after loopEnd or loopStart and loopEnd are on same place)*/ - char ____padding2[2]; -#endif OPL3 opl; int32_t outBuf[1024]; Setup m_setup; + bool LoadBank(const std::string &filename); + bool LoadBank(const void *data, size_t size); + bool LoadBank(FileAndMemReader &fr); + #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER /** - * @brief Utility function to read Big-Endian integer from raw binary data - * @param buffer Pointer to raw binary buffer - * @param nbytes Count of bytes to parse integer - * @return Extracted unsigned integer + * @brief MIDI file loading pre-process + * @return true on success, false on failure */ - static uint64_t ReadBEint(const void *buffer, size_t nbytes); + bool LoadMIDI_pre(); /** - * @brief Utility function to read Little-Endian integer from raw binary data - * @param buffer Pointer to raw binary buffer - * @param nbytes Count of bytes to parse integer - * @return Extracted unsigned integer + * @brief MIDI file loading post-process + * @return true on success, false on failure */ - static uint64_t ReadLEint(const void *buffer, size_t nbytes); + bool LoadMIDI_post(); /** - * @brief Standard MIDI Variable-Length numeric value parser without of validation - * @param [_inout] ptr Pointer to memory block that contains begin of variable-length value - * @return Unsigned integer that conains parsed variable-length value - */ - uint64_t ReadVarLen(uint8_t **ptr); - /** - * @brief Secure Standard MIDI Variable-Length numeric value parser with anti-out-of-range protection - * @param [_inout] ptr Pointer to memory block that contains begin of variable-length value, will be iterated forward - * @param [_in end Pointer to end of memory block where variable-length value is stored (after end of track) - * @param [_out] ok Reference to boolean which takes result of variable-length value parsing - * @return Unsigned integer that conains parsed variable-length value + * @brief Load music file from a file + * @param filename Path to music file + * @return true on success, false on failure */ - uint64_t ReadVarLenEx(uint8_t **ptr, uint8_t *end, bool &ok); -#endif - - bool LoadBank(const std::string &filename); - bool LoadBank(const void *data, size_t size); - bool LoadBank(FileAndMemReader &fr); -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER bool LoadMIDI(const std::string &filename); + + /** + * @brief Load music file from the memory block + * @param data pointer to the memory block + * @param size size of memory block + * @return true on success, false on failure + */ bool LoadMIDI(const void *data, size_t size); - bool LoadMIDI(FileAndMemReader &fr); /** * @brief Periodic tick handler. @@ -978,79 +805,129 @@ public: * @return desired number of seconds until next call */ double Tick(double s, double granularity); -#endif +#endif //ADLMIDI_DISABLE_MIDI_SEQUENCER /** * @brief Process extra iterators like vibrato or arpeggio * @param s seconds since last call */ - void TickIteratos(double s); + void TickIterators(double s); -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER - /** - * @brief Change current position to specified time position in seconds - * @param seconds Absolute time position in seconds - */ - void seek(double seconds); + /* RealTime event triggers */ /** - * @brief Gives current time position in seconds - * @return Current time position in seconds + * @brief Reset state of all channels */ - double tell(); + void realTime_ResetState(); /** - * @brief Gives time length of current song in seconds - * @return Time length of current song in seconds + * @brief Note On event + * @param channel MIDI channel + * @param note Note key (from 0 to 127) + * @param velocity Velocity level (from 0 to 127) + * @return true if Note On event was accepted */ - double timeLength(); + bool realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity); /** - * @brief Gives loop start time position in seconds - * @return Loop start time position in seconds or -1 if song has no loop points + * @brief Note Off event + * @param channel MIDI channel + * @param note Note key (from 0 to 127) */ - double getLoopStart(); + void realTime_NoteOff(uint8_t channel, uint8_t note); /** - * @brief Gives loop end time position in seconds - * @return Loop end time position in seconds or -1 if song has no loop points + * @brief Note aftertouch event + * @param channel MIDI channel + * @param note Note key (from 0 to 127) + * @param atVal After-Touch level (from 0 to 127) */ - double getLoopEnd(); + void realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal); /** - * @brief Return to begin of current song + * @brief Channel aftertouch event + * @param channel MIDI channel + * @param atVal After-Touch level (from 0 to 127) */ - void rewind(); + void realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal); /** - * @brief Set tempo multiplier - * @param tempo Tempo multiplier: 1.0 - original tempo. >1 - faster, <1 - slower + * @brief Controller Change event + * @param channel MIDI channel + * @param type Type of controller + * @param value Value of the controller (from 0 to 127) */ - void setTempo(double tempo); -#endif//ADLMIDI_DISABLE_MIDI_SEQUENCER - - /* RealTime event triggers */ - void realTime_ResetState(); - - bool realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity); - void realTime_NoteOff(uint8_t channel, uint8_t note); - - void realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal); - void realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal); - void realTime_Controller(uint8_t channel, uint8_t type, uint8_t value); + /** + * @brief Patch change + * @param channel MIDI channel + * @param patch Patch Number (from 0 to 127) + */ void realTime_PatchChange(uint8_t channel, uint8_t patch); + /** + * @brief Pitch bend change + * @param channel MIDI channel + * @param pitch Concoctated raw pitch value + */ void realTime_PitchBend(uint8_t channel, uint16_t pitch); + + /** + * @brief Pitch bend change + * @param channel MIDI channel + * @param msb MSB of pitch value + * @param lsb LSB of pitch value + */ void realTime_PitchBend(uint8_t channel, uint8_t msb, uint8_t lsb); + /** + * @brief LSB Bank Change CC + * @param channel MIDI channel + * @param lsb LSB value of bank number + */ void realTime_BankChangeLSB(uint8_t channel, uint8_t lsb); + + /** + * @brief MSB Bank Change CC + * @param channel MIDI channel + * @param lsb MSB value of bank number + */ void realTime_BankChangeMSB(uint8_t channel, uint8_t msb); + + /** + * @brief Bank Change (united value) + * @param channel MIDI channel + * @param bank Bank number value + */ void realTime_BankChange(uint8_t channel, uint16_t bank); + /** + * @brief Turn off all notes and mute the sound of releasing notes + */ void realTime_panic(); + /** + * @brief Device switch (to extend 16-channels limit of MIDI standard) + * @param track MIDI track index + * @param data Device name + * @param length Length of device name string + */ + void realTime_deviceSwitch(size_t track, const char *data, size_t length); + /** + * @brief Currently selected device index + * @param track MIDI track index + * @return Multiple 16 value + */ + uint64_t realTime_currentDevice(size_t track); + + /** + * @brief Send raw OPL chip command + * @param reg OPL Register + * @param value Value to write + */ + void realTime_rawOPL(uint8_t reg, uint8_t value); + #if defined(ADLMIDI_AUDIO_TICK_HANDLER) // Audio rate tick handler void AudioTick(uint32_t chipId, uint32_t rate); @@ -1074,11 +951,6 @@ private: unsigned props_mask, int32_t select_adlchn = -1); -#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER - bool ProcessEventsNew(bool isSeek = false); - void HandleEvent(size_t tk, const MidiEvent &evt, int &status); -#endif - // Determine how good a candidate this adlchannel // would be for playing a note from this instrument. int64_t CalculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins, uint16_t /*MidCh*/) const; -- cgit v1.2.3 From f20f618327deba5091a384eb749fd4b4f7c10a2f Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Thu, 21 Jun 2018 05:01:50 +0300 Subject: Fixed build of MIDI sequencer out of pre-included private ADLMIDI's header --- src/adlmidi_private.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 446bae0..06d21ab 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -134,7 +134,7 @@ typedef int32_t ssize_t; #include "file_reader.hpp" #ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER -// Rename class to avoid ABI conflicts +// Rename class to avoid ABI collisions #define BW_MidiSequencer AdlMidiSequencer #include "midi_sequencer.hpp" typedef BW_MidiSequencer MidiSequencer; -- cgit v1.2.3 From 86038a9ccafd7e848e67535f7995d86601cb1e0f Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Thu, 21 Jun 2018 05:07:47 +0300 Subject: Remove useless "_parent" pointer from OPL3 class --- src/adlmidi_private.hpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 06d21ab..b80d2f2 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -207,7 +207,6 @@ inline int32_t adl_cvtU32(int32_t x) return (uint32_t)adl_cvtS32(x) - (uint32_t)INT32_MIN; } -class MIDIplay; struct ADL_MIDIPlayer; class OPL3 { @@ -216,7 +215,6 @@ public: friend class AdlInstrumentTester; uint32_t NumChannels; char ____padding[4]; - ADL_MIDIPlayer *_parent; #ifndef ADLMIDI_HW_OPL std::vector > cardsOP2; #endif -- cgit v1.2.3 From cca01359c3f7acc5cfd016d59561fae41b72793e Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Thu, 21 Jun 2018 05:49:47 +0300 Subject: Fix for "NOMINMAX" redefinition warning on Windows --- src/adlmidi_private.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index b80d2f2..058a431 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -39,7 +39,7 @@ #define ADLMIDI_UNSTABLE_API #ifdef _WIN32 -#define NOMINMAX +#define NOMINMAX 1 #endif #if defined(_WIN32) && !defined(__WATCOMC__) @@ -51,7 +51,7 @@ typedef __int64 ssize_t; # else typedef __int32 ssize_t; # endif -# define NOMINMAX //Don't override std::min and std::max +# define NOMINMAX 1 //Don't override std::min and std::max # else # ifdef _WIN64 typedef int64_t ssize_t; -- cgit v1.2.3 From ebee7962d7a2691e38d585dac9b9c0e3d286364c Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Thu, 21 Jun 2018 09:43:34 +0300 Subject: SysEx: Use `size_t` for size values instead of `unsigned int` --- src/adlmidi_private.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 67f1ccb..280232f 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -914,7 +914,7 @@ public: * @param size Length of SysEx message * @return true if message was passed successfully. False on any errors */ - bool realTime_SysEx(const uint8_t *msg, unsigned size); + bool realTime_SysEx(const uint8_t *msg, size_t size); /** * @brief Turn off all notes and mute the sound of releasing notes @@ -967,9 +967,9 @@ private: YamahaModel_XG = 0x4C }; - bool doUniversalSysEx(unsigned dev, bool realtime, const uint8_t *data, unsigned size); - bool doRolandSysEx(unsigned dev, const uint8_t *data, unsigned size); - bool doYamahaSysEx(unsigned dev, const uint8_t *data, unsigned size); + bool doUniversalSysEx(unsigned dev, bool realtime, const uint8_t *data, size_t size); + bool doRolandSysEx(unsigned dev, const uint8_t *data, size_t size); + bool doYamahaSysEx(unsigned dev, const uint8_t *data, size_t size); private: enum -- cgit v1.2.3 From b2259a0ad2da07729eb285eda4a833e5b0f1f7eb Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Thu, 21 Jun 2018 14:11:48 +0300 Subject: Attempt to fix MSVC 2015 build --- src/adlmidi_private.hpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 280232f..54d69b8 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -108,7 +108,6 @@ typedef int32_t ssize_t; #include #include -#include /* * Workaround for some compilers are has no those macros in their headers! -- cgit v1.2.3 From be2e41fe5d800520ee50ca93729c8633407fb1fc Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Fri, 22 Jun 2018 17:30:34 +0200 Subject: handle sysex resets --- src/adlmidi_private.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 54d69b8..b7bdc17 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -980,7 +980,7 @@ private: Upd_All = Upd_Pan + Upd_Volume + Upd_Pitch, Upd_Off = 0x20, Upd_Mute = 0x40, - Upt_OffMute = Upd_Off + Upd_Mute + Upd_OffMute = Upd_Off + Upd_Mute }; void NoteUpdate(uint16_t MidCh, -- cgit v1.2.3 From 16831e97a68049d27329db4630dcfbfa58b1d8fd Mon Sep 17 00:00:00 2001 From: JP Cimalando Date: Fri, 22 Jun 2018 17:58:31 +0200 Subject: handle MIDI master volume --- src/adlmidi_private.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index b7bdc17..71f0068 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -723,6 +723,7 @@ public: std::vector Ch; bool cmf_percussion_mode; + uint8_t m_masterVolume; uint8_t m_sysExDeviceId; MIDIEventHooks hooks; -- cgit v1.2.3 From 159bb5b202cd088db920ccc073d952122dea85ba Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Fri, 22 Jun 2018 23:25:13 +0300 Subject: Added support for synthesizer mode - in GS mode, RPN XG-related vibrato depth events will be ignored (GS does using NRPN values are stored separately and are NOT handled) - in GS mode ignore LSB value of the bank number --- src/adlmidi_private.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 71f0068..ec194c6 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -726,6 +726,15 @@ public: uint8_t m_masterVolume; uint8_t m_sysExDeviceId; + enum SynthMode + { + Mode_GM = 0x00, + Mode_GS = 0x01, + Mode_XG = 0x02, + Mode_GM2 = 0x04, + }; + uint32_t m_synthMode; + MIDIEventHooks hooks; private: -- cgit v1.2.3 From f6c6b70c488ba392236e1a4f5d2a32ceda00bf24 Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Sat, 23 Jun 2018 06:40:27 +0300 Subject: Added CC66 Sostenuto support! Sostenuto is the pedal hold that does hold of only currently playing notes and doesn't holds notes are will begin after turning of sostenuto on, unlike to the Pedal (CC64 Sustain) event. --- src/adlmidi_private.hpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index ec194c6..1d68bae 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -349,8 +349,9 @@ public: uint8_t bank_lsb, bank_msb; uint8_t patch; uint8_t volume, expression; - uint8_t panning, vibrato, aftertouch, sustain; + uint8_t panning, vibrato, aftertouch; uint16_t portamento; + bool sustain; bool portamentoEnable; int8_t portamentoSource; // note number or -1 double portamentoRate; @@ -564,7 +565,7 @@ public: updateBendSensitivity(); volume = 100; expression = 127; - sustain = 0; + sustain = false; vibrato = 0; aftertouch = 0; std::memset(noteAftertouch, 0, 128); @@ -612,8 +613,14 @@ public: { LocationData *prev, *next; Location loc; - bool sustained; - char ____padding[7]; + enum { + Sustain_None = 0x00, + Sustain_Pedal = 0x01, + Sustain_Sostenuto = 0x02, + Sustain_ANY = Sustain_Pedal | Sustain_Sostenuto, + }; + uint8_t sustained; + char ____padding[6]; MIDIchannel::NoteInfo::Phys ins; // a copy of that in phys[] //! Has fixed sustain, don't iterate "on" timeout bool fixed_sustain; @@ -1011,7 +1018,10 @@ private: AdlChannel::LocationData *j, MIDIchannel::activenoteiterator i); void Panic(); - void KillSustainingNotes(int32_t MidCh = -1, int32_t this_adlchn = -1); + void KillSustainingNotes(int32_t MidCh = -1, + int32_t this_adlchn = -1, + uint8_t sustain_type = AdlChannel::LocationData::Sustain_ANY); + void MarkSostenutoNotes(int32_t MidCh = -1); void SetRPN(unsigned MidCh, unsigned value, bool MSB); void UpdatePortamento(unsigned MidCh); void NoteUpdate_All(uint16_t MidCh, unsigned props_mask); -- cgit v1.2.3 From efbbd382b84b73d706a16fb54c51bf48df7b22cf Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Sat, 23 Jun 2018 09:01:35 +0300 Subject: Added support for CC67-SoftPedal --- src/adlmidi_private.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 1d68bae..840ba21 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -352,6 +352,7 @@ public: uint8_t panning, vibrato, aftertouch; uint16_t portamento; bool sustain; + bool softPedal; bool portamentoEnable; int8_t portamentoSource; // note number or -1 double portamentoRate; @@ -566,6 +567,7 @@ public: volume = 100; expression = 127; sustain = false; + softPedal = false; vibrato = 0; aftertouch = 0; std::memset(noteAftertouch, 0, 128); -- cgit v1.2.3 From e248d9ddc8ba3023e265a18d44fb5dca6193f8ec Mon Sep 17 00:00:00 2001 From: Vitaly Novichkov Date: Sat, 23 Jun 2018 23:29:29 +0300 Subject: Little clean-up and beautify --- src/adlmidi_private.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/adlmidi_private.hpp') diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 840ba21..f34404d 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -946,6 +946,7 @@ public: * @param length Length of device name string */ void realTime_deviceSwitch(size_t track, const char *data, size_t length); + /** * @brief Currently selected device index * @param track MIDI track index -- cgit v1.2.3