summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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));
}
}
}