supercollider

atolf lftoa

using supercollider i reverse-engineered two old max/msp externals from cycling'74. they came as part of the pluggo installer and were compiled in the cfm binary format. this format is since long defunct and cfm externals can't be loaded into max/msp running under windows or newer intel macs (afaik). luckily i could still run the externals and helpfiles under max4.6 on my old ppc mac.

and as far as i could tell, the source code for these binaries were never released. so i took the trial&error route and managed to figure out how they work internally by using simple input strings like 'aa', 'ab', 'ac', 'ba', 'bb', 'aba', 'abc' etc. then i just observed the output arrays of floating point numbers and tried to mimic that in supercollider code. it was fairly quick to come up with the algorithms that encode (atolf) and decode (lftoa) shown below.

also a note on max vs sc: no way i could have solved this using max/msp only. algorithms like these are horrendous to implement with patchcords. see the mess in the screenshots below. also max/msp floatinpoint numberboxes as well as the [print] object does not show the whole 32bit float values! they round off to 6 digits after the decimal point. why? so max/msp can calculate just fine using 32bit floats as long as you don't try to print or output them in any way.

anyway, i first wrote RedALF for supercollider (it is now in the redSys quark) and from that i then patched f0.atolf and f0.lftoa (now part of my f0.abs max/msp abstractions).

(
~atolf= {|str|
        var res= [1/2**5];
        var tre= [2**12, 2**20, 2**28];
        str.do{|chr, i|
                var j= i.div(3);
                if(i%3==2, {
                        res= res++(1/2**5);
                });
                res.put(j, res[j]+(chr.ascii/tre[i%3]));
        };
        res;
};
~lftoa= {|arr|
        var res= "";
        arr.do{|val|
                var a, b, c;
                val= val-(1/2**5)*(2**12);
                a= val.asInteger;
                val= val-a*(2**8);
                b= val.asInteger;
                val= val-b*(2**8);
                c= val.asInteger;
                res= res++a.asAscii++b.asAscii++c.asAscii;
        };
        res;
};
)
a= ~atolf.value("aber")   //--> [0.055025476962328, 0.05908203125]
~lftoa.value(a)  //--> "aber"

sinusdeklinationen

a quick port of a very simple pure-data demonstration patch made by malte steiner. just to show one way how to go about things in supercollider.

get the pd patch here... sinusdeklinationen.pd

and then compare it with the following...

//--sinusdeklinationen by malte steiner, ported to sc by redFrik

s.boot;

(
SynthDef(\sinuscell, {|out= 0, pan= 0, amp= 0.5, fre= 400, atk= 1, sus= 0.2, rel= 1|
        var env= EnvGen.kr(Env.linen(atk, sus, rel, amp), doneAction:2);
        var snd= SinOsc.ar(fre, 0, env);
        Out.ar(out, Pan2.ar(snd, pan));
}).send(s);
)

(
var cells= [-1, -0.6, -0.5, 0, 0.2, 0.5, 0.4, 1];
~masterVol= 0.1;
cells.do{|c|
        Routine({
                inf.do{
                        var fre= 1100.rand;
                        var atk= 1.0.rand;
                        var sus= 0.2;
                        var rel= 1.0.rand;
                        Synth(\sinuscell, [\fre, fre, \amp, 1.0.rand*~masterVol, \atk, atk, \sus, sus, \rel, rel, \pan, c]);
                        (atk+sus+rel).wait;
                };
        }).play;
};
)

~masterVol= 0.2
~masterVol= 0.02

//stop with cmd+.

redUniverse: support for discrete worlds

clean-up #30:

as the last thing for this month-of-cleaning-up-old-code-and-taking-care-of-forgotten-projects, i finally wrote some methods that i had been planning for a long time. they add support for discrete worlds to my redUniverse quark.

it's all fairly simple.

in a 2 dimensional world there are 8 neighbouring cells/locations. the surroundings method returns them.

a= RedWorld(RedVector[100, 200])  //a 2d world
a.surroundings
[ [ -1, -1 ], [ -1, 0 ], [ -1, 1 ], [ 0, -1 ], [ 0, 1 ], [ 1, -1 ], [ 1, 0 ], [ 1, 1 ] ]

