p={Saw.ar(SinOsc.kr(30,0,440,440),mul:0.2)+AY.ar(SinOsc.kr(1200,0,713,713),mul:0.5);}.plot(0.01);

(
{
 var snd,cutoff;
 snd=Saw.ar(SinOsc.kr(30,0,440,440),mul:0.2)+AY.ar(SinOsc.kr(1200,0,713,713),mul:0.5);
 cutoff=Saw.kr(50,0.3,0.3)+PinkNoise.kr(0.1);
 snd=CombN.ar(snd,0.01,XLine.kr(0.00713, 1, 140),0.2);
 snd=RLPF.ar(snd,713*cutoff,0.2);
 snd!2;
}.plot(0.1);
)

il suono principale nasce dalla sovrapposizione tra un segnale a dente di sega modulato in frequenza da una sinusoide e il suono generato dal chip sonoro AY, modulato in frequenza sempre da una sinusoide;

la cutoff del Filtro Passa Basso Risonante RLPF è modulata da un segnale di controllo che è dato dalla somma tra un segnale a dente di sega e un segnale generato da un generatore di rumore rosa la cui ampiezza è moltiplicata per 0.1;

il delaytime, tempo di ritardo, della linea di ritardo del Filtro a Pettine CombN senza interpolazione è modulato da un generatore di curva esponenziale, che in 140 secondi passa dal valore 0.00713 al valore 1; il suono fatto passare in questa linea di ritardo subisce una trasformazione a livello timbrico, dovuta a cancellazione e rafforzamento di diverse armoniche; lo spettro armonico del segnale risultante assume la forma di un pettine; il passaggio attraverso questo Filtro produce un carattere metallico nel timbro finale del suono;






s.boot;

p={RLPF.ar(Pulse.ar([11, 13]), LFNoise1.ar([3, 7], 200, 300), 0.01)*0.1}.plot;
play({RLPF.ar(Pulse.ar([11, 13]), LFNoise1.ar([3, 7], 200, 300), 0.01)*0.1})





















qui abbiamo un RLPF, un filtro passa basso risonante che intercetta due Pulse a bassa frequenza, e CutOff modulato da un UGen LFNoise1 che genera valori random interpolati linearmente a un rate dato dalla frequenza; in questo caso sono due le Ugen in gioco; normalmente l'LFNoise1 genera valori random tra -1 e 1, in questo caso tra 100 e 500; l'rq del filtro è impostato a 0.01, sarebbe il reciproco di q; q è dato dal rapporto tra la CutOff e la larghezza di banda; in questo caso, minore è il valore di rq e più risonanza avra il filtro; il tutto è moltiplicato per 0.1 per attenuare l'ampiezza del segnale in uscita;

RLPF.ar(in: 0.0, freq: 440.0, rq: 1.0, mul: 1.0, add: 0.0)

RLPF.scopeResponse;
























(
{
GVerb.ar((
{
var burstEnv, att = 0, dec = 0.001;
var burst, delayTime, delayDecay = 0.1;
var midiPitch = 37; // A 440
delayTime = midiPitch.midicps.reciprocal;

burstEnv = EnvGen.kr(Env.perc(att, dec), gate: PinkNoise.kr(1/delayDecay));
burst = PinkNoise.ar(burstEnv);
CombL.ar(burst, delayTime, delayTime,delayDecay, add: burst);
}
),270,30,0.7,drylevel:0.5)
}.play
)

p={LFNoise1.kr(freq: 500.0, mul: 1.0, add: 0.0)}.plot(5);





















qui abbiamo un segnale PinkNoise che viene fatto passare attraverso una linea di ritardo a pettine, Comb Filter, con interpolazione lineare; il segnale passando attraverso questa linea di ritardo e subendo delle inversioni di fase per diverse frequenze del suo spettro, una volta sommato al segnale originale produce questo spettro a pettine dovuto alla sovrapposizione del segnale diretto e alla copia del segnale leggermente ritardata e quindi alla cancellazione e il rinforzo di diverse frequenze; la somma tra i due timbri produce quindi rinforzi e annullamenti periodici nell'ampiezza dello spettro passante; il trattamento fornito dal Comb Filter aggiunge al segnale passante una severa componente metallica; l'ampiezza del segnale PinkNoise è modulata da un inviluppo percussivo attivato attraverso il gate da un altro segnale PinkNoise di controllo; il tutto è fatto passare all'interno di una Ugen di riverbero;


p={PinkNoise.ar(10)}.plot;




















i = Image.fromWindow(p.parent, p.interactionView.bounds);
i.write("~/Desktop/pinknoise.png".standardizePath);
i.free




Reverse Engineering SCCode : «Kepler 22-b atmosphere» by vividsnow




