aboutsummaryrefslogtreecommitdiff
path: root/src/adlmidi_midiplay.cpp
diff options
context:
space:
mode:
authorVitaly Novichkov <Wohlstand@users.noreply.github.com>2018-11-20 01:58:00 +0300
committerGitHub <noreply@github.com>2018-11-20 01:58:00 +0300
commitc936e5e9157f806ac056349ad4d6a6eba2a5af0c (patch)
tree72068feb108b84d2695f596e67f04253df2d0185 /src/adlmidi_midiplay.cpp
parentf96317a88d0f6157adbdd2973ce0847c7d83f99e (diff)
parent1b82ca4e654759d69f18b0a772820f40567b0059 (diff)
downloadlibADLMIDI-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.cpp427
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);
-}