aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWohlstand <admin@wohlnet.ru>2017-11-26 03:08:47 +0300
committerWohlstand <admin@wohlnet.ru>2017-11-26 03:08:47 +0300
commitb92cc8e942b91268b096757fe22aca8368ea3de6 (patch)
tree086ee97fed7ed2aad2e64e8870021ba032fd9c59 /src
parent52bbba002d7f39334e833f3ec9e1de010d161bdf (diff)
parent5fa684bd2732f638763cd62bed831ccc6aafc0bf (diff)
downloadlibADLMIDI-b92cc8e942b91268b096757fe22aca8368ea3de6.tar.gz
libADLMIDI-b92cc8e942b91268b096757fe22aca8368ea3de6.tar.bz2
libADLMIDI-b92cc8e942b91268b096757fe22aca8368ea3de6.zip
Merge branch 'master' into get-rid-of-backup-buffer
Diffstat (limited to 'src')
-rw-r--r--src/adlmidi_midiplay.cpp29
-rw-r--r--src/adlmidi_opl3.cpp19
-rw-r--r--src/adlmidi_private.hpp41
3 files changed, 67 insertions, 22 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index ea46f16..69db6b0 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -110,6 +110,11 @@ static const uint8_t PercussionMap[256] =
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+inline bool isXgPercChannel(uint8_t msb, uint8_t lsb)
+{
+ return (msb == 0x7E || msb == 0x7F) && (lsb == 0);
+}
+
void MIDIplay::AdlChannel::AddAge(int64_t ms)
{
if(users.empty())
@@ -908,6 +913,7 @@ void MIDIplay::realTime_ResetState()
chan.lastlrpn = 0;
chan.lastmrpn = 0;
chan.nrpn = false;
+ chan.brightness = 127;
NoteUpdate_All(uint16_t(ch), Upd_All);
NoteUpdate_All(uint16_t(ch), Upd_Off);
}
@@ -1194,10 +1200,12 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
case 0: // Set bank msb (GM bank)
Ch[channel].bank_msb = value;
+ Ch[channel].is_xg_percussion = isXgPercChannel(Ch[channel].bank_msb, Ch[channel].bank_lsb);
break;
case 32: // Set bank lsb (XG bank)
Ch[channel].bank_lsb = value;
+ Ch[channel].is_xg_percussion = isXgPercChannel(Ch[channel].bank_msb, Ch[channel].bank_lsb);
break;
case 5: // Set portamento msb
@@ -1220,11 +1228,14 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
NoteUpdate_All(channel, Upd_Volume);
break;
+ case 74: // Change brightness
+ Ch[channel].brightness = value;
+ NoteUpdate_All(channel, Upd_Volume);
+ break;
+
case 64: // Enable/disable sustain
Ch[channel].sustain = value;
-
if(!value) KillSustainingNotes(channel);
-
break;
case 11: // Change expression (another volume factor)
@@ -1251,6 +1262,7 @@ void MIDIplay::realTime_Controller(uint8_t channel, uint8_t type, uint8_t value)
Ch[channel].vibdelay = 0;
Ch[channel].panning = 0x30;
Ch[channel].portamento = 0;
+ Ch[channel].brightness = 127;
//UpdatePortamento(MidCh);
NoteUpdate_All(channel, Upd_Pan + Upd_Volume + Upd_Pitch);
// Kill all sustained notes
@@ -1449,6 +1461,8 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
if(props_mask & Upd_Volume)
{
uint32_t volume;
+ bool is_percussion = (MidCh == 9) || Ch[MidCh].is_xg_percussion;
+ uint8_t brightness = is_percussion ? 127 : Ch[MidCh].brightness;
switch(opl.m_volumeScale)
{
@@ -1471,12 +1485,11 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
else
{
// The formula below: SOLVE(V=127^3 * 2^( (A-63.49999) / 8), A)
- volume = volume > 8725 ? static_cast<unsigned int>(std::log((double)volume) * 11.541561 + (0.5 - 104.22845)) : 0;
+ volume = volume > 8725 ? static_cast<uint32_t>(std::log(static_cast<double>(volume)) * 11.541561 + (0.5 - 104.22845)) : 0;
// The incorrect formula below: SOLVE(V=127^3 * (2^(A/63)-1), A)
//opl.Touch_Real(c, volume>11210 ? 91.61112 * std::log(4.8819E-7*volume + 1.0)+0.5 : 0);
}
-
- opl.Touch_Real(c, volume);
+ opl.Touch_Real(c, volume, brightness);
//opl.Touch(c, volume);
}
break;
@@ -1486,7 +1499,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
volume = 2 * ((Ch[MidCh].volume * Ch[MidCh].expression) * 127 / 16129) + 1;
//volume = 2 * (Ch[MidCh].volume) + 1;
volume = (DMX_volume_mapping_table[vol] * volume) >> 9;
- opl.Touch_Real(c, volume);
+ opl.Touch_Real(c, volume, brightness);
}
break;
@@ -1495,7 +1508,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
volume = ((Ch[MidCh].volume * Ch[MidCh].expression) * 127 / 16129);
volume = ((64 * (vol + 0x80)) * volume) >> 15;
//volume = ((63 * (vol + 0x80)) * Ch[MidCh].volume) >> 15;
- opl.Touch_Real(c, volume);
+ opl.Touch_Real(c, volume, brightness);
}
break;
@@ -1504,7 +1517,7 @@ void MIDIplay::NoteUpdate(uint16_t MidCh,
//volume = 63 - W9X_volume_mapping_table[(((vol * Ch[MidCh].volume /** Ch[MidCh].expression*/) * 127 / 16129 /*2048383*/) >> 2)];
volume = 63 - W9X_volume_mapping_table[(((vol * Ch[MidCh].volume * Ch[MidCh].expression) * 127 / 2048383) >> 2)];
//volume = W9X_volume_mapping_table[vol >> 2] + volume;
- opl.Touch_Real(c, volume);
+ opl.Touch_Real(c, volume, brightness);
}
break;
}
diff --git a/src/adlmidi_opl3.cpp b/src/adlmidi_opl3.cpp
index 421148d..2d1f3e8 100644
--- a/src/adlmidi_opl3.cpp
+++ b/src/adlmidi_opl3.cpp
@@ -271,7 +271,7 @@ void OPL3::NoteOn(unsigned c, double hertz) // Hertz range: 0..131071
}
}
-void OPL3::Touch_Real(unsigned c, unsigned volume)
+void OPL3::Touch_Real(unsigned c, unsigned volume, uint8_t brightness)
{
if(volume > 63)
volume = 63;
@@ -332,9 +332,22 @@ void OPL3::Touch_Real(unsigned c, unsigned volume)
{
bool do_modulator = do_ops[ mode ][ 0 ] || ScaleModulators;
bool do_carrier = do_ops[ mode ][ 1 ] || ScaleModulators;
- Poke(card, 0x40 + o1, do_modulator ? (x | 63) - volume + volume * (x & 63) / 63 : x);
+
+ uint32_t modulator = do_modulator ? (x | 63) - volume + volume * (x & 63) / 63 : x;
+ uint32_t carrier = do_carrier ? (y | 63) - volume + volume * (y & 63) / 63 : y;
+
+ if(brightness != 127)
+ {
+ brightness = static_cast<uint8_t>(std::round(127.0 * std::sqrt((static_cast<double>(brightness)) * (1.0 / 127.0))) / 2.0);
+ if(!do_modulator)
+ modulator = (modulator | 63) - brightness + brightness * (modulator & 63) / 63;
+ if(!do_carrier)
+ carrier = (carrier | 63) - brightness + brightness * (carrier & 63) / 63;
+ }
+
+ Poke(card, 0x40 + o1, modulator);
if(o2 != 0xFFF)
- Poke(card, 0x40 + o2, do_carrier ? (y | 63) - volume + volume * (y & 63) / 63 : y);
+ Poke(card, 0x40 + o2, carrier);
}
// Correct formula (ST3, AdPlug):
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index f58f02f..32c3637 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -249,7 +249,7 @@ public:
void NoteOff(size_t c);
void NoteOn(unsigned c, double hertz);
- void Touch_Real(unsigned c, unsigned volume);
+ void Touch_Real(unsigned c, unsigned volume, uint8_t brightness = 127);
//void Touch(unsigned c, unsigned volume)
void Patch(uint16_t c, size_t i);
@@ -465,6 +465,8 @@ public:
int64_t vibdelay;
uint8_t lastlrpn, lastmrpn;
bool nrpn;
+ uint8_t brightness;
+ bool is_xg_percussion;
struct NoteInfo
{
// Current pressure
@@ -501,17 +503,34 @@ public:
typedef activenotemap_t::iterator activenoteiterator;
char ____padding2[5];
activenotemap_t activenotes;
-
+ void reset()
+ {
+ portamento = 0;
+ bank_lsb = 0;
+ bank_msb = 0;
+ patch = 0;
+ volume = 100;
+ expression = 127;
+ panning = 0x30;
+ vibrato = 0;
+ sustain = 0;
+ bend = 0.0;
+ bendsense = 2 / 8192.0;
+ vibpos = 0;
+ vibspeed = 2 * 3.141592653 * 5.0;
+ vibdepth = 0.5 / 127;
+ vibdelay = 0;
+ lastlrpn = 0;
+ lastmrpn = 0;
+ nrpn = false;
+ brightness = 127;
+ is_xg_percussion = false;
+ }
MIDIchannel()
- : portamento(0),
- bank_lsb(0), bank_msb(0), patch(0),
- volume(100), expression(127),
- panning(0x30), vibrato(0), sustain(0),
- bend(0.0), bendsense(2 / 8192.0),
- vibpos(0), vibspeed(2 * 3.141592653 * 5.0),
- vibdepth(0.5 / 127), vibdelay(0),
- lastlrpn(0), lastmrpn(0), nrpn(false),
- activenotes() { }
+ : activenotes()
+ {
+ reset();
+ }
};
// Additional information about OPL3 channels