and in a 3 dimensional world, the number of surrounding cells grows to 26. that is 3*3*3-1 where the minus one is the [0, 0] location.

a= RedWorld(RedVector[100, 200, 300])  //a 3d world
a.surroundings
[ [ -1, -1, -1 ], [ -1, -1, 0 ], [ -1, -1, 1 ], [ -1, 0, -1 ], [ -1, 0, 0 ], [ -1, 0, 1 ], [ -1, 1, -1 ], [ -1, 1, 0 ], [ -1, 1, 1 ], [ 0, -1, -1 ], [ 0, -1, 0 ], [ 0, -1, 1 ], [ 0, 0, -1 ], [ 0, 0, 1 ], [ 0, 1, -1 ], [ 0, 1, 0 ], [ 0, 1, 1 ], [ 1, -1, -1 ], [ 1, -1, 0 ], [ 1, -1, 1 ], [ 1, 0, -1 ], [ 1, 0, 0 ], [ 1, 0, 1 ], [ 1, 1, -1 ], [ 1, 1, 0 ], [ 1, 1, 1 ] ]

and the numbers for 4, 5 and 6 dimensional worlds (not that i ever used >3) are 80, 242, 728 respectively. (a RedWorld can have any number of dimensions.)

also it is possible to not only get the directly adjacent cell, but neighbours further away. this example bumps up the surroundingArea variable from the default 1 to 2. now the surroundings are all the cells next to and two steps away from [0, 0].

a= RedWorld(RedVector[100, 200])  //a 2d world
a.surroundingArea= 2
a.surroundings
[ [ -2, -2 ], [ -2, -1 ], [ -2, 0 ], [ -2, 1 ], [ -2, 2 ], [ -1, -2 ], [ -1, -1 ], [ -1, 0 ], [ -1, 1 ], [ -1, 2 ], [ 0, -2 ], [ 0, -1 ], [ 0, 1 ], [ 0, 2 ], [ 1, -2 ], [ 1, -1 ], [ 1, 0 ], [ 1, 1 ], [ 1, 2 ], [ 2, -2 ], [ 2, -1 ], [ 2, 0 ], [ 2, 1 ], [ 2, 2 ] ]

that is 24 neighbour locations per single cell in a 2d world.

so the surroundings method only give relative positions and the size of the neighbourhood. not so useful. but there are the two other methods called surroundingLocations and neighbours that is what one should use. surroundingLocations takes an object and returns a list of locations depending on the current surroundings.

a= RedWorld(RedVector[100, 200])  //a 2d world
b= RedObject(a, RedVector[10, 20])  //an object at location [10, 20]
a.surroundingLocations(b)  //get the surrounding locations of object b
[ RedVector[ 9, 19 ], RedVector[ 9, 20 ], RedVector[ 9, 21 ], RedVector[ 10, 19 ], RedVector[ 10, 21 ], RedVector[ 11, 19 ], RedVector[ 11, 20 ], RedVector[ 11, 21 ] ]

and last the neighbours method that returns an array of any nearby objects.

a= RedWorld(RedVector[100, 200])  //a 2d world
b= RedObject(a, RedVector[10, 20])  //an object at location [10, 20]
c= RedObject(a, RedVector[11, 21])  //an object at location [11, 21]
a.neighbours(b)  //get the neighbouring objects of object b
[ a RedObject ]

the different worlds deals with border conditions differently. RedWorld wraps all the locations around and RedWorld3 filters out locations. compare...

a= RedWorld(RedVector[100, 200])  //a 2d world without borders
b= RedObject(a, RedVector[0, 0])  //an object at upper left corner location [0, 0]
a.surroundingLocations(b)  //get the surrounding locations of object b
[ RedVector[ 99, 199 ], RedVector[ 99, 0 ], RedVector[ 99, 1 ], RedVector[ 0, 199 ], RedVector[ 0, 1 ], RedVector[ 1, 199 ], RedVector[ 1, 0 ], RedVector[ 1, 1 ] ]
a= RedWorld3(RedVector[100, 200])  //a 2d world with borders
b= RedObject(a, RedVector[0, 0])  //an object at upper left corner location [0, 0]
a.surroundingLocations(b)  //get the surrounding locations of object b
[ RedVector[ 0, 1 ], RedVector[ 1, 0 ], RedVector[ 1, 1 ] ]

