New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support loading SoundFonts >2GiB on Windows #629
Conversation
Since sizeof(long) == 4 even on 64 bit Windose, big files cannot be loaded natively via the ANSI C file API. This change makes fluidsynth's file callback API use long long, which is guaranteed to be at least 64 bit wide.
|
1)Here, 2gb-win branch compile successfully using VS2010 on Windows XP (32 bits CPU). May be a simple test trying to seek above the 32bit integer limit and reading some small SF2 chunk Please, if you think I can help ask me. |
|
Thanks @jjceresa . I wasn't sure about XP, because I read that fseeki64 might not be available. @trolley813 If you could test the 2gb-win branch with your huge soundfont that would be great. I'll keep thinking about how to set up a unit test for this. |
|
@trolley813 in case you prefer test it without building, I can send you directly the win32 binary dll. It should work even on recent Windows. |
The presence of fseeki64() and ftelli64() depends on the version of the msvcrt you are using it seems. But this code: is working fine even on Windows 98, just tried. |
@carlo-bramini , Thanks for the try. Please have you enough RAM to try loading a File > 2 Gbytes ? |
On Windows 9x/ME, this test is not possible or it is not really a good idea to do because the OS cannot handle more than 512MB of RAM by design. On NT-based Windows, such test could be done, but where to find so huge soundfonts? Or can I create it myself with some tools? |
I tried to switch to https://github.com/FluidSynth/fluidsynth/blob/2gbtest/src/sfloader/fluid_sfont.c#L114-L117 However, this breaks the unit tests even more: https://dev.azure.com/tommbrt/tommbrt/_build/results?buildId=1434&view=results
I have no idea what's wrong. |
|
Forgot to mention that I can also reproduce this locally: Win10 Build 1803 |
Here, I tried building manually a huge SF2 file using
Swami uses the |
|
Just noticed that
Complete utter garbage... So, what to do instead?
Opinions? I sympathize with 3., but for that I need to know how And don't worry about the 2GB soundfont test. I have an idea how to set up a unit test for that. But at first we need to find a FILE API usage that does not break existing tests... |
Here still using VS2010 on WinXP |
Thank you very much! I'll try to test it. |
Really? That's good, but how can this be? According to the web, support for |
Right, I was confused by VS2010's "intellisense" that displays that As Using It seems that |
|
Thanks! I've tested it with this free (GPLv3) soundfont (part 1 is 3.99GiB), and it seems to work. |
The unit tests keep failing when compiling with MinGW x86 on x64 Windows10. This is related to the change introduced in #629. The exact reason for the failure is unknown. I assume it's a broken MinGW implementation of the function `fgetpos()` or `_fseeki64()`, as the tests run fine for WindowsXP x86. However, I have little interest in further investigation, as I don't consider using MinGWx86 on x64 to be a valid use-case.
|
It's really interesting that my theory about why certain widespread SoundFont implementations are limited to 2GiB was proved right in the case of FluidSynth. My theory was that the code handling size treated the value as a 32-bit signed integer despite the fact that negative file size isn't possible. Thus, by using signed 32bit integers, half of the available potential for sample size was erased. This hurt 24-bit banks dramatically due to the samples being 1.5 times larger. With stereo and a non-conservative recording time, plus a larger sample rate, you can easily exceed 2GiB, thus the signed integer bug artificially limited bank quality by up to a factor of 2. My hope is that this type of fix (treating SF2 size as a uint32 or long long or other type of value able to go from zero all the way up to 2^32 rather than as a signed 32bit integer or God forbid a 32bit float) ends up in other SoundFont environment besides FluidSynth, such as Timidity and such. To me, it's a bug that became relevant whenever people started to have the disk space to store banks at sizes that were previously considered outlandish back in the olden days of soundfonts. Even in 2005 during the X-Fi and SoundFont 2.04 days there were plenty of systems that didn't have enough drive space to justify using a 4GiB bank, a size that was supported natively on Audigy, Audigy 2, and X-Fi cards without requiring software synths like the kind you would use on machines without those cards. To me, plenty of devs of various software SoundFont synths didn't really consider that people might actually hit 2^32 in file size in the future, given how drive space even in 2005 was precious. 2005 was before Macintosh machines switched over to Intel and was before Vista happened, as well as the year before extended support for Windows 9x ended. There were plenty of older PowerPC Macs around and plenty of low quality early Windows XP machines originally meant to run Windows 2000 or 98 floating around, plus other systems with drive space low enough to make 4GiB SoundFonts unrealistic to have on your machine then. So even at the time of the X-Fi there were devs who didn't think that people would need to use the full 2^32 bytes file size supported by the Audigy, Audigy 2, and X-Fi, and their code grew around that. Thus it became a popular bug, and sometimes it deterred people from even attempting banks that large, and people became used to that artificial limit, which may have accidentally kept the bug around longer because people had good banks that weren't anywhere near the limit that they thought were hood enough. Except that people, such as myself, made larger banks, and then this happened. I thank you for fixing this terrible bug! |
However, there are some additional complications with using functions like Actually, I believe that SF2 should be superseded with a new community-based "standard" (not to be confused with SF3, an unofficial extension) more suitable for modern systems, in particular it should allow 64-bit file sizes (a vast majority of modern desktop of even mobile systems are 64-bit), since the 4GiB (2^32) limit is as of now, well, not so large either. |
Me and a fellow SF2 maker have actually been working on such a replacement! We have used 64-bit RIFF, and we have gotten LSB Bank Select, as well as more features out of SF2. We call what we are proposing SFe. I can send a draft soon, but let me show you what an LSB Bank Select SF2 does https://drive.google.com/file/d/1cerpko6kL4SctyHG9ozYFtwePmbHX7CW/view The SF2 used is a modified excerpt of my FOSS JummBox SoundFont, available at http://stgiga.itch.io/jummboxsoundfont or http://musical-artifacts.com/artifacts/2722 |
We also came up with an entirely new standard too, but this was before we found hidden features in SF2 and found ways to extend it. NGMSS |
|
Thank you! I'm also started working on a new standard (something between SF2 and a (zipped) SFZ). But this is probably not a proper place to discuss it (since it's off-topic and not (directly) related to FluidSynth). |

Since
sizeof(long)==4even on 64 bit Windows, big files cannot be loaded natively via the ANSI C file API. This change makes fluidsynth's file callback API uselong long, which is guaranteed to be at least 64 bit wide. This change breaks ABI and therefore requires an SOVERSION bump. Resolves #628.Although the WindowsXP CI build pipeline reports success, I don't trust that it really can be built on WinXP. @jjceresa Could you pls. compile the 2gb-win branch on WinXP, and:
Also, the CI pipeline that uses MinGW x86 currently fails executing the unit tests:
https://dev.azure.com/tommbrt/tommbrt/_build/results?buildId=1413&view=results
For some reason, the
_fseeki64()call influid_is_soundfont()fluidsynth/src/sfloader/fluid_sffile.c
Line 364 in 631c979
does not advance the file pointer by 4 anymore, it only advances by 3. This causes the next
fread()to read0x62667300rather than0x6266736B(=="sfbk" identifier). I'll deal with this after feedback from @jjceresa.