https://svn.code.sf.net/p/pure-data/svn/trunk/externals/template seems to be gone :/ has anyone made a backup?
Compiling puredata externals
- Edited
I guess this should help
https://github.com/pure-data/helloworld
when building on Bela you will want to use at least
make PDINCLUDEDIR=/usr/local/include/libpd/
or
make PD_INCLUDE=/usr/local/include/libpd/
(or something similar, it really depends on your Makefile
).
so that it can find m_pd.h
in /usr/local/include/libpd/
.
Hello,
I think I have similar problem.
I've uploaded and successfully compiled zexy on bella.
Then I moved the compiled external to ~/Bela/projects/pd-externals/ , but my patch located on ~/Bela/projects/Bela-pd does not recognize zexy.
I've tried also to put it into my patch folder, recompile all by doing ./bela-update which resets all and checked for libpd_add_to_search_path("../pd-externals"); in core/default_libpd_render.cpp.
Still the problem exists.
My board is up to date using master-dev branch.
Please help.
how are you importing your zexy
library?
also, do you want to send me your .pd_linux
binary so I can test in on my side?
giuliomoro Maybe that's the missing point as I expected external is being imported automagically as the path is given in core/default_libpd_render.cpp If it comes to usage of it, I am just trying to use datetime objects of zexy. Will send you all the files this afternoon.
- Edited
libpd
will look in pd-externals
for files with the same name as the object you are creating when you try to load an external. As I understand it, zexy
comes as a single-file library, so that, e.g.: there is no date.pd_linux
file in pd-externals
. For this reason, when you try to create the [date]
object, it fails.
There is one way of importing libraries that will work with both Pd and libpd
: create in your patch an object with the name of the library, e.g.: [zexy]
(note: this must be created in your patch before any other object, as the order of creation matters). Then you will be able to create, e.g.: [date]
.
Pd on your computer allows one additional way of doing it: you can go to preferences->startup and preload some libraries (e.g.: zexy
).
On libpd
(on Bela and elsewhere) you can import libraries by manually calling their ..._setup()
function. This involves something like this in the render
file:
NOTE: broken code do not use (see comment below)
// forward declare external setup functions
void zexy_setup();
bool setup(BelaContext* context, void* args) {
.....
// init libpd
libpd_init();
// load libs
zexy_setup();
....
}
Again, you could simply create a [zexy]
object and forget about changing the C++ source code. Yet, if you want to do that , you have a couple of options to apply these changes:
- you could edit the
core/default_libpd_render.cpp
file (not through the Bela IDE). This change is global for all your libpd projects, but when you update the board, these changes will be lost. - you could copy that file to your project's folder and apply the edits on such copy, so the file becomes part of your project and is resilient to changes in the core code. You will then have to do this for each individual project.
More documentation on libpd
and external libraries is here. Note that you don't need the part about "Adding external source files" if you already compiled the library as an external.
giuliomoro Okay,
First of all thanks for your help! After your post I am starting to catch it up. I did a test: created a new patch with zexy and date objects. It came up with zexy message in terminal so it is loaded Now I need to reorder stuff in my patch so zexy will be first one.
I was not aware of how it works. I'll also try your second idea with editing cpp file.
Will post my findings.
Thanks! It's time to get a good filter in my patch...
An easy way to make [zexy]
the first object in the patch is to cut everything else, create [zexy]
and then paste. This way the other objects will come after [zexy]
.
giuliomoro This is exactly what I did. Thanks.
I haven't yet had much luck with calling zexy setup in cpp, but I'll try to work it out.
Anyway the trick with adding zexy as the first element is something I prefer as this way I am able to call it only inside patches that really need that.
Thanks a lot again.
giuliomoro On libpd (on Bela and elsewhere) you can import libraries by manually calling their ..._setup() function. This involves something like this in the render file:
In hindsight, this would not work: the linker will detect that you are declaring and trying to use a symbol that is undefined at link time. So that may work if you are linking those files(e.g.: the zexy .o
files) in your project, but not if you are dynamically loading them as you do with externals.
Im looking to create some pure data externals for bela...
(Ive created max externals before so hopefully not too painful )
anyway, Im seeing that there seem to be multiple template projects for building, these seems to be:
- Makefile supplied with the pure data install (doc/6.externals/Makefile)
- svn Makefile template ( https://svn.code.sf.net/p/pure-data/svn/trunk/externals/template )
- pd-lib-builder (https://github.com/pure-data/pd-lib-builder) , as used by https://github.com/pure-data/helloworld
pd-lib-builder seems to be the latest, and used by a few projects? is this the one to go for?
what Id like is to base my projects on the most supported, and in particular cross-platform e.g. bela (arm), windows, mac, linux (32/64 bit x86)
thoughts?
- Edited
also this one http://puredata.info/docs/developer/Libdir, if it is not included in the above list?
No particular preference myself, the few externals I built (mrpeach, zexy, abl_link~) just seemed to work out of the box with their makefiles on Bela, as long as I could figure out what the right parameter for make
was (e.g.: PDINCLUDEDIR=/usr/local/include/libpd/
vs PD_INCLUDE=/usr/local/include/libpd/
). Oh I also compiled all the externals that come with Pd-l2ork
, so perhaps have a look at how those are handled.
giuliomoro
for now Ive gone with pd-lib-builder, seems to have most targets (e.g. iOS) and works well enough.
saying that, Im sure I could easily move to others if required.
got an external building on macOS, now off to test it with PD on bela
make sure you specify some Cortex-A8 specific optimizations, such as:
O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon -ftree-vectorize
and - if you use gcc
- : --fast-math
- Edited
ok, I have this now working nicely with pd-lib-builder...
it already has detection for RPI2 etc, so basically all I need to do was detect it was 'bela', the best i could think of was to look at release. so here are the simple changes I made... (diff , so + means added line)
giuliomoro , do you think there is a better way to detect bela?
Ive created a fork of pd-lib-builder, if we have an agreed approach then I can issue a PR to add bela as a target
changes made to pd-lib-builder
pd-lib-builder/Makefile.pdlibbuilder
# Beagle, Udoo, RPi2 etc.
ifeq ($(machine), armv7l)
+release := $(shell uname -r)
+ifeq (`$(findstring $`(release), 3.8.13xenomai-bone41), $(release))
+ $(info bela build)
+ arch.c.flags = -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon -ftree-vectorize --fast-math
+else
arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard
endif
+endif
then you can compile with this, to build and install it into the correct place for bela to pick it up.
make PDINCLUDEDIR=/usr/local/include/libpd/ PDLIBDIR=~/Bela/projects/pd-externals install
BTW... ive just noticed... if I'm powered off USB (connected to computer etc) its extremely noisy (unbearable), yet perfectly ok, if its power via 5v jack, normal?
Side note: not quite sure what the best approach for building externals for windows is...pd_lib_builder (& others) seem to use MinGW, which whilst they work, appear to mean you need to have MinGW installed/setup to use the external... since the generated dll is dependent on it. not really an issue for me, not really a big windows user
- Edited
thetechnobear giuliomoro , do you think there is a better way to detect bela?
Not sure.
Truth is, there is nothing special about Bela in the way you build externals (except if you want to use POSIX wrappers for Xenomai, but that is a different story), so the compiler flags I suggested above are good for any Cortex-A8. In fact, the Pi2 has 4 Cortex-A8 cores, so the same flags should work fine for it as well.
Perhaps try to grep /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 2 (v7l)
BogoMIPS : 993.47
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x3
CPU part : 0xc08
CPU revision : 2
Hardware : Generic AM33XX (Flattened Device Tree)
Revision : 0000
Serial : 0000000000000000
If you find things like neon
in there, this will be good indicators that you would need -mfpu=neon
, and probably --fast-math
. Note: using -mfpu=neon
is needed to actually use the Neon fpu because otherwise the compiler would tend to use the vfpv3
, for most stuff, as the latter is IEEE754-compliant, while Neon is not. But we tend not to care about denormals and/or signed NANs when doing audio, so we are happy with the faster, non-compliant Neon. Similarly. -ffast-math
tells the compiler to feel free to use non-compliant unit and operation re-ordering. Note: I just found out that -ffast-math
is actually supported by clang
. I guess--fast-math
, which I was using earlier, was just a legacy gcc
option? Bottom line: you can use -ffast-math
regardless of the compiler.
However, grep
ping for neon
is not enough for -mtune=cortex-a8
. In practice, I am not even sure -mtune=cortex-a8
is needed when compiling natively. You can check running gcc
with --verbose
without -mtune
if -mtune=cortex-a8
is implied. If that is implied, it would also be interesting to see how gcc
detects that.
-ftree-vectorize
is good for any architecture which has a SIMD unit (that is: probably all architectures that you would build Pd externals for, these days). It does not seem to be implied by -O3
, but also I do not understand the difference between this and -free-loop-vectorize
. More here.
-mfloat=hard
is system dependent but I am not sure how you would detect it. Again, probably the presence of neon
or vfp
would make you think that there is a floating point unit and that -mfloat=hard
, because it would be silly - and slower - to run soft-float. Again, this can probably be omitted when compiling natively, and again you can check with --verbose
.
Last, if from cpuinfo
you get
Hardware : Generic AM33XX (Flattened Device Tree)
there is a pretty good chance you are on a BeagleBone, and if you get that, plus something from uname -a | grep -i xeno
, then you most likely are on Bela.
Forgot to mention:
sometimes a great performance booster on the Cortex A8 can be achieved using single precision constants. This is because expressions like
float b = 1;
float a = 0.5 * b;
the second line will do something along the lines of:
- notice that
0.5
is adouble
constant - extend
b
to adouble
and to a full 64-bit precisiondouble
multiplication - narrow down the result to a
float
and store it intoa
double
operation on the A8 are supported only on the vfp
, therefore the multiplication above would never run on the Neon unit.
If you write the code, you could fix it by adding an f
to the floating point constant:
float b = 1;
float a = 0.5f * b;
or type-casting the constant it or assigning it to a variable before using it (best is to type cast to something like sample_t
which is also appropriately typedef
ined elsewhere in the code.
Instead of changing the source code, a low-hanging fruit is the solution of telling gcc
: -fsingle-precision-constant
(unsupported by clang
). However, this may lead to potential precision issues where the programmer actually wanted to store a double
precision constant, as it would turn ALL floating point constants to single-precision (including those assigned to a double
variable). Therefore, the program
#include <stdio.h>
void main(void)
{
float a = 99.99999999;
double b = 99.9999999;
printf("a: %.20f,\nb: %.20f\n", a, b);
}
would produce:
without -fsingle-precision-constant
a: 100.00000000000000000000,
b: 99.99999990000000593682
with -fsingle-precision-constant
a: 100.00000000000000000000,
b: 100.00000000000000000000
Whether this is a problem or not, is very much dependent on the codebase, so I would advise against adding it to the compiler flags by default.
Hi All,
Novice questions. Even reading this thread I am unsure about what is going on.
So some quick questions -
1/ I have been to patch storage and I would like to use The Soundhack plugins on my Bela. Is this possible? I see source code is provided
2/ I see some of them are compiled for Organelle does that mean they can be put on Bela? Moreover can Organelle patches be used on Bela?
3/If all that is possible where do I start learning about compiling patches on Bela, that will explain what is going on.
I know I am trying to run before I can walk but the Organelle folks have it great and I want some of the fun and make my own interface!!
Thanks for your time.
Best
S
- Edited
I am not sure what architecture the Organelle runs on. Is it x86 or ARM?
If it's ARM, then possibly Pd externals compiled for it may run on Bela, as long as they have been compiled against the same version of PureData.
In practice, I would suggest you compile your own. It is normally straightforward, but it could be painful.
Most externals come with a Makefile
or any other script to build them. If you are lucky they will also have some documentation. You would normally:
- copy the folder to Bela
- have a look at the
Makefile
. There should be a variable called something likePDINCLUDEDIR
orPD_INCLUDE
(see examples above). When you invokemake
you need to define that variable on the command line so that it points to the folder where the libpd headers are. In the case of Bela, this is/usr/local/include/libpd/
. - from a terminal,
cd
into the folder and type something likemake PDINCLUDEDIR=/usr/local/include/libpd/
(or replacePDINCLUDEDIR
with the appropriate variable requested by yourMakefile
. - hopefully this will work and you will get a file called
externalaname.pd_linux
. If you do, then copy that over to/root/Bela/projects/pd-externals/
and you can then start using it in your patches. - if the
make
fails, that will commonly be because of a missing dependency. The documentation that comes with the external should be able to get you through the dependencies, so try to fix that, rinse and repeat
If you find any issues with the above, let us know and we can probably get you through if you are stuck. Also, the examples above in this page should help you.
Regarding Organelle patches being used on Bela, that really depends on how they are written. I have seen they have some way to access their buttons and pots which is different from ours, so you may have to edit them to be able to control them from Bela.
However, as long as you have the needed externals, they should work, provided you do the above changes for controlling them.