Got something working for background processing in with YIELD/RESUME/STOP actions, so the code doesn't have to be written in a contorted way (just put YIELD in strategic places and hope you leave enough stack for the rest of the code, which should also leave the stack as it found it).

I'm planning on using this for the computer player of the tokamak game to amortize the cost of the AI over several frames (and maybe also visualize its algorithms).

```
( bg.tal )

|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]

%STOP { ;stopped ;pc STA2 BRK }
%YIELD { ;yield JSR2 }
%RESUME { .pc LDZ2 JMP2 }

|0000
@pc $2
@frame $2

|0100
;on-frame .Screen/vector DEO2
,background JMP

@on-frame
.frame LDZ2 #0001 ADD2 .frame STZ2
RESUME

@yield
STH2r .pc STZ2
BRK

@stopped
YIELD
,stopped JMP

@background
#00
&for-line ( end current )
EQUk ,&break-line JCN
LIT 'z LIT 'a
&for-letters ( end current )
DUP .Console/write DEO
YIELD
EQUk ,&break-letters JCN
INC
,&for-letters JMP
&break-letters
POP2
.Console/write DEO
INC
,&for-line JMP
&break-line
POP2
STOP
```

I started porting (a card game invented by @netzzz that I implemented in but never polished for release) to emulated microcomputer.

learning the assembly language and IO device APIs went fine thanks to the fine tutorial of @compudanzas

will see if there is enough space to implement the computer player, currently the ROM is already almost 4kB and it is still far from playable.

meanwhile I have noticed some typos lead to incomprehensible errors e.g. mistyping `&,label` instead of `,&label`

tokamak.mathr.co.uk/ (online-playable version not available at the moment, try again mid-December)
code.mathr.co.uk/tokamak

// mathr 2021-10-21 looptober

typedef double sample;
SR 48000
"dsp.h"
R sample

typedef struct
{
int reloaded;
double t;
BIQUAD O[2][3];
DELAY D0;float b0[SR];
DELAY D1;float b1[SR];
} S;

int go(S *s,int nin,const float *in,int nout,float *out)
{
if (s->reloaded)
{
s->reloaded=0;
s->D0.length=SR;
s->D1.length=SR;
}
R bpm=138/2.;
R hz=35*3./2;
R cps=bpm/60/4;
R t=(s->t+=cps/SR);
R F=pow(envL(slow(2,t))*envLR(rotL(4,slow(2,t))),2);
pair H[3][4] =
{{{4,4},{4,4},{2,5},{6,3}}
,{{2,5},{6,6},{4,6},{4,4}}
,{{6,6},{2,8},{5,8},{3,5}}
};
R D[2]={delread4(&s->D1,125/hz),delread4(&s->D0,125/hz)};
R C[2]={D[0]*cosine2(t)-sine2(t)*D[1],D[0]*sine2(t)+cosine2(t)*D[1]};
C[0]*=2;
C[1]*=2;
R l=t;
t=pow(2,saw(slow(4,t)))-1;
for (int c=0;c<2;++c)
{
for (int i=0;i<3;++i)
{
R N=timeCat(H[i],fast(2,t));
R q=100;
R O=sine2(biquad(bandpass(&s->O[c][i],hz*N,q),C[c]));
C[c]+=O;
}
}
R K[2]={0,0};
for (int k=0;k<8;++k)
{
R E=pow(isaw(fast(2*pow(2,k),saw(t))),2);
R m=tanh(4*sine2(12*E)*(1+E))*(k==0?t:k==7?1-t:1);
K[0]+=cosine2(k/7.*l)*m;
K[1]+=sine2(k/7.*l)*m;
}
delwrite(&s->D0,tanh(K[0]+0.1*C[1]));
delwrite(&s->D1,tanh(K[1]+0.1*C[0]));
for (int c=0;c<nout;++c) {
out[c]=c<2?0.3*mix(C[c],K[c],0.5)*F:0;
}
return 0;
}

// unshrunk at code.mathr.co.uk/clive/blob/60

Show thread
claude boosted

longer C program than anticipated to convert PGM to ASCII (black -> 1, everything else -> 0) 