the neighbours method is quite slow at the moment, but i hope to be able to speed it up considerably later on.

anyway, here is the complete svn diff.

redLeech

clean-up #28:

code that performs itself. this is number six in a series all working in a similar manner. see low life, more low life and even more low life.
this virtual leech runs around the code and suck up words now and then. when it's full (c.size>30) it spits them all out wherever it happens to be. and some characters are lost so the code slowly disappears.
in the end of the video it got stuck in a loop so i killed it off manually with the delete key.

thanks to chris for the title.

supercollider document attached below. osx only afaik.

AttachmentSize
Binary Data redLeech.scd993 bytes

redUniverse: clean-up and some new features

clean-up #26:

my redUniverse quark still have a lot of features missing that i want to put in. it is endless work and i only get to it now and then. but at least after today the helpfiles are in a bit better shape, and examples are changed to use animate to run more smoothly (most now look a lot better!).

* new helpfiles for RedHiddenObject, RedParticle, RedBoid, RedRock, RedFood, RedAgent.
* slightly changed formatting for almost all the other included helpfiles.
* wrote addForceWander1D and addForceWander3D methods for RedBoid.
* wrote addForceAngular3D, pendulumOffset3D, pendulumLoc3D.
* added 2 boids examples and 1 pendulum to show the new features.
* changed almost all the other examples to use animate instead of play and to close the window at cmd+.

here is the complete svn diff.

vertex

clean-up #25:

attached is a little class that draws polygons in supercollider. with inspiration from processing.
if you want to use the \point type of shape it will look better with smoothing set to false and Vertex.pointSize= 0;

update 101211: attached a simple BezierVertez class. it works like this one.
update 101215: improved the \triangleFan type in vertex.sc.
update 141012: minor update to BezierVertez.sc - added close argument

