porres / pd-else

ELSE - EL Locus Solus' Externals for Pure Data
Do What The F*ck You Want To Public License
299 stars 35 forks source link

compiling [sfont~] and including it in ELSE #1243

Closed porres closed 2 years ago

porres commented 2 years ago

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.

charlesneimog commented 2 years ago

First, the easy part, the compiled object to Win64!

Fluidsynth_Windows64.zip

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:

  1. Seems the, at least on Windows, we need the source files of all dynamic libraries (not just fluidsynth).
  2. Seems that you need make some code using cmake.
timothyschoen commented 2 years ago

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.

porres commented 2 years ago

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...

porres commented 2 years ago

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 commented 2 years ago

@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 :(

porres commented 2 years ago

I've only been waiting two years to include fluidsynth~ in ELSE, so no rush :)

porres commented 2 years ago

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

porres commented 2 years ago

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

Lucarda commented 2 years ago

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.

Lucarda commented 2 years ago

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.

timothyschoen commented 2 years ago

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.

porres commented 2 years ago

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."

charlesneimog commented 2 years ago

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

charlesneimog commented 2 years ago

"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?

porres commented 2 years ago

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 ;)

porres commented 2 years ago

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.

porres commented 2 years ago

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."

timothyschoen commented 2 years ago

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

porres commented 2 years ago

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 ;)

porres commented 2 years ago

for one, you can specify any set of frequencies for all 128 keys in fluidsynth!

timothyschoen commented 2 years ago

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.

porres commented 2 years ago

as it seems, we may need to be able to compile fluidsynth in linux and eliminate many unused dependencies for the pd external

timothyschoen commented 2 years ago

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.

timothyschoen commented 2 years ago
Screenshot 2022-05-05 at 16 08 08

Almost all other dependencies can be disabled in the cmakelists :O

Lucarda commented 2 years ago

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

timothyschoen commented 2 years ago

Nice, I missed that. Combined with the glib-free fork, it basically allows us to create a dependency-free version very easily.

Lucarda commented 2 years ago

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).

timothyschoen commented 2 years ago

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!

timothyschoen commented 2 years ago

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?

Lucarda commented 2 years ago

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.

reduzent commented 2 years ago

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

Lucarda commented 2 years ago

@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)
charlesneimog commented 2 years ago

On Ubuntu it not work too. In console I just have the message, else/fluidsynth~ could not be created.

Lucarda commented 2 years ago

@charlesneimog

Are you sure you renamed the extracted folder fluidsynth~ to "else". (back-up somewhere safe your current normal "else" folder.)

porres commented 2 years ago

I just have the message, else/fluidsynth~ could not be created.

this just means the binary has not been found, not a loading error

reduzent commented 2 years ago

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.

reduzent commented 2 years ago

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!

charlesneimog commented 2 years ago

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!

porres commented 2 years ago

I created Linux builds with a locally compiled fluidsynth with restricted params

@reduzent what are these "restricted params"? Examples?

Lucarda commented 2 years ago

@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;
porres commented 2 years ago

try now

Lucarda commented 2 years ago

that worked.

reduzent commented 2 years ago

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.

reduzent commented 2 years ago

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

reduzent commented 2 years ago

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...

Lucarda commented 2 years ago

I had failed with my 2 above "Windows Only" speculated solutions:

porres commented 2 years ago

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!

porres commented 2 years ago

@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.

porres commented 2 years ago

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?

reduzent commented 2 years ago

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.