```
<stdio.h>
int main(int argc, char **argv)
{
int width, height, maxval, x, y, c, d;
if (3 != scanf("P5\n%d %d %d", &width, &height, &maxval))
{
fprintf(stderr, "%s: could not parse PGM P5 header\n", argv[0]);
return 1;
}
if (getchar() != '\n')
{
fprintf(stderr, "%s: bad header termination\n", argv[0]);
return 1;
}
if (maxval < 256)
{
/* one byte per pixel */
for (y = 0; y < height; ++y)
{
for (x = 0; x < width; ++x)
{
c = getchar();
if (c == EOF)
{
fprintf(stderr, "%s: premature end of file\n", argv[0]);
return 1;
}
putchar(c == 0 ? '1' : '0');
}
putchar('\n');
}
return 0;
}
else if (maxval < 65536)
{
/* two bytes per pixel, MSB first */
for (y = 0; y < height; ++y)
{
for (x = 0; x < width; ++x)
{
c = getchar();
if (c == EOF)
{
fprintf(stderr, "%s: premature end of file\n", argv[0]);
return 1;
}
d = getchar();
if (d == EOF)
{
fprintf(stderr, "%s: premature end of file\n", argv[0]);
return 1;
}
putchar(c == 0 && d == 0 ? '1' : '0');
}
putchar('\n');
}
return 0;
}
else
{
fprintf(stderr, "%s: unsupported maxval\n", argv[0]);
return 1;
}
}
```

@wendy @jine @automatist @praxeology @crickxson

Could you pipe the ASCII generator output through

sed s/00/0/g | sed s/11/1/g

to fix it?

Maybe the extra 0/1 per pixel is coming from an alpha channel?

Alternatively,

Convert to binary PGM (part of NetPBM family of formats)

It has an ASCII header, "P5" followed by width height maxval in decimal separated by whitespace, with a single \n after the maxval.

