Managed to fractalize a variant based on a sheared stack of toruses (such that the ends join up into a helix). Still has assumptions about the rise per revolution being small, but it turned out well. Rendered with "Raymond", my physically-inspired raytracer, using a material similar to water but more extreme in both index of refraction and absorption coefficients.

Render at 3840x2160 with 256 subframes took about 1.5 hours. Exported from FragM in EXR format, colour balance adjusted in Darktable, cropped/framed in GNU IMP.

Show thread

If you need a lot of harmonics, it can be done in parallel (SIMD? FPGA?) by using the relations:

$$
T_{2n} = T_n^2 - 1
T_{2n+1} = T_{n+1} T_n - x
$$

For the second kind, I think you can use these ones:

$$
U_{2n-1} = 2 T_n U_{n-1}
U_{2n} = T_{2n} + x U_{2n-1}
$$

(hope I didn't make any mistakes working that out)

Show thread

Implemented bandlimited PWM via difference of two bandlimited saws (constructed by additive synthesis):

```
vec2 saw(float t)
{
float s = sin(t);
float c = cos(t);
float su = 1.0;
float sv = 2.0 * c;
float cu = 1.0;
float cv = c;
float sgn = 1.0;
int k = 1;
float sum = 0.0;
float dsum = 0.0;
while (k <= 16)
{
float term = sgn * su / float(k++);
float dterm = sgn * cu;
sum += term;
dsum += dterm;
sgn = -sgn;
float sw = 2.0 * c * sv - su; su = sv; sv = sw;
float cw = 2.0 * c * cv - cu; cu = cv; cv = cw;
}
return vec2(s * sum, dsum);
}
```

(This computes the derivative too for waveform plotting purposes.)

Show thread

Experimenting with Chebyshev polynomials to do additive synthesis based on a single sine and cosine value pair.

Rough estimate 5 floating point arithmetic operations for each additional next harmonic, of which 3 are for the polynomial recurrence and 2 are for gain and accumulation. Compared to 3 flops and 1 `sin()` call for the obvious way. The `sin()` call way can do sparse harmonics much more easily though.

Figured out the single helix version, by realizing that the line through a point to the nearest point on the surface must lie on a plane containing the axis of the helix. There are three candidate points, conceptualized as the two neighbouring arcs above and below, and the arc opposite:

```
330 compatibility

providesColor
"MathUtils.frag"
"Complex.frag"
"DE-Raytracer.frag"

Helix

uniform float HelixD; slider[0.0,2.0,10.0]
uniform float HelixR; slider[0.0,1.0,10.0]
uniform float Helixr; slider[0.0,0.5,10.0]

uniform float time;

float DE(vec3 q)
{
q.z += time * 2.0 * PI * HelixD;
float dz = mod(q.z + HelixD * atan(q.y, q.x) + PI * HelixD, 2.0 * PI * HelixD) - PI * HelixD;
float xy = length(q.xy);
float d1 = length(vec2(xy - HelixR, dz - PI * HelixD));
float d2 = length(vec2(xy + HelixR, dz));
float d3 = length(vec2(xy - HelixR, dz + PI * HelixD));
return min(min(d1, d2), d3) - Helixr;
}

vec3 baseColor(vec3 q, vec3 n)
{
return vec3(0.5) + 0.5 * cross(n, normalize(vec3(-1.0, 1.0, -1.0)));
}
```

Show thread

Implemented a double helix based on an idea from 's `Knot.frag` (not knighty's, the other one, based on forum posts by DarkBeam).

Not sure how to -ize it, wanted to turn it into a of helices of helices etc. Nor how to make it a single helix (I only managed to colour the two halves individually...).

I think each strand is an Archimedean Serpentine, but I'm not 100% sure on terminology..

