Capítulo 3
Ataque e Decaimento
Em nenhum instrumento real o som se mantém com uma amplitude constante,
normalmente temos variações de intensidade, tipicamente mais altos no início e
silenciando ao longo do tempo. Para tornar os instrumentos mais factíveis, podemos
controlar essa amplitude usando as funções de envelope.
Uma função de envelope é um formato de onda que delinea a amplitude que a
onda de saída deve ter. De uma certa forma, ela empacota a amplitude da onda de saída
como um envelope real.
No Csound para usarmos o efeito de ataque e decaimento em uma nota,
precisamos que a onda de saída seja modulada por um envelope. Um tipo de função de
envelope muito usado para simular instrumentos acústicos é o ADSR, attack-decay-
sustain-release. Como em um instrumento real, essa onda tem um ataque rápido, depois
um leve decaimento, suntenta por algum tempo, e então silencia.
Como vimos antes o parâmetro de amplitude kamp de buzz é um parâmetro de
performance, então para aplicarmos o ADSR basta modularmos a amplitude de saída de
buzz. Usaremos uma função de envelope no parâmetro kenv, ao invés de usarmos um
valor fixo, modulando assim a amplitude de buzz.
 
<CsoundSynthesizer>
<CsOptions>
-o linseg.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
instr 1
  ; Amplitude do sinal dada pelo envelope de saída de linseg
  kenv linseg 0, p3/5, 5000, p3/5, 2500, p3 * 2/5, 2500, p3/5, 0
  ; Frequência fundamental
  kcps = 440
  ; Número da f-table.
  ifn = 1
  ; Número de harmônicos
  knh = 5
  ; Toca com amplitude variável kenv, a partir da frequência 
  ; fundamental de 440 Hz, a onda dos 5 primeiros harmônicos do seno
  a1 buzz kenv, kcps, knh, ifn
  
  ; Manda o som armazenado em a1 para o arquivo de saída, linseg.wav 
  out a1
