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;




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






// 18
// Nathaniel Virgo
(
play{
    p = PinkNoise.ar(1!2);
    BRF.ar(
        p + Blip.ar(p+2,400),
        150,
        2,
        0.1
    )
    +
    LPF.ar( FreeVerb2.ar( *LPF.ar( p + 0.2 * Dust.ar( 0.1 ), 60) ++ [ 1, 1, 0.2, 1e4 ]).tanh, 2000)
}
)





(1!2).postln -> [ 1, 1 ]
PinkNoise *ar (mul: 1.0, add: 0.0)
PinkNoise.ar([1,1])

Genera rumore rosa il cui spettro decade in potenza di 3 dB per ottava, il che fornisce uguale potenza nell'arco di ciascuna ottava. Questa versione ha un limite di banda di 8 ottave.

Al rumore rosa viene aggiunto un segnale

Blip.ar(freq: 440.0,  numharm: 200.0,  mul: 1.0,  add: 0.0)
che è un segnale di impulsi limitato in banda; il numero di armoniche nel nostro caso è settato a 400; la frequenza è data dal doppio PinkNoise; quella specie di rumore di gocce di acqua che cadono che si sente è dovuto all'UGen Blip.ar;

il segnale risultante è fatto passare in un filtro risonante rifiuta banda, BRF.ar(in: 0.0, freq: 440.0, rq: 1.0, mul: 1.0, add: 0.0)



BRF.scopeResponse

a questo segnale è aggiunto un secondo segnale :




















LPF.ar( FreeVerb2.ar( *LPF.ar( p + 0.2 * Dust.ar( 0.1 ), 60) ++ [ 1, 1, 0.2, 1e4 ]).tanh, 2000)

Un "*" prima di un array all'interno di una funzione divide gli elementi dell'array e li passa agli args, nel nostro caso alla UGen FreeVerb2.ar. Diventa più chiaro facendo questo con il metodo Array.with che genera un nuovo array e prevede elementi separati.

Array.with(*LPF.ar (PinkNoise.ar (1! 2) + 0.2 * Dust.ar (0.1), 60) ++ [1, 1, 0.2, 1e4])
-> [ a LPF, a LPF, 1, 1, 0.2, 10000.0 ]

quindi la UGen avra questi args : FreeVerb2.ar(in: LPF,  in2: LPF,  mix: 1,  room: 1,  damp: 0.2,  mul: 10000.0,  add: 0.0)

questo segnale genera un forte boato, 1 volta ogni 10 secondi circa, dovuto all'impulso creato dal Dust moltiplicato per il Rumore Rosa;

La precedenza sinistra-destra di SC provoca l'aggiunta di un offset di 0,2 (al Rumore Rosa stereo) prima della moltiplicazione con l'impulso Dust.
La funzione sigmoide tanh mantiene il segnale tra -1 e + 1;

Per quanto riguarda l'offset di 0,2. Ho solo un presupposto: il file di aiuto di PinkNoise dice:

NOTA: è stato osservato che i valori prodotti da questa UGen sono molto probabilmente tra -0,65 e +0,81 circa (prima di essere moltiplicati per mul).

Quindi potrebbe essere che l'intenzione fosse quella di mantenere il segnale all'incirca al di sotto di 1, con probabilità molto alta.

// Modo per attivare e esplorare le Eccezioni con la GUI

Exception.debug = true;

// Metodo per salvare l'immagine del Plot

p= {BRF.ar( PinkNoise.ar(1!2) + Blip.ar(PinkNoise.ar(1!2)+2,400), 150, 2, 0.1) }.plot(10);
i = Image.fromWindow(p.parent, p.interactionView.bounds);
i.write("~/concat.png".standardizePath);
i.free

// Metodo per tracciare una Synth

(
SynthDef(\resonz, { |out, freq = 440|
    var    sig, ffreq;
    sig = PinkNoise.ar(1!2);
    Out.ar(out, FreeVerb2.ar( *LPF.ar( sig + 0.2 * Dust.ar( 0.1 ), 60) ++ [ 1, 1, 0.2, 1e4 ]).tanh, 0.1)
}).send(s);

)

a = Synth(\resonz);
a.trace;

// Metodo per capire come è composto un segnale

sig = PinkNoise.ar(1 ! 2).postln;
sig = LPF.ar (sig + 0.2 * Dust.ar(0.1), 60).postln;
sig = (sig ++ [1, 1, 0.2, 1e4]).postln;
sig = FreeVerb2.ar(*sig).postln;