```
330 compatibility

providesColor
"MathUtils.frag"
"Complex.frag"
"DE-Raytracer.frag"

Helix

uniform float HelixD; slider[0.0,2.0,10.0]
uniform float HelixR; slider[0.0,1.0,10.0]
uniform float Helixr; slider[0.0,0.5,10.0]

uniform float time;

float DE(vec3 q)
{
q.z += HelixD * time;
float t = (mod(q.z / HelixD + 0.5, 1.0) - 0.5) * 2.0 * PI;
q.xy *= mat2(cos(t), sin(t), -sin(t), cos(t));
q.z = 0;
float s = atan(HelixD / (2.0 * PI), HelixR);
q.yz *= mat2(cos(s), -sin(s), sin(s), cos(s));
return length(vec2(length(q.xy) - HelixR, q.z)) - Helixr;
}

vec3 baseColor(vec3 q, vec3 n)
{
q.z += HelixD * time;
float t = (mod(q.z / HelixD + 0.5, 1.0) - 0.5) * 2.0 * PI;
q.xy *= mat2(cos(t), sin(t), -sin(t), cos(t));
return vec3(0.5) + 0.5 * sign(q.x) * n;
}
```

18th

rhythmic beeping

source code composed in mathr.co.uk/barry/v2/ , rendered to WAV using barry command line version, trimmed to first 2^22 samples using Audacity, encoded with LAME.

```
: audio { c t -- o }
t t 0x401 c 2 * - * 17 t 16 >> 3 & + >> 0x11 t 18 >> 0xF & 1 + * & <<
i8
;

RUN audio
1 -> increment
0 -> time
```

Show thread

17th

modulating PWM drone with echoed high pitched things and various fast kicks (with a bit of DC offset, sorry)

source code composed in mathr.co.uk/barry/v2/ , rendered to WAV using barry command line version.

```
: dup { x -- x x }
x x
;

: env { a t -- a }
a t ~ 0x7FFF & dup * 15 >> dup * 15 >> * 15 >>
;

: audio { c t | r s -- o }
t 15 >> 3 2 c * + * 7 & 6 % 1 + -> r
t 256 r + * 9 >> 0xFF & t 256 r - * 9 >> 0xFF & - 1 >>
r t t t * * * 0xFF & i8 i64 -> s
s 2 * 0xFF & i8 i64 t 0x4000 - env 0 >>
s 3 * 0xFF & i8 i64 t 0x7000 - env 1 >>
s 5 * 0xFF & i8 i64 t 0xA000 - env 2 >>
+ + t 14 >> 7 & 7 != *
r t * ~ 0x3FFF & dup * 15 >> dup * 15 >> 0x7F & 0x40 - t 20 >> 3 & 0 != *
+ t 19 >> 3 & 0 != *
+ 1 >>
i8
;

RUN audio
1 -> increment
0 -> time
```

(Previous one was 14th.)

Show thread

14th

(Loud noise with some high frequencies and no dynamic variation.)

Composed in mathr.co.uk/barry/v2/ , rendered in barry command line.

Reminds me of an electric train changing up gears when leaving a station.

Attached is just an excerpt of the start (first 2^23 samples), it continues indefinitely (technically, it will repeat after at most 2^64 samples, due to arbitrary computational limit).

Source code:

```
: wave { c t n -- o }
t t 1 n << 1 2 c * - - * n >> c 0 ~ * ^ * 1 n << 1 2 c * - + * n >> i8
;

: audio { c t -- o }
c t 19 wave
c t 18 wave
c t 17 wave
c t 16 wave
^ ^ ^
;

RUN audio
1 -> increment
0 -> time
```

(Last one I did was on the 3rd, not made enough time for noisevember this year...)

Show thread

2.15.1.3 (prerelease, not yet final) running on 0.4.13 (all 32bit, in VirtualBox, single core).

Getting ReactOS working was a chore until I followed their instructions precisely (had no joy with QEMU at all).

Tempted to try it on an old Pentium4 desktop I have here, will see if there are Windows XP-era drivers for its graphics card still available from reputable sites...

Show thread

3rd