endin
</CsInstruments>
<CsScore>
; Tabela #1: uma simples onda de seno.
f 1 0 16384 10 1
; Toca o instrumento #1 por 5 segundos, começando em 0 segundos
i 1 0 5
e
</CsScore>
</CsoundSynthesizer>
Fig.1: linseg.csd, o uso de linseg para gerar um envelope de amplitude
Aqui temos o mesmo arquivo buzz.csd, exceto que agora a amplitude é dada
pelo opcode linseg, que traça segmentos de linha entre os parâmetros dados. A sintaxe de
linseg é:
kres linseg ia, idur1, ib [, idur2] [, ic] [...]
onde os parâmetros de inicialização são dados por:
. ia é o valor do primeiro ponto
. idur1 é a duração do segmento de linha entre o primeiro e o segundo ponto
. ib é o valor do segundo ponto
. idur2 é a duração do segmento de  linha entre entre o segundo e terceiro
ponto.
. ic é o valor do terceiro ponto
e etc. Não há parâmetros de performance em linseg, apenas parâmetros de inicialização.
Então olhando para a seção orchestra de linseg.csd, vemos a inicialização de
kenv:
kenv linseg 0, p3/5, 5000, p3/5, 2500, p3 * 2/5, 2500, p3/5, 0
Temos que p3 é a duração total da nota dada pelo arquivo score. Então o
primeiro segmento de linha será um ataque do valor 0 ao valor 5000 com duração de um
quinto da duração da nota, o segundo segmento será um decaimento do valor 5000 para o
valor 2500, depois há uma sustentação no valor 2500, e finalmente um release para o
valor 0 na última parte.
Usamos a seção CsScore de linseg.csd para tocar a nota por 5 segundos, para ser
possível perceber nitidamente as variações de amplitude dadas por linseg. Executando o
Csound para obter o arquivo de saída linseg.wav, nota-se como há um ataque inicial e
logo depois um decaimento.
Se quisermos que o envelope tenha um único segmento de linha, existe o opcode
bem mais simples line, cuja sintaxe é:
kres line ia, idur1, ib
que simplesmente traça um segmento de linha entre ia e ib com duração idur1.
Muitas vezes não queremos gerar o envelope na seção CsInstruments, como
no exemplo anterior, mas queremos gerá-lo como uma forma de onda em uma f-table na
seção CsScore. Podemos usar a função GEN07 para gerar a f-table de envelope. A
sintaxe de GEN07 é:
f  #    time    size   7   a   n1   b   n2   c  ...
Aqui os parâmetros a, b, c, etc são valores que a onda deve alcançar através de um
segmento de linha, e n1, n2, etc é a quantidade de pontos que este segmento de linha deve
ter entre um valor e outro. Se declararmos por exemplo a f-table como:
f 1 0 16384 7 0 4096 5000 4096 2500 4096 2500 4096 0
ela será um segmento de linha de 0 até 5000 com 4096 pontos, em seguida outro
segmento de linha de 5000 até 2500 com 4096 pontos, e etc. Todos os segmentos nesses
exemplo tiveram 4096 pontos, podendo ser outros valores, mas a soma dos tamanhos
deve ser igual ao tamanho total, aqui 16384 pontos. Se a soma tiver tamanho diferente do
total, a onda será truncada ou preenchida com zeros.
Vamos então usar essa declaração de f-table na seção CsScore de nosso arquivo
gen07.csd, como veremos na figura 2.
Queremos então gerar um envelope à partir da onda que está na na f-table 2, e
através dela controlar a amplitude da f-table 1, que é uma senóide. 
Temos que ter em mente que a f-table 2 não vai modular apenas um comprimento
de onda da f-table 1, mas vai modular a onda por quanto tempo a nota durar. Então se a
nota durar 10 segundos, temos que “esticar” a f-table 2 para ocupar 10 segundos e assim
modular toda a onda.
Felizmente, isso pode ser feito com um simples cálculo na declaração de oscil,
usando então:
kenv oscil kamp, 1/p3, ienv
teremos então em kenv a forma de onda da f-table 2 com exatamente p3 segundos de
duração. Se especificarmos por exemplo no arquivo score que a nota terá 10 segundos, p3
= 10, então para que o envelope tenha também 10 segundos precisamos gerar com o
opcode oscil uma onda com período de 10 segundos. Se queremos que kenv tenha
período 10, precisamos apenas especificar em oscil que sua frequência seja 1/10, ou seja,
basta definir a frequência em oscil como 1/p3 para gerar o envelope com exatamente a
duração da nota.
O nosso arquivo gen07.csd então ficará:
<CsoundSynthesizer>
<CsOptions>
-o gen07.wav
</CsOptions>
<CsInstruments>
; Inicializa as variáveis globais.
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
; Instrumento #1.
instr 1
  ; Frequência fundamental
  kcps = 440
  ; Número da f-table do seno.
  ifn = 1
  ; Número de harmônicos
  knh = 5
  ; Número da f-table de envelope
  ienv = 2
  
  ; Gera o envelope com amplitude 5000, duração de p3 segundos e a 
  ; forma de onda armazenada na f-table 2.
  kenv oscil 5000, 1/p3, ienv
  ; Toca com amplitude variável de envelope kenv, a partir da 
  ; frequência fundamental de 440 Hz, a onda dos 5 primeiros 
  ; harmônicos do seno
  a1 buzz kenv, kcps, knh, ifn
  
  ; Manda o som armazenado em a1 para o arquivo de saída, gen07.wav 
  out a1
