shithub: choc

Download patch

ref: 10ccadee87aee30e07b66606d9d155f8cc9d7a77
parent: 0e83eb0e72e9f68e0a20a8fdd81ec31d9f2c3cd3
parent: 816f94a8220b1fe3315a64faca855dcf90c44c6b
author: Simon Howard <[email protected]>
date: Mon Oct 5 06:33:08 EDT 2015

Merge pull request #618 from khokh2001/opl-volume-fix

opl: DMX MIDI channel volume calculation fix.

--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -85,6 +85,7 @@
     // Volume level
 
     int volume;
+    int volume_base;
 
     // Pan
 
@@ -311,6 +312,7 @@
 static boolean music_initialized = false;
 
 //static boolean musicpaused = false;
+static int start_music_volume;
 static int current_music_volume;
 
 // GENMIDI lump instrument data:
@@ -572,8 +574,7 @@
 
     // Multiply note volume and channel volume to get the actual volume.
 
-    midi_volume = 2 * (volume_mapping_table[(voice->channel->volume
-                  * current_music_volume) / 127] + 1);
+    midi_volume = 2 * (volume_mapping_table[voice->channel->volume] + 1);
 
     full_volume = (volume_mapping_table[voice->note_volume] * midi_volume)
                 >> 9;
@@ -645,12 +646,20 @@
     }
 }
 
+static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume,
+                             boolean clip_start);
+
 // Set music volume (0 - 127)
 
 static void I_OPL_SetMusicVolume(int volume)
 {
-    unsigned int i;
+    unsigned int i, j;
 
+    if (current_music_volume == volume)
+    {
+        return;
+    }
+
     // Internal state variable.
 
     current_music_volume = volume;
@@ -657,11 +666,20 @@
 
     // Update the volume of all voices.
 
-    for (i = 0; i < num_opl_voices; ++i)
+    for (i = 0; i < num_tracks; ++i)
     {
-        if (voices[i].channel != NULL)
+        for (j = 0; j < MIDI_CHANNELS_PER_TRACK; ++j)
         {
-            SetVoiceVolume(&voices[i], voices[i].note_volume);
+            if (j == 9)
+            {
+                SetChannelVolume(&tracks[i].channels[j],
+                                 volume, false);
+            }
+            else
+            {
+                SetChannelVolume(&tracks[i].channels[j],
+                                 tracks[i].channels[j].volume_base, false);
+            }
         }
     }
 }
@@ -1117,10 +1135,23 @@
     // channel, and change the instrument.
 }
 
-static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume)
+static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume,
+                             boolean clip_start)
 {
     unsigned int i;
 
+    channel->volume_base = volume;
+
+    if (volume > current_music_volume)
+    {
+        volume = current_music_volume;
+    }
+
+    if (clip_start && volume > start_music_volume)
+    {
+        volume = start_music_volume;
+    }
+
     channel->volume = volume;
 
     // Update all voices that this channel is using.
@@ -1232,7 +1263,7 @@
     switch (controller)
     {
         case MIDI_CONTROLLER_MAIN_VOLUME:
-            SetChannelVolume(channel, param);
+            SetChannelVolume(channel, param, true);
             break;
 
         case MIDI_CONTROLLER_PAN:
@@ -1379,6 +1410,10 @@
 
     running_tracks = num_tracks;
 
+    start_music_volume = current_music_volume;
+
+    I_SetMusicVolume(current_music_volume);
+
     for (i = 0; i < num_tracks; ++i)
     {
         MIDI_RestartIterator(tracks[i].iter);
@@ -1453,7 +1488,8 @@
     // TODO: Work out sensible defaults?
 
     channel->instrument = &main_instrs[0];
-    channel->volume = 127;
+    channel->volume = current_music_volume;
+    channel->volume_base = 127;
     channel->pan = 0x30;
     channel->bend = 0;
 }
@@ -1506,6 +1542,8 @@
     // TODO: this is wrong
 
     us_per_beat = 500 * 1000;
+
+    start_music_volume = current_music_volume;
 
     for (i = 0; i < num_tracks; ++i)
     {