Name Mapping System
In the previous chapter, we’ve seen that we can have a Faust primitive with a label, and use
the same label as a control name in erbui
to make the mapping.
This is convenient as long as your process
only references local labels in the file.
But this falls short in a certain number of cases, but don’t worry! Every cases are handled
with an uniform simple approach.
First, we might use an audio object from an imported module, which would have for
example a hslider
with the same label freq
. How do we disambiguate which is which?
This is explained below in Address binding.
Second, you might use an audio object that exports a lot of different labels. For example
you might use dm.phaser2_demo
. This one has 3 checkbox
and 8 hslider
!
With the small space on your module, you will need to make some choices, and for
example decide that the Phaser Output Level
should be always 0.5.
If the default value for this primitive is not 0.5, we need a way to set this value.
How do we assign custom default values to a Faust primitive?
This is explained below in Custom value initialization.
Finally, all primitives in Faust are scalar values. On the other hand, some Eurorack-blocks
controls represent a compound type with more than one property, that is, it can hold more than
one scalar value. The dichromatic LED LedBi
is an example of it: it has the properties r
and
g
, which represents respectively the intensity of the red and green emitted color.
How do we map a Faust label to a property inside of a control?
This is explained below in Compound property binding.
Address binding
Let’s take dm.phaser2_demo
to understand a bit more how name mapping works.
Make a new Phaser Faust project using erbb init --name Phaser --language faust
and change the dsp file like the following:
// Phaser.dsp
import("stdfaust.lib");
process = dm.phaser2_demo;
If you build the project now, the erbui
transpiler will complain that you have the wrong
number of audio inputs and outputs.
This is because dm.phaser2_demo
is a stereo effect and erbb init
generated
by default a mono input/output effect.
Let’s first fix this quickly by adding one more audio input and output at the end of our erbui
file, and rearranging the layout of those audio jack connectors:
// Phaser.erbui
module Phaser {
width 12hp
board kivu12
material aluminum
header { label "Phaser" }
control audio_in AudioIn {
position 4hp, 96mm
label "IN L"
}
control audio_in2 AudioIn {
position 8hp, 96mm
label "IN R"
}
control audio_out AudioOut {
position 4hp, 111mm
label "OUT L"
}
control audio_out2 AudioOut {
position 8hp, 111mm
label "OUT R"
}
Now, let’s build the project. If you go to your IDE build logs, you will see the following:
warning: non mapped checkbox /PHASER2/0x00/Bypass
warning: non mapped checkbox /PHASER2/0x00/Invert Internal Phaser Sum
warning: non mapped checkbox /PHASER2/0x00/Vibrato Mode
warning: non mapped hslider /PHASER2/0x00/Speed
warning: non mapped hslider /PHASER2/0x00/Notch Depth (Intensity)
warning: non mapped hslider /PHASER2/0x00/Feedback Gain
warning: non mapped hslider /PHASER2/0x00/Notch width
warning: non mapped hslider /PHASER2/0x00/Min Notch1 Freq
warning: non mapped hslider /PHASER2/0x00/Max Notch1 Freq
warning: non mapped hslider /PHASER2/0x00/Notch Freq Ratio: NotchFreq(n+1)/NotchFreq(n)
warning: non mapped hslider /PHASER2/0x00/Phaser Output Level
Note
If your IDE doesn’t show message logs or accessing them is not convenient,
just can also build with erbb build simulator
instead from your terminal.
They represent the list of all values in Faust that do not have a mapping in erbui
.
/PHASER2/0x00/Bypass
represents an address in Faust,
which can be used with OSC for example.
Let’s say we want to bind the Phaser speed to a control in erbui
.
You do this by adding a Faust binding, using its Faust address:
control speed Pot {
faust { bind { address "/PHASER2/0x00/Speed" } }
position 6hp, 34mm
style rogan, 6ps
label "FREQ"
}
You can now build again the project, and you will see that the warning for the phaser speed has disappeared. Those warnings are handy, because you get to see what is mapped or not.
But wait! In our first example, Your First Module with Faust, we didn’t use any of this Faust address binding.
How could this possibly work?
This is the “syntactic sugar” we were talking about in the previous chapter:
when you don’t declare a binding, Eurorack-blocks will synthetize one for you.
It created implicitely a line like the following, which happens to match the
Faust generated freq
primitive address, as long as the label is local to the Faust dsp file.
control freq Pot {
faust { bind { address "/LowPass/freq" } } // synthetized
}
Custom value initialization
We can go on and map all the primitives we want in Faust with a control in erbui
.
But now we might come to the point where either we don’t have enough space in our
Eurorack module to put another control,
or better, if we planned our design rigorously, that we want to map
only a subset of the Faust primitives to physical Eurorack controls.
Inside an imported Faust library, we might have source code like the following:
fc = hslider("freq", 1000, 100, 10000, 1);
So that means that the default value for this Faust primitive, if we don’t bind it, would be 1000Hz. Now let’s say that we want it to be 80Hz by default. We can do this by specifying a Faust initial value for the address of this primitive. How can we do this? With our Phaser module example, let’s say we want to set the default value of “Phaser Min Notch1 Freq” to 80Hz:
// Phaser.erbui
module Phaser {
width 12hp
board kivu12
material aluminum
header { label "Phaser" }
faust {
init { address "/PHASER2/0x00/Min Notch1 Freq" value 80 }
}
control speed Pot {
faust { bind { address "/PHASER2/0x00/Speed" } }
position 6hp, 34mm
style rogan, 6ps
label "FREQ"
}
Note that this definition is done at module
scope.
You can now build the project again, and you will see that the warning for
“Phaser Min Notch1 Freq” has disappeared.
Those warnings are helpful, because they allow you to go systematically through every Faust primitives: you either bind them or give them an initial value explicitly. Should the default value of the imported library be at the correct value already, you can just use the “init” value of the primitive in the library to make the warning go away.
Compound property binding
As we said in the introduction, all Faust primitives represent scalar values.
But at the same time, some erbui
controls can have more than one property!
How can we map that?
For this, we just need to specify the property
in our binding.
Let’s say that we have 2 vbargraph
with label “LED Red” and “LED Green”.
We just need to specify a specific property in our binding:
control led_bi LedBi {
faust {
bind { property r address "/Phaser/LED Red" }
bind { property g address "/Phaser/LED Green" }
}
position 10hp, 80mm
label "LED"
}
Just for the sake of completion (most likely you will never need to use that),
this works with init
too!
Let’s say that you would want to give a specific value to a property.
You can use the same init
syntax we used at module scope,
but inside the control rather than the module:
control led_bi LedBi {
faust {
bind { property r address "/Phaser/LED Red" }
init { property g value 0.5 }
}
position 10hp, 80mm
label "LED"
}
That’s it! This chapter cover most of your needs when using Faust with Eurorack-blocks.