[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [fluid-dev] About Supporting 2GiB+ Soundfonts on Windows
From: |
Carlo Bramini |
Subject: |
Re: [fluid-dev] About Supporting 2GiB+ Soundfonts on Windows |
Date: |
Tue, 17 Mar 2020 13:31:30 +0100 (CET) |
Hello,
although it is true that you cannot handle files larger than 2GB with current
code, there is one thing that's strange in that bug report.
If you really have not large file support, the first function to fail should be
fseek() and not ftell(), so the first message you should read in the console
should be "Seek to end of file failed" and not "Get end of file position
failed". And this is what happens on Windows with oldest common runtime, try to
believe. And when this happens, this means that MSVCRT does not also provide
functions like _fseeki64/_ftelli64, this is unavoidable. But if the bug report
says that the function that fails is ftell(), probably it means that the
program is using a CRT with large file support. In this case, you can bypass
the limitation of ftell() in this way:
fsize = fcbs->ftell(sf->sffd);
if (fsize == FLUID_FAILED)
{
FLUID_LOG(FLUID_WARN, "Get end of file position failed");
/* Try alternative way for large file support */
fsize = get_large_file_size(sf->sffd);
if (fsize == FLUID_FAILED)
{
FLUID_LOG(FLUID_ERR, "Get large file size failed");
goto error_exit;
}
}
and then you can add a function like this one (I used traditional fseek/ftell
instead of _fluid_file_callbacks_t for simplicity):
int64_t get_large_file_size(FILE *fp)
{
int res = fseek(fp, 0L, SEEK_END);
long offset = 0x40000000L; /* 1GiB */
long rel;
int64_t size = 0;
if (res < 0)
return res;
for (;;)
{
res = fseek(fp, -offset, SEEK_CUR);
if (res < 0)
return res;
size += offset;
rel = ftell(fp);
if (rel < 0)
continue;
return size + rel;
}
return size;
}
and you won't need to change the ABI of the library, at least for now.
Technically, I don't think that it would be a big problem: "filesize" is
compared with "chunk.size", which is 32bit so, if I understood correctly, this
limits the size of a single SF2 file to 4GiB by design and this also means that
there will be a maximum of 3 calls to fseek/ftell before computing the size of
the large file. I have not tested on Unix, but if LIBC provides large file
support, I expect that it will also work on it.
What do you think?
Sincerely.
Carlo Bramini.
> Il 17 marzo 2020 alle 9.44 "Tom M. via fluid-dev" <address@hidden> ha scritto:
>
>
> > If you decided to require C99, I would think you would want to use int64_t
> > and its relatives for portability.
>
> I actually had "long long" in mind, because int64_t would require
> fluidsynth's header to include stdint.h, and whenever possible I would
> like to avoid polluting our header with any C system header (for the
> sake of portability to C++). Also note that int64_t is an optional
> type and may only be provided if the implementation supports it. (The
> latter doesn't really make sense in practice, because long long is an
> intrinsic type guaranteed to be at least 64 bits wide. And because
> long long must be available, int64_t will also be available.)
>
> Based on Reinhold's thought, the idea would be to use something like
>
> #if defined(_MSVC_VER < VisualStudio2015)
> typedef __int64 fluid_long_long_t; // even on 32bit windows
> #else
> typedef long long fluid_long_long_t;
> #endif
>
> in our public header. Which basically means: Fluidsynth's source code
> stays C89. The public header will be compatible with C99 (or C++11)
> UNLESS it's being compiled with an old VS in which case we provide a
> fallback. This should provide enough portability while still retaining
> ABI compatibility between and MSVC and MinGW compiled fluidsynth.
>
> Should it really be that simple or am I missing smth.?
>
> Tom
>
> _______________________________________________
> fluid-dev mailing list
> address@hidden
> https://lists.nongnu.org/mailman/listinfo/fluid-dev