How to code Axoloti objects


#23

sure :smile: 100% for internal editing. But as long as we have the option to edit in external way, it is fine with me. I can live with that :smile:


#24

I agree. Since i discovered the build-in editor - the xml / c-code mix makes much more sense. And the sha key get updated on every save witch is very convenient and ... . Its just not so easy to let go of my beloved xcode editor.


#25

Yep. Works fine now.


#26

Some more questions about coding a axo.

  • What kind of inlets do we have?
  • What is there value range?
  • What is a bool32?
  • How often is a bool32.rising inlet called? 3kHz?
  • Does the BUFSIZE change or is it fixed?
  • Can i use control-rate and sample-rate code at the same time and access the same local data?
  • Why is a bool32.rising inlet displayed as int32_t in the code-editor?
  • Is it possible to debug my code?

    <inlets>
    <bool32.rising name="t" description="trigger"/>
    </inlets>

Custom Object Baby Steps
#27

Have you read this?


#28

Yellow = boolean at k-rate
Blue = fractional at k-rate
Green = integer at k-rate
Red = fractional at s-rate

The rising/positive/bipolar are only annotations to the inlet/outlets, and do not enforce anything.

fractional : -0x08000000 to 0x07FFFFFF corresponds to -64.0 .. 64.0

k-rate, yes

It's currently fixed in axoloti_defines.h at 16 samples.
Using different buffersizes is future work.

yes. Sample-rate code is just wrapped in a loop after control-rate code.

Where in the code editor?

For firmware development I use an STLink-V2 (hardware). Then you can use OpenOCD/GDB eventually integrated in Eclipse...

For "functional debugging", you can use
void LogTextMessage(const char* format, ...);
but printing text at k-rate or s-rate will trip the watchdog and cause a processor reset.
Often I add outlets during development and watch data with disp/hex or scope....


#29

Yes. And it is a great start. But after reading it i had more questions on my mind. :smile:
Some concepts are hard to understand coming from a straight c / objective-c dsp world.

For example. If i define a inlet as bool32 and process its value at k-rate how is the bool32 value computed? Is there a main loop which averages & evaluates 16 samples and returns a 0 || 1 and than calls my k-rate code?


#30

s-rate?

Ok. I thought 'rising' would imply some sort of a simple transient check

Cool. That's what i need.

object-editor -> inlets -> type

Didn't think of that. Simple but elegant.


#31

Sorry I wish I could help you.I have no coding experience at all and I am not that techical. Except for the few new versions of objects i made for Axoloti by copy paste :smile: But would really like to learn more about it.


#32

sorry, yes, s-rate

future work, transient checking is currently a responsibility of the object.

booleans are indeed exposed to the object code with int32_t type.


#33

Some questions about the axo files.

Why can't params have a description like outlets?

<params>
    <int32 name="slice" description="slice me up">
    <MinValue i="1"/>
    <MaxValue i="8"/>
    </int32>
</params>

I get compiler errors if i try to uses it


#34

@johannes Thanks a lot. Description on params works fine now. (git pull & build)


#35

i just managed to duplicate/alter an object (or 2) with Xcode under osx and get it to pass the startup by manually changing the UUID and SHA values. The Axoloti software then tells you what the correct SHA etc. should be. By editing them 1 by 1 i got it to pass :smile:

no more red lines and my first object: "or 3"

or 3.axo (826 Bytes)


#36

Some more questions regarding float values.

I have a custom axo and i want to display its float output via a display object

<outlets>
    <frac32.positive name="bpm" description="bpm"/>
</outlets>

I could not find a display/f object so i though i write one. But there seems be be no frac32.label (the equivalent to a int32.label) to write to.

<displays>
    <frac32.label name="v" noLabel="true"/>
</displays>

The question is
* how can i display fractional number?
* how does the display magic of the LFO object work where you can click on its value and the output format changes? eg. factor, hz, ms, bpm?


#37