endin
</CsInstruments>
<CsScore>
; Tabela #1: uma onda de seno.
f 1 0 16384 10 1
; Tabela #2: função de envelope usando GEN7.
f 2 0 16384 7 0 4096 5000 4096 2500 4096 2500 4096 0
; Toca o instrumento #1 por 5 segundos, começando em 0 segundos
i 1 0 5
e
</CsScore>
</CsoundSynthesizer>
Fig. 2: gen07.csd
Aqui usamos kenv para modular a saída do opcode buzz, mas poderíamos ter
usado kenv de uma outra maneira produzindo o mesmo efeito:
a1 buzz 1, kcps, knh, ifn  
out a1*kenv
Ou seja, pegamos a saída a1 de buzz, sem ter a amplitude modulada, e a
modulamos multiplicando a1 por kenv, que tecnicamente é o que o Csound faz para
modular a amplitude. Apesar de ambos os métodos terem efeitos idênticos, quando
possível é melhor usar o método da Fig.2, por ser mais claro e legível.
Até aqui usamos opcodes que não são específicos para funções de envelope,
como linseg e oscil. Entretanto existe uma classe de opcodes projetadas especificamente
para produzir funções de envelope, e o mais importante deles é envlpx. A sintaxe de
envlpx é:
kres envlpx kamp, irise, idur, idec, ifn, iatss, iatdec [, ixmod]
Onde os parâmetros de inicialização são:
. kamp é a amplitude de saída
. irise é o tempo de ataque da função
. idur é o tempo total do envelope
. idec é o tempo de decaimento
. ifn é o índice da forma de onda do ataque
. iatss é a abreviação para attenuation of steady state, é o fator de atenuação
para o leve decaimento que existe na fase de sustentação da nota. O valor 1 diz que a
sustentação deve ser absoluta, enquanto para valores maiores que 1 há um aumento da
amplitude do sinal e para valores entre 0 e 1 há um decaimento durante o tempo de
sustentação da nota. Como a atenuação é exponencial, não se deve usar o valor zero.
. iatdec é o fator de atenuação na etapa de decaimento da nota, esse valor deve ser
positivo e normalmente é da ordem de 0.01, para não haver um corte no final da nota.
. ixmod é opcional, o default é zero. Para valores positivos existe um
retardamento no ataque ou decaimento definido em iatss, enquanto para valores
negativos há uma aceleração, nesse período de sustentação da nota.
Vamos usar uma maneira mais simples de envlpx, utilizando como forma de onda
de ataque uma reta, e usaremos a atenuação na sustentação constante. Esse será nosso
arquivo envlpx.csd:
<CsoundSynthesizer>
<CsOptions>
-o envlpx.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
; Instrumento #1.
instr 1
  ; Frequência fundamental
  kcps = 440
  ; Número da f-table do seno.
  ifn = 1
  ; Número de harmônicos
  knh = 5
  
  ; Gera o envelope com amplitude 5000, duração de p3 segundos,
  ; sendo p3/5 segundos de ataque e p3*2/5 de decaimento, com a 
  ; forma de onda de ataque armazenada na f-table 2.
  kamp = 5000
  irise = p3/5
  idur = p3
  idec = p3*2/5
  ienv = 2
  iatss = 1
  iatdec = 0.01
  ; Cria o envelope de amplitude
  kenv envlpx kamp, irise, idur, idec, ienv, iatss, iatdec
  ; Toca com amplitude variável de envelope kenv, a partir da 
  ; frequência fundamental de 440 Hz, a onda dos 5 primeiros 
  ; harmônicos
  a1 buzz kenv, kcps, knh, ifn
  
  ; Manda o som armazenado em a1 para o arquivo de saída, envlpx.wav 
  out a1
