The original source code is from http://dood.al/pinktrombone/
Port for Bela: written in C++, plugged into the simple Bela API.
Compile and run
You need the
dev-libbela branch of the Bela repo in
If the board is connected to the internet, this should get you sorted, otherwise use your imagination to get the correct repos and branches on the board.
git clone firstname.lastname@example.org:giuliomoro/pink-trombone.git /root/pink-trombone cd /root/pink-trombone git checkout bela git clone email@example.com:BelaPlatform/Bela.git /root/Bela cd /root/Bela git checkout dev-libbela # Apply a patch that will give you some more CPU patch core/PRU.cpp < /root/pink-trombone/PRU.cpp.patch make coreclean # Build libbela in /root/Bela/lib make lib # Tell the dynamic loader about libbela ldconfig /root/Bela/lib
cd /root/pink-trombone make
This is not a good example of C++ code.
Once this was done and the thing was basically running, I had to understand more about the code in order to be able to use it. See if you can make any sense of the comments at the top of
The most often applied change was
Math namespace which implements the required
Math functions. Replacing these with the equivalents from
math_neon could improve the performance perhaps?
All the methods and properties are
Final result is pretty crappy looking but it works.
I keep everything in
trombone.cpp because I could not be bothered factoring out the
class declarations (and also because some methods are called multiple times per sample, so they benefit from inlining), though this makes the compile a bit slower than I'd wish for.
The Cortex-A8 on Bela does not really like
double operations, so I also
typedef float sample_t and casted all the relevant numeric constants to
This could have been done by using the
-fsingle-precision-constant compiler options, but it is only supported by
gcc, while I used
clang because it gives better performance.
As I understand it, you have these controls on the model:
Tract. This is represented as an array of 44 values ("
index"). Typical values are between 0 and 2.
- the openness of the
- the pitch of the
Glottis(the x-axis in the "voicebox" in the GUI)
Glottis(the y-axis in the "voicebox" in the GUI). This also affects the
- transients are generated when the diameter at one
indexused to be 0 and becomes > 0, basically when an obstruction of the tract is removed. This happens automatically as you change the
diametervalues, but you could also add them manually with
- the amount of
turbulencedue to reduced
Most of these (except the
turbulence) can be safely updated manually (see example in the
Alternatively, you can fake touches, this includes generic touches (anywhere in the Tract) and
tongueTouch: the one touch that controls the position of the tongue (the circle in the GUI).
After you add a touch you need to call
TractUI->handleTouches() for it to be handled.
I did not implement
Glottis::handleTouches(), it is easier to just set the
The trick with touches at the moment is that it is not easy to place them in the righ place. I ended up printing touch coordinates from the GUI and then hard-code them in the code.
The good thing about touches is that they take care of the
turbulence parameter, which is not achieved otherwise (I mean I tried to implement it (see "attempt to compensate for touch.fricative_intensity when setting" in the code), but it's too CPU intensive).
More stuff is in the comments at the top of the file, everything is in the code.