Sapphire Zoo: a programmable chaotic oscillator

Recently I started a conversation here about chaotic oscillators. This got me inspired!

I have been sequestered in my code cave for the last couple of weeks working on a fun project that I’m now ready to reveal. I’m creating a programmable chaotic oscillator module called Sapphire Zoo. On the surface, Zoo looks a lot like my existing modules Frolic, Glee, and Lark.

But once you right-click on the panel, you will see a huge difference: the ability to enter your own velocity vector formulas to create an unlimited variety of chaotic attractors!

Here is a demo video:

Zoo is the final chaotic attractor module I will likely ever create for the Sapphire plugin, because it can by itself create an unlimited number of attractors, while Frolic, Glee, and Lark can each only calculate one attractor.

I have not yet submitted Zoo to VCV Rack for approval. I’m looking for testers willing to manually install and use a pre-release build. The current pre-release is here:

And here is the Sapphire Zoo documentation.

There are two main ways you can use Zoo:

  • Use the factory presets for the following attractors: Bouali, Halvorsen, Lorenz, and Rössler.
  • (Advanced) Find a formula from a website like this and program it yourself. You will definitely need to read and understand the documentation, plus it helps to have basic understanding of algebra.

You can even help me create factory presets for additional attractors! Upload them to this thread and if I like them, I will include them in the official release.

Let me know what you think, and have fun!

20 Likes

Love it! Looks like a winner!

I would like to start testing (playing with it), but I am swamped with a bunch of projects at the moment.

But I do have an idea.

Presets are nice, except they set all the parameters in addition to the formulas, and there is no CV control.

It would be nice to have knob and CV control over the current attractor formulas, as well as a display for the selected user defined name for the attractor. You could allow the user to specify a directory of attractors that the knob/CV would select from. The faceplate parameters would not change when selecting a new attractor. Presumably the formulas would be calibrated so that switching between attractors would yield relatively smooth transitions.

Perhaps create a formal “saved attractor” concept that is separate from presets. In the context menu you could allow the user to save and load attractors. A normal saved preset would include the selected attractor information.

It could be an expander - Zookeeper!

You could take it a step further and provide formula display/entry fields on the expander, as well as a save button. But I don’t think you would always want the formulas displayed.

I know docB already has a universal Preset expander module that gives CV control over any module’s presets. But Zookeeper would be more focused, and way more stylish I am sure!

1 Like

Wow, you really gave me a lot to think about. Thank you, Dave!

In particular, I already am sold on the idea of loading a preset without affecting the parameter knobs.

But CV control + smooth transitions… that is a really cool idea.

I love this name and this idea. The actual Zookeeper might end up being an updated version of Chaops:

There is some unused panel space, plus I wouldn’t mind making it a few HP wider. I already find the expander chain [Chaops, Zoo, Tricorder] to be essential for entering a new attractor formula. I use Chaops to freeze and reset Zoo. Then I can enter formulas peacefully without worrying about the simulation diverging to infinity.

When everything looks right, I unfreeze and verify correct behavior on Tricorder.

I set Zoo to max SPEED with Turbo Mode enabled. If things get out of control, freeze again and press the R (recall) button on Chaops to recover from NAN/infinity and start over.

So yes, I could add more functionality to Chaops for Zoo in particular, especially in the context menus.

2 Likes

Yeah. Hopefully it does not go the way of my idea to run an attractor in reverse. I have a slight worry that a valid point in space for one attractor might be invalid for another.

My experience is: yes and no. In general, most of these formulas seem to be able to pull an alien location into their orbit. The downside is it can take a while for it to settle into the “personality” of the new attractor.

That brings up another detail about Zoo: you can use Chaops on the left to store a point to memory location 0. When you save the resulting Zoo preset, memory 0 becomes the initial point for that attractor. In other words, this is how you define the starting location of your custom attractor.

It’s good to set max speed + turbo mode, let the attractor settle into its personality. Then turn off turbo and put speed back at default (0). Click the freeze button F in Chaops. If you like the starting point, click the S button in Chaops to store to memory 0. Iterate a few times until you are happy. Then save the Zoo preset and memory 0 becomes the starting point.

(Confusing detail: you press memory buttons on Chaops, but the actual memory is in Zoo.)

That might actually be a fun “feature” to explore!

2 Likes

I’m in the process of adding a few more presets. It takes a while to test them, tune the parameter ranges for stability, etc.

I found a fun one called the Three Scroll.

2 Likes

This looks super cool!!

Yes, tons more pre-sets please. It’s fun to play with, but it’s not really clear how to create new formulas without doing research… so I’ll have to return to that one after reading some more.

Just playing with it a bit, I was wondering if you could come up with any kind of CV controls that could be used to change parameters in the formulas, or to modulate those sliders in the context menu. It would be really cool if we could somehow change parameters of the chaos system by CV, It could open up the possibility to have the chaos transition between different modes in sync with input triggers or modulation.

So my only complaint with the design is basically that I wanted the context menu open so I could mess with the controls – but the context menu then blocks the Tricorder screen so I can’t see what’s happening when I move the controls till I close the menu again…

Also, just wanted to say that I really really like your Echo module. That is such an impressive interface design!!

1 Like

You had me at “programmable”…

Ok, so now I get to ask you the question you asked me way back when; how does the programmable part work?

mahlen

1 Like

