We’ve updated our Terms of Use to reflect our new entity name and address. You can review the changes here.
We’ve updated our Terms of Use. You can review the changes here.

Paul Lanksy Simulator (coded in Chuck by Loscha)

from Icosahedraly Yours, Loscha by Loscha

/
  • Streaming + Download

    Includes unlimited streaming via the free Bandcamp app, plus high-quality download in MP3, FLAC and more.
    Purchasable with gift card

      $5 AUD

     

about

Over a decade old, this is the best piece of coding I ever wrote.
It is written in the Audio specific langauge Chuck chuck.cs.princeton.edu

I was sitting at home with the Casio MT-65, and I was trying to transcribe Mild un Leise, by Paul Lansky.
I noticed there was a predictable algorithm to the notes (which makes sense, it was generated by computer code, after all). So I set about writing a program that would emulate the piece of music. I think I did a pretty good job.

You can see Paul Lansky's page at Princeton
paul.mycpanel.princeton.edu
And download the original Mild un Leise here paul.mycpanel.princeton.edu/mymp3.html

I've included the code for those of you who are interested in running and editing the piece for yourself. I didn't deliberately seed this random iteration of the piece, I Just set the length of the file to an arbitrary length and rendered it. I applied light dynamic compression but not other processing was added.

Paying for this track allows you to remix, implement, sample, rework and execute the code provided.

lyrics

// The Lanskyizer
// My loving tribute to Paul Lansky.
// Last updated May 2007
// This is a ChucK-style version of Lanksy's seminal composition, Mild und Leise
//
// The idea for this came to me when I was transcribing MuL to play on keyboards.
// I had the piece opened in a wave editor, and was labelling each "cluster" as a region,
// and naming the regions the notes played.
// I became quickly aware of the overall structure of the piece,
// in a music theory kind of way, so I decided that it would be not too difficult,
// and a good skilltest to attempt to make a version in ChucK.

// Debug Note:
// I've had problems with ChucK & miniAudicle thinking it is referencing arrays out of bounds
// out of bounds in this code, so, I had to upwardly expand most arrayed ugens upwardly.
//
// All Feedback, Ideas & Improvements welcome; loscha@gmail.com

2 => int chatty; // Internal message level, 0 for none, 1 for simple, 2 for detailed.
44100::samp => dur samp_per_second;
now => time start_time;
<<<"\n\nWelcome to Lanskyizer ----------------------------\n\n","">>>;
<<<"Uptime for Engine", now / samp_per_second, "seconds","">>>;
Pan2 pan[5];
SinOsc lh[3];
SinOsc rh[3];
SinOsc mod[3];

ADSR env[5];
ADSR modenv[3];
2 => lh[1].sync;
2 => lh[2].sync;
2 => rh[1].sync;
2 => rh[2].sync;

JCRev rev[5];
.2 => rev[1].mix;
.2 => rev[2].mix;
.2 => rev[3].mix;
.2 => rev[4].mix;

mod[1] => modenv[1] => lh[1] => env[1] => rev[1]=> pan[1] => dac;
mod[1] => modenv[1] => lh[2] => env[2] => rev[2]=> pan[2] => dac;
mod[2] => modenv[2] => rh[1] => env[3] => rev[3]=> pan[3] => dac;
mod[2] => modenv[2] => rh[2] => env[4] => rev[4]=> pan[4] => dac;
mod[1] => blackhole;
mod[2] => blackhole;


int lhroot, rhroot;
int lhinterval, rhinterval;
int lhattack, lhrelease;
int rhattack, rhrelease;
int m1g, m2g;
int m1rf, m2rf;
float newdelay;
float weight;
int numberofclustersplayed;
int mod1attack, mod1decay, mod1release;
float mod1sustain;
int mod2attack, mod2decay, mod2release;
float mod2sustain;





-.8 => pan[1].pan; // 1 & 2 are left channel
-.9 => pan[2].pan;
.8 => pan[3].pan; // 3 & 4 are right channel
.9 => pan[4].pan;

.2 => pan[1].gain;
.2 => pan[2].gain;
.2 => pan[3].gain;
.2 => pan[4].gain;

// Algorithm:
// Generate random notes for left and right hand
// generate interval weighted stats
// which hand plays first
// fm relative to root

