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);