schellingb / TinySoundFont

SoundFont2 synthesizer library in a single C/C++ file
MIT License
608 stars 71 forks source link

Unicode open #69

Open WindowsNT opened 2 years ago

WindowsNT commented 2 years ago

In Windows, it's essential to be able to open unicode paths. I 've altered it to this:

TSFDEF tsf* tsf_load_filename(const wchar_t* filename)
{
    tsf* res;
    struct tsf_stream stream = { TSF_NULL, (int(*)(void*,void*,unsigned int))&tsf_stream_stdio_read, (int(*)(void*,unsigned int))&tsf_stream_stdio_skip };
    #if __STDC_WANT_SECURE_LIB__
    FILE* f = TSF_NULL; _wfopen_s(&f, filename, L"rb");
    #else
    FILE* f = _wfopen(filename, L"rb");
    #endif
    if (!f)
    {
        //if (e) *e = TSF_FILENOTFOUND;
        return TSF_NULL;
    }
    stream.data = f;
    res = tsf_load(&stream);
    fclose(f);
    return res;
}
schellingb commented 2 years ago

The library can't use platform specific functions like that so we're limited to offering the fopen variant. The official way to do this would be to use tsf_load directly in your application. Something like:

int main(int argc, char *argv[])
{
    struct TSFStream
    {
        static int Read(FILE* f, void* ptr, unsigned int size) { return (int)fread(ptr, 1, size, f); }
        static int Skip(FILE* f, unsigned int count) { return !fseek(f, count, SEEK_CUR); }
    };
    tsf_stream stream = { TSF_NULL, (int(*)(void*,void*,unsigned int))&TSFStream::Read, (int(*)(void*,unsigned int))&TSFStream::Skip };
    FILE* f = TSF_NULL;
    _wfopen_s(&f, L"file.sf2", L"rb");
    g_TinySoundFont = tsf_load(&stream);
    fclose(f);

    ...
}

But of course you're free to change the library as you did.

If that seems too annoying, maybe the library could offer a new function that takes a FILE* instead of a path directly?

// in tsf.h
TSFDEF tsf* tsf_load_file(FILE* f);
// in a program
int main(int argc, char *argv[])
{
    FILE* f = _wfopen(L"path.sf2", L"rb")
    tsf* sf = tsf_load_file();
    fclose(f);

    ...
}