Input needed: functions wishlist

Thing that I found is that you can’t call a function before it’s been defined (no forward declarations).

Also once everything is loaded, the loading mechanism then calls all the slider functions to set them to the preset values, so if you call a function in a slider definition, the initial code runs, then the functions defined in slider functions run - all of them but I don’t know in what order.

But you’re right, you don’t need a setup() function.

Don’t forget that a slider only loads the previous value IF it’s been saved by running previously. On first run, the slider won’t do that.

@wizard , I know it’s on the bottom of the editing page on the PB, but could you update the website expression page?

Pixelblaze Expression Docs — Ben Hencke is still lacking all of v3 changes like array functions, and so on.

I find myself using that page more often when I’m online as it’s handy.

@Scruffynerf
Thanks for the heads up. I had forgot that was there! I’ve updated the page with links to the GitHub source docs.

I think Smooth Speed Slider is a good candidate for a built-in function. Many PBers will encounter the problem early, and be confused at first. The subtlety of the smooth solutions in that thread might be over the average head. I had pondered the ‘maintaining phase’ aspect but was glad to find it solved for me!

1 Like

@sorceror ,
Yes, that has been discussed before as well, and is on the list.

Goals:

  1. A global speed slider like brightness
  2. Changing speed without causing animation jumps
  3. Not breaking timesync across multiple PB - sync the global speed too.
  4. New stateful API, perhaps a timer object, to keep track of internal phase state.
  5. Both timer adjustable speed and global speed so you can add more speed sliders in addition to the global one to fine tune some particular aspect.

Not really a function, but … I was thinking that it would be neat if there was a way to retain values between pattern changes. So for example, to keep a time-slider-controlled wave smooth, or to set a “theme color” which applies to every pattern in a playlist.

Maybe something like:

 export persistent var foo;

which stores foo’s value in a metaglobal hash table when leaving a pattern, and restores it after the next pattern is compiled.

2 Likes

At first, I didn’t understand, I was like “but pattern vars do persist, if you leave and come back…”

but you meant a shared var for multiple patterns.

Yeah, that would be interesting, a ‘superglobal’.

Shared globals would be very useful, but shared functions would be far more useful still. I have lots of ideas for utility functions that could be reused across patterns, and currently the idea of having to cut and paste them (and then maintain all those copies) puts me off creating them. Perhaps a separate editor page that could contain code that is automatically included in every pattern would be an easy way to implement this? Though I can see that being problematic in some situations, e.g. for sharing patterns between users.

1 Like

An “include” would solve all of that… Including libraries, global stuff, etc.

include("coordinates")
include("myglobalslider")

2 Likes

Yes, “include” would be a great way to do that, but automagically persisting included values (e.g. of same-named sliders) between patterns might lead to unexpected results. I’d rather be intentional about that with a keyword or by storing such things in a global hash table.

“include” also puts more demands on the internal file system. I’m willing to forego installable libraries 'till we have a little more storage and CPU time for file I/O.

export persistent is an interesting idea. I’d like to have it as a feature.

It’s got a lot of potential implementation pitfalls though. How many variables should I be able to export? How do I handle namespace conflicts? Can I “export persistent” an allocated array? (probably not) If so, how large? How about a single variable containing a pointer? (No!) An array of pointers to functions? (NOOOOOO!!!)

1 Like

I don’t see why that’s true. If anything, having include would reduce pattern size, since redundant code would be included, instead of repeated in each pattern. Keeping in mind that PB uses byte code to store binary programs, even though it’s got an editor that allows easy on the fly editing, it’s really not using the text format except as human readable editing and recompiled.

In this case, include “pattern name” would essentially grab the code from that pattern as if it was typed directly. And treat it as if it was there.

Seems much simpler than worrying about the internal file system.

I think we have all voted for some sort of library function. I have a ton of boilerplate code that just gets pasted into every pattern, and whenever I update it, I have to copy and paste every pattern with the updated version…

I would like to vote for literal arrays. I still struggle not being able to create a look up table. For palettes, corrections, speed vs calculation etc.

2 Likes

Wow, this reply makes 60 comments on this thread and some of the above has been implemented.

Might be worth reviewing, and pulling out what’s done, and what could be done without adding it to the firmware first. (Mappixels being a good example, we’ve got code that can “fake it”, so maybe a working library example and then if it’s really useful, it can be done in firmware [and faster]? )

I’ll clean this up more, later… better posted now than not.
Code examples will be linked to originals, or other posts with better versions.
Will resort and organize more.

Summary of items above

key - 
x - now in 3.18 (if not before)
0 - not yet
code - can be done in code
? - not enough details to flesh out?
u - unknown
coming - mentioned as in development now
  • x - hypot(x,y) - sqrt(xx + yy)
  • x - hypot3(x, y, z) - sqrt(xx + yy + z*z)
  • x - trunc(n) - removes fractional components for positive or negative numbers. e.g.
  • x - frac(n) - just the fractional component, like n % 1. e.g. frac(5.5) == .5 frac(-5.5)
  • x - mod(a, b) a modulo b, AKA floored division 2.
    0 - friendly palettes
    ? - Probability stuff
    u - Sampling from arbitrary distributions via the inverse CDF process 1
    u - Bernoulli state machines normalized to delta (independent of frame rate) for better flickering than random()
    ? - real constants that don’t incur the speed penalty of accessing a variable.
    x - Arctan2
    coming - a way to access XY(Z) map coordinates outside of render2d(3d)
    coming? - a way to access non-normalized XYZ coordinates outside of render2d(3d)
    ? - The sound scaling/normalizing functions in some kind of reduced or simpler format