you can inspect the header with "head -n 2 file.pgm" (or maybe -n 3, if the maxval isn't there)

you can chop it off by "tail -n+3" (or maybe -n+4)

if maxval is less than 256 (the normal case) there is one byte per pixel following (grayscale).

you can then convert these to ASCII 0 1 with sed (which can also probably do the grouping into however many characters per line you need).

personally I'd probably write a short C program to do it

(1/2)

claude boosted

i'm looking for a C/C++/QT programmer who would make multitouch in #SuperCollider GUI system work.

I need this for my project and I have a small budget so I'm prepared to pay for this work.

pls boost. dm/email me if you're interested.

https://github.com/supercollider/supercollider/issues/3755

claude boosted

I just got a spam email (presumably trying to trick me into visiting links for tracking) in reply to (actually not a reply, but just copy/pasted content afacit) a message I sent to sc-users mailing list (which is now defunct) in June 2020...

I guess the archive with addresses is leaked/scraped and they're probing for suckers?

@jine then you could use pdftk to extract desired page ranges from the PDF:

```
pdftk bram-stoker_dracula.pdf cat 179-192 output xv.pdf
```

@jine pandoc sorta worked for me in one very brief test just now (paper size and margins are strange, may be fixable with some options, but text seems readable, and pictures seem present)

```
wget standardebooks.org/ebooks/bram
pandoc bram-stoker_dracula.epub --pdf-engine=xelatex -o bram-stoker_dracula.pdf
```

(I got a flood of unicode warnings, I don't know if they're important...)

I think I fixed the precision loss in this fractal, at least for some of the locations which were broken. Was pretty hard. Not sure if there's a generally applicable solution.

It needed a couple of case analyses similar to the diffabs() function (which evaluates |X+x|-|X| without catastrophic precision loss when x is small compared to X) but specific to this fractal.

Show thread

Separated Perpendicular fractal formula is not working for deep zooms with perturbation techniques as intended.

around the outside, inside looks more reasonable. In other locations (more often) the opposite happens. Other locations are perfectly fine to 1e50 zoom level and beyond. Some kind of precision loss somewhere...

Formula:
```
a, b = coordinates of pixel
xn = (abs(x) - 7/2) * abs(x) - y * y + a;
yn = 2 * (7/4 - abs(x)) * y + b;
x = xn;
y = yn;
```

Perturbation techniques applied to give iterations of low-precision deltas vs high-precision reference. This goes wrong somewhere and too much information is lost from the low-precision numbers, causing pixelation

Started work on a new project, still very much at proof of concept stage:

mathr.co.uk/paintin/demo.txt

```
// mathr - 2021-10-11 -

typedef double sample;
SR 48000
"dsp.h"
R sample

typedef struct
{
int reloaded;
double t;
R note[2][3];
BIQUAD env[2][3];
PHASOR osc[2][3][2];
} S;

int go(S *s, int inchannels, const float *in, int outchannels, float *out)
{
if (s->reloaded)
{
s->reloaded = 0;
panic(s);
}
R bpm = 138 * 4./6;
R hz = 35;
R cps = bpm / 60 / 4;
R t = (s->t += cps / SR);
R fade = pow
( envL(slow(4, t))
* envLR(rotL(4, slow(4, t))
), 2);
pair chords[3][4] =
{ { { 4, 4 }, { 2, 4 }, { 2, 5 }, { 4, 3 } }
, { { 2, 5 }, { 4, 6 }, { 3, 6 }, { 3, 4 } }
, { { 4, 6 }, { 2, 8 }, { 4, 8 }, { 2, 5 } }
};
R chord[2] = { 0, 0 };
for (int c = 0; c < 2; ++c)
{
for (int i = 0; i < 3; ++i)
{
R stereo = rotL(sine2(slow(4, t + (c - 0.5))) / 64, t);
R note = timeCat(chords[i], stereo);
R trig = (s->note[c][i] != note) * 500 * fade;
s->note[c][i] = note;
R q = mix(flatq, 5, envL(slow(8, t)));
R env = sine2(biquad(highpass(&s->env[c][i], cps * note, q), trig));
R osc = sine2(phasor(&s->osc[c][i][0], hz * (1 + (c - 0.5)/16) + (i - 1) / 30.0 + 1000 * env * sine2(phasor(&s->osc[c][i][1], hz * note))));
chord[c] += osc;
}
}
for (int c = 0; c < outchannels; ++c) {
out[c] = c < 2 ? 0.2 * chord[c] * fade : 0;
}
return 0;
}
```

Show thread
claude boosted

I spoke to artist Joana Moll about her new piece for the Media Wall at The Photographers' Gallery last week.

We discussed microprocessors, their impact on the environment and the role of artists and the art world in the transition to a less polluting society.

You can read our conversation at Unthinking photography:

unthinking.photography/article

```
// mathr - 2021-10-06 -
typedef double R;
SR 48000
"dsp.h"
R sample
typedef struct
{
int reloaded;
double t;
R note[2][3];
BIQUAD env[2][3];
PHASOR osc[2][3],bosc[2][3];
}S;
int go(S *s,int nin,const float *in,int nout,float *out)
{
if (s->reloaded)
{
s->reloaded=0;
panic(s);
}
R bpm=138*4./3;
R hz=35;
R cps=bpm/60/4;
R t=(s->t+=cps/SR);
R fade=pow(envL(slow(4,t))*envLR(rotL(4,slow(4,t))),2);
pair chords[3][4]=
{{{4,4},{2,4},{2,5},{4,3}}
,{{2,5},{4,6},{3,6},{3,4}}
,{{4,6},{2,8},{4,8},{2,5}}};
R chord[2]={0,0};
R bass=0;
for(int c=0;c<2;++c){
for(int i=0;i<3;++i){
R stereo=rotL(sine2(slow(4,t+(c-0.5)))/64,t);
R note=timeCat(chords[i],stereo);
R trig=(s->note[c][i]!=note)*500*fade;
s->note[c][i]=note;
R q=mix(flatq,5,envL(slow(8,t)));
R env=sine2(biquad(highpass(&s->env[c][i],cps*note/3,q),trig));
R osc=square2(phasor(&s->osc[c][i],hz*note*3));
R pulse=exp2(square(fast(3,t)))/4;
R bosc=trisaw2(saw(slow(2,t)),phasor(&s->bosc[c][i],hz*note*3*pulse));
bass+=bosc;
chord[c]+=env*osc;
}
}
bass*=fade;
for (int c=0;c<nout;++c) {
out[c]=c<2?0.2*mix(chord[c],bass,0.5):0;
}
return 0;
}
```

Show thread

Triangle Inequality Average colouring for escape time fractals:

$$
t = \sum \frac{ |z| - |(|z-c|-|c|)| }{ |(|z-c|+|c|)| - |(|z-c|-|c|)| }
$$
where $c$ is constant (determined by pixel) and $z$ varies (by iteration of the fractal formula)

This suffers from catastrophic cancellation when $|z| << |c|$, but it's possible to rearrange the calculation. Let $z=x+iy$ and $c=a+ib$, then

$$
|z-c|-|c| = \frac{ x^2 + y^2 - 2ax - 2by }{ \sqrt{ |z-c|^2 + |c|^2 } + |c| }
$$

Now my deep zooms with TIA colouring no longer have glitches around mini-sets due to loss of precision.

Still need to add some tweaks (like only considering the last few iterations before escape) to make it look good, with deep zooms the contrast just washes right out with standard TIA.

Somewhat more interesting than deep zooming is using it for interior regions with a relatively low iteration count.

Reference: math.stackexchange.com/questio

claude boosted

workshop teaching opportunity 

I'm recruiting again for guest online workshop leaders for some (paid) workshops for Babycastles, the art collective/videogame crew/DIY space I work with in NY.

Playlist of past online workshops here:
https://www.youtube.com/watch?v=K56tl3rOUM8&list=PLJzpMnmDTJIUBNOpzI5qdPJ1cXhITBSq-

Topics I'm interested in hosting:

Intro to PD/Pure Data, Intro or Intermediate Twine (or Inform), Intro to Klik n Play, Intro / Intermediate Puzzlescript, Beginner, Intermediate and advanced workshops in Unity or Godot, Hotglue, Love2d,

Show older
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.