while (true)
{
if (chatty > 1) <<<"\n\nNew Section Begins Here!\n\n","">>>;

//-------------------------------------------------
// Root and Interval semi randomization
Std.rand2(40,70) => lhroot;
Std.rand2(60,90) => rhroot;

Std.rand2f(-1,1) => weight;
if (weight > .4)
{
5 => lhinterval;
}
else
{
5 => lhinterval;
}


Std.rand2f(-1,1) => weight;
if (weight > .5)
{
5 => rhinterval;
}
else
{
7 => rhinterval;
}

//-------------------------------------------------
// Envelope semi randomization


Std.rand2(200,2000) => lhattack;
Std.rand2(100,800) => lhrelease;
Std.rand2(200,2000) => rhattack;
Std.rand2(100,800) => rhrelease;


Std.rand2(0,1500) => mod1attack;
Std.rand2(0,1500) => mod1decay;
Std.rand2f(.7,1) => mod1sustain;
Std.rand2(0,1500) => mod1release;
Std.rand2(0,1500) => mod2attack;
Std.rand2(0,1500) => mod2decay;
Std.rand2f(.7,1) => mod2sustain;
Std.rand2(0,1500) => mod2release;



modenv[1].set (mod1attack * 1::ms, mod1decay * 1::ms, mod1sustain, mod1release * 1::ms);
modenv[2].set (mod2attack * 1::ms, mod2decay * 1::ms, mod2sustain, mod2release * 1::ms);


env[1].set( lhattack*2::ms, 600::ms, .5, lhrelease*3::ms );
env[2].set( lhattack*2::ms, 600::ms, .5, lhrelease*3::ms );
env[3].set( rhattack*2::ms, 600::ms, .5, rhrelease*3::ms );
env[4].set( rhattack*2::ms, 600::ms, .5, rhrelease*3::ms );
Std.rand2(50,700) => m1g; // modulator gain
Std.rand2(50,800) => m2g;
Std.rand2(-1,2) => m1rf; // modulator relative frequency
Std.rand2(-1,3) => m2rf;
lhroot + m1rf*12 => Std.mtof => mod[1].freq;
rhroot + m2rf*12 => Std.mtof => mod[2].freq;
m1g => mod[1].gain;
m1g => mod[2].gain;

if (chatty > 1)
{
<<<"LHattack",lhattack,"RHattack", rhattack,"">>>;
<<<"RHrelease", lhrelease,"RHrelease",rhrelease,"\n","">>>;
<<<"LH root",lhroot,"LH interval",lhinterval,"">>>;
<<<"Mod1 gain",m1g,"Mod1 relative frequency",m1rf*12,"">>>;
<<<"RH root", rhroot,"RH interval", rhinterval,"">>>;
<<<"Mod2 gain",m2g,"Mod2 relative frequency",m2rf*12,"\n","">>>;
}

lhroot => Std.mtof => lh[1].freq;
lhroot + lhinterval => Std.mtof => lh[2].freq;
rhroot => Std.mtof => rh[1].freq;
rhroot + rhinterval => Std.mtof => rh[2].freq;


lhrelease + rhrelease * 8 => newdelay;

10 => float maxplay;
2 => float minplay;
Std.rand2f(0,maxplay) => weight; // occasionally play only one hand

if (weight < (maxplay-minplay))
{
spork ~rhplay();
}
else
{
if (chatty >1) <<<"lh skipped","">>>;
}
if (weight > minplay)
{
spork ~lhplay();
}
else
{
if (chatty >1) <<<"rh skipped","">>>;
}



numberofclustersplayed++;
if (chatty > 1) <<<"Waiting",newdelay,"">>>;
if (chatty > 0)
{
<<<"Time Elapsed:", (now - start_time ) / 44100::samp >>>;
<<<numberofclustersplayed,"">>>;
}

newdelay * 1::ms => now;
} // End main loop

fun void lhplay ()
{
Std.rand2(0,32) * 50::ms => now;
env[1].keyOn();
env[2].keyOn();
modenv[1].keyOn();
lhattack * 2::ms => now;
Std.rand2(0,32) * 50::ms => now;
env[1].keyOff();
env[2].keyOff();
modenv[1].keyOff();

}

fun void rhplay ()
{
Std.rand2(1,32) * 50::ms => now;
env[3].keyOn();
env[4].keyOn();
modenv[2].keyOn();
lhattack * 2::ms => now;
Std.rand2(0,32) * 50::ms => now;
env[3].keyOff();
env[4].keyOff();
modenv[2].keyOff();

}

credits

from Icosahedraly Yours, Loscha, released January 14, 2018
By Edward r Jones aka Loscha, inspired by Paul Lansky

license

all rights reserved

tags

about

Loscha Melbourne, Australia

Loscha is the artistic Pseudonym of Edward Jones.
He has multiple disabilities, and is on the Autistic Spectrum.
These works explore texture, memory, and coaxing sounds from little black metal boxes.

contact / help

Contact Loscha

Streaming and
Download help

Redeem code

Report this track or account

If you like Loscha, you may also like: