!! Supercollider-Server und Perl-Client via Midi-Nachfolger OSC 

Alle Details auf der Originalseite von Alex ~McLean: 
http://www.perl.com/pub/a/2004/08/31/livecode.html "''Hacking perl in nightclubs''"

Alex schlägt ein Script simple.sc für den Supercollider-Server vor, Inhalt siehe unten.
 
Gestartet wird das fertige Script mit  
%%prettify 
{{{
sclang ./simple.sc -:
}}}
/%

Also, laut Alex lautet der Quellcode für simple.sc:

%%prettify 
{{{
// by alexatslabdotorg
// http://yaxu.org/

// simple.sc - a rather naive but working SuperCollider patch containing 
// a synthesiser and sample player
//
// Copyright (C) Alex McLean 2004
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



(
  var s, response, buffers;
  s = Server.local;
  s.freeAll;
  s.latency = 0;
  buffers = Dictionary.new;

  SynthDef("synthy", { arg freq=440,formfreq=100,gate=0.0,bwfreq=200,ts=1,lgain=1,rgain=1,
                       crackle=0, browndel=0, envtype;
                        var x;
                        x = Formant.ar(
                                       [freq - 0.1, freq + 0.1],
                                       formfreq,
                                       bwfreq
                                      );
                        x = x + if (crackle > 1.5, Crackle.ar(crackle), 0);
                        x = x * [lgain, rgain];
                                               x = if (browndel > 0, 
                                DelayN.ar(x, 0.02, 0.02, 1, BrownNoise.ar(x.distort, 0) * browndel), 
                                x
                               );
                        x = EnvGen.kr(Env.perc,
                                      doneAction: 2, timeScale: ts
                                     ) * x;
                        Out.ar(0, x);
                      }
          ).send(s);

  SynthDef('player',
           { arg out=0, bufnum=0, rate=1, lgain=1, rgain=1, ts=1, crackle=1, browndel=0;
             var x, y, buffer, delayedSignal, mixedSignal;
             x = PlayBuf.ar([1, 1], bufnum, rate);
             x = x + if (crackle > 1.5, Crackle.ar(crackle), 0);
             x = x * [lgain, rgain];
             x = if (browndel > 0, 
                     DelayN.ar(x, 0.02, 0.02, 1, BrownNoise.ar(x.distort, 0) * browndel), 
                     x
                    );
             x = EnvGen.kr(Env.perc, doneAction: 2, 
                                     timeScale: ts) * x;
             Out.ar(0, x);
           }
          ).send(s);


  response = { 
    arg time, responder, message; 
    var mybuf, sample, lgain, rgain, crackle, noise, ts, browndel, rate, envtype;
    if (message[1] == 'on',
      {
        sample   = message[2];
        lgain    = message[3];
        rgain    = message[4];
        crackle  = message[5];
        noise    = message[6];
        ts       = message[7];
        browndel = message[8];
       rate     = message[9];
        envtype  = message[10];

        mybuf = buffers.at(sample);
        if (mybuf == nil, 
            {mybuf = Buffer.read(s, sample);
             buffers.add(sample -> mybuf);
            }
           );
        
        SystemClock.sched(time - Date.getDate.rawSeconds,
          {Synth.new("player", [
                                \lgain, lgain / 100, 
                                \rgain, rgain / 100, 
                                \crackle, crackle / 100,
                                \browndel, browndel / 100,
                                \ts, ts / 100,
                                \rate, rate / 100,
                                \envtype,  envtype,
                                \out, 
                                0, 
                                \bufnum, mybuf.bufnum]
                     ); 
                    nil
          }
        );
      });
    };

    o = OSCresponder(nil, '/trigger', response);
    o.add;


  response = { 
    arg time, responder, message; 
    if (message[1] == 'on',
      {
        SystemClock.sched(time - Date.getDate.rawSeconds,
          {Synth("synthy", [\num,      message[2],
                             \formfreq, message[3] / 127 * 1000,
                             \bwfreq,   message[4] / 127 * 1000,
                             \ts,       message[5] / 100,
                             \freq,     message[2].midicps / 4.0,
                             \lgain,    message[6] / 100,
                             \rgain,    message[7] / 100,
                             \crackle,  message[8] / 100,
                             \browndel, message[9] / 100,
                             \envtype,  message[10]
                            ]
                ); nil;
          };
        );
      });
    };

    o = OSCresponder(nil, '/play', response);
    o.add;

    "[started]".postln;
)
}}}
/%

Quelle: http://cpan.org/authors/id/Y/YA/YAXU/perl-music-article/examples/simple.sc

!! Hier nun die Clientseite mit Perl

The simple.sc script listens for OSC messages, which you can send from feedback.pl using the built in methods ‘play’ and ‘trigger’ like this:

You’ll need a few modules installed from CPAN to get it to work. %%strike Audio::Beep/%, Audio::OSC and Time::HiRes.\\
...\\
Once everything is ready, run [feedback.pl|http://cpan.org/authors/id/Y/YA/YAXU/perl-music-article/examples/feedback-0.1.pl] and type this little script in: 

%%prettify 
{{{
  sub bang {
      my $self = shift;
      $self->code->[0] = '# ' . $self->{bangs};
      $self->modified;
  }
}}}
/%

Press ctrl-x and it will start to run. $self->{bangs} contains the number of bangs since the script was started, and this is written to the first line of the code (make sure that line doesn’t have anything important in it). Calling $self->modified tells the editor that the code has changed, causing it to refresh the screen with the changes.

OK, lets make some sounds.

%%prettify 
{{{
  sub bang {
      my $self = shift;
      # play a "middle c" note every fourth bang
      $self->play({num => 60})
        if $self->{bangs} % 4 == 0;
  }
}}}
/%


You can also trigger a sample in this way:

%%prettify 
{{{
  sub bang {
      my $self = shift;
      # play a drum sample for 100 milliseconds, panned slightly to the left,
      # every sixth bang
      $self->trigger({sample => '/home/alex/samples/drum.wav'
                      ts     => 100,
                      pan    => 0.4
                     }
                    )
        if $self->{bangs} % 6 == 0;
  }
}}}
/%

für Fortgeschrittene schreibt Alex:\\
It gets weirder – the running code can edit its own source code. This is really useful for user feedback. 
I quite often write code that puts comments in its source that tells me what the running code is up to. 
So, the human interface to the running code is its source code. 
You edit the code to modify the process; the process edits the code in response. 
That’s why it’s called feedback.pl.

If you want to see what I mean, download feedback.pl from:

http://cpan.org/authors/id/Y/YA/YAXU/perl-music-article/examples/feedback-0.1.pl

Check the source code of feedback.pl to see how the OSC message is sent, and to seek out extra parameters to effect the sound further.