\section{Definições de sintetizador}
\label{sec:synthdef}
Até aqui, sem dificuldade alguma, pudemos \emph{definir} sintetizadores e fazê-los \emph{tocar} imediatamente. Além disso, a mensagem \texttt{.set} nos deu alguma flexibilidade para alterar os controles do sintetizador em tempo real. No entanto, há situações em que você pode querer definir seus sintetizadores antes (sem tocá-los imediatamente) e tocá-los somente depois. Em essência, isso significa que temos de separar o momento de escrever a receita (a definição de sintetizador) do momento de assar o bolo (criar o som).
\subsection{SynthDef e Synth}
\texttt{SynthDef} é o que usamos para "escrever a receita" de um sintetizador. Depois você pode tocá-la com \texttt{Synth}. Aqui está um exemplo simples.
\begin{lstlisting}[style=SuperCollider-IDE, basicstyle=\scttfamily\footnotesize]
// Definição de sintetizador com o objeto SynthDef
SynthDef("minhaSenoide1", {Out.ar(0, SinOsc.ar(770, 0, 0.1))}).add;
// Toque uma nota com o objeto Synth
x = Synth("minhaSenoide1");
x.free;
// Um exemplo ligeiramente mais flexível usando argumentos
// e um envelope com desligamento automático (doneAction: 2)
SynthDef("minhaSenoide2", {arg freq = 440, amp = 0.1;
var env = Env.perc(level: amp).kr(2);
var snd = SinOsc.ar(freq, 0, env);
Out.ar(0, snd);
}).add;
Synth("minhaSenoide2"); // usando os valores pré-definidos;
Synth("minhaSenoide2", [\freq, 770, \amp, 0.2]);
Synth("minhaSenoide2", [\freq, 415, \amp, 0.1]);
Synth("minhaSenoide2", [\freq, 346, \amp, 0.3]);
Synth("minhaSenoide2", [\freq, rrand(440, 880)]);
\end{lstlisting}
O primeiro argumento para a \texttt{SynthDef} é um nome para o sintetizador definido pelo usuário. O segundo argumento é uma função na qual você especifica um \emph{gráfico de UGens} (assim é chamada uma combinação de UGens). Note que você tem de usar \texttt{Out.ar} explicitamente para indicar para qual canal você quer enviar o sinal. Finalmente, a \texttt{SynthDef} recebe a mensagem \texttt{.add} ao final, que diz que você está a adicionando a uma coleção de sintetizadores que o SC conhece. Isso fica valendo até a hora que você fechar o SuperCollider.
Depois que você criar uma ou mais definições de sintetizador com \texttt{SynthDef}, você pode tocá-las com \texttt{Synth}: o primeiro argumento é o nome do sintetizador que você quer usar e o segundo argumento (opcional) é um array com quaisquer parâmetros que você queira especificar (freq, amp, etc.)
\subsection{Exemplo}
Eis um exemplo mais longo. Depois que a SynthDef é adicionada, nós utilizamos um truque com um array para criar um acode de 6 notas com alturas e amplitudes aleatórias. Cada sintetizador é armazenado em uma das posições do array, para que possamos desligá-los individualmente.
\begin{lstlisting}[style=SuperCollider-IDE, basicstyle=\scttfamily\footnotesize]
// Criar SynthDef
(
SynthDef("uau", {arg freq = 60, amp = 0.1, gate = 1, uaurelease = 3;
var chorus, fonte, filtromod, env, som;
chorus = Lag.kr(freq, 2) * LFNoise2.kr([0.4, 0.5, 0.7, 1, 2, 5, 10]).range(1, 1.02);
fonte = LFSaw.ar(chorus) * 0.5;
filtromod = SinOsc.kr(1/16).range(1, 10);
env = Env.asr(1, amp, uaurelease).kr(2, gate);
som = LPF.ar(in: fonte, freq: freq * filtromod, mul: env);
Out.ar(0, Splay.ar(som))
}).add;
)
// Observe a Node Tree
s.plotTree;
// Criar um acorde de 6 notas
a = Array.fill(6, {Synth("uau", [\freq, rrand(40, 70).midicps, \amp, rrand(0.1, 0.5)])}); // tudo em uma única linha
// Encerrar notas uma por uma
a[0].set(\gate, 0);
a[1].set(\gate, 0);
a[2].set(\gate, 0);
a[3].set(\gate, 0);
a[4].set(\gate, 0);
a[5].set(\gate, 0);
// AVANÇADO: rode o acorde de 6 notas novamente e depois execute esta linha.
// Você consegue imaginar o que está acontecendo?
SystemClock.sched(0, {a[5.rand].set(\freq, rrand(40, 70).midicps); rrand(3, 10)});
\end{lstlisting}
Para ajudá-lo a entender a SynthDef acima:
\begin{itemize}
\item O som resultante é a soma de sete osciladores dentes-de-serra com afinações muito próximas passando por um filtro passa-baixa ("low pass").
\item Estes sete osciladores são criador por expansão multicanal.
\item O que é a variável \texttt{chorus}? É a frequência \texttt{freq} multiplicada por um \texttt{LFNoise2.kr}. Aqui começa a expansão multicanal, porque um array de 7 itens é fornecido como argumento para o LFNoise2. O resultado é que sete cópias do LFNoise2 são criadas, cada uma rodando a uma velocidade diferente retirada da lista \texttt{[0.4, 0.5, 0.7, 1, 2, 5, 10]}. Suas saídas são restritas ao âmbito de 1.0 a 1.02.
\item Como um atributo extra, note que \texttt{freq} está empacotado em um \texttt{Lag.kr}. Sempre que uma nova frequência alimenta o Synth, a UGen Lag simplesmente cria uma rampa entre o valor velho e o valor novo. O "lag time" (duração da rampa), neste caso, é 2 segundos. Isso é o que causa o efeito de glissando que você ouve após rodar a última linha do exemplo.
\item A fonte sonora \texttt{LFSaw.ar} recebe a variável \texttt{chorus} como sua frequência. Em um exemplo concreto: para um valor \texttt{freq} de 60 Hz, a variável \texttt{chorus} resultaria em uma expressão como
$$60 * [1.01, 1.009, 1.0, 1.02, 1.015, 1.004, 1.019]$$
na qual os números da lista estariam constantemente subindo e descendo de acordo com as velocidades de cada LFNoise2. O resultado final é uma lista de sete frequências sempre deslizando entre 60 e 61.2 (60 * 1.02). Isso é chamado \textit{efeito chorus}, por isso o nome da variável.
\item Quando a variável \texttt{chorus} é usada como freq de \texttt{LFSaw.ar}, acontece expansão multicanal: temos agora sete ondas dentes-de-serra com frequências ligeiramente diferentes.
\item A variável \texttt{filtromod} é só um oscilador senoidal movendo-se muito lentamente (1 ciclo a cada 16 segundos), com seu âmbito de saída escalonado para 1-10. Isso será usado para modular a frequência de corte do filtro passa-baixa.
\item A variável \texttt{som} contém o filtro passa-baixa (LPF), que recebe \texttt{fonte} como entrada e atenua todas as frequências acima de sua frequência de corte. Este corte não é um valor fixo: ele é a expressão \texttt{freq * filtromod}. Então no exemplo, ao assumir freq = 60, isso torna-se um número entre 60 e 600. Lembre-se que filtromod é um número oscilando entre 1 e 10, de maneira que a multiplicação seria 60 * (1 a 10).
\item \texttt{LPF} também expande multicanal para sete cópias. O envelope de amplitude \texttt{env} também é aplicado neste ponto.
\item Finalmente, \texttt{Splay} pega esse array de sete canais e mixa em estéreo.
\end{itemize}
\subsection{Nos bastidores}
Este processo em duas etapas de primeiro criar a SynthDef (com um nome próprio) e depois chamar um Synth é o que o SC faz o tempo todo quando você escreve comandos simples como \texttt{{SinOsc.ar}.play}. SuperCollider desdobra isso em (a) criar uma SynthDef temporária e (b) tocá-la imediatamente (essa é a razão dos nomes temp_01, temp_02 que você vê na Post window). Tudo isso nos bastidores, para sua conveniência.
\begin{lstlisting}[style=SuperCollider-IDE, basicstyle=\scttfamily\footnotesize]
// Quando você faz isso:
{SinOsc.ar(440)}.play;
//O que o SC está fazendo é isso:
{Out.ar(0, SinOsc.ar(440))}.play;
// O que por sua vez na verdade é isso:
SynthDef("nomeTemporario", {Out.ar(0, SinOsc.ar(440))}).play;
// E todos eles são atalhos desta operação em duas etapas:
SynthDef("nomeTemporario", {Out.ar(0, SinOsc.ar(440))}).add; // criar a definição de um sintetizador
Synth("nomeTemporario"); // tocá-lo
\end{lstlisting}