You just keep’em coming (as do all the previous posters here, incidentally). :+1:t2: Awesome. Like Dave I don’t have a ton of time for this right at the moment, but I look forward to trying it out when things clear up a bit!

Here is a preset based on FOUR-WING from Strange Attractors

FOUR-WING.vcvm (2.6 KB)

Why this one? No reason other than it was not previously listed in thread.

If it looks OK, I’ll be glad to build more.

1 Like

Hi Mahlen! I’m glad you asked because what I came up with is interesting. I started out with this approach:

  1. Take a string like “a*x^2 + b” and parse it into an expression tree.
  2. Convert the expression tree into a postfix expression like this: ax2^*b+.
  3. Evaluate the postfix expression using a stack: operators like + pop two items from the stack and push the sum back to the stack.

It turns out that this approach was not as efficient as I wanted. It takes too many real CPU instructions to execute just one postfix instruction. Most of the time is spent decoding the operator and pushing and popping things, not actually crunching numbers.

I kept thinking about how to make this more efficient, and I finally had an inspiration: create a virtual machine with only one kind of instruction. If every instruction is the same, there is no need for an opcode.

The fundamental instruction I came up with is:

reg[r] = reg[a]*reg[b] + reg[c]

where reg is an array of floating point memory locations called registers, and r a b c are integer indexes into the register array. Every instruction can then be encoded using operands only. Again, no opcode is needed. So the above operation is represented as the tuple (r, a, b, c).

It turns out you can do everything needed for these kinds of attractors using this fundamental operation. For example, to subtract:

x-y=(-1)y+x

To multiply two numbers together:

xy=xy+0

I implemented + - * / and ^ when the exponent is an integer 1…9.

Then I wrote the compiler that converts the parse tree into these instructions instead of postfix/stack stuff. It is about 10 times as fast as postfix evaluation!

This leads to an amazingly fast evaluator function.

        void run()
        {
            for (const BytecodeInstruction& inst : func)
                reg[inst.r] = reg[inst.a]*reg[inst.b] + reg[inst.c];
        }

Here is an example of output from my unit tests of the Rössler attractor, where you can see the compiler output “disassembled” back into something more human readable:

compile(vx = -y-z)
compile(vy = x+a*y)
compile(vz = b+z*(x-c))

PROGRAM:
    REGISTERS:
        [ 0] :   0.2000000000000000    // a
        [ 1] :   0.2000000000000000    // b
        [ 2] :   7.0000000000000000    // c
        [ 3] :   0.1000000000000000    // d
        [ 4] :   0.1100000000000000    // x
        [ 5] :   0.1200000000000000    // y
        [ 6] :   0.1300000000000000    // z
        [ 7] :   0.0000000000000000    // out_0
        [ 8] :   0.0000000000000000
        [ 9] :  -1.0000000000000000    // (-1)
        [10] :   0.0000000000000000    // (0)
        [11] :   0.0000000000000000    // out_1
        [12] :   0.0000000000000000    // out_2
        [13] :   0.0000000000000000
    INSTRUCTIONS:
        [ 8] = [ 9]*[ 5] + [10]    // reg_8 = (-1)*y + (0)
        [ 7] = [ 9]*[ 6] + [ 8]    // out_0 = (-1)*z + reg_8
        [11] = [ 0]*[ 5] + [ 4]    // out_1 = a*y + x
        [13] = [ 9]*[ 2] + [ 4]    // reg_13 = (-1)*c + x
        [12] = [ 6]*[13] + [ 1]    // out_2 = z*reg_13 + b

2 Likes

managed to upload a bad preset just one minute…

From Attraktoren

Xing-Yun.vcvm (2.5 KB)

edit - cleanup links

@scook, thank you so much! I just added your Four-Wing preset. It will be included in the next pre-release. I only adjusted the parameter ranges a little bit. It makes a pretty curve!

I also like the Strange Attractors website you linked! So cool! There is an abundance of stuff to study.

I will continue to look at the other presets you submitted.

Hi @codyge! Thank you for all of your kind words. It means a lot.

The way it works is through the CHAOS knob. You will see a letter A B C D on top of that knob. When you right click you will see

Select the letter of the parameter you want to modify. Then when you turn the CHAOS knob you are making an adjustment to that parameter. I hope this makes sense.

Then you can use the attached CV input and attenuverter knob to automate changes.

Currently you can’t automate changing from one parameter (chaos mode) to another, or simultaneously controlling multiple parameters. That is the kind of thing I will have to think about more.

I hear you and I agree. The user experience for programming new formulas is not very good. And the reason is, I decided early on making it “user friendly” was going to be far too much work. I wanted something that worked, and was easier than creating yet another chaos module every time I found a new formula I wanted. From my own selfish point of view, Zoo is a huge saver of development time already!

I don’t think I will try to optimize the programming experience because in my mind it is secondary to having a consistent panel design with Frolic, Glee, and Lark.

1 Like

Messed up SPROTT so I deleted it, sorry.

I will create a few more with better values.

1 Like

OK. No need to hurry… it will be at least a week before I am ready to submit this to VCV Rack. Also, I will keep making pre-release builds as we go, so everyone watching here can share the new presets.

Sounds good

Here is one based on 2.6 Chen-Celikovsky Attraktor from Attraktoren

Chen-Celikovsky.vcvm (2.6 KB)

The Xing-Yun preset I posted above will freeze Zoo when the speed approaches 7 (non-turbo mode).

VCV does not crash and Zoo restarts OK if initialized from its context menu.