? - sound normalizing (perhaps on the sensor board itself).
? - has2DMap() - true/false
? - has3DMap() - true/false
? - pixelMapDimensions() returns 1, 2, or 3. Even if no map is installed, we’d assume the default pixel map of index/pixelCount.
coming - render should be passed x or I should add render1D(index, x). At some point I will add support for 1D pixel maps too, with a default pixel map where x will be index/pixelCount and would be very easy to upgrade existing patterns.
x - scaling in one or more dimensions
coming - Map walking functions.
This lets you walk through the pixel map outside of a render call and could be used to make a pattern 2D/3D aware yet still only export render or pre-process pixels.
mapPixels(fn) - walk through the pixels with pixel map coordinates. fn is invoked with 4 arguments: (index, x, y, z) though you can specify fewer. If no pixel map is installed, x will be the same as index/pixelCount, and y and z will be 0. For 2D pixel maps z would be 0.
map2DPixels(fn) - walk through the 2D pixel map, if installed (if not, nothing happens). fn is invoked with 3 arguments: (index, x, y).
map3DPixels(fn) - walk through the 3D pixel map, if installed (if not, nothing happens). fn is invoked with 4 arguments: (index, x, y, z).
x - Pixel Map Coordinate Transformation

? - clock functions need something for sub-seconds… if I could call a function like ClockSeconds for smaller values, like for milliseconds, that would be fine.
? - inter-device communication?
? - A real round function, preferably with the ability to limit precision.
? - A playback from memory. Something that will let me pre-calculate (long) patterns and play them back at rates limited only by the hardware.
? - Ability to add an external serial RAM/EPROM or SD for (long) pattern storage.
? - Quadrature Encoder read - the ability to use an encoder as an input device without having to bit-bang in the script. :wink:
x - various array functions
? - more info in websocket (like first pixel color)
? - universal/persistant speed slider
? - universal/persistant variables
? - include (for libraries, etc)
? - literal arrays

code - “Perceptual HSV”, phsv(h, s, v).

  // Perceptual HSV
  function phsv(h, s, v) {
    h = wave((h % 1 + (h < 0)) / 2 + .75)
    hsv(h, sqrt(s), v * v)
  }

code - Seedable deterministic PRNG.
(we have a few of these, I'll link later)

code - Parameterized noise generation

code - vectors (can be done with 2 element array)

? - A unit normal table (Z table). Math.js calls this norm(x).

code - A dimming function where every element in an array is reduced by some amount every time it is called

function fade(amount){
for(m=0;m<strlength;m++){
pixelsb[m]=pixelsb[m]-min(pixelsb[m],amount)
} }

? - allocate an image buffer that could be drawn into.
code - rendering functions that will draw 1D objects of a specific size, color, hue onto an array, like the following

function dots(increment){
increment=increment/100+maxFrequencyMagnitude*100
for(n=0;n<5;n++){
if(Radius[n]<1){
MaxSize[n]=clamp(random(5)+energyAverage*500,2,20)
Positions[n]=floor(random(strlength-MaxSize[n]*2-2)+MaxSize[n])
Radius[n]=1
Color[n]=loval+(maxFrequency)/100+random(0.2)
Expanding[n]=1

}
  if(Expanding[n]==1){
  Radius[n]+=increment
  if(Radius[n]>=MaxSize[n]){Expanding[n]=0;Radius[n]=MaxSize[n]}
}
else{Radius[n]-=increment}

for(i=0;i<Radius[n];i++){
  pixelsh[Positions[n]+i]=Color[n]+i/30
  pixelsb[Positions[n]+i]=(1-i/MaxSize[n])
  pixelsh[Positions[n]-i]=Color[n]+i/30
  pixelsb[Positions[n]-i]=(1-i/MaxSize[n])
}
fade(0.05)
}}

code - inoise1d(x), inoise2d(x,y), inoise3d(x,y,z)

code - beatsin/beatsin16

//       beatsin( BPM, low, high) returns an value that
//                    rises and falls in a sine wave, 'BPM' times per minute,
//                    between the values of 'low' and 'high'.
function beatsin(bpm, low, high) {
  return wave(time(0.91552734375/bpm)) * (high - low) + low
}

code - A “pixel morph” function that lets me specify a beginning value, ending value, and transition rate. Generates a smooth(ed) transition between the two values.

code - complex numbers

AS THIS SUMMARY IS UNSTABLE… PLEASE DON’T ADD MORE TO THIS THREAD, maybe it’s time for a new thread?

@Scruffynerf , awesome compilation!

I had started a new thread here at the end of April, but folks kept replying here. :man_shrugging:

Keep in mind some of those APIs are alternative design choices, and only one will be implemented. Thats why I went with a poll.

Time for a fresh start? I can archive both and make a new one.

FYI, markdown tables work:

Foo Bar Baz
data1 other stuff more things
:white_check_mark: emoji? :no_entry_sign:

I think having the giant thread summary is nice. Its good for discussion, though I’m not sure tracking current status long term would work well via forum. It’s good to get folks’ feedback and talk about choices/options, and the giant summary is sure to remind folks and bring up some more discussion.

1 Like

Yeah, you could lock both and I’ll post a full summary on the new one?

I have being using After Effects a lot lately and the wiggle function could be very useful here as well. It is a form of constrained random that takes 2 parameters. wiggle(,)

There maybe a way to do this now but an offset for the time/wave functions.

The others are having access to some of the variables in the web portal. I want to be able to read and write to the master brightness slider, and the time OFF/ time ON variables.

I love all the idea to have tweens built in this would be very useful.