(
fork {   
    Ndef(\ttwnd).play; //(d,2,addAction:\addToHead);
    loop {
        var seed = thisThread.randSeed = 100000000.rand.debug('seed');
        Ndef(\ttwnd, {
            var freq = [20, 7500];
            Splay.ar(
                {
                    var bands = 2.rrand(10);
                    var sig = { [BPF,RLPF,RHPF].choose.ar(
                        LFNoise2.ar(freq[0].rrand(freq[1]), LFNoise2.kr(0.1.exprand(10))),
                        Array.rand(bands, freq[0], freq[1]),
                        Array.rand(bands, 0.2, 1.8)
                    ).mean } ! 2;
                    Rotate2.ar(sig[0], sig[1], LFSaw.kr(0.1.exprand(10)));
                } ! 4.rrand(6).debug('source'), // creazione dell'array da passare a Splay
                                0.5.rrand(1) // spread dell'Splay
            );
        }).fadeTime_(1.rrand(4.0)); // fadeTime randomico
        10.0.rrand(40).debug('wait(bts)').wait;
    }
}
)

Struttura del codice, un loop interno a una Routine;
qui una versione semplificata;

(

{

loop {   
    "1*********".postln;
    1.0.wait;   
    "2*********".postln;
    1.0.wait;   
    "3*********".postln;
    1.0.wait;   
    "4*********".postln;
    1.0.wait;   
}
   

}.fork;    

)

UGen :

Ndef è una definizione di un Nodo Proxy;

Ndef registra i Synth attraverso un nome chiave. Tutti gli accessi ai Synth registrati attraverso l'Ndef avvengono tramite quel nome chiave. I Synth registrati possono essere sostituiti con altri Synth durante la riproduzione. I Synth si dissolvono e vengono sostituiti automaticamente e il tempo di sostituzione può essere quantificato.

Ndef è un riferimento in un Proxy, costituisce un'alternativa al ProxySpace. Tutti i metodi sono ereditati da NodeProxy.


thisThread.randSeed = 100000000.rand.debug('seed'); il seed, il seme della distribuzione randomica del thread;


Splay spalma sui canali stereo un array di canali,

Splay.arr(inArray, spread: 1, level: 1, center: 0.0, levelComp: true)

spread = 0, tutti i canali finiscono al centro, 1 massima diffusione, immagino parli del pan?


[BPF,RLPF,RHPF].choose sceglie ogni volta il tipo di filtro, passa band, passa basso risonante, passa alto risonante;


LFNoise2 generatore di rumore, genera valori random, interpolati quadraticamente,

Interpolazione. L'interpolazione consiste nel processo utile a determinare la "migliore" stima dei valori di una funzione f(x) quando ci sono a disposizione solo un numero finito di punti noti. L'Interpolazione lineare può introdurre notevoli errori nella stima dei valori della funzione per l'assenza di curvatura. Ma avendo a disposizione tre punti è possibile introdurre una curvatura del secondo ordine (parabola) per interpolare meglio i dati;

f2(x)=a0+a1x+a2x^2

LFNoise2.ar(freq: 500.0, mul: 1.0, add: 0.0)

Analisi Codice :

Splay.ar(
                {
                    var bands = 2.rrand(10);
                    var sig = { [BPF,RLPF,RHPF].choose.ar(
                        LFNoise2.ar(freq[0].rrand(freq[1]), LFNoise2.kr(0.1.exprand(10))),
                        Array.rand(bands, freq[0], freq[1]),
                        Array.rand(bands, 0.2, 1.8)
                    ).mean } ! 2;
                    Rotate2.ar(sig[0], sig[1], LFSaw.kr(0.1.exprand(10)));
                } ! 4.rrand(6).debug('source'), // creazione dell'array da passare a Splay
                                0.5.rrand(1) // spread dell'Splay
            )


viene prima scelto randomicamente il numero di bands;
il segnale viene creato facendo passare attraverso un filtro (BPF, RLPF o RHPF) un generatore di rumore a interpolazione quadratica

RLPF.ar(in: 0.0, freq: 440.0, rq: 1.0, mul: 1.0, add: 0.0)

in : LFNoise2.ar
freq : Array.rand(bands, freq[0], freq[1])

Array.rand(size, minVal, maxVal) // quindi qui avviene un'espansionzione multicanale a seconda del numero scelto per bands

rq : Array.rand(bands, 0.2, 1.8), la frequenza di risonanza; il reciproco di Q (bandwidth/cutoffFreq)

dopo di che interviene .mean che

collassa tutti i canali su un canale e poi il !2 che li espande su due canali;

{(SinOsc.ar(440)!2).mean}.plot  // verifica del funzionamento di .mean
{(SinOsc.ar(440)!2)}.plot
{(SinOsc.ar(440)!2).mean}.play
{(SinOsc.ar(440)!2)}.play

i due segnali sig[0] e sig[1] vengono passati a Rotate2

Rotate2 prende questi due segnali, in questo caso i due canali stereo, e li ruota spazialmente, in base a un angolo che in questo caso è fornito dall'output dell'UGen LFSaw, che è un oscillatore "dente di sega" non limitato in banda;

! 4.rrand(6).debug('source'); // creazione dell'array da passare a Splay, da 4 a 6 elementi;

che prende questo array di canali e li spalma su i due canali stereo;


0.1.exprand(10); genera valori random da 0.1 a 10 con probabilità esponenziali; dall'osservazione sembrano più probabili i valori bassi; in effetti dal grafico, sono più probabili i valori bassi;




rrand funzione che serve a generare valori random;

1.rrand(4.0) random da 1 a 4

wait(bts) è una stringa di debug