summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Howard2014-11-01 21:03:32 -0400
committerSimon Howard2014-11-01 21:03:32 -0400
commitd051bd5d55a998f2ff4f74f718e23c98cbf49b88 (patch)
treec993c52321cb8f0a7dbeb4fc621ae9f2bbc65eb4
parent6cbe5972d39b882a0fc8e5ddfc83b3f72a8b7031 (diff)
parent37aae66760717b106acf602c180140096d95d036 (diff)
downloadchocolate-doom-d051bd5d55a998f2ff4f74f718e23c98cbf49b88.tar.gz
chocolate-doom-d051bd5d55a998f2ff4f74f718e23c98cbf49b88.tar.bz2
chocolate-doom-d051bd5d55a998f2ff4f74f718e23c98cbf49b88.zip
Merge pull request #465 from khokh2001/opl-fix
opl additive voice volume calculation fix Adjust how the OPL volume register values are calculated based on the channel, note and global MIDI volume, to better match how the Doom DMX library performs these calculations (thanks Alexey Khokholov / khokh2001).
-rw-r--r--src/i_oplmusic.c59
1 files changed, 29 insertions, 30 deletions
diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c
index 433e78fa..9960d35d 100644
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -515,46 +515,45 @@ static void SetVoiceInstrument(opl_voice_t *voice,
static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume)
{
genmidi_voice_t *opl_voice;
+ unsigned int midi_volume;
unsigned int full_volume;
- unsigned int op_volume;
- unsigned int reg_volume;
-
+ unsigned int car_volume;
+ unsigned int mod_volume;
+
voice->note_volume = volume;
-
+
opl_voice = &voice->current_instr->voices[voice->current_instr_voice];
-
+
// Multiply note volume and channel volume to get the actual volume.
-
- full_volume = (volume_mapping_table[voice->note_volume]
- * volume_mapping_table[voice->channel->volume]
- * volume_mapping_table[current_music_volume]) / (127 * 127);
-
- // The volume of each instrument can be controlled via GENMIDI:
-
- op_volume = 0x3f - opl_voice->carrier.level;
-
+
+ midi_volume = 2 * (volume_mapping_table[(voice->channel->volume
+ * current_music_volume) / 127] + 1);
+
+ full_volume = (volume_mapping_table[voice->note_volume] * midi_volume) >> 9;
+
// The volume value to use in the register:
-
- reg_volume = (op_volume * full_volume) / 128;
- reg_volume = (0x3f - reg_volume) | opl_voice->carrier.scale;
-
+ car_volume = 0x3f - full_volume;
+
// Update the volume register(s) if necessary.
-
- if (reg_volume != voice->reg_volume)
+
+ if (car_volume != voice->reg_volume)
{
- voice->reg_volume = reg_volume;
-
- OPL_WriteRegister(OPL_REGS_LEVEL + voice->op2, reg_volume);
-
+ voice->reg_volume = car_volume | (opl_voice->carrier.scale & 0xc0);
+
+ OPL_WriteRegister(OPL_REGS_LEVEL + voice->op2, voice->reg_volume);
+
// If we are using non-modulated feedback mode, we must set the
// volume for both voices.
- // Note that the same register volume value is written for
- // both voices, always calculated from the carrier's level
- // value.
-
- if ((opl_voice->feedback & 0x01) != 0)
+
+ if ((opl_voice->feedback & 0x01) != 0 && opl_voice->modulator.level != 0x3f)
{
- OPL_WriteRegister(OPL_REGS_LEVEL + voice->op1, reg_volume);
+ mod_volume = 0x3f - opl_voice->modulator.level;
+ if (mod_volume >= car_volume)
+ {
+ mod_volume = car_volume;
+ }
+ OPL_WriteRegister(OPL_REGS_LEVEL + voice->op1,
+ mod_volume | (opl_voice->modulator.scale & 0xc0));
}
}
}