(
        var win= Window("vertex test", Rect(100, 100, 430, 320), false);
        win.drawHook= {
                Pen.fillColor= Color.white;
                Pen.strokeColor= Color.black;
               
                Pen.use{
                        Pen.translate(10, 10);
                        Vertex.beginShape();
                        Vertex(Point(30, 20));
                        Vertex(Point(85, 20));
                        Vertex(Point(85, 75));
                        Vertex(Point(30, 75));
                        Vertex.endShape(1);             //1 means close
                        Pen.fillStroke;                 //also try fill and stroke
                };
                Pen.use{
                        Pen.translate(110, 10);
                        Vertex.beginShape(\points);
                        Vertex(Point(30, 20));
                        Vertex(Point(85, 20));
                        Vertex(Point(85, 75));
                        Vertex(Point(30, 75));
                        Vertex.endShape();
                        Pen.stroke;
                };
                Pen.use{
                        Pen.translate(210, 10);
                        Vertex.beginShape(\lines);
                        Vertex(Point(30, 20));
                        Vertex(Point(85, 20));
                        Vertex(Point(85, 75));
                        Vertex(Point(30, 75));
                        Vertex.endShape();
                        Pen.stroke;
                };
                Pen.use{
                        Pen.translate(310, 10);
                        Vertex.beginShape();
                        Vertex(Point(30, 20));
                        Vertex(Point(85, 20));
                        Vertex(Point(85, 75));
                        Vertex(Point(30, 75));
                        Vertex.endShape(0);             //0 means not close (default)
                        Pen.stroke;
                };
               
                Pen.use{
                        Pen.translate(10, 110);
                        Vertex.beginShape();
                        Vertex(Point(30, 20));
                        Vertex(Point(85, 20));
                        Vertex(Point(85, 75));
                        Vertex(Point(30, 75));
                        Vertex.endShape(1);             //1 means close
                        Pen.stroke;
                };
                Pen.use{
                        Pen.translate(110, 110);
                        Vertex.beginShape(\triangles);
                        Vertex(Point(30, 75));
                        Vertex(Point(40, 20));
                        Vertex(Point(50, 75));
                        Vertex(Point(60, 20));
                        Vertex(Point(70, 75));
                        Vertex(Point(80, 20));
                        Vertex.endShape();
                        Pen.fillStroke;                 //also try fill and stroke
                };
                Pen.use{
                        Pen.translate(210, 110);
                        Vertex.beginShape(\triangleStrip);
                        Vertex(Point(30, 75));
                        Vertex(Point(40, 20));
                        Vertex(Point(50, 75));
                        Vertex(Point(60, 20));
                        Vertex(Point(70, 75));
                        Vertex(Point(80, 20));
                        Vertex(Point(90, 75));
                        Vertex.endShape();
                        Pen.fillStroke;                 //also try fill and stroke
                };
                Pen.use{
                        Pen.translate(310, 110);
                        Vertex.beginShape(\triangleFan);
                        Vertex(Point(57.5, 50));
                        Vertex(Point(57.5, 15));
                        Vertex(Point(92, 50));
                        Vertex(Point(57.5, 85));
                        Vertex(Point(22, 50));
                        Vertex(Point(57.5, 15));
                        Vertex.endShape();
                        Pen.fillStroke;                 //also try fill and stroke
                };
               
                Pen.use{
                        Pen.translate(10, 210);
                        Vertex.beginShape(\quads);
                        Vertex(Point(30, 20));
                        Vertex(Point(30, 75));
                        Vertex(Point(50, 75));
                        Vertex(Point(50, 20));
                        Vertex(Point(65, 20));
                        Vertex(Point(65, 75));
                        Vertex(Point(85, 75));
                        Vertex(Point(85, 20));
                        Vertex.endShape();
                        Pen.fillStroke;                 //also try fill and stroke
                };
                Pen.use{
                        Pen.translate(110, 210);
                        Vertex.beginShape(\quadStrip);
                        Vertex(Point(30, 20));
                        Vertex(Point(30, 75));
                        Vertex(Point(50, 20));
                        Vertex(Point(50, 75));
                        Vertex(Point(65, 20));
                        Vertex(Point(65, 75));
                        Vertex(Point(85, 20));
                        Vertex(Point(85, 75));
                        Vertex.endShape();
                        Pen.fillStroke;                 //also try fill and stroke
                };
                Pen.use{
                        Pen.translate(210, 210);
                        Vertex.beginShape();
                        Vertex(Point(20, 20));
                        Vertex(Point(40, 20));
                        Vertex(Point(40, 40));
                        Vertex(Point(60, 40));
                        Vertex(Point(60, 60));
                        Vertex(Point(20, 60));
                        Vertex.endShape(1);             //also try 0 here
                        Pen.fillStroke;                 //also try fill and stroke
                };
                Pen.use{
                        Pen.translate(310, 210);
                        Vertex.beginShape();
                        14.do{
                                Vertex(Point(85.rand, 85.rand));
                        };
                        Vertex.endShape(1);             //also try 0 here
                        Pen.fillStroke;                 //also try fill and stroke
                };
        };
        win.front;
)
//http://processing.org/reference/bezierVertex_.html
(
        var win= Window("beziervertex test1", Rect(100, 100, 300, 300), false);
        win.drawHook= {
                Pen.fillColor= Color.white;
                Pen.strokeColor= Color.black;
                BezierVertex.beginShape(Point(30, 20));
                BezierVertex(Point(80, 0), Point(80, 75), Point(30, 75));
                BezierVertex.endShape;
                Pen.stroke;                             //also try fillStroke and fill
        };
        win.front;
)

//http://processing.org/reference/bezierVertex_.html
(
        var win= Window("beziervertex test2", Rect(100, 100, 300, 300), false);
        win.drawHook= {
                Pen.fillColor= Color.white;
                Pen.strokeColor= Color.black;
                BezierVertex.beginShape(Point(30, 20));
                BezierVertex(Point(80, 0), Point(80, 75), Point(30, 75));
                BezierVertex(Point(50, 80), Point(60, 25), Point(30, 20));
                BezierVertex.endShape;
                Pen.fillStroke;                 //also try stroke and fill
        };
        win.front;
)

AttachmentSize
Binary Data Vertex.sc1.6 KB
Binary Data BezierVertex.sc342 bytes

Pages

Subscribe to RSS - supercollider