diff options
author | Wohlstand <admin@wohlnet.ru> | 2025-05-24 00:04:48 +0300 |
---|---|---|
committer | Wohlstand <admin@wohlnet.ru> | 2025-05-24 00:04:48 +0300 |
commit | 175adb293ba37c527411a5684fe3994a43d95493 (patch) | |
tree | 4b917c2a65426b312ee78691ba985a4508ad80d5 /src/adlmidi_midiplay.cpp | |
parent | eb7014e8f8772cc37462c2398a8f3a602e7a8302 (diff) | |
download | libADLMIDI-175adb293ba37c527411a5684fe3994a43d95493.tar.gz libADLMIDI-175adb293ba37c527411a5684fe3994a43d95493.tar.bz2 libADLMIDI-175adb293ba37c527411a5684fe3994a43d95493.zip |
Fixed another crash because of channels-users confusion
Diffstat (limited to 'src/adlmidi_midiplay.cpp')
-rw-r--r-- | src/adlmidi_midiplay.cpp | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp index 33a812d..e092fa2 100644 --- a/src/adlmidi_midiplay.cpp +++ b/src/adlmidi_midiplay.cpp @@ -1567,10 +1567,13 @@ bool MIDIplay::killSecondVoicesIfOverflow(int32_t &new_chan) AdlChannel::LocationData &jd = j->value; MIDIchannel::notes_iterator it = m_midiChannels[jd.loc.MidCh].find_activenote(jd.loc.note); + assert(m_chipChannels[new_chan].users.size() <= 1); + if(it.is_end()) /* Invalid user of channel */ { - m_chipChannels[new_chan].users.erase(j); + m_chipChannels[new_chan].users.clear(); m_chipChannels[new_chan].koff_time_until_neglible_us = 0; + synth.noteOff(new_chan); ret = true; return ret; } @@ -1579,9 +1582,10 @@ bool MIDIplay::killSecondVoicesIfOverflow(int32_t &new_chan) if(info.chip_channels_count == 2) { - m_chipChannels[new_chan].users.erase(j); + m_chipChannels[new_chan].users.clear(); m_chipChannels[new_chan].koff_time_until_neglible_us = 0; info.phys_erase_at(&info.chip_channels[1]); + synth.noteOff(new_chan); ret = true; } } @@ -1595,6 +1599,33 @@ void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInf Synth &synth = *m_synth; + if(!m_setup.enableAutoArpeggio) + { + // Kill all notes on this channel with no mercy + for(AdlChannel::users_iterator jnext = m_chipChannels[c].users.begin(); !jnext.is_end();) + { + AdlChannel::users_iterator j = jnext; + AdlChannel::LocationData &jd = j->value; + ++jnext; + + if(jd.sustained == AdlChannel::LocationData::Sustain_None) + { + MIDIchannel::notes_iterator i = m_midiChannels[jd.loc.MidCh].find_activenote(jd.loc.note); + if(i.is_end()) + m_chipChannels[c].users.erase(j); + else + noteUpdate(j->value.loc.MidCh, i, Upd_Off, static_cast<int32_t>(c)); + } + else + m_chipChannels[c].users.erase(j); + } + + synth.noteOff(c); + m_chipChannels[c].users.clear(); + + return; + } + //bool doing_arpeggio = false; for(AdlChannel::users_iterator jnext = m_chipChannels[c].users.begin(); !jnext.is_end();) { @@ -1608,13 +1639,6 @@ void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInf // UNLESS we're going to do arpeggio MIDIchannel::notes_iterator i (m_midiChannels[jd.loc.MidCh].ensure_find_activenote(jd.loc.note)); - if(!m_setup.enableAutoArpeggio) - { - // Kill the note - noteUpdate(j->value.loc.MidCh, i, Upd_Off, static_cast<int32_t>(c)); - continue; - } - // Check if we can do arpeggio. if(((jd.vibdelay_us < 70000) || (jd.kon_time_until_neglible_us > 20000000)) && jd.ins == ins) { @@ -1700,6 +1724,10 @@ void MIDIplay::killOrEvacuate(size_t from_channel, 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); +#ifndef NDEBUG + if(!m_setup.enableAutoArpeggio) + assert(m_chipChannels[cs].users.size() <= 1); +#endif m_chipChannels[from_channel].users.erase(j); return; } |