Ticket #6436: music-glitch-possible-fix.txt

File music-glitch-possible-fix.txt, 3.4 KB (added by eriktorbjorn, 6 years ago)

Proof-of-concept for a possible workaround

Line 
1diff --git a/engines/kyra/sound_midi.cpp b/engines/kyra/sound_midi.cpp
2index fc6e92a..1bedb43 100644
3--- a/engines/kyra/sound_midi.cpp
4+++ b/engines/kyra/sound_midi.cpp
5@@ -36,7 +36,7 @@ public:
6        MidiOutput(OSystem *system, MidiDriver *output, bool isMT32, bool defaultMT32);
7        ~MidiOutput();
8 
9-       void setSourceVolume(int source, int volume, bool apply=false);
10+       void setSourceVolume(int source, int volume, bool apply=false, bool immediate=false);
11 
12        void initSource(int source);
13        void deinitSource(int source);
14@@ -82,6 +82,9 @@ private:
15 
16                byte noteCount;
17 
18+               bool hasPendingVolume;
19+               byte pendingVolume;
20+
21                Controller controllers[9];
22        } _channels[16];
23 
24@@ -235,18 +238,22 @@ void MidiOutput::send(uint32 b) {
25                        }
26 
27                        if (note != -1) {
28+                               int ch = _sources[_curSource].channelMap[channel];
29                                if (remove) {
30                                        _sources[_curSource].notes[note].channel = 0xFF;
31 
32-                                       --_channels[_sources[_curSource].channelMap[channel]].noteCount;
33+                                       --_channels[ch].noteCount;
34                                } else {
35                                        _sources[_curSource].notes[note].channel = channel;
36                                        _sources[_curSource].notes[note].note = param1;
37 
38-                                       ++_channels[_sources[_curSource].channelMap[channel]].noteCount;
39+                                       ++_channels[ch].noteCount;
40                                }
41-
42-                               sendIntern(event, _sources[_curSource].channelMap[channel], param1, param2);
43+                               if (!remove && _channels[ch].hasPendingVolume) {
44+                                       sendIntern(0xB0, ch, 0x07, _channels[ch].pendingVolume);
45+                                       _channels[ch].hasPendingVolume = false;
46+                               }
47+                               sendIntern(event, ch, param1, param2);
48                        }
49                }
50                return;
51@@ -316,7 +323,7 @@ void MidiOutput::metaEvent(byte type, byte *data, uint16 length) {
52        _output->metaEvent(type, data, length);
53 }
54 
55-void MidiOutput::setSourceVolume(int source, int volume, bool apply) {
56+void MidiOutput::setSourceVolume(int source, int volume, bool apply, bool immediate) {
57        _sources[source].volume = volume;
58 
59        if (apply) {
60@@ -324,7 +331,12 @@ void MidiOutput::setSourceVolume(int source, int volume, bool apply) {
61                        // Controller 0 in the state table should always be '7' aka
62                        // volume control
63                        byte realVol = (_sources[source].controllers[i][0].value * volume) >> 8;
64-                       sendIntern(0xB0, i, 0x07, realVol);
65+                       if (immediate) {
66+                               sendIntern(0xB0, i, 0x07, realVol);
67+                       } else {
68+                               _channels[i].hasPendingVolume = true;
69+                               _channels[i].pendingVolume = realVol;
70+                       }
71                }
72        }
73 }
74@@ -339,6 +351,9 @@ void MidiOutput::initSource(int source) {
75 
76                for (int j = 0; j < 9; ++j)
77                        _sources[source].controllers[i][j] = _channels[i].controllers[j];
78+
79+               _channels[i].hasPendingVolume = false;
80+               _channels[i].pendingVolume = 0;
81        }
82 }
83 
84@@ -584,7 +599,7 @@ void SoundMidiPC::updateVolumeSettings() {
85        const int newMusVol = (mute ? 0 : ConfMan.getInt("music_volume"));
86        _sfxVolume = (mute ? 0 : ConfMan.getInt("sfx_volume"));
87 
88-       _output->setSourceVolume(0, newMusVol, newMusVol != _musicVolume);
89+       _output->setSourceVolume(0, newMusVol, newMusVol != _musicVolume, true);
90        _musicVolume = newMusVol;
91 
92        for (int i = 1; i < 4; ++i)
93@@ -768,7 +783,7 @@ void SoundMidiPC::onTimer(void *data) {
94 
95                if (midi->_fadeStartTime + musicFadeTime > midi->_vm->_system->getMillis()) {
96                        int volume = (byte)((musicFadeTime - (midi->_vm->_system->getMillis() - midi->_fadeStartTime)) * midi->_musicVolume / musicFadeTime);
97-                       midi->_output->setSourceVolume(0, volume, true);
98+                       midi->_output->setSourceVolume(0, volume, true, true);
99                } else {
100                        for (int i = 0; i < 16; ++i)
101                                midi->_output->stopNotesOnChannel(i);