endin
</CsInstruments>
<CsScore>
; Tabela #1, uma onda de seno.
f 1 0 16384 10 1
; Tabela #2, um envelope ascendente.
f 2 0 129 7 0 128 1
; Toca o instrumento #1 por 5 segundos, começando em 0 segundos
i 1 0 5
e
</CsScore>
</CsoundSynthesizer>
Fig.5: envlpx.csd
Na seção CsScore tocamos o instrumento por 5 segundos, e definimos a
segunda f-table como a forma da onda de ataque de envlpx, que será uma reta ascendente
usando a nossa já conhecida função GEN07. 
Ao gerar o arquivo envlpx.wav, notamos uma variação de intensidade mais
suave devido ao decaimento exponencial.
Um tipo especial de modulação de envelope é a modulação de anel ou ring
modulation. Trata-se de uma das formas mais simples de síntese, e sua definição é
simplesmente quando multiplicamos um sinal de entrada por um segundo sinal
modulador, como fazemos no envelope. Entretanto quando a função moduladora não tem
uma frequência com período igual à duração da nota, como uma função normal de
envelope, mas possui uma frequência própria, ela passa a ser uma moduladora de anel.
Enquanto ao somamos dois sinais mantemos seus dois espectros de frequência,
isso não ocorre na multiplicação. Quando multiplicamos dois sinais com frequências
diferentes surgem novos harmônicos que não estavam presentes antes em nenhum dos
dois sinais, e outros harmônicos desaparecem.
A seguir veremos um tipo de modulação que é uma aproximação da modulação
de anel, já que o sinal modulador será de baixa frequência e atualizado apenas pela taxa
de controle k-rate. Nele temos uma onda inicial cuja forma é um pulso com um oitavo de
duração e sete oitavos de silêncio, armazenados na f-table 1 . Sobrepomos então oito
versões dessa onda na saída, cada uma com uma defasagem de 45 graus em relação a
anterior, e cada uma com variações aleatórias na amplitude, que alterarão bastante o
espectro de frequências do sinal original.
Nesse instrumento usamos o opcode gerador de números aleatórios randi, e a
sintaxe de randi que usaremos é apenas:
kres randi kamp, kcps
Em kamp temos a amplitude máxima que os números aleatórios assumirão,
positiva e negativa, e kcps é a frequência na qual esses números são gerados. O sufixo i
em randi significa que a cada novo ponto gerado ele é interpolado com o anterior,
gerando uma curva contínua entre números subsequentes. 
Veremos também agora um outro artifício muito usado que é o de-click, uma
onda de envelope que retira possíveis cliques da onda de saída atenuando o início e o fim
dessa onda. Isso será feito através das linhas:
kdclick  linseg  0, .02, 1, p3-.04, 1, .02, 0
out      aout*iamp*kdclick
A seguir temos o programa, que é uma versão do instrumento originalmente
criado por Steven Cook, com variações aleatórias de amplitude e suas diferenças de fase.
Essas variações de baixa frequência será nosso sinal modulador, e alterará drasticamente
o espectro de frequências do sinal, dando um belo efeito etéreo e não-harmônico.
<CsoundSynthesizer>
<CsOptions>
-o randi.wav
</CsOptions>
<CsInstruments>
sr     = 44100
kr     = 4410
ksmps  = 10
nchnls = 1
instr    1
iamp   = 30000   
icps   = cpspch(p4) 
ifn    = 1         
kdclick  linseg  0, .02, 1, p3-.04, 1, .02, 0
k1       randi  1, 01
k2       randi  1, 02
k3       randi  1, 03
k4       randi  1, 04
k5       randi  1, 05
k6       randi  1, 06
k7       randi  1, 07
k8       randi  1, 08
a1       oscil  k1, icps, ifn
a2       oscil  k2, icps, ifn, .125
a3       oscil  k3, icps, ifn, .25
a4       oscil  k4, icps, ifn, .375
a5       oscil  k5, icps, ifn, .5
a6       oscil  k6, icps, ifn, .625
a7       oscil  k7, icps, ifn, .75
a8       oscil  k8, icps, ifn, .875
aout     sum  a1, a2, a3, a4, a5, a6, a7, a8
out      aout*iamp*kdclick
endin
</CsInstruments>
<CsScore>
f1 0 4096 7 1 256 0 3584 0 256 1 ; Pulso com um oitavo da duração.
i1    0  4  05.00
e
</CsScore>
</CsoundSynthesizer>
Fig.6: randi.csd