aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/adlmidi_midiplay.cpp81
-rw-r--r--src/adlmidi_private.hpp17
-rw-r--r--src/midi_sequencer_impl.hpp3
3 files changed, 57 insertions, 44 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index 630c93f..1969190 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -252,7 +252,8 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
}
}
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
noteOff(channel, note);
// On Note on, Keyoff the note first, just in case keyoff
// was omitted; this fixes Dance of sugar-plum fairy
@@ -441,7 +442,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
}
}
- int64_t s = calculateAdlChannelGoodness(a, voices[ccount]);
+ int64_t s = calculateChipChannelGoodness(a, voices[ccount]);
if(s > bs)
{
bs = (int32_t)s; // Best candidate wins
@@ -458,7 +459,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
continue; // Could not play this note. Ignore it.
}
- prepareAdlChannelForNewNote(static_cast<size_t>(c), voices[ccount]);
+ prepareChipChannelForNewNote(static_cast<size_t>(c), voices[ccount]);
adlchannel[ccount] = c;
}
@@ -517,13 +518,15 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
void MIDIplay::realTime_NoteOff(uint8_t channel, uint8_t note)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
noteOff(channel, note);
}
void MIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t atVal)
{
- channel = channel % 16;
+ 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)
@@ -544,13 +547,15 @@ void MIDIplay::realTime_NoteAfterTouch(uint8_t channel, uint8_t note, uint8_t at
void MIDIplay::realTime_ChannelAfterTouch(uint8_t channel, uint8_t atVal)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].aftertouch = atVal;
}
void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
switch(type)
{
case 1: // Adjust vibrato
@@ -699,39 +704,45 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
void MIDIplay::realTime_PatchChange(uint8_t channel, uint8_t patch)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].patch = patch;
}
void MIDIplay::realTime_PitchBend(uint8_t channel, uint16_t pitch)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].bend = int(pitch) - 8192;
noteUpdateAll(channel, Upd_Pitch);
}
void MIDIplay::realTime_PitchBend(uint8_t channel, uint8_t msb, uint8_t lsb)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].bend = int(lsb) + int(msb) * 128 - 8192;
noteUpdateAll(channel, Upd_Pitch);
}
void MIDIplay::realTime_BankChangeLSB(uint8_t channel, uint8_t lsb)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].bank_lsb = lsb;
}
void MIDIplay::realTime_BankChangeMSB(uint8_t channel, uint8_t msb)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].bank_msb = msb;
}
void MIDIplay::realTime_BankChange(uint8_t channel, uint16_t bank)
{
- channel = channel % 16;
+ if(static_cast<size_t>(channel) > m_midiChannels.size())
+ channel = channel % 16;
m_midiChannels[channel].bank_lsb = uint8_t(bank & 0xFF);
m_midiChannels[channel].bank_msb = uint8_t((bank >> 8) & 0xFF);
}
@@ -1001,7 +1012,7 @@ void MIDIplay::AudioTick(uint32_t chipId, uint32_t rate)
}
#endif
-void MIDIplay::noteUpdate(uint16_t midCh,
+void MIDIplay::noteUpdate(size_t midCh,
MIDIplay::MIDIchannel::activenoteiterator i,
unsigned props_mask,
int32_t select_adlchn)
@@ -1013,7 +1024,7 @@ void MIDIplay::noteUpdate(uint16_t midCh,
const int midiins = static_cast<int>(info.midiins);
const adlinsdata2 &ains = *info.ains;
AdlChannel::Location my_loc;
- my_loc.MidCh = midCh;
+ my_loc.MidCh = static_cast<uint16_t>(midCh);
my_loc.note = info.note;
for(unsigned ccount = 0, ctotal = info.chip_channels_count; ccount < ctotal; ccount++)
@@ -1236,7 +1247,7 @@ void MIDIplay::setErrorString(const std::string &err)
errorStringOut = err;
}
-int64_t MIDIplay::calculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const
+int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const
{
int64_t s = (m_synth.m_musicMode != OPL3::MODE_CMF) ? -m_chipChannels[c].koff_time_until_neglible : 0;
@@ -1306,7 +1317,7 @@ int64_t MIDIplay::calculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteI
}
-void MIDIplay::prepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins)
+void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins)
{
if(m_chipChannels[c].users_empty()) return; // Nothing to do
@@ -1424,7 +1435,7 @@ void MIDIplay::panic()
}
}
-void MIDIplay::killSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t sustain_type)
+void MIDIplay::killSustainingNotes(int32_t midCh, int32_t this_adlchn, uint8_t sustain_type)
{
uint32_t first = 0, last = m_synth.m_numChannels;
@@ -1444,7 +1455,7 @@ void MIDIplay::killSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t s
AdlChannel::LocationData *j = jnext;
jnext = jnext->next;
- if((MidCh < 0 || j->loc.MidCh == MidCh)
+ if((midCh < 0 || j->loc.MidCh == midCh)
&& ((j->sustained & sustain_type) != 0))
{
int midiins = '?';
@@ -1462,7 +1473,7 @@ void MIDIplay::killSustainingNotes(int32_t MidCh, int32_t this_adlchn, uint8_t s
}
}
-void MIDIplay::markSostenutoNotes(int32_t MidCh)
+void MIDIplay::markSostenutoNotes(int32_t midCh)
{
uint32_t first = 0, last = m_synth.m_numChannels;
for(uint32_t c = first; c < last; ++c)
@@ -1474,46 +1485,46 @@ void MIDIplay::markSostenutoNotes(int32_t MidCh)
{
AdlChannel::LocationData *j = jnext;
jnext = jnext->next;
- if((j->loc.MidCh == MidCh) && (j->sustained == AdlChannel::LocationData::Sustain_None))
+ if((j->loc.MidCh == midCh) && (j->sustained == AdlChannel::LocationData::Sustain_None))
j->sustained |= AdlChannel::LocationData::Sustain_Sostenuto;
}
}
}
-void MIDIplay::setRPN(unsigned MidCh, unsigned value, bool MSB)
+void MIDIplay::setRPN(size_t midCh, unsigned value, bool MSB)
{
- bool nrpn = m_midiChannels[MidCh].nrpn;
- unsigned addr = m_midiChannels[MidCh].lastmrpn * 0x100 + m_midiChannels[MidCh].lastlrpn;
+ bool nrpn = m_midiChannels[midCh].nrpn;
+ unsigned addr = m_midiChannels[midCh].lastmrpn * 0x100 + m_midiChannels[midCh].lastlrpn;
switch(addr + nrpn * 0x10000 + MSB * 0x20000)
{
case 0x0000 + 0*0x10000 + 1*0x20000: // Pitch-bender sensitivity
- m_midiChannels[MidCh].bendsense_msb = value;
- m_midiChannels[MidCh].updateBendSensitivity();
+ m_midiChannels[midCh].bendsense_msb = value;
+ m_midiChannels[midCh].updateBendSensitivity();
break;
case 0x0000 + 0*0x10000 + 0*0x20000: // Pitch-bender sensitivity LSB
- m_midiChannels[MidCh].bendsense_lsb = value;
- m_midiChannels[MidCh].updateBendSensitivity();
+ m_midiChannels[midCh].bendsense_lsb = value;
+ m_midiChannels[midCh].updateBendSensitivity();
break;
case 0x0108 + 1*0x10000 + 1*0x20000:
if((m_synthMode & Mode_XG) != 0) // Vibrato speed
{
- if(value == 64) m_midiChannels[MidCh].vibspeed = 1.0;
- else if(value < 100) m_midiChannels[MidCh].vibspeed = 1.0 / (1.6e-2 * (value ? value : 1));
- else m_midiChannels[MidCh].vibspeed = 1.0 / (0.051153846 * value - 3.4965385);
- m_midiChannels[MidCh].vibspeed *= 2 * 3.141592653 * 5.0;
+ if(value == 64) m_midiChannels[midCh].vibspeed = 1.0;
+ else if(value < 100) m_midiChannels[midCh].vibspeed = 1.0 / (1.6e-2 * (value ? value : 1));
+ else m_midiChannels[midCh].vibspeed = 1.0 / (0.051153846 * value - 3.4965385);
+ m_midiChannels[midCh].vibspeed *= 2 * 3.141592653 * 5.0;
}
break;
case 0x0109 + 1*0x10000 + 1*0x20000:
if((m_synthMode & Mode_XG) != 0) // Vibrato depth
{
- m_midiChannels[MidCh].vibdepth = ((value - 64) * 0.15) * 0.01;
+ m_midiChannels[midCh].vibdepth = ((value - 64) * 0.15) * 0.01;
}
break;
case 0x010A + 1*0x10000 + 1*0x20000:
if((m_synthMode & Mode_XG) != 0) // Vibrato delay in millisecons
{
- m_midiChannels[MidCh].vibdelay = value ? int64_t(0.2092 * std::exp(0.0795 * (double)value)) : 0;
+ m_midiChannels[midCh].vibdelay = value ? int64_t(0.2092 * std::exp(0.0795 * (double)value)) : 0;
}
break;
default:/* UI.PrintLn("%s %04X <- %d (%cSB) (ch %u)",
@@ -1532,7 +1543,7 @@ void MIDIplay::updatePortamento(size_t midCh)
}
-void MIDIplay::noteOff(uint16_t midCh, uint8_t note)
+void MIDIplay::noteOff(size_t midCh, uint8_t note)
{
MIDIchannel::activenoteiterator
i = m_midiChannels[midCh].activenotes_find(note);
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index 07b55af..c4860a3 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -227,6 +227,7 @@ public:
//! Just a padding. Reserved.
char ____padding[4];
#ifndef ADLMIDI_HW_OPL
+ //! Running chip emulators
std::vector<AdlMIDI_SPtr<OPLChipBase > > m_chips;
#endif
@@ -254,6 +255,7 @@ public:
BankMap m_insBanks;
//! MIDI bank-wide setup
AdlBankSetup m_insBankSetup;
+
public:
//! Blank instrument template
static const adlinsdata2 m_emptyInstrument;
@@ -1303,7 +1305,7 @@ private:
* @param props_mask Properties to update
* @param select_adlchn Specify chip channel, or -1 - all chip channels used by the note
*/
- void noteUpdate(uint16_t midCh,
+ void noteUpdate(size_t midCh,
MIDIchannel::activenoteiterator i,
unsigned props_mask,
int32_t select_adlchn = -1);
@@ -1315,14 +1317,13 @@ private:
*/
void noteUpdateAll(size_t midCh, unsigned props_mask);
-
/**
* @brief Determine how good a candidate this adlchannel would be for playing a note from this instrument.
* @param c Wanted chip channel
* @param ins Instrument wanted to be used in this channel
* @return Calculated coodness points
*/
- int64_t calculateAdlChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const;
+ int64_t calculateChipChannelGoodness(size_t c, const MIDIchannel::NoteInfo::Phys &ins) const;
/**
* @brief A new note will be played on this channel using this instrument.
@@ -1330,7 +1331,7 @@ private:
* @param ins Instrument wanted to be used in this channel
* Kill existing notes on this channel (or don't, if we do arpeggio)
*/
- void prepareAdlChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins);
+ void prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInfo::Phys &ins);
/**
* @brief Kills note that uses wanted channel. When arpeggio is possible, note is evaluating to another channel
@@ -1354,14 +1355,14 @@ private:
* @param this_adlchn Chip channel, -1 - all chip channels
* @param sustain_type Type of systain to process
*/
- void killSustainingNotes(int32_t MidCh = -1,
+ void killSustainingNotes(int32_t midCh = -1,
int32_t this_adlchn = -1,
uint8_t sustain_type = AdlChannel::LocationData::Sustain_ANY);
/**
* @brief Find active notes and mark them as sostenuto-sustained
* @param MidCh MIDI channel, -1 - all MIDI channels
*/
- void markSostenutoNotes(int32_t MidCh = -1);
+ void markSostenutoNotes(int32_t midCh = -1);
/**
* @brief Set RPN event value
@@ -1369,7 +1370,7 @@ private:
* @param value 1 byte part of RPN value
* @param MSB is MSB or LSB part of value
*/
- void setRPN(unsigned MidCh, unsigned value, bool MSB);
+ void setRPN(size_t midCh, unsigned value, bool MSB);
/**
* @brief Update portamento setup in MIDI channel
@@ -1382,7 +1383,7 @@ private:
* @param midCh MIDI channel
* @param note Note to off
*/
- void noteOff(uint16_t midCh, uint8_t note);
+ void noteOff(size_t midCh, uint8_t note);
/**
* @brief Update processing of vibrato to amount of seconds
diff --git a/src/midi_sequencer_impl.hpp b/src/midi_sequencer_impl.hpp
index 501de8f..af8ec59 100644
--- a/src/midi_sequencer_impl.hpp
+++ b/src/midi_sequencer_impl.hpp
@@ -172,7 +172,8 @@ void BW_MidiSequencer::MidiTrackRow::sortEvents(bool *noteStates)
controllers.reserve(events.size());
controllers.push_back(events[i]);
}
- else if((events[i].type == MidiEvent::T_SPECIAL) && (events[i].subtype == MidiEvent::ST_MARKER))
+ else if((events[i].type == MidiEvent::T_SPECIAL)
+ && ((events[i].subtype == MidiEvent::ST_MARKER) || (events[i].subtype == MidiEvent::ST_DEVICESWITCH)))
{
if(metas.capacity() == 0)
metas.reserve(events.size());