diff options
author | Vitaly Novichkov <Wohlstand@users.noreply.github.com> | 2018-04-19 00:38:33 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-19 00:38:33 +0300 |
commit | 954f7e9860f4409eb46e0906dc95e3f2678f4caf (patch) | |
tree | 3eae66c1e86655f81ba6bc65cedcc016256ff9af /src | |
parent | 985f08d9ab40ffa6367261281660e6c3e5b0720f (diff) | |
parent | 9a4d104c76cacf92ce109fb56750cd7ec1f58def (diff) | |
download | libADLMIDI-954f7e9860f4409eb46e0906dc95e3f2678f4caf.tar.gz libADLMIDI-954f7e9860f4409eb46e0906dc95e3f2678f4caf.tar.bz2 libADLMIDI-954f7e9860f4409eb46e0906dc95e3f2678f4caf.zip |
Merge pull request #71 from jpcima/hard-realtime-phys3
Phys code rewrite
Diffstat (limited to 'src')
-rw-r--r-- | src/adlmidi_midiplay.cpp | 39 | ||||
-rw-r--r-- | src/adlmidi_private.hpp | 62 |
2 files changed, 73 insertions, 28 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 0636921..80f36ce 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -1093,8 +1093,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) //uint16_t i[2] = { ains.adlno1, ains.adlno2 }; bool pseudo_4op = ains->flags & adlinsdata::Flag_Pseudo4op; - size_t chans_count = (pseudo_4op || (ains->adlno1 != ains->adlno2)) ? 2 : 1; - MIDIchannel::NoteInfo::Phys voices[2] = + MIDIchannel::NoteInfo::Phys voices[MIDIchannel::NoteInfo::MaxNumPhysChans] = { {0, ains->adlno1, false}, {0, ains->adlno2, pseudo_4op} @@ -1202,15 +1201,15 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) ir.first->tone = tone; ir.first->midiins = midiins; ir.first->insmeta = meta; - ir.first->chip_channels_max = chans_count; + ir.first->chip_channels_count = 0; - for(size_t ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) + for(unsigned ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) { int32_t c = adlchannel[ccount]; if(c < 0) continue; - voices[ccount].chip_chan = static_cast<uint16_t>(c); - ir.first->chip_channels[ccount] = voices[ccount]; + uint16_t chipChan = static_cast<uint16_t>(adlchannel[ccount]); + ir.first->phys_ensure_find_or_create(chipChan)->assign(voices[ccount]); } NoteUpdate(channel, ir.first, Upd_All | Upd_Patch); return true; @@ -1446,7 +1445,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, my_loc.MidCh = MidCh; my_loc.note = info.note; - for(size_t ccount = 0; ccount < info.chip_channels_max; ccount++) + for(unsigned ccount = 0, ctotal = info.chip_channels_count; ccount < ctotal; ccount++) { const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount]; uint16_t c = ins.chip_chan; @@ -1464,7 +1463,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, } } - for(size_t ccount = 0; ccount < info.chip_channels_max; ccount++) + for(unsigned ccount = 0; ccount < info.chip_channels_count; ccount++) { const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount]; uint16_t c = ins.chip_chan; @@ -1506,9 +1505,8 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, hooks.onNote(hooks.onNote_userData, c, tone, midiins, -1, 0.0); } - //info.phys.erase(j); - if(ccount == (info.chip_channels_max - 1)) - info.chip_channels_max = 0; + info.phys_erase_at(&ins); // decrements channel count + --ccount; // adjusts index accordingly continue; } @@ -1633,7 +1631,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh, } } - if(info.chip_channels_max == 0) + if(info.chip_channels_count == 0) Ch[MidCh].activenotes_erase(i); } @@ -2219,7 +2217,7 @@ void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo // Collision: Kill old note, // UNLESS we're going to do arpeggio MIDIchannel::activenoteiterator i - (Ch[j->first.MidCh].activenotes_find(j->first.note)); + (Ch[j->first.MidCh].activenotes_ensure_find(j->first.note)); // Check if we can do arpeggio. if((j->second.vibdelay < 70 @@ -2289,15 +2287,8 @@ void MIDIplay::KillOrEvacuate(size_t from_channel, i->vol, 0.0); } - for(size_t cchan = 0; cchan < i->chip_channels_max; cchan++) - { - MIDIchannel::NoteInfo::Phys &chan = i->chip_channels[cchan]; - if(chan.chip_chan == static_cast<uint16_t>(from_channel)) - { - chan = j->second.ins; - chan.chip_chan = cs; - } - } + i->phys_erase(static_cast<uint16_t>(from_channel)); + i->phys_ensure_find_or_create(cs)->assign(j->second.ins); ch[cs].users.insert(*j); ch[from_channel].users.erase(j); return; @@ -2515,7 +2506,7 @@ retry_arpeggio: { NoteUpdate( i->first.MidCh, - Ch[ i->first.MidCh ].activenotes_find(i->first.note), + Ch[ i->first.MidCh ].activenotes_ensure_find(i->first.note), Upd_Off, static_cast<int32_t>(c)); goto retry_arpeggio; @@ -2523,7 +2514,7 @@ retry_arpeggio: NoteUpdate( i->first.MidCh, - Ch[ i->first.MidCh ].activenotes_find(i->first.note), + Ch[ i->first.MidCh ].activenotes_ensure_find(i->first.note), Upd_Pitch | Upd_Volume | Upd_Pan, static_cast<int32_t>(c)); } diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp index 6391f2a..69a833c 100644 --- a/src/adlmidi_private.hpp +++ b/src/adlmidi_private.hpp @@ -87,6 +87,7 @@ typedef int32_t ssize_t; #include <cmath> #include <cstdarg> #include <cstdio> +#include <cassert> #if !(defined(__APPLE__) && defined(__GLIBCXX__)) #include <cinttypes> //PRId32, PRIu32, etc. #else @@ -620,17 +621,23 @@ public: size_t insmeta; enum { - MaxNumPhysChans = 2 + MaxNumPhysChans = 2, + MaxNumPhysItemCount = MaxNumPhysChans, }; struct Phys { - //! Destinition chip channel + //! Destination chip channel uint16_t chip_chan; //! ins, inde to adl[] size_t insId; //! Is this voice must be detunable? bool pseudo4op; + void assign(const Phys &oth) + { + insId = oth.insId; + pseudo4op = oth.pseudo4op; + } bool operator==(const Phys &oth) const { return (insId == oth.insId) && (pseudo4op == oth.pseudo4op); @@ -641,9 +648,49 @@ public: } }; //! List of OPL3 channels it is currently occupying. - Phys chip_channels[MaxNumPhysChans]; + Phys chip_channels[MaxNumPhysItemCount]; //! Count of used channels. - size_t chip_channels_max; + unsigned chip_channels_count; + // + Phys *phys_find(unsigned chip_chan) + { + Phys *ph = NULL; + for(unsigned i = 0; i < chip_channels_count && !ph; ++i) + if(chip_channels[i].chip_chan == chip_chan) + ph = &chip_channels[i]; + return ph; + } + Phys *phys_find_or_create(unsigned chip_chan) + { + Phys *ph = phys_find(chip_chan); + if(!ph) { + if(chip_channels_count < MaxNumPhysItemCount) { + ph = &chip_channels[chip_channels_count++]; + ph->chip_chan = chip_chan; + } + } + return ph; + } + Phys *phys_ensure_find_or_create(unsigned chip_chan) + { + Phys *ph = phys_find_or_create(chip_chan); + assert(ph); + return ph; + } + void phys_erase_at(const Phys *ph) + { + unsigned pos = ph - chip_channels; + assert(pos < chip_channels_count); + for(unsigned i = pos + 1; i < chip_channels_count; ++i) + chip_channels[i - 1] = chip_channels[i]; + --chip_channels_count; + } + void phys_erase(unsigned chip_chan) + { + Phys *ph = phys_find(chip_chan); + if(ph) + phys_erase_at(ph); + } }; char ____padding2[5]; NoteInfo activenotes[128]; @@ -693,6 +740,13 @@ public: activenotes[note].active ? &activenotes[note] : 0); } + activenoteiterator activenotes_ensure_find(uint8_t note) + { + activenoteiterator it = activenotes_find(note); + assert(it); + return it; + } + std::pair<activenoteiterator, bool> activenotes_insert(uint8_t note) { NoteInfo &info = activenotes[note]; |