1 /* 2 * libOPNMIDI is a free Software MIDI synthesizer library with OPN2 (YM2612) emulation 3 * 4 * MIDI parser and player (Original code from ADLMIDI): Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi> 5 * OPNMIDI Library and YM2612 support: Copyright (c) 2017-2020 Vitaly Novichkov <admin@wohlnet.ru> 6 * 7 * Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation: 8 * http://iki.fi/bisqwit/source/adlmidi.html 9 * 10 * This program is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation, either version 3 of the License, or 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 #ifndef OPNMIDI_MIDIPLAY_HPP 25 #define OPNMIDI_MIDIPLAY_HPP 26 27 #include "opnbank.h" 28 #include "opnmidi_private.hpp" 29 #include "opnmidi_ptr.hpp" 30 #include "structures/pl_list.hpp" 31 32 /** 33 * @brief Hooks of the internal events 34 */ 35 struct MIDIEventHooks 36 { MIDIEventHooksMIDIEventHooks37 MIDIEventHooks() : 38 onNote(NULL), 39 onNote_userData(NULL), 40 onDebugMessage(NULL), 41 onDebugMessage_userData(NULL) 42 {} 43 44 //! Note on/off hooks 45 typedef void (*NoteHook)(void *userdata, int adlchn, int note, int ins, int pressure, double bend); 46 NoteHook onNote; 47 void *onNote_userData; 48 49 //! Library internal debug messages 50 typedef void (*DebugMessageHook)(void *userdata, const char *fmt, ...); 51 DebugMessageHook onDebugMessage; 52 void *onDebugMessage_userData; 53 }; 54 55 class OPNMIDIplay 56 { 57 friend void opn2_reset(struct OPN2_MIDIPlayer*); 58 public: 59 explicit OPNMIDIplay(unsigned long sampleRate = 22050); 60 ~OPNMIDIplay(); 61 62 void applySetup(); 63 64 void partialReset(); 65 void resetMIDI(); 66 67 private: 68 void resetMIDIDefaults(int offset = 0); 69 70 public: 71 /**********************Internal structures and classes**********************/ 72 73 /** 74 * @brief Persistent settings for each MIDI channel 75 */ 76 struct MIDIchannel 77 { 78 //! Default MIDI volume 79 uint8_t def_volume; 80 //! Default LSB of a bend sensitivity 81 int def_bendsense_lsb; 82 //! Default MSB of a bend sensitivity 83 int def_bendsense_msb; 84 85 //! LSB Bank number 86 uint8_t bank_lsb, 87 //! MSB Bank number 88 bank_msb; 89 //! Current patch number 90 uint8_t patch; 91 //! Volume level 92 uint8_t volume, 93 //! Expression level 94 expression; 95 //! Panning level 96 uint8_t panning, 97 //! Vibrato level 98 vibrato, 99 //! Channel aftertouch level 100 aftertouch; 101 //! Portamento time 102 uint16_t portamento; 103 //! Is Pedal sustain active 104 bool sustain; 105 //! Is Soft pedal active 106 bool softPedal; 107 //! Is portamento enabled 108 bool portamentoEnable; 109 //! Source note number used by portamento 110 int8_t portamentoSource; // note number or -1 111 //! Portamento rate 112 double portamentoRate; 113 //! Per note Aftertouch values 114 uint8_t noteAftertouch[128]; 115 //! Is note aftertouch has any non-zero value 116 bool noteAfterTouchInUse; 117 //! Reserved 118 char _padding[6]; 119 //! Pitch bend value 120 int bend; 121 //! Pitch bend sensitivity 122 double bendsense; 123 //! Pitch bend sensitivity LSB value 124 int bendsense_lsb, 125 //! Pitch bend sensitivity MSB value 126 bendsense_msb; 127 //! Vibrato position value 128 double vibpos, 129 //! Vibrato speed value 130 vibspeed, 131 //! Vibrato depth value 132 vibdepth; 133 //! Vibrato delay time 134 int64_t vibdelay_us; 135 //! Last LSB part of RPN value received 136 uint8_t lastlrpn, 137 //! Last MSB poart of RPN value received 138 lastmrpn; 139 //! Interpret RPN value as NRPN 140 bool nrpn; 141 //! Brightness level 142 uint8_t brightness; 143 144 //! Is melodic channel turned into percussion 145 bool is_xg_percussion; 146 147 /** 148 * @brief Per-Note information 149 */ 150 struct NoteInfo 151 { 152 //! Note number 153 uint8_t note; 154 //! Current pressure 155 uint8_t vol; 156 //! Note vibrato (a part of Note Aftertouch feature) 157 uint8_t vibrato; 158 //! Tone selected on noteon: 159 int16_t noteTone; 160 //! Current tone (!= noteTone if gliding note) 161 double currentTone; 162 //! Gliding rate 163 double glideRate; 164 //! Patch selected on noteon; index to bank.ins[] 165 size_t midiins; 166 //! Is note the percussion instrument 167 bool isPercussion; 168 //! Note that plays missing instrument. Doesn't using any chip channels 169 bool isBlank; 170 //! Whether releasing and on extended life time defined by TTL 171 bool isOnExtendedLifeTime; 172 //! Time-to-live until release (short percussion note fix) 173 double ttl; 174 //! Patch selected 175 const OpnInstMeta *ains; 176 enum 177 { 178 MaxNumPhysChans = 2, 179 MaxNumPhysItemCount = MaxNumPhysChans 180 }; 181 182 struct FindPredicate 183 { FindPredicateOPNMIDIplay::MIDIchannel::NoteInfo::FindPredicate184 explicit FindPredicate(unsigned note) 185 : note(note) {} operator ()OPNMIDIplay::MIDIchannel::NoteInfo::FindPredicate186 bool operator()(const NoteInfo &ni) const 187 { return ni.note == note; } 188 unsigned note; 189 }; 190 191 /** 192 * @brief Reference to currently using chip channel 193 */ 194 struct Phys 195 { 196 //! Destination chip channel 197 uint16_t chip_chan; 198 //! ins, inde to adl[] 199 OpnTimbre ains; 200 assignOPNMIDIplay::MIDIchannel::NoteInfo::Phys201 void assign(const Phys &oth) 202 { 203 ains = oth.ains; 204 } operator ==OPNMIDIplay::MIDIchannel::NoteInfo::Phys205 bool operator==(const Phys &oth) const 206 { 207 return (ains == oth.ains); 208 } operator !=OPNMIDIplay::MIDIchannel::NoteInfo::Phys209 bool operator!=(const Phys &oth) const 210 { 211 return !operator==(oth); 212 } 213 }; 214 215 //! List of OPN2 channels it is currently occupying. 216 Phys chip_channels[MaxNumPhysItemCount]; 217 //! Count of used channels. 218 unsigned chip_channels_count; 219 phys_findOPNMIDIplay::MIDIchannel::NoteInfo220 Phys *phys_find(unsigned chip_chan) 221 { 222 Phys *ph = NULL; 223 for(unsigned i = 0; i < chip_channels_count && !ph; ++i) 224 if(chip_channels[i].chip_chan == chip_chan) 225 ph = &chip_channels[i]; 226 return ph; 227 } phys_find_or_createOPNMIDIplay::MIDIchannel::NoteInfo228 Phys *phys_find_or_create(uint16_t chip_chan) 229 { 230 Phys *ph = phys_find(chip_chan); 231 if(!ph) { 232 if(chip_channels_count < MaxNumPhysItemCount) { 233 ph = &chip_channels[chip_channels_count++]; 234 ph->chip_chan = chip_chan; 235 } 236 } 237 return ph; 238 } phys_ensure_find_or_createOPNMIDIplay::MIDIchannel::NoteInfo239 Phys *phys_ensure_find_or_create(uint16_t chip_chan) 240 { 241 Phys *ph = phys_find_or_create(chip_chan); 242 assert(ph); 243 return ph; 244 } phys_erase_atOPNMIDIplay::MIDIchannel::NoteInfo245 void phys_erase_at(const Phys *ph) 246 { 247 intptr_t pos = ph - chip_channels; 248 assert(pos < static_cast<intptr_t>(chip_channels_count)); 249 for(intptr_t i = pos + 1; i < static_cast<intptr_t>(chip_channels_count); ++i) 250 chip_channels[i - 1] = chip_channels[i]; 251 --chip_channels_count; 252 } phys_eraseOPNMIDIplay::MIDIchannel::NoteInfo253 void phys_erase(unsigned chip_chan) 254 { 255 Phys *ph = phys_find(chip_chan); 256 if(ph) 257 phys_erase_at(ph); 258 } 259 }; 260 261 //! Reserved 262 char _padding2[5]; 263 //! Count of gliding notes in this channel 264 unsigned gliding_note_count; 265 //! Count of notes having a TTL countdown in this channel 266 unsigned extended_note_count; 267 268 //! Active notes in the channel 269 pl_list<NoteInfo> activenotes; 270 typedef pl_list<NoteInfo>::iterator notes_iterator; 271 typedef pl_list<NoteInfo>::const_iterator const_notes_iterator; 272 find_activenoteOPNMIDIplay::MIDIchannel273 notes_iterator find_activenote(unsigned note) 274 { 275 return activenotes.find_if(NoteInfo::FindPredicate(note)); 276 } 277 ensure_find_activenoteOPNMIDIplay::MIDIchannel278 notes_iterator ensure_find_activenote(unsigned note) 279 { 280 notes_iterator it = find_activenote(note); 281 assert(!it.is_end()); 282 return it; 283 } 284 find_or_create_activenoteOPNMIDIplay::MIDIchannel285 notes_iterator find_or_create_activenote(unsigned note) 286 { 287 notes_iterator it = find_activenote(note); 288 if(!it.is_end()) 289 cleanupNote(it); 290 else 291 { 292 NoteInfo ni; 293 ni.note = note; 294 it = activenotes.insert(activenotes.end(), ni); 295 } 296 return it; 297 } 298 ensure_find_or_create_activenoteOPNMIDIplay::MIDIchannel299 notes_iterator ensure_find_or_create_activenote(unsigned note) 300 { 301 notes_iterator it = find_or_create_activenote(note); 302 assert(!it.is_end()); 303 return it; 304 } 305 306 /** 307 * @brief Reset channel into initial state 308 */ resetOPNMIDIplay::MIDIchannel309 void reset() 310 { 311 resetAllControllers(); 312 patch = 0; 313 vibpos = 0; 314 bank_lsb = 0; 315 bank_msb = 0; 316 lastlrpn = 0; 317 lastmrpn = 0; 318 nrpn = false; 319 is_xg_percussion = false; 320 } 321 322 resetAllControllersOPNMIDIplay::MIDIchannel323 void resetAllControllers() 324 { 325 volume = def_volume; 326 brightness = 127; 327 panning = 64; 328 329 resetAllControllers121(); 330 } 331 332 /** 333 * @brief Reset all MIDI controllers into initial state 334 */ resetAllControllers121OPNMIDIplay::MIDIchannel335 void resetAllControllers121() 336 { 337 bend = 0; 338 bendsense_msb = def_bendsense_msb; 339 bendsense_lsb = def_bendsense_lsb; 340 updateBendSensitivity(); 341 expression = 127; 342 sustain = false; 343 softPedal = false; 344 vibrato = 0; 345 aftertouch = 0; 346 std::memset(noteAftertouch, 0, 128); 347 noteAfterTouchInUse = false; 348 vibspeed = 2 * 3.141592653 * 5.0; 349 vibdepth = 0.5 / 127; 350 vibdelay_us = 0; 351 portamento = 0; 352 portamentoEnable = false; 353 portamentoSource = -1; 354 portamentoRate = HUGE_VAL; 355 } 356 357 /** 358 * @brief Has channel vibrato to process 359 * @return 360 */ hasVibratoOPNMIDIplay::MIDIchannel361 bool hasVibrato() 362 { 363 return (vibrato > 0) || (aftertouch > 0) || noteAfterTouchInUse; 364 } 365 366 /** 367 * @brief Commit pitch bend sensitivity value from MSB and LSB 368 */ updateBendSensitivityOPNMIDIplay::MIDIchannel369 void updateBendSensitivity() 370 { 371 int cent = bendsense_msb * 128 + bendsense_lsb; 372 bendsense = cent * (1.0 / (128 * 8192)); 373 } 374 375 /** 376 * @brief Clean up the state of the active note before removal 377 */ cleanupNoteOPNMIDIplay::MIDIchannel378 void cleanupNote(notes_iterator i) 379 { 380 NoteInfo &info = i->value; 381 if(info.glideRate != HUGE_VAL) 382 --gliding_note_count; 383 if(info.ttl > 0) 384 --extended_note_count; 385 } 386 MIDIchannelOPNMIDIplay::MIDIchannel387 MIDIchannel() : 388 def_volume(100), 389 def_bendsense_lsb(0), 390 def_bendsense_msb(2), 391 activenotes(128) 392 { 393 gliding_note_count = 0; 394 extended_note_count = 0; 395 reset(); 396 } 397 }; 398 399 /** 400 * @brief Additional information about OPN2 channels 401 */ 402 struct OpnChannel 403 { 404 struct Location 405 { 406 uint16_t MidCh; 407 uint8_t note; operator ==OPNMIDIplay::OpnChannel::Location408 bool operator==(const Location &l) const 409 { return MidCh == l.MidCh && note == l.note; } operator !=OPNMIDIplay::OpnChannel::Location410 bool operator!=(const Location &l) const 411 { return !operator==(l); } 412 char _padding[1]; 413 }; 414 struct LocationData 415 { 416 Location loc; 417 enum { 418 Sustain_None = 0x00, 419 Sustain_Pedal = 0x01, 420 Sustain_Sostenuto = 0x02, 421 Sustain_ANY = Sustain_Pedal | Sustain_Sostenuto 422 }; 423 uint32_t sustained; 424 char _padding[3]; 425 MIDIchannel::NoteInfo::Phys ins; // a copy of that in phys[] 426 //! Has fixed sustain, don't iterate "on" timeout 427 bool fixed_sustain; 428 //! Timeout until note will be allowed to be killed by channel manager while it is on 429 int64_t kon_time_until_neglible_us; 430 int64_t vibdelay_us; 431 432 struct FindPredicate 433 { FindPredicateOPNMIDIplay::OpnChannel::LocationData::FindPredicate434 explicit FindPredicate(Location loc) 435 : loc(loc) {} operator ()OPNMIDIplay::OpnChannel::LocationData::FindPredicate436 bool operator()(const LocationData &ld) const 437 { return ld.loc == loc; } 438 Location loc; 439 }; 440 }; 441 442 //! Time left until sounding will be muted after key off 443 int64_t koff_time_until_neglible_us; 444 445 //! Recently passed instrument, improves a goodness of released but busy channel when matching 446 MIDIchannel::NoteInfo::Phys recent_ins; 447 448 pl_list<LocationData> users; 449 typedef pl_list<LocationData>::iterator users_iterator; 450 typedef pl_list<LocationData>::const_iterator const_users_iterator; 451 find_userOPNMIDIplay::OpnChannel452 users_iterator find_user(const Location &loc) 453 { 454 return users.find_if(LocationData::FindPredicate(loc)); 455 } 456 find_or_create_userOPNMIDIplay::OpnChannel457 users_iterator find_or_create_user(const Location &loc) 458 { 459 users_iterator it = find_user(loc); 460 if(it.is_end() && users.size() != users.capacity()) 461 { 462 LocationData ld; 463 ld.loc = loc; 464 it = users.insert(users.end(), ld); 465 } 466 return it; 467 } 468 469 // For channel allocation: OpnChannelOPNMIDIplay::OpnChannel470 OpnChannel(): koff_time_until_neglible_us(0), users(128) 471 { 472 std::memset(&recent_ins, 0, sizeof(MIDIchannel::NoteInfo::Phys)); 473 } 474 OpnChannelOPNMIDIplay::OpnChannel475 OpnChannel(const OpnChannel &oth): koff_time_until_neglible_us(oth.koff_time_until_neglible_us), users(oth.users) 476 { 477 } 478 operator =OPNMIDIplay::OpnChannel479 OpnChannel &operator=(const OpnChannel &oth) 480 { 481 koff_time_until_neglible_us = oth.koff_time_until_neglible_us; 482 users = oth.users; 483 return *this; 484 } 485 486 /** 487 * @brief Increases age of active note in microseconds time 488 * @param us Amount time in microseconds 489 */ 490 void addAge(int64_t us); 491 }; 492 493 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER 494 /** 495 * @brief MIDI files player sequencer 496 */ 497 AdlMIDI_UPtr<MidiSequencer> m_sequencer; 498 499 /** 500 * @brief Interface between MIDI sequencer and this library 501 */ 502 AdlMIDI_UPtr<BW_MidiRtInterface> m_sequencerInterface; 503 504 /** 505 * @brief Initialize MIDI sequencer interface 506 */ 507 void initSequencerInterface(); 508 #endif //OPNMIDI_DISABLE_MIDI_SEQUENCER 509 510 struct Setup 511 { 512 int emulator; 513 bool runAtPcmRate; 514 unsigned int OpnBank; 515 unsigned int numChips; 516 unsigned int LogarithmicVolumes; 517 int VolumeModel; 518 int lfoEnable; 519 int lfoFrequency; 520 int chipType; 521 //unsigned int SkipForward; 522 int ScaleModulators; 523 bool fullRangeBrightnessCC74; 524 525 double delay; 526 double carry; 527 528 /* The lag between visual content and audio content equals */ 529 /* the sum of these two buffers. */ 530 double mindelay; 531 double maxdelay; 532 533 /* For internal usage */ 534 ssize_t tick_skip_samples_delay; /* Skip tick processing after samples count. */ 535 /* For internal usage */ 536 537 unsigned long PCM_RATE; 538 }; 539 540 /** 541 * @brief MIDI Marker entry 542 */ 543 struct MIDI_MarkerEntry 544 { 545 //! Label of marker 546 std::string label; 547 //! Absolute position in seconds 548 double pos_time; 549 //! Absolute position in ticks in the track 550 uint64_t pos_ticks; 551 }; 552 553 //! Available MIDI Channels 554 std::vector<MIDIchannel> m_midiChannels; 555 556 //! SysEx device ID 557 uint8_t m_sysExDeviceId; 558 559 /** 560 * @brief MIDI Synthesizer mode 561 */ 562 enum SynthMode 563 { 564 Mode_GM = 0x00, 565 Mode_GS = 0x01, 566 Mode_XG = 0x02, 567 Mode_GM2 = 0x04 568 }; 569 //! MIDI Synthesizer mode 570 uint32_t m_synthMode; 571 572 //! Installed function hooks 573 MIDIEventHooks hooks; 574 575 private: 576 //! Per-track MIDI devices map 577 std::map<std::string, size_t> m_midiDevices; 578 //! Current MIDI device per track 579 std::map<size_t /*track*/, size_t /*channel begin index*/> m_currentMidiDevice; 580 581 //! Chip channels map 582 std::vector<OpnChannel> m_chipChannels; 583 //! Counter of arpeggio processing 584 size_t m_arpeggioCounter; 585 586 #if defined(ADLMIDI_AUDIO_TICK_HANDLER) 587 //! Audio tick counter 588 uint32_t m_audioTickCounter; 589 #endif 590 591 //! Local error string 592 std::string errorStringOut; 593 594 //! Missing instruments catches 595 std::set<size_t> caugh_missing_instruments; 596 //! Missing melodic banks catches 597 std::set<size_t> caugh_missing_banks_melodic; 598 //! Missing percussion banks catches 599 std::set<size_t> caugh_missing_banks_percussion; 600 601 public: 602 603 const std::string &getErrorString(); 604 void setErrorString(const std::string &err); 605 606 //! OPN2 Chip manager 607 AdlMIDI_UPtr<Synth> m_synth; 608 609 //! Generator output buffer 610 int32_t m_outBuf[1024]; 611 612 //! Synthesizer setup 613 Setup m_setup; 614 615 /** 616 * @brief Load bank from file 617 * @param filename Path to bank file 618 * @return true on succes 619 */ 620 bool LoadBank(const std::string &filename); 621 622 /** 623 * @brief Load bank from memory block 624 * @param data Pointer to memory block where raw bank file is stored 625 * @param size Size of given memory block 626 * @return true on succes 627 */ 628 bool LoadBank(const void *data, size_t size); 629 630 /** 631 * @brief Load bank from opened FileAndMemReader class 632 * @param fr Instance with opened file 633 * @return true on succes 634 */ 635 bool LoadBank(FileAndMemReader &fr); 636 637 #ifndef OPNMIDI_DISABLE_MIDI_SEQUENCER 638 /** 639 * @brief MIDI file loading pre-process 640 * @return true on success, false on failure 641 */ 642 bool LoadMIDI_pre(); 643 644 /** 645 * @brief MIDI file loading post-process 646 * @return true on success, false on failure 647 */ 648 bool LoadMIDI_post(); 649 650 /** 651 * @brief Load music file from a file 652 * @param filename Path to music file 653 * @return true on success, false on failure 654 */ 655 656 bool LoadMIDI(const std::string &filename); 657 658 /** 659 * @brief Load music file from the memory block 660 * @param data pointer to the memory block 661 * @param size size of memory block 662 * @return true on success, false on failure 663 */ 664 bool LoadMIDI(const void *data, size_t size); 665 666 /** 667 * @brief Periodic tick handler. 668 * @param s seconds since last call 669 * @param granularity don't expect intervals smaller than this, in seconds 670 * @return desired number of seconds until next call 671 */ 672 double Tick(double s, double granularity); 673 #endif //OPNMIDI_DISABLE_MIDI_SEQUENCER 674 675 /** 676 * @brief Process extra iterators like vibrato or arpeggio 677 * @param s seconds since last call 678 */ 679 void TickIterators(double s); 680 681 682 /* RealTime event triggers */ 683 /** 684 * @brief Reset state of all channels 685 */ 686 void realTime_ResetState(); 687 688 /** 689 * @brief Note On event 690 * @param channel MIDI channel 691 * @param note Note key (from 0 to 127) 692 * @param velocity Velocity level (from 0 to 127) 693 * @return true if Note On event was accepted 694 */ 695 bool realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity); 696 697 /** 698 * @brief Note Off event 699 * @param channel MIDI channel 700 * @param note Note key (from 0 to 127) 701 */ 702 void realTime_NoteOff(uint8_t channel, uint8_t note); 703 704 /** 705 * @brief Note aftertouch event 706 * @param channel MIDI channel 707 * @param note Note key (from 0 to 127) 708 * @param atVal After-Touch level (from 0 to 127) 709 */ 710 void realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal); 711 712 /** 713 * @brief Channel aftertouch event 714 * @param channel MIDI channel 715 * @param atVal After-Touch level (from 0 to 127) 716 */ 717 void realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal); 718 719 /** 720 * @brief Controller Change event 721 * @param channel MIDI channel 722 * @param type Type of controller 723 * @param value Value of the controller (from 0 to 127) 724 */ 725 void realTime_Controller(uint8_t channel, uint8_t type, uint8_t value); 726 727 /** 728 * @brief Patch change 729 * @param channel MIDI channel 730 * @param patch Patch Number (from 0 to 127) 731 */ 732 void realTime_PatchChange(uint8_t channel, uint8_t patch); 733 734 /** 735 * @brief Pitch bend change 736 * @param channel MIDI channel 737 * @param pitch Concoctated raw pitch value 738 */ 739 void realTime_PitchBend(uint8_t channel, uint16_t pitch); 740 741 /** 742 * @brief Pitch bend change 743 * @param channel MIDI channel 744 * @param msb MSB of pitch value 745 * @param lsb LSB of pitch value 746 */ 747 void realTime_PitchBend(uint8_t channel, uint8_t msb, uint8_t lsb); 748 749 /** 750 * @brief LSB Bank Change CC 751 * @param channel MIDI channel 752 * @param lsb LSB value of bank number 753 */ 754 void realTime_BankChangeLSB(uint8_t channel, uint8_t lsb); 755 756 /** 757 * @brief MSB Bank Change CC 758 * @param channel MIDI channel 759 * @param lsb MSB value of bank number 760 */ 761 void realTime_BankChangeMSB(uint8_t channel, uint8_t msb); 762 763 /** 764 * @brief Bank Change (united value) 765 * @param channel MIDI channel 766 * @param bank Bank number value 767 */ 768 void realTime_BankChange(uint8_t channel, uint16_t bank); 769 770 /** 771 * @brief Sets the Device identifier 772 * @param id 7-bit Device identifier 773 */ 774 void setDeviceId(uint8_t id); 775 776 /** 777 * @brief System Exclusive message 778 * @param msg Raw SysEx Message 779 * @param size Length of SysEx message 780 * @return true if message was passed successfully. False on any errors 781 */ 782 bool realTime_SysEx(const uint8_t *msg, size_t size); 783 784 /** 785 * @brief Turn off all notes and mute the sound of releasing notes 786 */ 787 void realTime_panic(); 788 789 /** 790 * @brief Device switch (to extend 16-channels limit of MIDI standard) 791 * @param track MIDI track index 792 * @param data Device name 793 * @param length Length of device name string 794 */ 795 void realTime_deviceSwitch(size_t track, const char *data, size_t length); 796 797 /** 798 * @brief Currently selected device index 799 * @param track MIDI track index 800 * @return Multiple 16 value 801 */ 802 size_t realTime_currentDevice(size_t track); 803 804 #if defined(ADLMIDI_AUDIO_TICK_HANDLER) 805 // Audio rate tick handler 806 void AudioTick(uint32_t chipId, uint32_t rate); 807 #endif 808 809 private: 810 /** 811 * @brief Hardware manufacturer (Used for SysEx) 812 */ 813 enum 814 { 815 Manufacturer_Roland = 0x41, 816 Manufacturer_Yamaha = 0x43, 817 Manufacturer_UniversalNonRealtime = 0x7E, 818 Manufacturer_UniversalRealtime = 0x7F 819 }; 820 821 /** 822 * @brief Roland Mode (Used for SysEx) 823 */ 824 enum 825 { 826 RolandMode_Request = 0x11, 827 RolandMode_Send = 0x12 828 }; 829 830 /** 831 * @brief Device model (Used for SysEx) 832 */ 833 enum 834 { 835 RolandModel_GS = 0x42, 836 RolandModel_SC55 = 0x45, 837 YamahaModel_XG = 0x4C 838 }; 839 840 /** 841 * @brief Process generic SysEx events 842 * @param dev Device ID 843 * @param realtime Is real-time event 844 * @param data Raw SysEx data 845 * @param size Size of given SysEx data 846 * @return true when event was successfully handled 847 */ 848 bool doUniversalSysEx(unsigned dev, bool realtime, const uint8_t *data, size_t size); 849 850 /** 851 * @brief Process events specific to Roland devices 852 * @param dev Device ID 853 * @param data Raw SysEx data 854 * @param size Size of given SysEx data 855 * @return true when event was successfully handled 856 */ 857 bool doRolandSysEx(unsigned dev, const uint8_t *data, size_t size); 858 859 /** 860 * @brief Process events specific to Yamaha devices 861 * @param dev Device ID 862 * @param data Raw SysEx data 863 * @param size Size of given SysEx data 864 * @return true when event was successfully handled 865 */ 866 bool doYamahaSysEx(unsigned dev, const uint8_t *data, size_t size); 867 868 private: 869 /** 870 * @brief Note Update properties 871 */ 872 enum 873 { 874 Upd_Patch = 0x1, 875 Upd_Pan = 0x2, 876 Upd_Volume = 0x4, 877 Upd_Pitch = 0x8, 878 Upd_All = Upd_Pan + Upd_Volume + Upd_Pitch, 879 Upd_Off = 0x20, 880 Upd_Mute = 0x40, 881 Upd_OffMute = Upd_Off + Upd_Mute 882 }; 883 884 /** 885 * @brief Update active note 886 * @param MidCh MIDI Channel where note is processing 887 * @param i Iterator that points to active note in the MIDI channel 888 * @param props_mask Properties to update 889 * @param select_adlchn Specify chip channel, or -1 - all chip channels used by the note 890 */ 891 void noteUpdate(size_t midCh, 892 MIDIchannel::notes_iterator i, 893 unsigned props_mask, 894 int32_t select_adlchn = -1); 895 896 void noteUpdateAll(size_t midCh, unsigned props_mask); 897 898 /** 899 * @brief Determine how good a candidate this adlchannel would be for playing a note from this instrument. 900 * @param c Wanted chip channel 901 * @param ins Instrument wanted to be used in this channel 902 * @return Calculated coodness points 903 */ 904 int64_t calculateChipChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const; 905 906 /** 907 * @brief A new note will be played on this channel using this instrument. 908 * @param c Wanted chip channel 909 * @param ins Instrument wanted to be used in this channel 910 * Kill existing notes on this channel (or don't, if we do arpeggio) 911 */ 912 void prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins); 913 914 /** 915 * @brief Kills note that uses wanted channel. When arpeggio is possible, note is evaluating to another channel 916 * @param from_channel Wanted chip channel 917 * @param j Chip channel instance 918 * @param i MIDI Channel active note instance 919 */ 920 void killOrEvacuate( 921 size_t from_channel, 922 OpnChannel::users_iterator j, 923 MIDIchannel::notes_iterator i); 924 925 /** 926 * @brief Off all notes and silence sound 927 */ 928 void panic(); 929 930 /** 931 * @brief Kill note, sustaining by pedal or sostenuto 932 * @param MidCh MIDI channel, -1 - all MIDI channels 933 * @param this_adlchn Chip channel, -1 - all chip channels 934 * @param sustain_type Type of systain to process 935 */ 936 void killSustainingNotes(int32_t midCh = -1, 937 int32_t this_adlchn = -1, 938 uint32_t sustain_type = OpnChannel::LocationData::Sustain_ANY); 939 /** 940 * @brief Find active notes and mark them as sostenuto-sustained 941 * @param MidCh MIDI channel, -1 - all MIDI channels 942 */ 943 void markSostenutoNotes(int32_t midCh = -1); 944 945 /** 946 * @brief Set RPN event value 947 * @param MidCh MIDI channel 948 * @param value 1 byte part of RPN value 949 * @param MSB is MSB or LSB part of value 950 */ 951 void setRPN(size_t midCh, unsigned value, bool MSB); 952 953 /** 954 * @brief Update portamento setup in MIDI channel 955 * @param midCh MIDI channel where portamento needed to be updated 956 */ 957 void updatePortamento(size_t midCh); 958 959 /** 960 * @brief Off the note 961 * @param midCh MIDI channel 962 * @param note Note to off 963 * @param forceNow Do not delay the key-off to a later time 964 */ 965 void noteOff(size_t midCh, uint8_t note, bool forceNow = false); 966 967 /** 968 * @brief Update processing of vibrato to amount of seconds 969 * @param amount Amount value in seconds 970 */ 971 void updateVibrato(double amount); 972 973 /** 974 * @brief Update auto-arpeggio 975 * @param amount Amount value in seconds [UNUSED] 976 */ 977 void updateArpeggio(double /*amount*/); 978 979 /** 980 * @brief Update Portamento gliding to amount of seconds 981 * @param amount Amount value in seconds 982 */ 983 void updateGlide(double amount); 984 985 public: 986 /** 987 * @brief Checks was device name used or not 988 * @param name Name of MIDI device 989 * @return Offset of the MIDI Channels, multiple to 16 990 */ 991 size_t chooseDevice(const std::string &name); 992 993 /** 994 * @brief Gets a textual description of the state of chip channels 995 * @param text character pointer for text 996 * @param attr character pointer for text attributes 997 * @param size number of characters available to write 998 */ 999 void describeChannels(char *text, char *attr, size_t size); 1000 }; 1001 1002 #endif // OPNMIDI_MIDIPLAY_HPP 1003