diff options
author | Simon Howard | 2014-11-01 21:03:32 -0400 |
---|---|---|
committer | Simon Howard | 2014-11-01 21:03:32 -0400 |
commit | d051bd5d55a998f2ff4f74f718e23c98cbf49b88 (patch) | |
tree | c993c52321cb8f0a7dbeb4fc621ae9f2bbc65eb4 | |
parent | 6cbe5972d39b882a0fc8e5ddfc83b3f72a8b7031 (diff) | |
parent | 37aae66760717b106acf602c180140096d95d036 (diff) | |
download | chocolate-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.c | 59 |
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)); } } } |