What's New in Punctual

A summary of all the changes from Punctual 0.5.

New in Punctual 0.5.1.1

Reintroduced list expansions, which were removed in Punctual 0.5.

There are two types of list expansions:

  • [x, y .. z] expands to a list of numbers starting at x, incrementing by y-x, and ending at z.

For example: [0, 0.25 .. 1] expands to [0, 0.25, 0.5, 0.75, 1].

  • [x ... z] expands to a list of numbers starting at x, incrementing by 1 (or -1), and ending at z.

For example: [0 ... 5] expands to [0, 1, 2, 3, 4, 5]. [5 ... 0] expands to [5, 4, 3, 2, 1, 0].

New in Punctual 0.5.1

New functions pan, panp and splay

pan (combinatorial) and panp (pairwise) do equal-power panning over any number of output channels. Although their use is obvious in the audio domain, they can also be used to pan signals in the visual domain.

In this example, the pan function is used to pan a line between the three channels of the add output:

l << hline 0 0.01;
pan 3 (osc 0.13) l >> add;

The oscillator controls the speed of the panning, which is perceived as a color change in the line.

splay spreads n channels over m outputs (again, with the same equal-power algorithm).

xs << [-0.5,-0.25,0,0.25,0.5];
splay 3 $ circle [xs,0] 0.1 >> add;

In this example, the splay function spreads the five circles over three channels. Note that the first circle is sent to the first channel (red), the second between the first and second channels (yellow), and so on.

New in Punctual 0.5

If you’ve used Punctual before, you might be interested in the new features included in the recently released version 0.5. Below is a summary of the key updates.

Output Notations

Punctual 0.5 introduces new output notations, focusing on how patterns are combined rather than on the channels used.

While the old rgb and rgba notations still exist, they now have slightly different meanings.

The most commonly used output notations are now add and blend, with add being the equivalent of rgb in version 0.4, and blend equivalent to rgba. The mul notation completes the set of available outputs.

All deprecated output notations have been removed, including red, green, blue, hue, saturation, value, hsv, alpha, and fdbk.

For more details, see the output notations section.

Functions with Fewer Arguments

None of the texture-creating functions (fb, fft, ifft) require arguments anymore.

For example, where you previously wrote fb fxy, you now simply write fb. Other expressions can be adapted similarly: for example, fb frt can be replaced with setfxy frt fb. This update aligns these functions with img, vid, and cam, which already worked this way.

The fft function is now equivalent to the 0.4 expression fft fx.

Removed Functions

  • step: use seq, spr or sprp instead.
  • zip: not removed but deprecated. Use {} instead.

Functions with Different Meaning

  • tile and zoom: see the details below.

Reimplementation in PureScript

Punctual 0.5 has been completely rewritten in PureScript, a functional programming language that compiles directly to JavaScript. Prior to version 0.5, Punctual was written in Haskell.

This switch simplifies the process of generating the final JavaScript version from Punctual’s source code, making it easier to develop new features. Additionally, it opens up possibilities for users to create their own modified versions of Punctual more easily.

Exolang

Punctual is now an exolang in Estuary. Essentially, this means that the Punctual code can be modified and these changes can be applied in Estuary without needing to alter any of Estuary’s code. As a result, bug fixes and new features can be implemented more quickly.

Since exolangs can be imported dynamically into Estuary, you can now use different versions of Punctual or even your own customized versions seamlessly. Different Estuary cells can even run different versions of Punctual simultaneously.

User-Defined Functions

You can now define your own functions and add them to Punctual!

User-defined functions are written in Punctual itself, accept arguments, and can contain any Punctual expression. The only limitation is that user functions must be written as one-liners.

For example, the user-defined pixelate function implements a pixelation effect:

pixelate xy = setfxy $ (0.5+floor (fxy*:(xy/2)))/:(xy/2);

i << img "https://upload.wikimedia.org/wikipedia/commons/6/69/A_smiling_member_of_the_Ramnami_Samaj_%28edited%29.jpg";
pixelate [100,1000] i >> add;

External Script import

In addition to creating your own functions, you can now dynamically import Punctual code files using import.

Any variables or functions defined in an imported file are immediately available to the rest of your Punctual code.

Files to be imported must be hosted on a CORS-enabled server, just like any other resource (such as images or videos). See Using your own images and videos for ideas on how to set this up.

Time Shifting Functions

Time functions are a new category in Punctual that allow you to control when changes in patterns occur.

This set includes four functions: slow, fast, late, and early.

Here’s an example of how they work:

l << hline (saw 0.1) 0.01;
[1,1,1]*l >> add;
[1,0,0]*slow 2 l >> add;
[0,1,0]*fast 2 l >> add;
[0,0,1]*late 2 l >> add;
[1,1,0]*early 2 l >> add;

Sequences

Punctual now allows you to create sequences of expressions using the new seq function, which serves as a more flexible replacement for the removed step function.

seq overcomes the main limitation of step, which could only handle a single number in each step.

For example:

s << seq [osc 0.2, 0];
hline s 0.01 >> add;

This will draw a horizontal line at height 0 half the time, and move it up and down according to the oscillator during the other half.

You can also use signals with different numbers of channels (all signals will be adjusted to the maximum number of channels present):

hline (seq [osc 0.3, saw [0.1,0.2,0.3]]) 0.01 >> add

By default, seq completes one full iteration per cycle. You can control the speed and phase of the sequence using the time-shifting functions mentioned earlier.

Note, however, that this only covers cases where step was used with a saw oscillator.

For more complex cases, you can use spr (short for spread, combinatorial) or sprp (pairwise). They are like the old step function, but they work with multichannel semantics.

For example:

l << hline 0 0.01;
s << step [0.1, 0.5, 0, 0.8, 1.3] fx;
fit 1 $ spin s l >> add;

can be rewritten as:

l << hline 0 0.01;
s << spr [0.1, 0.5, 0, 0.8, 1.3] fx;
fit 1 $ spin s l >> add;

Additionally, you can use signals with different numbers of channels:

l << hline 0 0.01;
s << spr [0.1, -0.2, 0, {0.1, -0.1}, 0.2] fx;
fit 1 $ spin s l >> add;

Changes in Geometric Transformation Functions

In version 0.4, tile [1,4] would repeat a pattern once on the horizontal axis and four times on the vertical axis. This behavior is now achieved using tilexy.

In version 0.5, tile [1,4] repeats the pattern once and four times, creating two versions of the pattern. In 0.4, this would have been written as tile [1,1,4,4].

There are two additional functions: tilex, which only tiles patterns horizontally, and tiley, which only tiles them vertically.

The same changes apply to the zoom function, with corresponding zoomxy, zoomx, and zoomy options.

New Operator {}

In Punctual 0.5, [] combines lists combinatorially, whereas {} combines them pairwise.

In the following example, all nine circles are created by the [] expression, but only the three yellow ones appear when using {}:

x << [-0.5, 0.2, 0.8];
y << [-0.8, 0, 0.5];
[1,0,0]*(mono $ circle [x,y] 0.1) >> add;
[0,1,0]*(mono $ circle {x,y} 0.1) >> add;

In version 0.4, this result could be achieved using circle (zip x y) 0.1.

pxy

The new pxy shortcut has been added, which is equivalent to [px, py].

Not yet implemented

The unrep function, that worked in version 0.4, is not yet implemented in version 0.5.X.