aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Novichkov <admin@wohlnet.ru>2018-08-31 03:55:58 +0300
committerVitaly Novichkov <admin@wohlnet.ru>2018-08-31 03:55:58 +0300
commit6faa5b52cf5a0c41579f9720c947c8d3bbc9d08c (patch)
tree6d5d28788bd719e6439976cd4716673bc74bc654
parent4c7f23f8999c7f5d71071d0b94fc18effeb0a9eb (diff)
parentd8b894af640bd1e2b1115bd69c29b4654b3c6973 (diff)
downloadlibADLMIDI-6faa5b52cf5a0c41579f9720c947c8d3bbc9d08c.tar.gz
libADLMIDI-6faa5b52cf5a0c41579f9720c947c8d3bbc9d08c.tar.bz2
libADLMIDI-6faa5b52cf5a0c41579f9720c947c8d3bbc9d08c.zip
Merge branch 'master' into stable
-rw-r--r--CMakeLists.txt1
-rw-r--r--banks.ini6
-rw-r--r--include/adlmidi.h1
-rw-r--r--libADLMIDI-test.pro1
-rw-r--r--libADLMIDI.pro1
-rw-r--r--src/adldata.cpp8
-rw-r--r--src/adlmidi.cpp6
-rw-r--r--src/adlmidi_midiplay.cpp68
-rw-r--r--src/adlmidi_opl3.cpp129
-rw-r--r--src/adlmidi_private.hpp27
-rw-r--r--src/cvt_xmi2mid.hpp2
-rw-r--r--src/midi_sequencer_impl.hpp13
-rw-r--r--utils/gen_adldata/scrapped.txt2
13 files changed, 178 insertions, 87 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 91baffb..aeec85e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -226,6 +226,7 @@ if(WITH_MIDI_SEQUENCER)
list(APPEND libADLMIDI_SOURCES
${libADLMIDI_SOURCE_DIR}/src/adlmidi_sequencer.cpp
)
+ add_definitions(-DENABLE_END_SILENCE_SKIPPING)
endif()
if(NOT WITH_MUS_SUPPORT OR NOT WITH_MIDI_SEQUENCER)
diff --git a/banks.ini b/banks.ini
index 33b55c5..a91c6aa 100644
--- a/banks.ini
+++ b/banks.ini
@@ -472,10 +472,10 @@ format = TMB
file = "fm_banks/op3_files/gmopl_wohl_mod.tmb"
prefix = "b65"
-; Jammey O'Connel's bank used in his FM Driver for Win3x/9x and was
+; Jamie O'Connell's bank used in his FM Driver for Win3x/9x and was
; pre-included with his SB-Timbre editor. Percussions are custom.
[bank-66]
-name = "SB (Jammey O'Connel's bank)"
+name = "SB (Jamie O'Connell's bank)"
format = TMB
file = "fm_banks/op3_files/gmoconel.tmb"
prefix = "b66"
@@ -484,7 +484,7 @@ prefix = "b66"
; May be listened from the setup utiltiy while testing music,
; or in the Duke Nukem 3D Beta.
[bank-67]
-name = "TMB (Default bank of Apgee Sound System)"
+name = "TMB (Default bank of Apogee Sound System)"
format = TMB
file = "fm_banks/tmb_files/default.tmb"
prefix = "3drm67"
diff --git a/include/adlmidi.h b/include/adlmidi.h
index 6ae184e..e2bc035 100644
--- a/include/adlmidi.h
+++ b/include/adlmidi.h
@@ -329,6 +329,7 @@ extern ADLMIDI_DECLSPEC int adl_loadEmbeddedBank(struct ADL_MIDIPlayer *device,
* If you want to specify custom number of four operator channels,
* please call this function after bank change (adl_setBank() or adl_openBank()),
* otherwise, value will be overwritten by auto-calculated.
+ * If the count is specified as -1, an auto-calculated amount is used instead.
*
* @param device Instance of the library
* @param ops4 Count of four-op channels to allocate between all emulating chips
diff --git a/libADLMIDI-test.pro b/libADLMIDI-test.pro
index d98d6bd..ec5dd1a 100644
--- a/libADLMIDI-test.pro
+++ b/libADLMIDI-test.pro
@@ -18,6 +18,7 @@ LIBS += -lSDL2 -lpthread -ldl
#DEFINES += DISABLE_EMBEDDED_BANKS
#DEFINES += ADLMIDI_USE_DOSBOX_OPL
#DEFINES += ENABLE_BEGIN_SILENCE_SKIPPING
+DEFINES += ENABLE_END_SILENCE_SKIPPING
#DEFINES += DEBUG_TRACE_ALL_EVENTS
#DEFINES += DEBUG_TRACE_ALL_CHANNELS
diff --git a/libADLMIDI.pro b/libADLMIDI.pro
index 92c6009..0044b76 100644
--- a/libADLMIDI.pro
+++ b/libADLMIDI.pro
@@ -12,6 +12,7 @@ INSTALLINCLUDESTO = ADLMIDI
include($$PWD/../audio_codec_common.pri)
DEFINES += ADLMIDI_DISABLE_CPP_EXTRAS
+DEFINES += ENABLE_END_SILENCE_SKIPPING
macx: QMAKE_CXXFLAGS_WARN_ON += -Wno-absolute-value
diff --git a/src/adldata.cpp b/src/adldata.cpp
index 6606e1f..b7fd3a1 100644
--- a/src/adldata.cpp
+++ b/src/adldata.cpp
@@ -9449,8 +9449,8 @@ const char* const banknames[76] =
"TMB (Shadow Warrior)",
"DMX (Raptor)",
"OP3 (Modded GMOPL by Wohlstand)",
- "SB (Jammey O'Connel's bank)",
- "TMB (Default bank of Apgee Sound System)",
+ "SB (Jamie O'Connell's bank)",
+ "TMB (Default bank of Apogee Sound System)",
"WOPL (4op bank by James Alan Nguyen and Wohlstand)",
"TMB (Blood)",
"TMB (Lee)",
@@ -10882,8 +10882,8 @@ const AdlBankSetup adlbanksetup[75] =
{3, 0, 0, 0, 0}, //Bank 63, TMB (Shadow Warrior)
{2, 0, 0, 0, 0}, //Bank 64, DMX (Raptor)
{3, 0, 0, 0, 0}, //Bank 65, OP3 (Modded GMOPL by Wohlstand)
- {3, 0, 0, 0, 0}, //Bank 66, SB (Jammey O'Connel's bank)
- {3, 0, 0, 0, 0}, //Bank 67, TMB (Default bank of Apgee Sound System)
+ {3, 0, 0, 0, 0}, //Bank 66, SB (Jamie O'Connell's bank)
+ {3, 0, 0, 0, 0}, //Bank 67, TMB (Default bank of Apogee Sound System)
{0, 1, 1, 0, 0}, //Bank 68, WOPL (4op bank by James Alan Nguyen and Wohlstand)
{3, 0, 0, 0, 0}, //Bank 69, TMB (Blood)
{3, 0, 0, 0, 0}, //Bank 70, TMB (Lee)
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp
index c7c5cf3..26a21e4 100644
--- a/src/adlmidi.cpp
+++ b/src/adlmidi.cpp
@@ -351,6 +351,10 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4)
{
if(!device)
return -1;
+
+ if(ops4 == -1)
+ return adlRefreshNumCards(device);
+
MidiPlayer *play = GET_MIDI_PLAYER(device);
if((unsigned int)ops4 > 6 * play->m_setup.numChips)
{
@@ -364,7 +368,7 @@ ADLMIDI_EXPORT int adl_setNumFourOpsChn(ADL_MIDIPlayer *device, int ops4)
play->m_synth.m_numFourOps = play->m_setup.numFourOps;
play->m_synth.updateChannelCategories();
- return 0; //adlRefreshNumCards(device);
+ return 0;
}
ADLMIDI_EXPORT int adl_getNumFourOpsChn(struct ADL_MIDIPlayer *device)
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index ded81b3..9a76236 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -100,19 +100,19 @@ inline bool isXgPercChannel(uint8_t msb, uint8_t lsb)
return (msb == 0x7E || msb == 0x7F) && (lsb == 0);
}
-void MIDIplay::AdlChannel::addAge(int64_t ms)
+void MIDIplay::AdlChannel::addAge(int64_t us)
{
- const int64_t neg = static_cast<int64_t>(-0x1FFFFFFFl);
+ const int64_t neg = 1000 * static_cast<int64_t>(-0x1FFFFFFFll);
if(users_empty())
- koff_time_until_neglible = std::max(int64_t(koff_time_until_neglible - ms), neg);
+ koff_time_until_neglible_us = std::max(koff_time_until_neglible_us - us, neg);
else
{
- koff_time_until_neglible = 0;
+ koff_time_until_neglible_us = 0;
for(LocationData *i = users_first; i; i = i->next)
{
if(!i->fixed_sustain)
- i->kon_time_until_neglible = std::max(i->kon_time_until_neglible - ms, neg);
- i->vibdelay += ms;
+ i->kon_time_until_neglible_us = std::max(i->kon_time_until_neglible_us - us, neg);
+ i->vibdelay_us += us;
}
}
}
@@ -233,7 +233,7 @@ void MIDIplay::resetMIDI()
void MIDIplay::TickIterators(double s)
{
for(uint16_t c = 0; c < m_synth.m_numChannels; ++c)
- m_chipChannels[c].addAge(static_cast<int64_t>(s * 1000.0));
+ m_chipChannels[c].addAge(static_cast<int64_t>(s * 1e6));
updateVibrato(s);
updateArpeggio(s);
#if !defined(ADLMIDI_AUDIO_TICK_HANDLER)
@@ -578,6 +578,15 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
}
noteUpdate(channel, ir.first, Upd_All | Upd_Patch);
+
+ for(unsigned ccount = 0; ccount < MIDIchannel::NoteInfo::MaxNumPhysChans; ++ccount)
+ {
+ int32_t c = adlchannel[ccount];
+ if(c < 0)
+ continue;
+ m_chipChannels[c].addAge(0);
+ }
+
return true;
}
@@ -1113,9 +1122,9 @@ void MIDIplay::noteUpdate(size_t midCh,
if(d) // inserts if necessary
{
d->sustained = AdlChannel::LocationData::Sustain_None;
- d->vibdelay = 0;
+ d->vibdelay_us = 0;
d->fixed_sustain = (ains.ms_sound_kon == static_cast<uint16_t>(adlNoteOnMaxTime));
- d->kon_time_until_neglible = ains.ms_sound_kon;
+ d->kon_time_until_neglible_us = 1000 * ains.ms_sound_kon;
d->ins = ins;
}
}
@@ -1124,7 +1133,8 @@ void MIDIplay::noteUpdate(size_t midCh,
for(unsigned ccount = 0; ccount < info.chip_channels_count; ccount++)
{
const MIDIchannel::NoteInfo::Phys &ins = info.chip_channels[ccount];
- uint16_t c = ins.chip_chan;
+ uint16_t c = ins.chip_chan;
+ uint16_t c_slave = info.chip_channels[1].chip_chan;
if(select_adlchn >= 0 && c != select_adlchn)
continue;
@@ -1147,11 +1157,11 @@ void MIDIplay::noteUpdate(size_t midCh,
if(props_mask & Upd_Mute) // Mute the note
{
m_synth.touchNote(c, 0);
- m_chipChannels[c].koff_time_until_neglible = 0;
+ m_chipChannels[c].koff_time_until_neglible_us = 0;
}
else
{
- m_chipChannels[c].koff_time_until_neglible = ains.ms_sound_koff;
+ m_chipChannels[c].koff_time_until_neglible_us = 1000 * ains.ms_sound_koff;
}
}
}
@@ -1279,11 +1289,11 @@ void MIDIplay::noteUpdate(size_t midCh,
phase = ains.voice2_fine_tune;//0.125; // Detune the note slightly (this is what Doom does)
}
- if(vibrato && (!d || d->vibdelay >= m_midiChannels[midCh].vibdelay))
+ if(vibrato && (!d || d->vibdelay_us >= m_midiChannels[midCh].vibdelay_us))
bend += static_cast<double>(vibrato) * m_midiChannels[midCh].vibdepth * std::sin(m_midiChannels[midCh].vibpos);
#define BEND_COEFFICIENT 172.4387
- m_synth.noteOn(c, BEND_COEFFICIENT * std::exp(0.057762265 * (currentTone + bend + phase)));
+ m_synth.noteOn(c, c_slave, BEND_COEFFICIENT * std::exp(0.057762265 * (currentTone + bend + phase)));
#undef BEND_COEFFICIENT
if(hooks.onNote)
hooks.onNote(hooks.onNote_userData, c, noteTone, midiins, vol, midibend);
@@ -1321,7 +1331,8 @@ void MIDIplay::setErrorString(const std::string &err)
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;
+ int64_t koff_ms = m_chipChannels[c].koff_time_until_neglible_us / 1000;
+ int64_t s = (m_synth.m_musicMode != OPL3::MODE_CMF) ? -koff_ms : 0;
// Same midi-instrument = some stability
//if(c == MidCh) s += 4;
@@ -1329,10 +1340,9 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
{
s -= 4000;
- if(j->sustained == AdlChannel::LocationData::Sustain_None)
- s -= j->kon_time_until_neglible;
- else
- s -= (j->kon_time_until_neglible / 2);
+ int64_t kon_ms = j->kon_time_until_neglible_us / 1000;
+ s -= (j->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);
@@ -1344,8 +1354,8 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
{
s += 300;
// Arpeggio candidate = even better
- if(j->vibdelay < 70
- || j->kon_time_until_neglible > 20000)
+ if(j->vibdelay_us < 70000
+ || j->kon_time_until_neglible_us > 20000000)
s += 0;
}
@@ -1376,7 +1386,7 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
for(AdlChannel::LocationData *m = m_chipChannels[c2].users_first; m; m = m->next)
{
if(m->sustained != AdlChannel::LocationData::Sustain_None) continue;
- if(m->vibdelay >= 200) continue;
+ if(m->vibdelay_us >= 200000) continue;
if(m->ins != j->ins) continue;
n_evacuation_stations += 1;
}
@@ -1407,8 +1417,8 @@ void MIDIplay::prepareChipChannelForNewNote(size_t c, const MIDIchannel::NoteInf
(m_midiChannels[j->loc.MidCh].activenotes_ensure_find(j->loc.note));
// Check if we can do arpeggio.
- if((j->vibdelay < 70
- || j->kon_time_until_neglible > 20000)
+ if((j->vibdelay_us < 70000
+ || j->kon_time_until_neglible_us > 20000000)
&& j->ins == ins)
{
// Do arpeggio together with this note.
@@ -1458,8 +1468,8 @@ void MIDIplay::killOrEvacuate(size_t from_channel,
for(AdlChannel::LocationData *m = adlch.users_first; m; m = m->next)
{
- if(m->vibdelay >= 200
- && m->kon_time_until_neglible < 10000) continue;
+ if(m->vibdelay_us >= 200000
+ && m->kon_time_until_neglible_us < 10000000) continue;
if(m->ins != j->ins)
continue;
if(hooks.onNote)
@@ -1590,13 +1600,13 @@ void MIDIplay::setRPN(size_t midCh, unsigned value, bool MSB)
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 = (((int)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_us = value ? int64_t(209.2 * std::exp(0.0795 * (double)value)) : 0;
}
break;
default:/* UI.PrintLn("%s %04X <- %d (%cSB) (ch %u)",
@@ -1702,7 +1712,7 @@ retry_arpeggio:
if(i->sustained == AdlChannel::LocationData::Sustain_None)
{
- if(i->kon_time_until_neglible <= 0l)
+ if(i->kon_time_until_neglible_us <= 0)
{
noteUpdate(
i->loc.MidCh,
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index 5ea2053..60c173e 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -263,40 +263,85 @@ void OPL3::noteOff(size_t c)
writeRegI(chip, 0xB0 + g_channelsMap[cc], m_keyBlockFNumCache[c] & 0xDF);
}
-void OPL3::noteOn(size_t c, double hertz) // Hertz range: 0..131071
+void OPL3::noteOn(size_t c1, size_t c2, double hertz) // Hertz range: 0..131071
{
- size_t chip = c / 23, cc = c % 23;
- uint32_t octave = 0;
+ size_t chip = c1 / 23, cc1 = c1 % 23, cc2 = c2 % 23;
+ uint32_t octave = 0, ftone = 0, mul_offset = 0;
if(hertz < 0)
return;
- while(hertz >= 1023.5)
+ //Basic range until max of octaves reaching
+ while((hertz >= 1023.5) && (octave < 0x1C00))
+ {
+ hertz /= 2.0; // Calculate octave
+ octave += 0x400;
+ }
+ //Extended range, rely on frequency multiplication increment
+ while(hertz >= 1022.75)
{
- hertz /= 2.0; // Calculate octave
- if(octave < 0x1C00)
- octave += 0x400;
+ hertz /= 2.0; // Calculate octave
+ mul_offset++;
}
- octave += static_cast<uint32_t>(hertz + 0.5);
- uint32_t chn = g_channelsMap[cc];
+ ftone = octave + static_cast<uint32_t>(hertz + 0.5);
+ uint32_t chn = g_channelsMap[cc1];
+ const adldata &patch1 = m_insCache[c1];
+ const adldata &patch2 = m_insCache[c2 < m_insCache.size() ? c2 : 0];
- if(cc >= 18)
+ if(cc1 < 18)
{
- m_regBD[chip ] |= (0x10 >> (cc - 18));
- writeRegI(chip , 0x0BD, m_regBD[chip ]);
- //x |= 0x800; // for test
+ ftone += 0x2000u; /* Key-ON [KON] */
+
+ const bool natural_4op = (m_channelCategory[c1] == ChanCat_4op_Master);
+ const size_t opsCount = natural_4op ? 4 : 2;
+ const uint16_t op_addr[4] =
+ {
+ g_operatorsMap[cc1 * 2 + 0], g_operatorsMap[cc1 * 2 + 1],
+ g_operatorsMap[cc2 * 2 + 0], g_operatorsMap[cc2 * 2 + 1]
+ };
+ const uint32_t ops[4] =
+ {
+ patch1.modulator_E862 & 0xFF,
+ patch1.carrier_E862 & 0xFF,
+ patch2.modulator_E862 & 0xFF,
+ patch2.carrier_E862 & 0xFF
+ };
+
+ for(size_t op = 0; op < opsCount; op++)
+ {
+ if((op > 0) && (op_addr[op] == 0xFFF))
+ break;
+ if(mul_offset > 0)
+ {
+ uint32_t dt = ops[op] & 0xF0;
+ uint32_t mul = ops[op] & 0x0F;
+ if((mul + mul_offset) > 0x0F)
+ {
+ mul_offset = 0;
+ mul = 0x0F;
+ }
+ writeRegI(chip, 0x20 + op_addr[op], (dt | (mul + mul_offset)) & 0xFF);
+ }
+ else
+ {
+ writeRegI(chip, 0x20 + op_addr[op], ops[op] & 0xFF);
+ }
+ }
}
- else
+
+ if(chn != 0xFFF)
{
- octave += 0x2000u; /* Key-ON [KON] */
+ writeRegI(chip , 0xA0 + chn, (ftone & 0xFF));
+ writeRegI(chip , 0xB0 + chn, (ftone >> 8));
+ m_keyBlockFNumCache[c1] = (ftone >> 8);
}
- if(chn != 0xFFF)
+ if(cc1 >= 18)
{
- writeRegI(chip , 0xA0 + chn, (octave & 0xFF));
- writeRegI(chip , 0xB0 + chn, (octave >> 8));
- m_keyBlockFNumCache[c] = (octave >> 8);
+ m_regBD[chip ] |= (0x10 >> (cc1 - 18));
+ writeRegI(chip , 0x0BD, m_regBD[chip ]);
+ //x |= 0x800; // for test
}
}
@@ -312,15 +357,17 @@ void OPL3::touchNote(size_t c, uint8_t volume, uint8_t brightness)
uint8_t x = adli.modulator_40, y = adli.carrier_40;
uint32_t mode = 1; // 2-op AM
- if(m_channelCategory[c] == 0 || m_channelCategory[c] == 3)
+ if(m_channelCategory[c] == ChanCat_Regular ||
+ m_channelCategory[c] == ChanCat_Rhythm_Bass)
{
mode = adli.feedconn & 1; // 2-op FM or 2-op AM
}
- else if(m_channelCategory[c] == 1 || m_channelCategory[c] == 2)
+ else if(m_channelCategory[c] == ChanCat_4op_Master ||
+ m_channelCategory[c] == ChanCat_4op_Slave)
{
const adldata *i0, *i1;
- if(m_channelCategory[c] == 1)
+ if(m_channelCategory[c] == ChanCat_4op_Master)
{
i0 = &adli;
i1 = &m_insCache[c + 3];
@@ -452,31 +499,43 @@ void OPL3::silenceAll() // Silence all OPL channels.
void OPL3::updateChannelCategories()
{
- uint32_t fours = m_numFourOps;
+ const uint32_t fours = m_numFourOps;
- for(size_t chip = 0; chip < m_numChips; ++chip)
+ for(uint32_t chip = 0, fours_left = fours; chip < m_numChips; ++chip)
{
m_regBD[chip] = (m_deepTremoloMode * 0x80 + m_deepVibratoMode * 0x40 + m_rhythmMode * 0x20);
writeRegI(chip, 0x0BD, m_regBD[chip]);
- uint32_t fours_this_chip = std::min(fours, static_cast<uint32_t>(6u));
+ uint32_t fours_this_chip = std::min(fours_left, static_cast<uint32_t>(6u));
writeRegI(chip, 0x104, (1 << fours_this_chip) - 1);
- fours -= fours_this_chip;
+ fours_left -= fours_this_chip;
}
- // Mark all channels that are reserved for four-operator function
- if(m_rhythmMode == 1)
+ if(!m_rhythmMode)
+ {
+ for(size_t a = 0, n = m_numChips; a < n; ++a)
+ {
+ for(size_t b = 0; b < 23; ++b)
+ {
+ m_channelCategory[a * 23 + b] =
+ (b >= 18) ? ChanCat_Rhythm_Slave : ChanCat_Regular;
+ }
+ }
+ }
+ else
{
- for(size_t a = 0; a < m_numChips; ++a)
+ for(size_t a = 0, n = m_numChips; a < n; ++a)
{
- for(size_t b = 0; b < 5; ++b)
- m_channelCategory[a * 23 + 18 + b] = static_cast<char>(b + 3);
- for(size_t b = 0; b < 3; ++b)
- m_channelCategory[a * 23 + 6 + b] = ChanCat_Rhythm_Slave;
+ for(size_t b = 0; b < 23; ++b)
+ {
+ m_channelCategory[a * 23 + b] =
+ (b >= 18) ? static_cast<ChanCat>(ChanCat_Rhythm_Bass + (b - 18)) :
+ (b >= 6 && b < 9) ? ChanCat_Rhythm_Slave : ChanCat_Regular;
+ }
}
}
- size_t nextfour = 0;
- for(size_t a = 0; a < m_numFourOps; ++a)
+ uint32_t nextfour = 0;
+ for(uint32_t a = 0; a < fours; ++a)
{
m_channelCategory[nextfour] = ChanCat_4op_Master;
m_channelCategory[nextfour + 3] = ChanCat_4op_Slave;
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index f719f01..2fc12a4 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -399,10 +399,11 @@ public:
/**
* @brief On the note in specified chip channel with specified frequency of the tone
- * @param c Channel of chip (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param c1 Channel of chip [or master 4-op channel] (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
+ * @param c2 Slave 4-op channel of chip, unused for 2op (Emulated chip choosing by next formula: [c = ch + (chipId * 23)])
* @param hertz Frequency of the tone in hertzes
*/
- void noteOn(size_t c, double hertz);
+ void noteOn(size_t c1, size_t c2, double hertz);
/**
* @brief Change setup of instrument in specified chip channel
@@ -558,7 +559,7 @@ public:
//! Vibrato depth value
vibdepth;
//! Vibrato delay time
- int64_t vibdelay;
+ int64_t vibdelay_us;
//! Last LSB part of RPN value received
uint8_t lastlrpn,
//! Last MSB poart of RPN value received
@@ -801,7 +802,7 @@ public:
noteAfterTouchInUse = false;
vibspeed = 2 * 3.141592653 * 5.0;
vibdepth = 0.5 / 127;
- vibdelay = 0;
+ vibdelay_us = 0;
panning = 64;
portamento = 0;
portamentoEnable = false;
@@ -866,12 +867,12 @@ public:
//! Has fixed sustain, don't iterate "on" timeout
bool fixed_sustain;
//! Timeout until note will be allowed to be killed by channel manager while it is on
- int64_t kon_time_until_neglible;
- int64_t vibdelay;
+ int64_t kon_time_until_neglible_us;
+ int64_t vibdelay_us;
};
//! Time left until sounding will be muted after key off
- int64_t koff_time_until_neglible;
+ int64_t koff_time_until_neglible_us;
enum { users_max = 128 };
LocationData *users_first, *users_free_cells;
@@ -888,12 +889,12 @@ public:
void users_assign(const LocationData *users, size_t count);
// For channel allocation:
- AdlChannel(): koff_time_until_neglible(0)
+ AdlChannel(): koff_time_until_neglible_us(0)
{
users_clear();
}
- AdlChannel(const AdlChannel &oth): koff_time_until_neglible(oth.koff_time_until_neglible)
+ AdlChannel(const AdlChannel &oth): koff_time_until_neglible_us(oth.koff_time_until_neglible_us)
{
if(oth.users_first)
{
@@ -906,16 +907,16 @@ public:
AdlChannel &operator=(const AdlChannel &oth)
{
- koff_time_until_neglible = oth.koff_time_until_neglible;
+ koff_time_until_neglible_us = oth.koff_time_until_neglible_us;
users_assign(oth.users_first, oth.users_size);
return *this;
}
/**
- * @brief Increases age of active note in milliseconds time
- * @param ms Amount time in milliseconds
+ * @brief Increases age of active note in microseconds time
+ * @param us Amount time in microseconds
*/
- void addAge(int64_t ms);
+ void addAge(int64_t us);
};
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
diff --git a/src/cvt_xmi2mid.hpp b/src/cvt_xmi2mid.hpp
index decb25c..e8d9dbf 100644
--- a/src/cvt_xmi2mid.hpp
+++ b/src/cvt_xmi2mid.hpp
@@ -640,7 +640,7 @@ static int xmi2mid_GetVLQ2(struct xmi2mid_xmi_ctx *ctx, uint32_t *quant) {
int32_t data;
*quant = 0;
- for (i = 0; i < 4; i++) {
+ for (i = 0; xmi2mid_getsrcpos(ctx) != xmi2mid_getsrcsize(ctx); ++i) {
data = xmi2mid_read1(ctx);
if (data & 0x80) {
xmi2mid_skipsrc(ctx, -1);
diff --git a/src/midi_sequencer_impl.hpp b/src/midi_sequencer_impl.hpp
index 0fe6192..e54c7ee 100644
--- a/src/midi_sequencer_impl.hpp
+++ b/src/midi_sequencer_impl.hpp
@@ -614,6 +614,19 @@ bool BW_MidiSequencer::buildSmfTrackData(const std::vector<std::vector<uint8_t>
}
}
+#ifdef ENABLE_END_SILENCE_SKIPPING
+ //Have track end on its own row? Clear any delay on the row before
+ if(event.subtype == MidiEvent::ST_ENDTRACK && evtPos.events.size() == 1)
+ {
+ if (!m_trackData[tk].empty())
+ {
+ MidiTrackRow &previous = m_trackData[tk].back();
+ previous.delay = 0;
+ previous.timeDelay = 0;
+ }
+ }
+#endif
+
if((evtPos.delay > 0) || (event.subtype == MidiEvent::ST_ENDTRACK))
{
evtPos.absPos = abs_position;
diff --git a/utils/gen_adldata/scrapped.txt b/utils/gen_adldata/scrapped.txt
index 10c15cd..51a0497 100644
--- a/utils/gen_adldata/scrapped.txt
+++ b/utils/gen_adldata/scrapped.txt
@@ -75,7 +75,7 @@ static const char *const banknames[] =
"TMB (Shadow Warrior)",
"DMX (Raptor)",
"OP3 (Modded GMOPL by Wohlstand)",
- "SB (Jammey O'Connel's bank)",
+ "SB (Jamie O'Connell's bank)",
"TMB (Default bank of Build Engine)",
"OP3 (4op bank by James Alan Nguyen)",
"TMB (Blood)",