Global speed slider

I’m a little mixed on the merit of this.

Would a “Global speed” slider be a good thing?

It might break some things that trusted the definition of the timebase in time() and delta; For example, all LED clocks and timers are off, and patterns could cross the flicker fusion threshold (intentional flicker eliminated, or new unwanted flicker introduced).

I’ve never had a use case before now, which is that I like the default patterns, but want to slow them all down in the sequencer / playlist (to avoid being the really annoying neighbor). It worked fine to paste in a slider and / speed into every pattern on my first PB; Eventually I’m going to have six of them with Firestorm and it’d be handy to just change six “Global speed” settings instead of copy-pasting ~120 blocks of slider code and setting them all.

:thinking:

2 Likes

It’s an interesting thought, for sure. Like you, I’m a little hesitant to break the established timebase. I’ve been doing the same thing though, slowing down the default patterns for outdoor use.

Maybe a useGlobalSpeed() or globalSpeedSubscribe() api that switches base timers, that new patterns would be strongly encouraged to call, but that wouldn’t break older code?

1 Like

I think the global variable “need” is a ‘delay’ variable (0…1) still, and it shouldn’t affect ANY time otherwise. It would be a global like pixelcount, and if you used it in your pattern, you’d be affected by it. Maybe it goes into the UI next to brightness?

2 Likes

I like the idea of a global slider/setting that a pattern is free to use. This would have to allow for slower and faster settings.

I have also experimented with giving adjusted input to time() and delta. In general this works well to slow time, but breaks sync unless every controller has the same time scale. One way I could solve this is to send the timescale as well, overriding settings on synched controllers.

Time() is unique in that it can run backwards! It would be cool to make a time scrubber. Especially for a fancy sequence editor.

The POV experiments made me realize that there’s a need for a sub-ms scale time() like function as well, though sync at that level would be a challenge.

Having an API to mess with time would be cool as well, so that the animation speed could be reactive to some input like an accelerometer/gyro on a spinning poi/staff.

Ideally this would be glitch free, but that requires state. The way time () works, passing in different inputs throws the phase off.

A new stateful API may be needed, where you create time source objects and configure them. They could keep track of phase internally and adjust for speed settings while still syncing in a network unlike the ones made with delta.

5 Likes

+1 for looking at this to see if there’s a way to solve it with a reasonably simple API. (Maybe a checkbox “Use variable time base” in the pattern editor, checked by default?)

Last night, I too had the opportunity to spend an evening in the yard with laptop and freezing fingers trying out all my patterns on the approx. 70 foot strip with pixels spaced about 7 inches apart.

Jeff is right – you have to adjust almost everything for this kind of display. It’s a lot of space, and not very many pixels, so many things run fast!

1 Like

found this with search, +1 for interest in the feature! Im already putting a global hue and global speed into all of my individual patterns but would be nice.

2 Likes

@jeff

I, too, am interested in being able to change pattern speed either globally or with specific code inserted in a pattern. Could you elaborate what you mean by pasting in a slider and ‘/ speed’ ? I’d also be interested in your ‘ +/- 120 blocks of code?

I’d love to have something more sophisticated
than what I do.

I create a variable ‘timefactor’ add use it as a coefficient to time() functions with usually acceptable results, but each program is different. I can make that variable into a slider now, so that’s a wonderful feature. But knowing what’s an appropriate range of value for ‘timefactor’ is a mystery to me. I try large numbers, small numbers with success, but sometimes I think it should just be a number between 0 and 1 because it wraps? I’m not much of a coder; to me it’s like throwing darts. But it keeps my almost 70 year old brain active and I sure have fun playing with PB.

Hi @booli - I eventually just ended up setting all patterns the way I wanted them across my 6 PB by editing each pattern’s code on each of the 6 PB. I’m going to answer your question assuming you are just asking how I like to do my speed parameters on a single Pixelblaze. For this example, let’s assume the pattern relies on two timers. Imagine you found this in a pattern:

function beforeRender(delta) {
  t1 = time(.1)
  t2 = time(.03)
}

The first thing I like to do (just a personal preference) is to re-express these constants in terms of a period, in other words, a number I know is the number of seconds it will take to repeat. I usually round it off.

function beforeRender(delta) {
  t1 = time(6.5 / 65.536) // t1 repeats every 6.5 seconds
  t2 = time(2 / 65.536) // t2 repeats every 2 seconds
}

Then I like to make a global variable called speed. To make the timers go faster when speed is increased, you need to take the period parameter in time and divide by speed.

var speed = 1
function beforeRender(delta) {
  // t1 repeats every 6.5 seconds, but if speed == 2, then 3.25 seconds.
  t1 = time(6.5 / 65.536 / speed)
  t2 = time(2 / 65.536 / speed)
}

This makes editing the speed of my patterns as easy as loading it and changing one number.

Sometimes I’ll define a UI slider that helps me play with different speeds. For example, if I wanted to let the slider go from quarter speed to 4X speed:

var speed = 1
export function sliderSpeed(_v) {
  speed = .25 + 3.75 * _v)
  // When slider is full left, _v == 0, speed is .25. 
  // When slider is full right, _v == 1, speed is 4.
}

function beforeRender(delta) {
  // t1 repeats every 6.5 seconds, but if speed == 2, then 3.25 seconds.
  t1 = time(6.5 / 65.536 / speed)
  t2 = time(2 / 65.536 / speed)
}

If a pattern also uses delta (the number of milliseconds elapsed since the last time beforeRender() was called), you can scale that by speed as well. One way is to just overwrite the local variable delta inside beforeRender():

var speed = 1
function beforeRender(delta) {
  // t1 repeats every 6.5 seconds, but if speed == 2, then 3.25 seconds.
  t1 = time(6.5 / 65.536 / speed)
  t2 = time(2 / 65.536 / speed)
  delta = delta / speed
  // <other stuff that uses delta here>
}

And to get really fancy, if you are up for the challenge of writing code outside Pixelblaze to send websockets messages to your PB programmatically, you can put an export in front of var speed = 1, and set your speed variable from some other computer. This would be a path to simplify all patterns or sync speeds across multiple Pixelblazes.

2 Likes

We need a best practices thread for gems like the above write-up.

3 Likes

@jeff Awesome answer. Very clear and it really shows me a better way to accomplish what I want. Thanks for taking the time to lay it out so clearly step by step.

Web sockets are beyond me for now, but it’s interesting to know that’s possible.

If you have a small server, like a Raspberry Pi, you can set up a web sockets interface easily.

My MQTT to Pixelblaze python library is intended for exactly this scenario.

The example auto_pixelblaze.py will automatically discover all pixelblaze’s on your network, and connect them via websockets to an MQTT server (which can be running on the Pi also).

Mosquitto is the most common MQTT server for a Pi. Assuming you have installed Mosquitto, and my python library, you run:

auto_pixelblaze.py -b localhost

Then to set the global speed the command would be

mosquitto_pub -t /pixelblaze/command/all -m speed=2

This would set the speed variable on all your pixelblaze’s to 2 simultaneously.

You can actually send this command from anywhere on your network (that’s why its called an MQTT server). Lots of home automation software have MQTT support built in.

You can set any variable or slider control this way. There are lots of other commands though, you can switch the current pattern, change brightness, and so on.

1 Like