Closed porres closed 2 years ago
First, the easy part, the compiled object
to Win64!
About the use of Dynamic vs Static Libraries. I saw something about this in this link https://github.com/FluidSynth/fluidsynth/wiki/, but just for Windows.
I am researching about it, but not seems to be simple because:
cmake
. The unverified developer part is because you need to notarise the library. It's a painful process and you have to pay Apple €100 each year. I have an ID currently, so I could handle this for you if you want.
check this out ---> https://lists.nongnu.org/archive/html/fluid-dev/2022-05/msg00002.html maybe someone can helps us with universal signed dynamic libs
Seems the, at least on Windows, we need the source files of all dynamic libraries (not just fluidsynth).
I thought the source of fluidsynth was the source of dynamic libs, wrong?
I also thought there could be a way to just get all of the files and compile a binary that just copies them all under the hood. but then, I know nothing.
Let me invite to the discussion @Lucarda, who seems like an expert in compiling, at least for windows!
@timothyschoen I hope you appreciate the idea, cause I think it'd be incredible for PlugData to offer an object that plays soundfonts, do you realize how cool that would be for the standalone application?
Now, PlugData has a single binary, and a quite small one, for all Pd, ELSE, cyclone, and even the external abstractions. How do you do that? You seem like someone who knows how to grab all things and make it part of some monolith :) perhaps you can helps us here figuring out this issue with the dynamic libs.
I would really really like to offer an external for fluidsynth that is a single binary which contains all it needs right there.
By the way, Ceammc has 'fluid~', but it is part of the ceammc library and not a separate single binary external. but I don't see a libfluidsynth.3.dylib file in the package. I see many .dylib files, they are:
libceammc_core.dylib libfftw3f.3.dylib libFLAC.8.dylib libglib-2.0.0.dylib libgthread-2.0.0.dylib libiconv.2.dylib libintl.8.dylib libmodplug.1.dylib libogg.0.dylib libopus.0.dylib libpcre.1.dylib libportaudio.2.dylib librubberband.2.dylib libsamplerate.0.dylib libsndfile.1.0.31.dylib libvorbis.0.dylib libvorbisenc.2.dylib libwrapper_lib.dylib libz.1.2.11.dylib
many of these are the same we get for fluidsynth, so it's not like they made a monolithic binary with everything, but they're definitely hiding libfluidsynth.3.dylib somewhere, I wonder it it's part of libceammc_core.dylib
Anyway, what so you people think?
I'm actually ok if we just have to ship like a dozen of dylib files anyway, let's not make this harder than it has to be...
The unverified developer part is because you need to notarise the library. It's a painful process and you have to pay Apple €100 each year. I have an ID currently, so I could handle this for you if you want.
I'm not all that sure that's how it goes. I got the same warning when building ELSE from mojave and trying to load in monterey, whereas the monterey build works fine. Dan says I just need to build with a higher min OS version... now, as for the libs, I dunno, I guess they seem fine if I got them from homebrew from monterey.
anyway, if the people from fluidsynth provide us a signed and universal bluid for a wide range of macOSes, we don't have to worry about anything, the big hassle would be to figure out how to do it all on our own...
@timothyschoen I hope you appreciate the idea, cause I think it'd be incredible for PlugData to offer an object that plays soundfonts, do you realize how cool that would be for the standalone application?
Now, PlugData has a single binary, and a quite small one, for all Pd, ELSE, cyclone, and even the external abstractions. How do you do that? You seem like someone who knows how to grab all things and make it part of some monolith :) perhaps you can helps us here figuring out this issue with the dynamic libs.
I'm looking forward to trying it, it seems like a great addition to PlugData indeed! I like to make little algorithmic compositions every now and then, and being able to load nice sounds like this would be game-changing.
I've added the ELSE and cyclone sources to the static libpd library for PlugData, leaving me with only one thing left to link, so that makes it really simple. I do this by including pure-data as a subproject, and using my own cmakelists instead of the one shipped with it to add more sources.
We could do something similar here: include fluidsynth as a subproject, and use a custom cmakelists to make it export static libraries. That way we can be sure there are no external dependencies, and make it super simple to ship with ELSE. I'm currently swamped with work on PlugData (it's my graduation project for Music Technology school), so it might take me a bit of time before I can look at this :(
I've only been waiting two years to include fluidsynth~ in ELSE, so no rush :)
by the way, we've also been discussing this on the pd dev list, see https://lists.puredata.info/pipermail/pd-dev/2022-05/023062.html
by the way people, next item on the list would also be the inclusion of a SFZ player, see https://github.com/porres/pd-else/issues/1244
We could do something similar here: include fluidsynth as a subproject, and use a custom cmakelists to make it export static libraries
As @charlesneimog said the problem with this is that fluidsynth itself relays on other libraries. This could include many subprojects :(.
Note: Windows seems the less difficult OS to have a "single file" as there are things like ilmerge or with msys2/mingw there are .a
files for each .dll
so statically linking the libs should work (untested in this nested scenario) out of the box.
The idea of statically linking all into a single file is not so nice for fluidsynth~ i think. You could have 8 (or more) [fluidsynth~]s on your patch and you are going to unnecessarily load 7 more times of stuff (that does not need to be loaded multiple times) into the machine.
If you load a dynamic library twice with dlopen like pd does with externals, it actually only loads the whole library once. So if you statically link fluidsynth with the external, it will actually only be loaded into memory once. Opening the object 8 times will still only load 1 dylib.
I'm just wondering if it actually has a lot of deps, I can't seem to find them on the GitHub page and the readme says it doesn't depend on any external code.
I'm just wondering if it actually has a lot of deps, I can't seem to find them on the GitHub page and the readme says it doesn't depend on any external code.
when compiling the object on the mac I get all these libs, 13 of them, so 12 besides libfluidsynth.3.dylib
libFLAC.8.dylib libfluidsynth.3.dylib libglib-2.0.0.dylib libgthread-2.0.0.dylib libintl.8.dylib libogg.0.dylib libopus.0.dylib libpcre.1.dylib libportaudio.2.dylib libreadline.8.dylib libsndfile.1.dylib libvorbis.0.dylib libvorbisenc.2.dylib
It seems on Linux this is quite problematic. Roman on the pd-dev list is suggesting building fluidsynth from source with the minimal set of configure flags required for the pd external.
quoting him
"In the case of the fluidsynth~ external, using the dynamic libraries from my distro (Ubuntu 22.04) doesn't seem practical, as libfluidsynth.so.3 links against virtually half the system. After executing the localdep script, I end up with 53 *.so files. Most of them aren't actually used when libfluidsynth is used for the pd external. Creating a more stripped down build of libfluidsynth probably would make sense here."
I'm just wondering if it actually has a lot of deps, I can't seem to find them on the GitHub page and the readme says it doesn't depend on any external code.
See this page: https://github.com/FluidSynth/fluidsynth/wiki/BuildingWithCMake#building-on-os-x
"In the case of the fluidsynth~ external, using the dynamic libraries from my distro (Ubuntu 22.04) doesn't seem practical, as libfluidsynth.so.3 links against virtually half the system. After executing the localdep script, I end up with 53 *.so files. Most of them aren't actually used when libfluidsynth is used for the pd external. Creating a more stripped down build of libfluidsynth probably would make sense here."
Just to check if I undertood: When we put just libfluidsynth.so.3
inside fluidsynth~
(https://github.com/charlesneimog/pd-fluidsynth/releases/download/v0.0.1/fluidsynth_Linux64.zip), the object will load 53 *.so? So then the compiled object become very inefficient?
See this page: https://github.com/FluidSynth/fluidsynth/wiki/BuildingWithCMake#building-on-os-x
I had seen it, I just couldn't build it... if it ain't clear yet, I'm not a real programmer ;)
Just to check if I undertood: When we put just libfluidsynth.so.3 inside fluidsynth~ (https://github.com/charlesneimog/pd-fluidsynth/releases/download/v0.0.1/fluidsynth_Linux64.zip), the object will load 53 *.so? So then the compiled object become very inefficient?
just like fluidsynth~ needs 13 or so dynamic libs in the same folder so the external can be loaded, it seems linux may need this ridiculous amount of dependencies to be shipped - unless one builds fluidsynth~ with a minimized dependency for the Pd external.
quoting dan from the dev-list
"My two cents: I have tried in the past to bundle dynamic libs generated/downloaded by homebrew into app distributions to run on other systems and always run into problems. It hs always been simpler to statically link, either to the home-brew lib or by building the lib(s) myself using a script or makefile. For longer term projects, I generally prefer to automate building the lib statically then linking it directly into the program.
I forgot to mention that my response was directed more for macOS and possibly Windows where asking people to use a package manager is a bit more of a stretch as opposed to Linux. In general, dependent libs are packaged with the program itself and sometimes dynamic linking can be problematic, ie. on macOS you often have to (re)set the rpath in a built lib. That dance in avoided by simply statically linking at the expense of binary size. I'm not saying it's the best solution, but it may be more maintainable and usable in the case of a dynamically-loaded Pd external.
OTOH I believe GEM provides dynamic libs along with the externals on macOS but this most probably requires fiddling with the rpath, basically overriding the search path for the lib to it's found in a different, non-system location.
For Windows, if I recall correctly, you generally just need to place the dlls next to whatever is using them.
As for mixing static and dynamic linking, I believe that's not a problem as long as the dynamic libs are found."
So I'm not sure if fluidsynth has some unique capabilities that this project lacks, but wouldn't this be a much better fit for an external? It's a single header soundfont2 reader with no dependencies at all. Because it's very compact (2000 lines of code total), it wouldn't be very hard to modify it to suit our needs. The API is super simple as well.
The resulting external would be much smaller in size, the maintenance and build process will be much simpler too.
EDIT: read this for information and caveats
EDIT: https://github.com/schellingb/TinySoundFont/issues/14 for information and caveats
I supposed they's miss things like reverb and chorus, and I guess they also may not have all the microtonal capabilities fluidsytnh has. Fluidsynth is quite an amazing beast ;)
for one, you can specify any set of frequencies for all 128 keys in fluidsynth!
That does sound very nice, I guess we should go for that then. It's just a shame that a DSP application like fluidsynth has all these (imo unnecessary) dependencies like glib and gthread.
If you look at the code as well, it looks like glib hardly gets used, and for things that could just as well be done without an external library. When I have the time, I'd like to dive into it and see how much stuff I can eliminate.
as it seems, we may need to be able to compile fluidsynth in linux and eliminate many unused dependencies for the pd external
So someone already took glib out of fluidsynth, which is a nice starting point:
https://github.com/chirs241097/fluidsynth-sans-glib
I'll fork this and work on a version with even less dependencies.
Almost all other dependencies can be disabled in the cmakelists :O
Almost all other dependencies can be disabled in the cmakelists :O
@reduzent described Linux compile options that are not needed for the external on https://github.com/porres/pd-fluidsynth#--linux
Nice, I missed that. Combined with the glib-free fork, it basically allows us to create a dependency-free version very easily.
From what I remember from 2 years ago there's also the need of libsndfile
(which has itself other deps) to be able to open any SoundFont
(the audio files can be compressed in many formats).
I am able to compile and link without libsndfile, but I'm guessing it won't load any SoundFont then... I understand the problem now, because libsndfile quite a few dependencies... Sorry for my dumb assumptions btw, I didn't have any fluidsynth experience before this but it looks very promising!
I'm wondering: do we really need the whole libsndfile? I read that SoundFont2 audio format is more like WAV files, so why include a library that can also read OGG, flac, MP3 and more? Seems like we could just use a single-header wav reader like this:
https://github.com/adamstark/AudioFile/blob/master/AudioFile.h
Perhaps with some small modifications so it can correctly process the SoundFont2 files?
I am able to compile and link without libsndfile, but I'm guessing it won't load any SoundFont then...
I think it loads at least the default ones (not sure which they are).
I understand the problem now, because libsndfile quite a few dependencies...
Yes, back then we where not happy about not being able to open any soundfont. You can find many for download and try but some are "vorbis", or "FLAC", or "whatever"
Sorry for my dumb assumptions btw, I didn't have any fluidsynth experience before this
I also have no experience at all with fluidsynth.
but it looks very promising!
Yep.
I believe not all soundfonts use wave. According to https://www.fluidsynth.org/ SF3 uses vorbis. I created Linux builds with a locally compiled fluidsynth with restricted params. However, it still has full libsndfile support. I'd like to get some feedback if it works on different systems:
Dependencies are in a subfolder named $arch and the fluidsynth external uses the arch-specific file extension. This would allow to create a bundle supporting multiple archs.
This is the branch I work on for the LInux builds: https://github.com/reduzent/pd-fluidsynth/tree/build-linux
@reduzent in this thread we are trying/pre-discussing if there's a way to get a "single file" fluidsynth~. Seems difficult but @timothyschoen wants to try and @porres will like very much if this is possible.
I also like the challenge :)
Of course it might not be possible and your "folder with deps" approach is nice.
I tried the above $Linux-amd64-32).dek
on a debian11 live-usb. this is what i got on the console:
/home/user/Documents/Pd/externals/else/fluidsynth~.l_amd64:
/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found
(required by /home/user/Documents/Pd/externals/else/amd64/libfluidsynth.so.3)
On Ubuntu it not work too. In console I just have the message, else/fluidsynth~ could not be created
.
@charlesneimog
Are you sure you renamed the extracted folder fluidsynth~
to "else". (back-up somewhere safe your current normal "else" folder.)
I just have the message, else/fluidsynth~ could not be created.
this just means the binary has not been found, not a loading error
On Ubuntu it not work too. In console I just have the message,
else/fluidsynth~ could not be created
.
Change [else/fluidsynth~] in the help to [fluidsynth~] and make sure that else is installed so that the rest of the help-patch works.
I tried the above
$Linux-amd64-32).dek
on a debian11 live-usb. this is what i got on the console:/home/user/Documents/Pd/externals/else/fluidsynth~.l_amd64: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /home/user/Documents/Pd/externals/else/amd64/libfluidsynth.so.3)
Ok, that is valuable to know. I built the amd64 version on Ubuntu 22.04. I better use an old Debian for that, it seems. Thanks!
Sorry my bad. Here the error!
/home/jordana/Documents/PureData/External/else/fluidsynth~.l_amd64: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /home/jordana/Documents/PureData/External/else/amd64/libfluidsynth.so.3)
fluidsynth~ sf2/Famicom
... couldn't create
One weird thing, this just occur in the native Ubuntu, I have Ubuntu 20 in wsl on Windows and it works!
I created Linux builds with a locally compiled fluidsynth with restricted params
@reduzent what are these "restricted params"? Examples?
@porres I'm about to do experiments but I can't compile fluidsynth~ main
:
fluidsynth~.c:85:20: error: expected expression before '?' token
85 | int ch = ac == ? atom_getintarg(1, ac, av) : 0;
try now
that worked.
I created Linux builds with a locally compiled fluidsynth with restricted params
@reduzent what are these "restricted params"? Examples?
cmake .. \
-DCMAKE_INSTALL_PREFIX=/home/roman/.local \
-Denable-alsa=0 \
-Denable-jack=0 \
-Denable-ladspa=0 \
-Denable-oss=0 \
-Denable-pulseaudio=0 \
-Denable-network=0 \
-Denable-ipv6=0 \
-Denable-readline=0
EDIT: readline is also not needed.
I rebuilt the package for amd64 on a Debian bullseye machine (instead of Ubuntu 22.04). Hopefully, that gets rid of the glibc error:
https://netpd.org/~roman/tmp/fluidsynth~%5bv0.1%5d(Linux-amd64-32).dek
Oh my, it does load on Debian Bullseye now, but not on Debian Buster, which has glibc 2.28. Lesson to learn here: Use the oldest still supported OS release for building for the highest coverage of supported platforms.
Maybe I'll create some Debian 9 VMs...
I had failed with my 2 above "Windows Only" speculated solutions:
ilmerge
msys/mingw .a
files.
-static -lpthread
works but -static -lfluidsynth
don't. (there are lots of .a
files in ${MINGW_PREFIX}/lib
but not all are suitable for static linking I guess).-static -lFLAC -static -lvorbis -static ...
Lesson to learn here: Use the oldest still supported OS release for building for the highest coverage of supported platforms. Maybe I'll create some Debian 9 VMs...
I have a linux virtual machine that compiles ELSE for all linux platforms as well as windows. I have to use an old ubuntu 12 system for the exact same reason. When you have success on your task I'll try and see if I can also build it on my virtual machine!
@reduzent in this thread we are trying/pre-discussing if there's a way to get a "single file" fluidsynth~. Seems difficult but @timothyschoen wants to try and @porres will like very much if this is possible.
I also like the challenge :)
it's nice, but let's not waste too much energy. The first priority is to get it built for all platforms - macOS and Windows seems to be taken care, we only need to nail Linuxes now.
I am now design all sorts of microtonal features for this externals, which I'm very excited about (and so is @charlesneimog ). It should take me a while to mature things but I can get a minimal feature version working and we can release it right away. It should grant me an update of ELSE...
Moreover, I'm now questioning wether it makes sense to use the 'fluidsynth' name... it's just an engine used in a wide range of applications, see https://github.com/FluidSynth/fluidsynth/wiki/Applications
Usually object names reflect a task, this is a "soundfont" player, and might as well just be called "soundfont~", what do you think?
I have to use an old ubuntu 12 system for the exact same reason.
Debian 9 doesn't work, since fluidsynth requires cmake >= 3.13 which is not available in Debian 9. I don't see how it could work on Ubuntu 12. Do you use an old version fluidsynth? I think I select Debian 10 for my build machines now.. Let's see.
I wanna include https://github.com/porres/pd-fluidsynth in ELSE.
I need help compiling for Windows, Linux and M1 macs, @charlesneimog might help, so may @timothyschoen.
I can compile with the current situation for macOS intell, but:
Currently, we have a script that generates a wide number of dinamic libs as dependencies. Ideally, I think it'd be best to create a single binary with a static library as part of it... I have NO idea how to do that!
As for apple, ideally we should have a "fat" dinamic lib, that comprises interl and arm architectures (i.e. Universal build). For ELSE, I'm shipping a single fat pack for both intel 64 bits and arm64. It'd be nice if we kept this as a single package and also if it could include all dinamic libs as part of the binary as well.