SDL_mixer: playmidi.c (find_samples): timidity-0.2i behavior for gus patches:

From c6e7af735fd83d6146c230977c9a371da55b20e6 Mon Sep 17 00:00:00 2001
From: sezero <[EMAIL REDACTED]>
Date: Thu, 31 Jul 2025 05:56:50 +0300
Subject: [PATCH] playmidi.c (find_samples): timidity-0.2i behavior for gus
 patches:

casa3.mid from hexen2 sounds incorrect with the PersonalCopy-Lite gus
patches [1] converted from the corresponding soundfonts [2] using the
'unsf' tool.  However, it does sound correct either when using the
PersonalCopy-Lite soundfont itself, or with timidity-0.2i, or one of
its derivatives like libtimidity.

Tracked the issue down to playmidi.c changes between timidity-0.2i and
Timidity++-1.0.0:  It appears that find_samples() is returning 2
in Timidity++, whereas timidity-0.2i (which only supports gus patches)
only uses one.

So, limiting find_samples() for gus instruments to return 1 upon finding
the first sample does make the file play correctly.
The issue is present in Timidity++-2.14 / 2.15 too.  It may be a problem
with soundfont to gus patch conversion, but I am going to keep
this workaround until I have something better.

an equivalent of this patch has been accepted into timidity++, see:
https://sourceforge.net/p/timidity/git/ci/724babbbfa50440f0dc1a15b37945fa11ccd3520/

[1] http://archives.fedoraproject.org/pub/archive/fedora/linux/releases/10/Everything/i386/os/Packages/PersonalCopy-Lite-patches-4.1-3.fc9.noarch.rpm
[2] http://archives.fedoraproject.org/pub/archive/fedora/linux/releases/10/Everything/i386/os/Packages/PersonalCopy-Lite-soundfont-4.1-3.fc9.noarch.rpm
---
 src/timidity/playmidi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/timidity/playmidi.c b/src/timidity/playmidi.c
index d868c6d5..231b7d0a 100644
--- a/src/timidity/playmidi.c
+++ b/src/timidity/playmidi.c
@@ -176,7 +176,7 @@ static int find_samples(MidiSong *song, MidiEvent *e, int *vlist)
   Instrument *ip;
   Sample *sp, *closest;
   Sint32 f, cdiff, diff;
-  int i, nv, note;
+  int i, nv, maxnv, note;
 
   if (ISDRUMCHANNEL(song, e->channel))
     {
@@ -210,6 +210,7 @@ static int find_samples(MidiSong *song, MidiEvent *e, int *vlist)
   f = freq_table[note];
 
   nv = 0;
+  maxnv = (ip->type != INST_GUS) ? 32 : 1; /* GUS: emulate timidity-0.2i start_note() */
   for (i = 0, sp = ip->sample; i < ip->samples; i++, sp++)
     {
       if (sp->low_freq <= f && sp->high_freq >= f)
@@ -217,7 +218,7 @@ static int find_samples(MidiSong *song, MidiEvent *e, int *vlist)
 	  vlist[nv] = find_voice(song, e);
 	  song->voice[vlist[nv]].orig_frequency = f;
 	  song->voice[vlist[nv]].sample = sp;
-	  nv++;
+	  if (++nv == maxnv) break;
 	}
     }