‹ RedBMPEco ›

A Script that Rules the World

2010-11-21 01:26 supercollider

clean-up #6:

This is a hack from 2007. It was done in CocoaCollider, but now I updated it using the standard SCNSObject in SuperCollider. It works by talking to Google Earth via AppleScript.

//redFrik 2007 - updated 2010
//req. mac OSX, Google Earth, SC 3.6

//--init
(
s.waitForBoot{
    SynthDef(\redGoogleKick, {|out= 0, t_trig= 1, freq= 50, dur= 0.5, envFreq= 500, envAtk= 0.005, envRel= 0.1, amp= 1|
        var z, env, fenv, click;
        env= EnvGen.ar(Env.linen(0, 0, dur, amp), t_trig);
        fenv= EnvGen.kr(Env([envFreq, envFreq-freq*0.275+freq, freq], [envAtk, envRel]), t_trig);
        click= EnvGen.ar(Env.linen(0, 0, 0), t_trig);
        z= SinOsc.ar(fenv, 0, env, click);
        Out.ar(out, z);
    }).add;
    SynthDef(\redGoogleSynth, {|out= 0, t_trig= 1, freq= 200, atk= 0.005, dec= 0.5, pm= 0.5, amp= 1|
        var z, env, pmod;
        env= EnvGen.kr(Env.perc(atk, dec, 1, -3), t_trig);
        pmod= LFSaw.ar(freq*2.pow(TIRand.kr(1, 3, t_trig)), 0, env*pm);
        z= SinOsc.ar(freq, pmod, env);
        Out.ar(out, z*amp);
    }).add;
    SynthDef(\redGoogleDelay, {|in= 0, out= 0, depth= 3, time= 0.45, amp= 1, dist= 2, pan= 0|
        var src, z;
        src= In.ar(in, 1);
        z= CombL.ar(src, 1.5, time.min(1.5), depth, amp, src);
        Out.ar(out, Pan2.ar(Clip.ar(z*dist, -1, 1), pan));
    }, #[\ir, \ir, 0, 0.5, 0, 0, 0]).add;
};
f= {|cmd|
    {
        var o;
        o= SCNSObject("NSAppleScript", "initWithSource:", ["tell application \"Google Earth\"\n"++cmd++"\nend tell"]);
        o.invoke("executeAndReturnError:", [nil], true);
        o.release;
    }.defer;
};
f.value("open");
)

//--run (wait until localhost and google earth started, also disable all overlays in google earth)
(
f.value("SetViewInfo{latitude:0, longitude:0, distance:10000000, tilt:0, azimuth:0} speed 5");
d= Synth(\redGoogleDelay, [\out, 0, \in, 32]);
k= Synth(\redGoogleKick, [\t_trig, 0]);
e= Synth(\redGoogleSynth, [\out, 32, \t_trig, 0]);
Tdef(\redGoogle).play;
Tdef(\redGoogle, {
  var dist, xxx= 0, yyy= 0;
  300.do{|i|
    if(i%25==0, {
      if(i%100==0, {
        k.set(\t_trig, 1, \amp, 0.1, \out, 32, \freq, 2000, \dur, 1.5, \envAtk, 0.005, \envRel, 0.2);
      });
      e.set(\t_trig, 1, \freq, [500, 600, 700].wrapAt(i), \amp, 0.5, \dec, 0.5, \pm, 0.2);
      if(i%4==0, {
        xxx= xxx+1.0.rand2;
        yyy= yyy+20.rand2;
        f.value("SetViewInfo{latitude:"++1.0.rand2++", longitude:"++yyy++", distance:10000000, tilt:0, azimuth:0} speed 0.4");
      });
    });
    (1/25).wait;
  };
  f.value("SetViewInfo{latitude:0, longitude:0, distance:10000000, tilt:0, azimuth:0} speed 0.5");
  300.do{|i|
    if(i%25==0, {
      dist= [400, 600, 700, 800].wrapAt(i);
      k.set(\t_trig, 1, \amp, 1, \out, 32, \freq, 50, \dur, 0.5, \envAtk, 0.005, \envRel, 0.1);
      e.set(\t_trig, 1, \freq, dist, \amp, 0.5, \dec, 0.5, \pm, 1-(i/300));
      f.value("SetViewInfo{latitude:0, longitude:0, distance:"++8000000++", tilt:"++45.rand++", azimuth:0} speed 5");
    }, {
      if(i%25==1, {
        f.value("SetViewInfo{latitude:0, longitude:"++([100, -100].choose)++", distance:"++5000000++", tilt:0, azimuth:10} speed 0.5");
      });
    });
    (1/25).wait;
  };
  d.set(\dist, 4);
  f.value("SetViewInfo{latitude:52.45, longitude:-1.93, distance:300, tilt:0, azimuth:0} speed 0.5");
  50.do{|i|
    if(i%25==0, {
      k.set(\t_trig, 1, \amp, 1, \out, 32, \freq, 50, \dur, 0.5, \envAtk, 0.005, \envRel, 0.1);
      e.set(\t_trig, 1, \freq, [100, 500, 600, 700].wrapAt(i), \amp, 0.5, \dec, 1.1, \pm, 2);
    });
    (1/25).wait;
  };
  d.set(\dist, 5);
  500.do{|i|
    if(i%25==0, {
      k.set(\t_trig, 1, \amp, 1, \out, 32, \freq, 50, \dur, 0.5, \envAtk, 0.005, \envRel, 0.1);
      e.set(\t_trig, 1, \freq, [200, 500, 600, 700].wrapAt(i), \amp, 0.5, \dec, 1.1, \pm, 2);
      f.value("SetViewInfo{latitude:52.45, longitude:-1.93, distance:"++200.rrand(300)++", tilt:"++(i%45)++", azimuth:"++(i%180)++"} speed 1");
    }, {
      if(i%20==18, {
        k.set(\t_trig, 1, \amp, 0.3, \out, [0, 1].choose, \freq, [2100, 100].wrapAt(i), \dur, 0.9, \envAtk, 0.1.linrand, \envRel, i%3);
      })
    });
    (1/25).wait;
  };
})
)

f.value("quit");
/*
SCNSObject.dumpPool;
SCNSObject.freePool;
*/

Some notes:

There are two ways to run AppleScripts from within SuperCollider. One is to construct a string with osascript -e and a unixCmd, the other is creating a cocoa NSAppleScript object with the SCNSObject cocoa binding class. The later method is slightly more involved but runs way faster.

//--unixCmd version
"osascript -e 'tell application \"Finder\" to activate'".unixCmd;
"osascript -e 'tell application \"TextEdit\" to activate'".unixCmd;
//--NSObject version - this only work on old OSX SuperCollider versions
a= SCNSObject("NSAppleScript", "initWithSource:", ["tell application \"Finder\" to activate"]);
a.invoke("executeAndReturnError:", [nil], true);
a.release;

SCNSObject.dumpPool;  //should be 0
SCNSObject.freePool;  //free stray objects if any left

Also, I've attached a simple class that wraps the functionality. It's called RedEarth.

Attachments:
RedEarth.zip
‹ RedBMPEco ›