diff options
author | Vitaly Novichkov <Wohlstand@users.noreply.github.com> | 2018-11-20 01:58:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-20 01:58:00 +0300 |
commit | c936e5e9157f806ac056349ad4d6a6eba2a5af0c (patch) | |
tree | 72068feb108b84d2695f596e67f04253df2d0185 /src/adlmidi_midiplay.cpp | |
parent | f96317a88d0f6157adbdd2973ce0847c7d83f99e (diff) | |
parent | 1b82ca4e654759d69f18b0a772820f40567b0059 (diff) | |
download | libADLMIDI-c936e5e9157f806ac056349ad4d6a6eba2a5af0c.tar.gz libADLMIDI-c936e5e9157f806ac056349ad4d6a6eba2a5af0c.tar.bz2 libADLMIDI-c936e5e9157f806ac056349ad4d6a6eba2a5af0c.zip |
Merge pull request #192 from jpcima/std-structures
Std structures
Diffstat (limited to 'src/adlmidi_midiplay.cpp')
-rw-r--r-- | src/adlmidi_midiplay.cpp | 427 |
1 files changed, 158 insertions, 269 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 11e3f1a..f96243e 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -106,7 +106,7 @@ inline bool isXgPercChannel(uint8_t msb, uint8_t lsb) void MIDIplay::AdlChannel::addAge(int64_t us) { const int64_t neg = 1000 * static_cast<int64_t>(-0x1FFFFFFFll); - if(users_empty()) + if(users.empty()) { koff_time_until_neglible_us = std::max(koff_time_until_neglible_us - us, neg); if(koff_time_until_neglible_us < 0) @@ -115,11 +115,12 @@ void MIDIplay::AdlChannel::addAge(int64_t us) else { koff_time_until_neglible_us = 0; - for(LocationData *i = users_first; i; i = i->next) + for(users_iterator i = users.begin(); !i.is_end(); ++i) { - if(!i->fixed_sustain) - i->kon_time_until_neglible_us = std::max(i->kon_time_until_neglible_us - us, neg); - i->vibdelay_us += us; + LocationData &d = i->value; + if(!d.fixed_sustain) + d.kon_time_until_neglible_us = std::max(d.kon_time_until_neglible_us - us, neg); + d.vibdelay_us += us; } } } @@ -293,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; } @@ -467,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.ensure_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; @@ -564,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.ensure_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; @@ -588,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; } @@ -599,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) { @@ -628,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]; @@ -1115,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; @@ -1133,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; } @@ -1147,14 +1149,15 @@ void MIDIplay::noteUpdate(size_t midCh, if(props_mask & Upd_Patch) { synth.setPatch(c, ins.ains); - AdlChannel::LocationData *d = m_chipChannels[c].users_find_or_create(my_loc); - if(d) // inserts if necessary + AdlChannel::users_iterator i = m_chipChannels[c].find_or_create_user(my_loc); + if(!i.is_end()) // inserts if necessary { - d->sustained = AdlChannel::LocationData::Sustain_None; - d->vibdelay_us = 0; - d->fixed_sustain = (ains.ms_sound_kon == static_cast<uint16_t>(adlNoteOnMaxTime)); - d->kon_time_until_neglible_us = 1000 * ains.ms_sound_kon; - d->ins = ins; + AdlChannel::LocationData &d = i->value; + d.sustained = AdlChannel::LocationData::Sustain_None; + d.vibdelay_us = 0; + d.fixed_sustain = (ains.ms_sound_kon == static_cast<uint16_t>(adlNoteOnMaxTime)); + d.kon_time_until_neglible_us = 1000 * ains.ms_sound_kon; + d.ins = ins; } } } @@ -1172,15 +1175,15 @@ void MIDIplay::noteUpdate(size_t midCh, { if(!m_midiChannels[midCh].sustain) { - AdlChannel::LocationData *k = m_chipChannels[c].users_find(my_loc); - bool do_erase_user = (k && ((k->sustained & AdlChannel::LocationData::Sustain_Sostenuto) == 0)); + AdlChannel::users_iterator k = m_chipChannels[c].find_user(my_loc); + bool do_erase_user = (!k.is_end() && ((k->value.sustained & AdlChannel::LocationData::Sustain_Sostenuto) == 0)); if(do_erase_user) - m_chipChannels[c].users_erase(k); + m_chipChannels[c].users.erase(k); if(hooks.onNote) hooks.onNote(hooks.onNote_userData, c, noteTone, midiins, 0, 0.0); - if(do_erase_user && m_chipChannels[c].users_empty()) + if(do_erase_user && m_chipChannels[c].users.empty()) { synth.noteOff(c); if(props_mask & Upd_Mute) // Mute the note @@ -1198,9 +1201,9 @@ void MIDIplay::noteUpdate(size_t midCh, { // Sustain: Forget about the note, but don't key it off. // Also will avoid overwriting it very soon. - AdlChannel::LocationData *d = m_chipChannels[c].users_find_or_create(my_loc); - if(d) - d->sustained |= AdlChannel::LocationData::Sustain_Pedal; // note: not erased! + AdlChannel::users_iterator d = m_chipChannels[c].find_or_create_user(my_loc); + if(!d.is_end()) + d->value.sustained |= AdlChannel::LocationData::Sustain_Pedal; // note: not erased! if(hooks.onNote) hooks.onNote(hooks.onNote_userData, c, noteTone, midiins, -1, 0.0); } @@ -1302,24 +1305,24 @@ void MIDIplay::noteUpdate(size_t midCh, if(props_mask & Upd_Pitch) { - AdlChannel::LocationData *d = m_chipChannels[c].users_find(my_loc); + AdlChannel::users_iterator d = m_chipChannels[c].find_user(my_loc); // Don't bend a sustained note - if(!d || (d->sustained == AdlChannel::LocationData::Sustain_None)) + if(d.is_end() || (d->value.sustained == AdlChannel::LocationData::Sustain_None)) { MIDIchannel &chan = m_midiChannels[midCh]; double midibend = chan.bend * chan.bendsense; double bend = midibend + ins.ains.finetune; double phase = 0.0; uint8_t vibrato = std::max(chan.vibrato, chan.aftertouch); - vibrato = std::max(vibrato, i->vibrato); + vibrato = std::max(vibrato, info.vibrato); if((ains.flags & adlinsdata::Flag_Pseudo4op) && ins.pseudo4op) { phase = ains.voice2_fine_tune;//0.125; // Detune the note slightly (this is what Doom does) } - if(vibrato && (!d || d->vibdelay_us >= chan.vibdelay_us)) + if(vibrato && (d.is_end() || d->value.vibdelay_us >= chan.vibdelay_us)) bend += static_cast<double>(vibrato) * chan.vibdepth * std::sin(chan.vibpos); #define BEND_COEFFICIENT 172.4387 @@ -1333,18 +1336,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); } } @@ -1367,7 +1370,7 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note int64_t s = -koff_ms; // Rate channel with a releasing note - if(s < 0 && chan.users_empty()) + if(s < 0 && chan.users.empty()) { s -= 40000; // If it's same instrument, better chance to get it when no free channels @@ -1377,31 +1380,34 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note } // Same midi-instrument = some stability - for(AdlChannel::LocationData *j = chan.users_first; j; j = j->next) + for(AdlChannel::const_users_iterator j = chan.users.begin(); !j.is_end(); ++j) { + const AdlChannel::LocationData &jd = j->value; s -= 4000000; - int64_t kon_ms = j->kon_time_until_neglible_us / 1000; - s -= (j->sustained == AdlChannel::LocationData::Sustain_None) ? + int64_t kon_ms = jd.kon_time_until_neglible_us / 1000; + s -= (jd.sustained == AdlChannel::LocationData::Sustain_None) ? kon_ms : (kon_ms / 2); - MIDIchannel::activenoteiterator - k = const_cast<MIDIchannel &>(m_midiChannels[j->loc.MidCh]).activenotes_find(j->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(j->ins == ins) + if(jd.ins == ins) { s += 300; // Arpeggio candidate = even better - if(j->vibdelay_us < 70000 - || j->kon_time_until_neglible_us > 20000000) + if(jd.vibdelay_us < 70000 + || jd.kon_time_until_neglible_us > 20000000) s += 10; } // Percussion is inferior to melody - s += k->isPercussion ? 50 : 0; + s += info.isPercussion ? 50 : 0; /* if(k->second.midiins >= 25 && k->second.midiins < 40 @@ -1424,11 +1430,12 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note if(synth.m_channelCategory[c2] != synth.m_channelCategory[c]) continue; - for(AdlChannel::LocationData *m = m_chipChannels[c2].users_first; m; m = m->next) + for(AdlChannel::const_users_iterator m = m_chipChannels[c2].users.begin(); !m.is_end(); ++m) { - if(m->sustained != AdlChannel::LocationData::Sustain_None) continue; - if(m->vibdelay_us >= 200000) continue; - if(m->ins != j->ins) continue; + const AdlChannel::LocationData &md = m->value; + if(md.sustained != AdlChannel::LocationData::Sustain_None) continue; + if(md.vibdelay_us >= 200000) continue; + if(md.ins != jd.ins) continue; n_evacuation_stations += 1; } } @@ -1442,27 +1449,28 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins) { - if(m_chipChannels[c].users_empty()) return; // Nothing to do + if(m_chipChannels[c].users.empty()) return; // Nothing to do Synth &synth = *m_synth; //bool doing_arpeggio = false; - for(AdlChannel::LocationData *jnext = m_chipChannels[c].users_first; jnext;) + for(AdlChannel::users_iterator jnext = m_chipChannels[c].users.begin(); !jnext.is_end();) { - AdlChannel::LocationData *j = jnext; - jnext = jnext->next; + AdlChannel::users_iterator j = jnext; + AdlChannel::LocationData &jd = jnext->value; + ++jnext; - if(j->sustained == AdlChannel::LocationData::Sustain_None) + if(jd.sustained == AdlChannel::LocationData::Sustain_None) { // Collision: Kill old note, // UNLESS we're going to do arpeggio - MIDIchannel::activenoteiterator i - (m_midiChannels[j->loc.MidCh].activenotes_ensure_find(j->loc.note)); + MIDIchannel::notes_iterator i + (m_midiChannels[jd.loc.MidCh].ensure_find_activenote(jd.loc.note)); // Check if we can do arpeggio. - if((j->vibdelay_us < 70000 - || j->kon_time_until_neglible_us > 20000000) - && j->ins == ins) + if((jd.vibdelay_us < 70000 + || jd.kon_time_until_neglible_us > 20000000) + && jd.ins == ins) { // Do arpeggio together with this note. //doing_arpeggio = true; @@ -1481,16 +1489,18 @@ void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInf // Keyoff the channel so that it can be retriggered, // unless the new note will be introduced as just an arpeggio. - if(m_chipChannels[c].users_empty()) + if(m_chipChannels[c].users.empty()) synth.noteOff(c); } void MIDIplay::killOrEvacuate(size_t from_channel, - AdlChannel::LocationData *j, - MIDIplay::MIDIchannel::activenoteiterator i) + AdlChannel::users_iterator j, + 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 @@ -1509,33 +1519,34 @@ void MIDIplay::killOrEvacuate(size_t from_channel, continue; AdlChannel &adlch = m_chipChannels[c]; - if(adlch.users_size == AdlChannel::users_max) + if(adlch.users.size() == adlch.users.capacity()) continue; // no room for more arpeggio on channel - for(AdlChannel::LocationData *m = adlch.users_first; m; m = m->next) + for(AdlChannel::users_iterator m = adlch.users.begin(); !m.is_end(); ++m) { - if(m->vibdelay_us >= 200000 - && m->kon_time_until_neglible_us < 10000000) continue; - if(m->ins != j->ins) + AdlChannel::LocationData &mv = m->value; + + if(mv.vibdelay_us >= 200000 + && mv.kon_time_until_neglible_us < 10000000) continue; + if(mv.ins != jd.ins) continue; if(hooks.onNote) { 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(j->ins); - if(!m_chipChannels[cs].users_insert(*j)) - assert(false); - m_chipChannels[from_channel].users_erase(j); + 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; } } @@ -1548,7 +1559,7 @@ void MIDIplay::killOrEvacuate(size_t from_channel, ins );*/ // Kill it - noteUpdate(j->loc.MidCh, + noteUpdate(jd.loc.MidCh, i, Upd_Off, static_cast<int32_t>(from_channel)); @@ -1576,28 +1587,29 @@ void MIDIplay::killSustainingNotes(int32_t midCh, int32_t this_adlchn, uint32_t for(uint32_t c = first; c < last; ++c) { - if(m_chipChannels[c].users_empty()) + if(m_chipChannels[c].users.empty()) continue; // Nothing to do - for(AdlChannel::LocationData *jnext = m_chipChannels[c].users_first; jnext;) + for(AdlChannel::users_iterator jnext = m_chipChannels[c].users.begin(); !jnext.is_end();) { - AdlChannel::LocationData *j = jnext; - jnext = jnext->next; + AdlChannel::users_iterator j = jnext; + AdlChannel::LocationData &jd = j->value; + ++jnext; - if((midCh < 0 || j->loc.MidCh == midCh) - && ((j->sustained & sustain_type) != 0)) + if((midCh < 0 || jd.loc.MidCh == midCh) + && ((jd.sustained & sustain_type) != 0)) { int midiins = '?'; if(hooks.onNote) - hooks.onNote(hooks.onNote_userData, (int)c, j->loc.note, midiins, 0, 0.0); - j->sustained &= ~sustain_type; - if(j->sustained == AdlChannel::LocationData::Sustain_None) - m_chipChannels[c].users_erase(j);//Remove only when note is clean from any holders + hooks.onNote(hooks.onNote_userData, (int)c, jd.loc.note, midiins, 0, 0.0); + jd.sustained &= ~sustain_type; + if(jd.sustained == AdlChannel::LocationData::Sustain_None) + m_chipChannels[c].users.erase(j);//Remove only when note is clean from any holders } } // Keyoff the channel, if there are no users left. - if(m_chipChannels[c].users_empty()) + if(m_chipChannels[c].users.empty()) synth.noteOff(c); } } @@ -1608,15 +1620,16 @@ void MIDIplay::markSostenutoNotes(int32_t midCh) uint32_t first = 0, last = synth.m_numChannels; for(uint32_t c = first; c < last; ++c) { - if(m_chipChannels[c].users_empty()) + if(m_chipChannels[c].users.empty()) continue; // Nothing to do - for(AdlChannel::LocationData *jnext = m_chipChannels[c].users_first; jnext;) + for(AdlChannel::users_iterator jnext = m_chipChannels[c].users.begin(); !jnext.is_end();) { - AdlChannel::LocationData *j = jnext; - jnext = jnext->next; - if((j->loc.MidCh == midCh) && (j->sustained == AdlChannel::LocationData::Sustain_None)) - j->sustained |= AdlChannel::LocationData::Sustain_Sostenuto; + AdlChannel::users_iterator j = jnext; + AdlChannel::LocationData &jd = j->value; + ++jnext; + if((jd.loc.MidCh == midCh) && (jd.sustained == AdlChannel::LocationData::Sustain_None)) + jd.sustained |= AdlChannel::LocationData::Sustain_Sostenuto; } } } @@ -1675,9 +1688,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); } @@ -1686,7 +1699,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; @@ -1744,11 +1757,11 @@ retry_arpeggio: if(c > uint32_t(std::numeric_limits<int32_t>::max())) break; - size_t n_users = m_chipChannels[c].users_size; + size_t n_users = m_chipChannels[c].users.size(); if(n_users > 1) { - AdlChannel::LocationData *i = m_chipChannels[c].users_first; + AdlChannel::users_iterator i = m_chipChannels[c].users.begin(); size_t rate_reduction = 3; if(n_users >= 3) @@ -1759,23 +1772,24 @@ retry_arpeggio: for(size_t count = (m_arpeggioCounter / rate_reduction) % n_users, n = 0; n < count; ++n) - i = i->next; + ++i; - if(i->sustained == AdlChannel::LocationData::Sustain_None) + AdlChannel::LocationData &d = i->value; + if(d.sustained == AdlChannel::LocationData::Sustain_None) { - if(i->kon_time_until_neglible_us <= 0) + if(d.kon_time_until_neglible_us <= 0) { noteUpdate( - i->loc.MidCh, - m_midiChannels[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note), + d.loc.MidCh, + m_midiChannels[ d.loc.MidCh ].ensure_find_activenote(d.loc.note), Upd_Off, static_cast<int32_t>(c)); goto retry_arpeggio; } noteUpdate( - i->loc.MidCh, - m_midiChannels[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note), + d.loc.MidCh, + m_midiChannels[ d.loc.MidCh ].ensure_find_activenote(d.loc.note), Upd_Pitch | Upd_Volume | Upd_Pan, static_cast<int32_t>(c)); } @@ -1793,14 +1807,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)); @@ -1808,7 +1823,7 @@ void MIDIplay::updateGlide(double amount) if(currentTone != previousTone) { - it->currentTone = currentTone; + info.currentTone = currentTone; noteUpdate(static_cast<uint16_t>(channel), it, Upd_Pitch); } } @@ -1828,8 +1843,8 @@ void MIDIplay::describeChannels(char *str, char *attr, size_t size) { const AdlChannel &adlChannel = m_chipChannels[index]; - AdlChannel::LocationData *loc = adlChannel.users_first; - if(!loc) // off + AdlChannel::const_users_iterator loc = adlChannel.users.begin(); + if(loc.is_end()) // off { str[index] = '-'; } @@ -1855,8 +1870,8 @@ void MIDIplay::describeChannels(char *str, char *attr, size_t size) } uint8_t attribute = 0; - if (loc) // 4-bit color index of MIDI channel - attribute |= (uint8_t)(loc->loc.MidCh & 0xF); + if (!loc.is_end()) // 4-bit color index of MIDI channel + attribute |= (uint8_t)(loc->value.loc.MidCh & 0xF); attr[index] = (char)attribute; ++index; @@ -2095,129 +2110,3 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch) } #endif /* ADLMIDI_DISABLE_CPP_EXTRAS */ - -// Implement the user map data structure. - -bool MIDIplay::AdlChannel::users_empty() const -{ - return !users_first; -} - -MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_find(Location loc) -{ - LocationData *user = NULL; - for(LocationData *curr = users_first; !user && curr; curr = curr->next) - if(curr->loc == loc) - user = curr; - return user; -} - -MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_allocate() -{ - // remove free cells front - LocationData *user = users_free_cells; - if(!user) - return NULL; - users_free_cells = user->next; - if(users_free_cells) - users_free_cells->prev = NULL; - // add to users front - if(users_first) - users_first->prev = user; - user->prev = NULL; - user->next = users_first; - users_first = user; - ++users_size; - return user; -} - -MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_find_or_create(Location loc) -{ - LocationData *user = users_find(loc); - if(!user) - { - user = users_allocate(); - if(!user) - return NULL; - LocationData *prev = user->prev, *next = user->next; - *user = LocationData(); - user->prev = prev; - user->next = next; - user->loc = loc; - } - return user; -} - -MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_insert(const LocationData &x) -{ - LocationData *user = users_find(x.loc); - if(!user) - { - user = users_allocate(); - if(!user) - return NULL; - LocationData *prev = user->prev, *next = user->next; - *user = x; - user->prev = prev; - user->next = next; - } - return user; -} - -void MIDIplay::AdlChannel::users_erase(LocationData *user) -{ - if(user->prev) - user->prev->next = user->next; - if(user->next) - user->next->prev = user->prev; - if(user == users_first) - users_first = user->next; - user->prev = NULL; - user->next = users_free_cells; - users_free_cells = user; - --users_size; -} - -void MIDIplay::AdlChannel::users_clear() -{ - users_first = NULL; - users_free_cells = users_cells; - users_size = 0; - for(size_t i = 0; i < users_max; ++i) - { - users_cells[i].prev = (i > 0) ? &users_cells[i - 1] : NULL; - users_cells[i].next = (i + 1 < users_max) ? &users_cells[i + 1] : NULL; - } -} - -void MIDIplay::AdlChannel::users_assign(const LocationData *users, size_t count) -{ - ADL_UNUSED(count);//Avoid warning for release builds - assert(count <= users_max); - if(users == users_first && users) - { - // self assignment - assert(users_size == count); - return; - } - users_clear(); - const LocationData *src_cell = users; - // move to the last - if(src_cell) - { - while(src_cell->next) - src_cell = src_cell->next; - } - // push cell copies in reverse order - while(src_cell) - { - LocationData *dst_cell = users_allocate(); - assert(dst_cell); - LocationData *prev = dst_cell->prev, *next = dst_cell->next; - *dst_cell = *src_cell; - dst_cell->prev = prev; - dst_cell->next = next; - src_cell = src_cell->prev; - } - assert(users_size == count); -} |