aboutsummaryrefslogtreecommitdiff
path: root/src/adlmidi_midiplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/adlmidi_midiplay.cpp')
-rw-r--r--src/adlmidi_midiplay.cpp159
1 files changed, 78 insertions, 81 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index 80f36ce..d984fe1 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -117,18 +117,18 @@ inline bool isXgPercChannel(uint8_t msb, uint8_t lsb)
void MIDIplay::AdlChannel::AddAge(int64_t ms)
{
- if(users.empty())
+ if(users_empty())
koff_time_until_neglible =
std::max(int64_t(koff_time_until_neglible - ms), static_cast<int64_t>(-0x1FFFFFFFl));
else
{
koff_time_until_neglible = 0;
- for(users_t::iterator i = users.begin(); i != users.end(); ++i)
+ for(LocationData *i = users_first; i; i = i->next)
{
- i->second.kon_time_until_neglible =
- std::max(i->second.kon_time_until_neglible - ms, static_cast<int64_t>(-0x1FFFFFFFl));
- i->second.vibdelay += ms;
+ i->kon_time_until_neglible =
+ std::max(i->kon_time_until_neglible - ms, static_cast<int64_t>(-0x1FFFFFFFl));
+ i->vibdelay += ms;
}
}
}
@@ -1455,11 +1455,13 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(props_mask & Upd_Patch)
{
opl.Patch(c, ins.insId);
- AdlChannel::LocationData &d = ch[c].users[my_loc];
- d.sustained = false; // inserts if necessary
- d.vibdelay = 0;
- d.kon_time_until_neglible = ains.ms_sound_kon;
- d.ins = ins;
+ AdlChannel::LocationData *d = ch[c].users_find_or_create(my_loc);
+ if(d) { // inserts if necessary
+ d->sustained = false;
+ d->vibdelay = 0;
+ d->kon_time_until_neglible = ains.ms_sound_kon;
+ d->ins = ins;
+ }
}
}
@@ -1475,15 +1477,15 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
{
if(Ch[MidCh].sustain == 0)
{
- AdlChannel::users_t::iterator k = ch[c].users.find(my_loc);
+ AdlChannel::LocationData *k = ch[c].users_find(my_loc);
- if(k != ch[c].users.end())
- ch[c].users.erase(k);
+ if(k)
+ ch[c].users_erase(k);
if(hooks.onNote)
hooks.onNote(hooks.onNote_userData, c, tone, midiins, 0, 0.0);
- if(ch[c].users.empty())
+ if(ch[c].users_empty())
{
opl.NoteOff(c);
if(props_mask & Upd_Mute) // Mute the note
@@ -1499,8 +1501,9 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
{
// Sustain: Forget about the note, but don't key it off.
// Also will avoid overwriting it very soon.
- AdlChannel::LocationData &d = ch[c].users[my_loc];
- d.sustained = true; // note: not erased!
+ AdlChannel::LocationData *d = ch[c].users_find_or_create(my_loc);
+ if(d)
+ d->sustained = true; // note: not erased!
if(hooks.onNote)
hooks.onNote(hooks.onNote_userData, c, tone, midiins, -1, 0.0);
}
@@ -1602,10 +1605,10 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(props_mask & Upd_Pitch)
{
- AdlChannel::LocationData &d = ch[c].users[my_loc];
+ AdlChannel::LocationData *d = ch[c].users_find(my_loc);
// Don't bend a sustained note
- if(!d.sustained)
+ if(!d || !d->sustained)
{
double bend = Ch[MidCh].bend + opl.GetAdlIns(ins.insId).finetune;
double phase = 0.0;
@@ -1615,7 +1618,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
phase = ains.voice2_fine_tune;//0.125; // Detune the note slightly (this is what Doom does)
}
- if(Ch[MidCh].vibrato && d.vibdelay >= Ch[MidCh].vibdelay)
+ if(Ch[MidCh].vibrato && d->vibdelay >= Ch[MidCh].vibdelay)
bend += Ch[MidCh].vibrato * Ch[MidCh].vibdepth * std::sin(Ch[MidCh].vibpos);
#ifdef ADLMIDI_USE_DOSBOX_OPL
@@ -2130,30 +2133,27 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::Not
// Same midi-instrument = some stability
//if(c == MidCh) s += 4;
- for(AdlChannel::users_t::const_iterator
- j = ch[c].users.begin();
- j != ch[c].users.end();
- ++j)
+ for (AdlChannel::LocationData *j = ch[c].users_first; j; j = j->next)
{
s -= 4000;
- if(!j->second.sustained)
- s -= j->second.kon_time_until_neglible;
+ if(!j->sustained)
+ s -= j->kon_time_until_neglible;
else
- s -= (j->second.kon_time_until_neglible / 2);
+ s -= (j->kon_time_until_neglible / 2);
MIDIchannel::activenoteiterator
- k = const_cast<MIDIchannel &>(Ch[j->first.MidCh]).activenotes_find(j->first.note);
+ k = const_cast<MIDIchannel &>(Ch[j->loc.MidCh]).activenotes_find(j->loc.note);
if(k)
{
// Same instrument = good
- if(j->second.ins == ins)
+ if(j->ins == ins)
{
s += 300;
// Arpeggio candidate = even better
- if(j->second.vibdelay < 70
- || j->second.kon_time_until_neglible > 20000)
+ if(j->vibdelay < 70
+ || j->kon_time_until_neglible > 20000)
s += 0;
}
@@ -2181,14 +2181,11 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::Not
if(opl.four_op_category[c2]
!= opl.four_op_category[c]) continue;
- for(AdlChannel::users_t::const_iterator
- m = ch[c2].users.begin();
- m != ch[c2].users.end();
- ++m)
+ for(AdlChannel::LocationData *m = ch[c2].users_first; m; m = m->next)
{
- if(m->second.sustained) continue;
- if(m->second.vibdelay >= 200) continue;
- if(m->second.ins != j->second.ins) continue;
+ if(m->sustained) continue;
+ if(m->vibdelay >= 200) continue;
+ if(m->ins != j->ins) continue;
n_evacuation_stations += 1;
}
}
@@ -2202,27 +2199,25 @@ int64_t MIDIplay::CalculateAdlChannelGoodness(unsigned c, const MIDIchannel::Not
void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins)
{
- if(ch[c].users.empty()) return; // Nothing to do
+ if(ch[c].users_empty()) return; // Nothing to do
//bool doing_arpeggio = false;
- for(AdlChannel::users_t::iterator
- jnext = ch[c].users.begin();
- jnext != ch[c].users.end();
- )
+ for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;)
{
- AdlChannel::users_t::iterator j(jnext++);
+ AdlChannel::LocationData *j = jnext;
+ jnext = jnext->next;
- if(!j->second.sustained)
+ if(!j->sustained)
{
// Collision: Kill old note,
// UNLESS we're going to do arpeggio
MIDIchannel::activenoteiterator i
- (Ch[j->first.MidCh].activenotes_ensure_find(j->first.note));
+ (Ch[j->loc.MidCh].activenotes_ensure_find(j->loc.note));
// Check if we can do arpeggio.
- if((j->second.vibdelay < 70
- || j->second.kon_time_until_neglible > 20000)
- && j->second.ins == ins)
+ if((j->vibdelay < 70
+ || j->kon_time_until_neglible > 20000)
+ && j->ins == ins)
{
// Do arpeggio together with this note.
//doing_arpeggio = true;
@@ -2241,12 +2236,12 @@ void MIDIplay::PrepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo
// Keyoff the channel so that it can be retriggered,
// unless the new note will be introduced as just an arpeggio.
- if(ch[c].users.empty())
+ if(ch[c].users_empty())
opl.NoteOff(c);
}
void MIDIplay::KillOrEvacuate(size_t from_channel,
- AdlChannel::users_t::iterator j,
+ AdlChannel::LocationData *j,
MIDIplay::MIDIchannel::activenoteiterator i)
{
// Before killing the note, check if it can be
@@ -2265,14 +2260,15 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
if(opl.four_op_category[c] != opl.four_op_category[from_channel])
continue;
- for(AdlChannel::users_t::iterator
- m = ch[c].users.begin();
- m != ch[c].users.end();
- ++m)
+ AdlChannel &adlch = ch[c];
+ if(adlch.users_size == AdlChannel::users_max)
+ continue; // no room for more arpeggio on channel
+
+ for(AdlChannel::LocationData *m = adlch.users_first; m; m = m->next)
{
- if(m->second.vibdelay >= 200
- && m->second.kon_time_until_neglible < 10000) continue;
- if(m->second.ins != j->second.ins)
+ if(m->vibdelay >= 200
+ && m->kon_time_until_neglible < 10000) continue;
+ if(m->ins != j->ins)
continue;
if(hooks.onNote)
{
@@ -2288,9 +2284,10 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
}
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);
+ i->phys_ensure_find_or_create(cs)->assign(j->ins);
+ if(!ch[cs].users_insert(*j))
+ assert(false);
+ ch[from_channel].users_erase(j);
return;
}
}
@@ -2303,7 +2300,7 @@ void MIDIplay::KillOrEvacuate(size_t from_channel,
ins
);*/
// Kill it
- NoteUpdate(j->first.MidCh,
+ NoteUpdate(j->loc.MidCh,
i,
Upd_Off,
static_cast<int32_t>(from_channel));
@@ -2330,27 +2327,25 @@ void MIDIplay::KillSustainingNotes(int32_t MidCh, int32_t this_adlchn)
for(unsigned c = first; c < last; ++c)
{
- if(ch[c].users.empty()) continue; // Nothing to do
+ if(ch[c].users_empty()) continue; // Nothing to do
- for(AdlChannel::users_t::iterator
- jnext = ch[c].users.begin();
- jnext != ch[c].users.end();
- )
+ for(AdlChannel::LocationData *jnext = ch[c].users_first; jnext;)
{
- AdlChannel::users_t::iterator j(jnext++);
+ AdlChannel::LocationData *j = jnext;
+ jnext = jnext->next;
- if((MidCh < 0 || j->first.MidCh == MidCh)
- && j->second.sustained)
+ if((MidCh < 0 || j->loc.MidCh == MidCh)
+ && j->sustained)
{
int midiins = '?';
if(hooks.onNote)
- hooks.onNote(hooks.onNote_userData, (int)c, j->first.note, midiins, 0, 0.0);
- ch[c].users.erase(j);
+ hooks.onNote(hooks.onNote_userData, (int)c, j->loc.note, midiins, 0, 0.0);
+ ch[c].users_erase(j);
}
}
// Keyoff the channel, if there are no users left.
- if(ch[c].users.empty())
+ if(ch[c].users_empty())
opl.NoteOff(c);
}
}
@@ -2485,11 +2480,11 @@ retry_arpeggio:
if(c > uint32_t(std::numeric_limits<int32_t>::max()))
break;
- size_t n_users = ch[c].users.size();
+ size_t n_users = ch[c].users_size;
if(n_users > 1)
{
- AdlChannel::users_t::const_iterator i = ch[c].users.begin();
+ AdlChannel::LocationData *i = ch[c].users_first;
size_t rate_reduction = 3;
if(n_users >= 3)
@@ -2498,23 +2493,25 @@ retry_arpeggio:
if(n_users >= 4)
rate_reduction = 1;
- std::advance(i, (arpeggio_counter / rate_reduction) % n_users);
+ for(unsigned count = (arpeggio_counter / rate_reduction) % n_users,
+ n = 0; n < count; ++n)
+ i = i->next;
- if(i->second.sustained == false)
+ if(i->sustained == false)
{
- if(i->second.kon_time_until_neglible <= 0l)
+ if(i->kon_time_until_neglible <= 0l)
{
NoteUpdate(
- i->first.MidCh,
- Ch[ i->first.MidCh ].activenotes_ensure_find(i->first.note),
+ i->loc.MidCh,
+ Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note),
Upd_Off,
static_cast<int32_t>(c));
goto retry_arpeggio;
}
NoteUpdate(
- i->first.MidCh,
- Ch[ i->first.MidCh ].activenotes_ensure_find(i->first.note),
+ i->loc.MidCh,
+ Ch[ i->loc.MidCh ].activenotes_ensure_find(i->loc.note),
Upd_Pitch | Upd_Volume | Upd_Pan,
static_cast<int32_t>(c));
}