Reverse Engineering di un sc-tweet di Rukano

play{a[1,1.01,2,2.02,3.5,4.01,5.501];SinOsc.ar(Duty.kr(0.2,0,Dseq([10,11,0,12.2,0,0,10,0]+39,inf).midicps)*(a++(a*2))).sum!2/10}//DAF #sc

Un Oscillatore Sinusoidale, SinOsc.ar, la cui frequenza è estratta dalla lista di Dseq dall'UGen Duty ogni 0.2 secondi; il tutto è moltiplicato per 14 valori ottenuti concatendando l'array di 7 valori "a" al doppio di se stesso; quindi per ogni elemento estratto ogni 0.2 secondi da Duty.kr abbiamo 14 Sinusoidi che poi vengono sommate in un unico segnale; il segnale ottenuto viene poi duplicato sul canale sinistro e destro dell'uscita; l'ampiezza è divisa per 10;





















SinOsc.ar(freq: 440,  phase: 0.0,  mul: 1.0,  add: 0.0)

Duty.kr(dur: 1.0,  reset: 0.0,  level: 1.0,  doneAction: 0)

ogni "dur" secondi, viene richiesto un valore da ogni Ugen nella lista; nel nostro caso ogni 0.2 secondi, viene richiesto un elemento della lista ([10,11,0,12.2,0,0,10,0]+39).midicps che viene generato dalla Ugen Dseq;





















Dseq.new(list, repeats: 1)

Generatore di sequenze; genera un valore appartenente alla lista, ogni volta che viene interrogato da Ugen tipo Demand, Duty, Drand, ecc.

{a[1,1.01,2,2.02,3.5,4.01,5.501];SinOsc.ar(Duty.kr(0.2,0,Dseq([10,11,0,12.2,0,0,10,0]+39,inf).midicps)*(a++(a*2)))}.plot(10)





















(a++(a*2))
[ 1, 1.01, 2, 2.02, 3.5, 4.01, 5.501, 2, 2.02, 4, 4.04, 7.0, 8.02, 11.002 ]



play{AY.ar((Hasher.ar(Latch.ar(AY.ar((1..3)!2),Impulse.ar([7/3,1])))*337+317).round(73),0,LFNoise2.ar(3,1/3,1/3))/7}//#supercollider

AY.ar(tonea: 1777,  toneb: 1666,  tonec: 1555,  noise: 1,  control: 7,  vola: 15,  volb: 15,  volc: 15,  envfreq: 4,  envstyle: 1,  chiptype: 0,  mul: 1,  add: 0)

Emula lo strumento AY-3-8910 (a.k.a. the Yamaha YM2149) a tre voci, tre suoni chip.

i tre suoni chip :

tonea : (Hasher.ar(Latch.ar(AY.ar((1..3)!2),Impulse.ar([7/3,1])))*337+317).round(73)
toneb : 0
tonec : LFNoise2.ar(3,1/3,1/3)

Latch.ar(in: 0.0,  trig: 0.0)

Il Latch mantiene l'input quando viene triggherato e genera zero all'inizio fino a quando non viene triggherato; nel nostro caso è triggherato da un doppio generatore di impulsi; quindi probabilmente il Latch campiona due valori secondo frequenze diverse;

questo è il segnale che viene campionato sui due canali stereo secondo il trig dei due impulsi;

{AY.ar((1..3))}.plot





































{Latch.ar(AY.ar((1..3)!2),Impulse.ar([7/3,1]))}.plot





















{(Hasher.ar(Latch.ar(AY.ar((1..3)!2),Impulse.ar([7/3,1])))*337+317).round(73)}.plot(10)





















Hasher.ar(in: 0.0,  mul: 1.0,  add: 0.0)

L'Hasher è un generatore Hash, che genera valori tra -1 e 1 a seconda dell'input che riceve secondo una funzione Hash; lo stesso valore di input genererà lo stesso valore hash in output; il segnale di input non ha bisogno di essere nel range di -1 e 1.


Impulse.ar(freq: 440.0,  phase: 0.0,  mul: 1.0,  add: 0.0)

Genera in output impulsi non limitati in banda; in teoria quindi se si superano i 22050 Herz di frequenza avremo un mirror nello spettro in frequenza?

round

round(a, b)
a round: b
a.round(b)

Arrotonda al più vicino multiplo di b;

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

{LFNoise2.ar(3,1/3,1/3)}.plot(10)





