The disp/dial object shows the numeric value too. It also promotes the interpretation of a bounded range.
In dsp computation on the target processor, Axoloti avoids the use natural units like Hz, bpm, seconds... frequency as fraction of sample rate is a more relevant representation of frequency than Hz. Dividing by sample rate is inefficient, while a multiply is a single instruction cycle, division consumes many cycles. It is the GUI that shows the interpretation in natural units.
I think for bpm, the representation should be fraction of k-rate.
Similar to an analog modular system, control voltages are "voltage", sometimes calibrated to 1V/octave, and always bounded to the power supply voltage. If Axoloti would be an analog modular, it had a symmetrical 64 volt power supply and 1V/semitone calibration for pitch.
There is only display object currently that displays units other than "volt" (well, unitless), that is disp/note. So far there are no specific subtypes of frac32 outlets that hint what scaling is implied, so a connected disp/* could annotate the values with real-world units. This is not so difficult if the subtyped outlet connects directly to a disp/* object but gets hard when there are other objects in between, for example a multiplexer. Enforcing all inlets of a multiplexer to have the same subtype would make it inconveniently strict.
Compared to the Nord G2, well there are no disp/*-style objects at all there except tiny vu-meters in some objects.
The parameter/unit magic is in the java code - and needs a cleanup...


#38

I am sorry but I've read the answer above a few times now and i still don't get it. Maybe it helps if i break it down into it's parts.

ok. but i don't want to show a dial with a bounded range

ok. thats reasonable

It really depends on the receiver or point of view. In a musical context Hz makes more sense.

definitely yes. agree

So are you saying that instead of using a BPM output it's better to use a units-less "number of frames at k-rate" output and then use a dedicated display object to show the value in different units?

But what if i don't want to display the value but use it in a musical context like "play a sound file if bpm > 120". This is a rather unlikely event but still nice to have. Similar to a logic/counter object but with a time reference.

ok

Is it because you think we don't need this kind of object or because it is just not written jet and it would be a good addition?

I am not sure if i understand this one at all. Are you saying that to fully support this kind of subtyped outlet every stage of the chain has to forward the incoming subtype?

Thank you for your patience. :blush:


#39

It is currently not implemented. Not very difficult but I'd like to bundle this effort when developing custom object layouts.

Or semitones, or musical note...

That 'd quantize tempo to 0.333 milisecond intervals.
Phase increment per k-rate interval avoids that. Similar like the frequency parameter of "osc/sine lin", the maximum range 'd be nyquist frequency but at k-rate.

So if "subtypes" 'd be propagated though wires, a "math/>" object would need to propagate the subtype connected to one inlet to another inlet, and then propagate the subtype to a control dial connected. This example shows the complications of propagating subtypes.

But currently there are no such subtypes. To do your example - comparing bpm values - with the current infrastructure, one can search for the "voltage" corresponding to 120bpm on a linear k-rate frequency parameter, and adjust a unitless control to that voltage.

Propagating subtypes would seem practical in some scenario's, for example connecting a control dial to a pitch input could show semitones etc. Propagating through objects like math/+ makes my mind explode. A demux object could cause the propagated unit to change during runtime depending on the outlet selected. Math/> could propagate subtype from one inlet to another inlet. All these complications 'd make it rather non-intuitive.


#40

I'm trying to adapt code produced by the Faust compiler and embed it in Axoloti objects. I succeeded in porting karplus.dsp from the Faust examples, but only after writing a floatToFrac32 function to convert between floats generated by Faust and the numeric format Axoloti expects.

I see that CMSIS already contains a similar function arm_float_to_q31, which might be used instead of my custom code. When I reference it in an object, though, and try to compile the patch I get this error:

INFO: xpatch.cpp:(.text+0x4d8): undefined reference to `arm_float_to_q31'

How do I make my patch link against CMSIS?


#41

the other CMSIS functions are compiled into the firmware... so I suspect that is the best place for it.

you will find them in the makefile
firmware/Makefile

so you could add to that....

@johannes , what do you think add it to general firmware? sounds like it would be generally useful.


#42

Hmm the CMSIS BasicMathFunctions look like they benefit a lot from function inlining, adding them to firmware destroys their performance for short vectors. I expect better performance by not using these functions than linking to them in firmware.
Great to hear you're working on faust-to-axoloti-objects!