diff options
author | JP Cimalando <jpcima@users.noreply.github.com> | 2018-11-10 19:05:27 +0100 |
---|---|---|
committer | JP Cimalando <jpcima@users.noreply.github.com> | 2018-11-10 19:05:27 +0100 |
commit | 63ae4b909946eca9be11f2c5b0f0dc08ae706597 (patch) | |
tree | 9b6faf206e83d30a0e1a38dd56565f7c3b9f4609 | |
parent | 298160f0154a05030681a208a247e2ed309f89db (diff) | |
download | libADLMIDI-63ae4b909946eca9be11f2c5b0f0dc08ae706597.tar.gz libADLMIDI-63ae4b909946eca9be11f2c5b0f0dc08ae706597.tar.bz2 libADLMIDI-63ae4b909946eca9be11f2c5b0f0dc08ae706597.zip |
converted activenotes to generic list
-rw-r--r-- | src/adlmidi_midiplay.cpp | 131 | ||||
-rw-r--r-- | src/adlmidi_midiplay.hpp | 105 |
2 files changed, 96 insertions, 140 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 62c7ee3..370f723 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -294,12 +294,13 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if((synth.m_musicMode == Synth::MODE_RSXX) && (velocity != 0)) { // Check if this is just a note after-touch - MIDIchannel::activenoteiterator i = m_midiChannels[channel].activenotes_find(note); - if(i) + MIDIchannel::notes_iterator i = m_midiChannels[channel].find_activenote(note); + if(!i.is_end()) { - const int veloffset = i->ains->midi_velocity_offset; + MIDIchannel::NoteInfo &ni = i->value; + const int veloffset = ni.ains->midi_velocity_offset; velocity = (uint8_t)std::min(127, std::max(1, (int)velocity + veloffset)); - i->vol = velocity; + ni.vol = velocity; noteUpdate(channel, i, Upd_Volume); return false; } @@ -468,11 +469,11 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if(isBlankNote) { // Don't even try to play the blank instrument! But, insert the dummy note. - std::pair<MIDIchannel::activenoteiterator, bool> - dummy = midiChan.activenotes_insert(note); - dummy.first->isBlank = true; - dummy.first->ains = NULL; - dummy.first->chip_channels_count = 0; + MIDIchannel::notes_iterator i = midiChan.find_or_create_activenote(note); + MIDIchannel::NoteInfo &dummy = i->value; + dummy.isBlank = true; + dummy.ains = NULL; + dummy.chip_channels_count = 0; // Record the last note on MIDI channel as source of portamento midiChan.portamentoSource = static_cast<int8_t>(note); return false; @@ -565,18 +566,18 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) velocity = static_cast<uint8_t>(std::floor(static_cast<float>(velocity) * 0.8f)); // Allocate active note for MIDI channel - std::pair<MIDIchannel::activenoteiterator, bool> - ir = midiChan.activenotes_insert(note); - ir.first->vol = velocity; - ir.first->vibrato = midiChan.noteAftertouch[note]; - ir.first->noteTone = static_cast<int16_t>(tone); - ir.first->currentTone = tone; - ir.first->glideRate = HUGE_VAL; - ir.first->midiins = midiins; - ir.first->isPercussion = isPercussion; - ir.first->isBlank = isBlankNote; - ir.first->ains = ains; - ir.first->chip_channels_count = 0; + MIDIchannel::notes_iterator ir = midiChan.find_or_create_activenote(note); + MIDIchannel::NoteInfo &ni = ir->value; + ni.vol = velocity; + ni.vibrato = midiChan.noteAftertouch[note]; + ni.noteTone = static_cast<int16_t>(tone); + ni.currentTone = tone; + ni.glideRate = HUGE_VAL; + ni.midiins = midiins; + ni.isPercussion = isPercussion; + ni.isBlank = isBlankNote; + ni.ains = ains; + ni.chip_channels_count = 0; int8_t currentPortamentoSource = midiChan.portamentoSource; double currentPortamentoRate = midiChan.portamentoRate; @@ -589,8 +590,8 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) // Enable gliding on portamento note if (portamentoEnable && currentPortamentoSource >= 0) { - ir.first->currentTone = currentPortamentoSource; - ir.first->glideRate = currentPortamentoRate; + ni.currentTone = currentPortamentoSource; + ni.glideRate = currentPortamentoRate; ++midiChan.gliding_note_count; } @@ -600,10 +601,10 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity) if(c < 0) continue; uint16_t chipChan = static_cast<uint16_t>(adlchannel[ccount]); - ir.first->phys_ensure_find_or_create(chipChan)->assign(voices[ccount]); + ni.phys_ensure_find_or_create(chipChan)->assign(voices[ccount]); } - noteUpdate(channel, ir.first, Upd_All | Upd_Patch); + noteUpdate(channel, ir, Upd_All | Upd_Patch); for(unsigned ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount) { @@ -629,10 +630,10 @@ void MIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t at if(static_cast<size_t>(channel) > m_midiChannels.size()) channel = channel % 16; MIDIchannel &chan = m_midiChannels[channel]; - MIDIchannel::activenoteiterator i = m_midiChannels[channel].activenotes_find(note); - if(i) + MIDIchannel::notes_iterator i = m_midiChannels[channel].find_activenote(note); + if(!i.is_end()) { - i->vibrato = atVal; + i->value.vibrato = atVal; } uint8_t oldAtVal = chan.noteAftertouch[note % 128]; @@ -1116,12 +1117,12 @@ void MIDIplay::AudioTick(uint32_t chipId, uint32_t rate) #endif void MIDIplay::noteUpdate(size_t midCh, - MIDIplay::MIDIchannel::activenoteiterator i, + MIDIplay::MIDIchannel::notes_iterator i, unsigned props_mask, int32_t select_adlchn) { Synth &synth = *m_synth; - MIDIchannel::NoteInfo &info = *i; + MIDIchannel::NoteInfo &info = i->value; const int16_t noteTone = info.noteTone; const double currentTone = info.currentTone; const uint8_t vol = info.vol; @@ -1134,7 +1135,7 @@ void MIDIplay::noteUpdate(size_t midCh, if(info.isBlank) { if(props_mask & Upd_Off) - m_midiChannels[midCh].activenotes_erase(i); + m_midiChannels[midCh].activenotes.erase(i); return; } @@ -1313,7 +1314,7 @@ void MIDIplay::noteUpdate(size_t midCh, double bend = midibend + ins.ains.finetune; double phase = 0.0; uint8_t vibrato = std::max(m_midiChannels[midCh].vibrato, m_midiChannels[midCh].aftertouch); - vibrato = std::max(vibrato, i->vibrato); + vibrato = std::max(vibrato, info.vibrato); if((ains.flags & adlinsdata::Flag_Pseudo4op) && ins.pseudo4op) { @@ -1334,18 +1335,18 @@ void MIDIplay::noteUpdate(size_t midCh, if(info.chip_channels_count == 0) { - if(i->glideRate != HUGE_VAL) + if(info.glideRate != HUGE_VAL) --m_midiChannels[midCh].gliding_note_count; - m_midiChannels[midCh].activenotes_erase(i); + m_midiChannels[midCh].activenotes.erase(i); } } void MIDIplay::noteUpdateAll(size_t midCh, unsigned props_mask) { - for(MIDIchannel::activenoteiterator - i = m_midiChannels[midCh].activenotes_begin(); i;) + for(MIDIchannel::notes_iterator + i = m_midiChannels[midCh].activenotes.begin(); !i.is_end();) { - MIDIchannel::activenoteiterator j(i++); + MIDIchannel::notes_iterator j(i++); noteUpdate(midCh, j, props_mask); } } @@ -1387,11 +1388,13 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note s -= (jd.sustained == AdlChannel::LocationData::Sustain_None) ? kon_ms : (kon_ms / 2); - MIDIchannel::activenoteiterator - k = const_cast<MIDIchannel &>(m_midiChannels[jd.loc.MidCh]).activenotes_find(jd.loc.note); + MIDIchannel::notes_iterator + k = const_cast<MIDIchannel &>(m_midiChannels[jd.loc.MidCh]).find_activenote(jd.loc.note); - if(k) + if(!k.is_end()) { + const MIDIchannel::NoteInfo &info = k->value; + // Same instrument = good if(jd.ins == ins) { @@ -1403,7 +1406,7 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note } // Percussion is inferior to melody - s += k->isPercussion ? 50 : 0; + s += info.isPercussion ? 50 : 0; /* if(k->second.midiins >= 25 && k->second.midiins < 40 @@ -1460,8 +1463,8 @@ void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInf { // Collision: Kill old note, // UNLESS we're going to do arpeggio - MIDIchannel::activenoteiterator i - (m_midiChannels[jd.loc.MidCh].activenotes_ensure_find(jd.loc.note)); + MIDIchannel::notes_iterator i + (m_midiChannels[jd.loc.MidCh].ensure_find_activenote(jd.loc.note)); // Check if we can do arpeggio. if((jd.vibdelay_us < 70000 @@ -1491,11 +1494,12 @@ void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInf void MIDIplay::killOrEvacuate(size_t from_channel, AdlChannel::users_iterator j, - MIDIplay::MIDIchannel::activenoteiterator i) + MIDIplay::MIDIchannel::notes_iterator i) { Synth &synth = *m_synth; uint32_t maxChannels = ADL_MAX_CHIPS * 18; AdlChannel::LocationData &jd = j->value; + MIDIchannel::NoteInfo &info = i->value; // Before killing the note, check if it can be // evacuated to another channel as an arpeggio @@ -1529,17 +1533,17 @@ void MIDIplay::killOrEvacuate(size_t from_channel, { hooks.onNote(hooks.onNote_userData, (int)from_channel, - i->noteTone, - static_cast<int>(i->midiins), 0, 0.0); + info.noteTone, + static_cast<int>(info.midiins), 0, 0.0); hooks.onNote(hooks.onNote_userData, (int)c, - i->noteTone, - static_cast<int>(i->midiins), - i->vol, 0.0); + info.noteTone, + static_cast<int>(info.midiins), + info.vol, 0.0); } - i->phys_erase(static_cast<uint16_t>(from_channel)); - i->phys_ensure_find_or_create(cs)->assign(jd.ins); + info.phys_erase(static_cast<uint16_t>(from_channel)); + info.phys_ensure_find_or_create(cs)->assign(jd.ins); m_chipChannels[cs].users.push_back(jd); m_chipChannels[from_channel].users.erase(j); return; @@ -1683,9 +1687,9 @@ void MIDIplay::updatePortamento(size_t midCh) void MIDIplay::noteOff(size_t midCh, uint8_t note) { - MIDIchannel::activenoteiterator - i = m_midiChannels[midCh].activenotes_find(note); - if(i) + MIDIchannel::notes_iterator + i = m_midiChannels[midCh].find_activenote(note); + if(!i.is_end()) noteUpdate(midCh, i, Upd_Off); } @@ -1694,7 +1698,7 @@ void MIDIplay::updateVibrato(double amount) { for(size_t a = 0, b = m_midiChannels.size(); a < b; ++a) { - if(m_midiChannels[a].hasVibrato() && !m_midiChannels[a].activenotes_empty()) + if(m_midiChannels[a].hasVibrato() && !m_midiChannels[a].activenotes.empty()) { noteUpdateAll(static_cast<uint16_t>(a), Upd_Pitch); m_midiChannels[a].vibpos += amount * m_midiChannels[a].vibspeed; @@ -1776,7 +1780,7 @@ retry_arpeggio: { noteUpdate( d.loc.MidCh, - m_midiChannels[ d.loc.MidCh ].activenotes_ensure_find(d.loc.note), + m_midiChannels[ d.loc.MidCh ].ensure_find_activenote(d.loc.note), Upd_Off, static_cast<int32_t>(c)); goto retry_arpeggio; @@ -1784,7 +1788,7 @@ retry_arpeggio: noteUpdate( d.loc.MidCh, - m_midiChannels[ d.loc.MidCh ].activenotes_ensure_find(d.loc.note), + m_midiChannels[ d.loc.MidCh ].ensure_find_activenote(d.loc.note), Upd_Pitch | Upd_Volume | Upd_Pan, static_cast<int32_t>(c)); } @@ -1802,14 +1806,15 @@ void MIDIplay::updateGlide(double amount) if(midiChan.gliding_note_count == 0) continue; - for(MIDIchannel::activenoteiterator it = midiChan.activenotes_begin(); - it; ++it) + for(MIDIchannel::notes_iterator it = midiChan.activenotes.begin(); + !it.is_end(); ++it) { - double finalTone = it->noteTone; - double previousTone = it->currentTone; + MIDIchannel::NoteInfo &info = it->value; + double finalTone = info.noteTone; + double previousTone = info.currentTone; bool directionUp = previousTone < finalTone; - double toneIncr = amount * (directionUp ? +it->glideRate : -it->glideRate); + double toneIncr = amount * (directionUp ? +info.glideRate : -info.glideRate); double currentTone = previousTone + toneIncr; bool glideFinished = !(directionUp ? (currentTone < finalTone) : (currentTone > finalTone)); @@ -1817,7 +1822,7 @@ void MIDIplay::updateGlide(double amount) if(currentTone != previousTone) { - it->currentTone = currentTone; + info.currentTone = currentTone; noteUpdate(static_cast<uint16_t>(channel), it, Upd_Pitch); } } diff --git a/src/adlmidi_midiplay.hpp b/src/adlmidi_midiplay.hpp index d16d851..f7dc0fa 100644 --- a/src/adlmidi_midiplay.hpp +++ b/src/adlmidi_midiplay.hpp @@ -140,8 +140,6 @@ public: { //! Note number uint8_t note; - //! Is note active - bool active; //! Current pressure uint8_t vol; //! Note vibrato (a part of Note Aftertouch feature) @@ -166,6 +164,15 @@ public: MaxNumPhysItemCount = MaxNumPhysChans }; + struct FindPredicate + { + explicit FindPredicate(unsigned note) + : note(note) {} + bool operator()(const NoteInfo &ni) const + { return ni.note == note; } + unsigned note; + }; + /** * @brief Reference to currently using chip channel */ @@ -245,87 +252,31 @@ public: unsigned gliding_note_count; //! Active notes in the channel - NoteInfo activenotes[128]; - - struct activenoteiterator - { - explicit activenoteiterator(NoteInfo *info = NULL) - : ptr(info) {} - activenoteiterator &operator++() - { - if(ptr->note == 127) - ptr = NULL; - else - for(++ptr; ptr && !ptr->active;) - ptr = (ptr->note == 127) ? NULL : (ptr + 1); - return *this; - } - activenoteiterator operator++(int) - { - activenoteiterator pos = *this; - ++*this; - return pos; - } - NoteInfo &operator*() const - { return *ptr; } - NoteInfo *operator->() const - { return ptr; } - bool operator==(activenoteiterator other) const - { return ptr == other.ptr; } - bool operator!=(activenoteiterator other) const - { return ptr != other.ptr; } - operator NoteInfo *() const - { return ptr; } - private: - NoteInfo *ptr; - }; - - activenoteiterator activenotes_begin() - { - activenoteiterator it(activenotes); - return (it->active) ? it : ++it; - } + pl_list<NoteInfo> activenotes; + typedef typename pl_list<NoteInfo>::iterator notes_iterator; + typedef typename pl_list<NoteInfo>::const_iterator const_notes_iterator; - activenoteiterator activenotes_find(uint8_t note) + notes_iterator find_activenote(unsigned note) { - assert(note < 128); - return activenoteiterator( - activenotes[note].active ? &activenotes[note] : NULL); + return activenotes.find_if(NoteInfo::FindPredicate(note)); } - activenoteiterator activenotes_ensure_find(uint8_t note) + notes_iterator ensure_find_activenote(unsigned note) { - activenoteiterator it = activenotes_find(note); - assert(it); + notes_iterator it = find_activenote(note); + assert(!it.is_end()); return it; } - std::pair<activenoteiterator, bool> activenotes_insert(uint8_t note) - { - assert(note < 128); - NoteInfo &info = activenotes[note]; - bool inserted = !info.active; - if(inserted) info.active = true; - return std::pair<activenoteiterator, bool>(activenoteiterator(&info), inserted); - } - - void activenotes_erase(activenoteiterator pos) - { - if(pos) - pos->active = false; - } - - bool activenotes_empty() - { - return !activenotes_begin(); - } - - void activenotes_clear() + notes_iterator find_or_create_activenote(unsigned note) { - for(uint8_t i = 0; i < 128; ++i) { - activenotes[i].note = i; - activenotes[i].active = false; + notes_iterator it = find_activenote(note); + if(it.is_end()) { + NoteInfo ni; + ni.note = note; + it = activenotes.insert(activenotes.end(), ni); } + return it; } /** @@ -391,8 +342,8 @@ public: } MIDIchannel() + : activenotes(128) { - activenotes_clear(); gliding_note_count = 0; reset(); } @@ -432,7 +383,7 @@ public: struct FindPredicate { - FindPredicate(Location loc) + explicit FindPredicate(Location loc) : loc(loc) {} bool operator()(const LocationData &ld) const { return ld.loc == loc; } @@ -907,7 +858,7 @@ private: * @param select_adlchn Specify chip channel, or -1 - all chip channels used by the note */ void noteUpdate(size_t midCh, - MIDIchannel::activenoteiterator i, + MIDIchannel::notes_iterator i, unsigned props_mask, int32_t select_adlchn = -1); @@ -943,7 +894,7 @@ private: void killOrEvacuate( size_t from_channel, AdlChannel::users_iterator j, - MIDIchannel::activenoteiterator i); + MIDIchannel::notes_iterator i); /** * @brief Off all notes and silence sound |