```
: audio { c t -- o } t t 3 >> c 0 ~ * ^ + 0xF & t t 7 >> 3 & 1 + >> t 16 t 18 >> 7 & - >> 3 & 4 + & 3 * 7 & 1 + * t ~ 10 >> 0xF & * 4 >> t 0xFF & t ~ 7 t 18 >> 7 & + >> 0x1F & * 6 >> + 1 >> i8 ;
RUN audio
1 -> increment
0 -> time
```

composed with mathr.co.uk/barry/v2/
recorded with barry command line tool (fixed the bug that had broken it)
trimmed and DC offset removed with Audacity
encoded with LAME

(I made no noisevembeat 2nd)

Show thread

1st

```
: audio { c t -- o } t t 14 >> c 0 ~ * ^ + 0x3F & t t 15 >> 3 & 13 + >> 7 & 5 * 7 & 1 + * t ~ 8 >> 0x3F & * 6 >> t t ~ 8 >> 0x3F & * 6 >> ^ i8 ;
RUN audio
1 -> increment
0 -> time
```

composed with
mathr.co.uk/barry/v2/
recorded from Firefox with parec
trimmed with Audacity
encoded with LAME

mathr.co.uk/zoomasm
I released version 1.0 "felicitats" yesterday. It's a tool for assembling from exponential strip keyframes with RGB and/or raw iteration data in EXR format - the colouring is controlled by an snippet with a few presets included (or write your own).

(However, the only software I know of that can export keyframes for input to zoomasm, is 2.15 branch which is not yet released... so getting that done is my new focus.)

I implemented (hopefully ) , as well as linear and step modes, for depth in my tool for assembling animations from exponential strip keyframes. Much smoother than the piecewise linear that was the only option before (no more speed discontinuities at waypoints, unless you want them).

Got (base 10) numeric display working with log-domain (base 2) input (so that exponent is not limited by single precision floating point). I just need to finish up adding minus sign support for the exponent (it can go negative)...

Show thread

Made a as an fragment (function from (x, y, t) to colour).

Oriented box signed distance function from Inigo Quilez:
iquilezles.org/www/articles/di

Segments activated by a load of conditionals on each digit's value.

Digits found by repeated divmod 10 stuff, after multiplying by 10000 (sets maximum number of digits after the point).

Leading zeros stripped with a simple loop (that stops at the point). I have code to strip trailing zeros too, but changing values are seldom affected.

Anti-aliasing of the decimal point seems to be a bit off, looks a bit too blurry. Want to add an option to move it to the baseline too.

Currently there are controls for glyph size, point size, segment length, segment thickness, foreground and background colours.

Eventual aim is to port the number rendering to the zoom video assembler I've been working on, to display zoom depth. Will need some extra fiddling, as that needs to be in log-domain and expanded to scientific notation without overflow.

Need to add motion blur to the zoom assembler first, otherwise the least significant digits will be too stroboscopic.

Figured out how to do bidirectional communication with a subprocess using Win32 API. POSIX version still to do. Now I can pipe raw PPM image streams to FFmpeg and display the output logs in my program. Did some fiddly things too to stop a flood of status lines (in a terminal they are overwritten in place using carriage return without newline). Also made a simple Dear ImGui theme function, so my UI is red when recording, green when playing, and blue when idle.

Figured out how to fix in on with driver : simply enable the display - thought I'd tried it before, but maybe I was doing it wrong, or it didn't work properly in earlier versions (I was on Debian Buster/stable for a long while, now on Bullseye/testing).

I made a thing. Formula is Mandelbrot set modified to have power 2.005 instead of 2, coloured with additive blending of an orbit trap on the negative real axis (cycling between red, green, blue depending on iteration number).

The center point of the zoom is preperiodic point with preperiod 645 and period 12 (this fact was used to refine the coordinates to be more precise). Iteration count was 3000.

The zoom factor for the loop (both rotation and scaling) was found by overlaying two copies and fiddling with sliders until it lined up again.

Probably too much motion blur and not enough samples for anti-aliasing (256 per pixel), but it took almost 2 hours to render this 2 second thing...

Show more
post.lurk.org

Welcome to post.lurk.org, an instance for discussions around cultural freedom, experimental, new media art, net and computational culture, and things like that.