Genera valori casuali interpolati quadraticamente ad una velocità data dalla divisione intera più vicina della frequenza di campionamento freq.
copiare gli sc di supercolliderenoise.tgz in /usr/share/SuperCollider/SCClassLibrary/Common/Renoise/
tutti tranne ResponseDefs.sc che va in  /usr/share/SuperCollider/SCClassLibrary/Common/Control/


// declare an event type which sends OSC commands to Renoise

(
Event.addEventType(\renoise, { |server|
  var renoiseOscServer = NetAddr("127.0.0.1", 8000);
  var notes = [~midinote.value, ~ctranspose.value, ~velocity.value, ~sustain.value, ~lag.value, ~timingOffset.value, ~instr.value, ~track.value].flop;
  var timeNoteOn, timeNoteOff, instrument, track, velocity;
  var serverLatency;

  serverLatency = server.latency ? 0;

  notes.do {|note|
    instrument = note[6] ? -1;
    track = note[7] ? -1;
    velocity = note[2].asInt.clip(0,127);

    // sustain and timingOffset are in beats, lag is in seconds
    timeNoteOn = (thisThread.clock.tempo.reciprocal*note[5])+note[4]+server.latency;
    timeNoteOff = (thisThread.clock.tempo.reciprocal*(note[3]+note[5]))+note[4]+server.latency;
    SystemClock.sched(timeNoteOn, {renoiseOscServer.sendMsg("/renoise/trigger/note_on", instrument.asInt, track.asInt, (note[0]+note[1]).asInt, velocity )});
    SystemClock.sched(timeNoteOff, {renoiseOscServer.sendMsg("/renoise/trigger/note_off", instrument.asInt, track.asInt, (note[0]+note[1]).asInt)});
  }
});
)

// Now start Renoise OSC server, load a sample, and try some patterns

// straight timing
(
Pbind(*[
  type: \renoise,
  legato: Pgauss(0.2,0.05,inf),
  dur: 0.2,
  degree: [2,5,12],
  track: Prand([0,1], inf),
  ctranspose: Pseq([0,0,0,0,4,4,4,4,5,5,5,5],inf),
  velocity: Pgauss(64,10,inf),
]).play;
)

// loose timing
(
Pbind(*[
  type: \renoise,
  legato: 0.1,
  dur: 0.2,
  midinote: [66, 69, 74],
  lag: Pwhite(-0.05!3, 0.05)
]).play;
)


MIDIClient.init;
MIDIIn.connectAll;
r = Renoise();
r = Renoise("127.0.0.1", 8000);


(
SynthDef(\sound, { |out = 0, gate = 1, freq = 440, amp = 0.5|
    var sig, env;

    env = EnvGen.kr(Env.adsr(0.01, 0.9, 0.3, 1), gate, doneAction: 2);

    sig = Pulse.ar(freq) * amp * env;

    Out.ar(out, sig);
}).add
)

r.createSynthDefInstrument(\sound)


















s = Server.default.boot;

// create a new analyzer

FreqScope.new(400, 200, 0, server: s);

(
{
var carrier, modulator, carrfreq, modfreq;
carrfreq= MouseX.kr(440,5000,'exponential');
modfreq= MouseY.kr(1,5000,'exponential');
carrier= SinOsc.ar(carrfreq,0,0.5);
modulator= SinOsc.ar(modfreq,0,0.5);
carrier*modulator;
}.scope
)






si definisce prima una SynthDef chiamata bz che crea un suono sinusoidale stereo a 80Hz di frequenza
poi con il Pbind come nel secondo caso si crea una sequenza di degree (convertiti in frequenza) usando la nona ottava, ogni nota dura 0.1 e ha una amp di 0.05

per quanto riguarda lo Routine, si definisce un'insieme di comandi che vengono poi chiamati in sequenza dalla direttiva r.next, difatto un metodo della routine r;


santjago3.altervista.org/_altervista_ht/oscrenoise.tgz

# sc - renoise
[SuperCollider][] and [Renoise][] extensions that allow integration of the two tools.

## Status
Currently only a single part of the SC extension exists. The class
does two things currently:

*    Maps SynthDef's to Renoise instruments such that they can be     sequenced/played/recorded in the manner of any other Renoise     instrument.
  
*    Provides quick access to all of Renoise's [OSC commands][]

Although this code is functional you should note that this is work in progress and is likely to change significantly.

It's only been tested on Linux with Jack installed.