Capítulo 5
Efeitos
No capítulo 3 vimos a modulação de amplitude através das funções de envelope, e
aqui veremos a alteração de frequências através dos efeitos de chorus, vibrato, reverb,
distrorção, flanger e um oscilador FM. Veremos que a medida que usamos mais efeitos, o
som ficará mais complexo e interessante. Nos exemplos a seguir você criará sons que
sempre ouviu a partir de pacotes comerciais, com uma versatilidade muito superior dada
à abrangência e parametrização de Csound.  
O efeito chorus
Um efeito muito usado é o chorus, que simula a execução de vários instrumentos
em uníssono. Existe algumas técnicas para transformar o som de um único instrumento,
em algo tocado por vários instrumentos juntos.
Um dos métodos para alcançar esse efeito é a combinação de várias ondas com
suas frequências ligeiramente diferentes para gerar o efeito de chorus. O segundo método
é alterar levemente o atraso dos instrumentos entre si.
Para termos esse atraso entre os instrumentos vamos usar o par de opcodes delayr
e
delayw. O funcionamente desses opcodes é simples, primeiro criamos uma linha de
atraso através da declaração:
ares delayr idlt
Com idlt especificando o tempo de atraso dessa linha, e qualquer sinal que seja
escrito nela sofrerá esse atraso antes de chegar a ares. Depois de criada essa linha,
podemos escrever nela através de delayw, como em:
delayw asig
E asig será escrito em ares com o atraso idlt. Sempre que houver uma declaração
delayw, ela se referirá ao delayr anterior mais próximo.
Podemos ver na fig. 1 a definição de dois instrumentos: o primeiro é a
combinação do sinal de três opcodes buzz com frequências alteradas e depois atrasados
para gerar o efeito chorus, e depois somamos as três ondas para gerar a onda de saída. O
segundo é análogo, mas usamos o opcode vco, criado por Hans Mikelson, que é um
oscilador capaz de gerar ondas de vários tipos. A sintaxe de vco é:
ares vco xamp, xcps, iwave, kpw [, ifn]
    [, imaxd] [, ileak] [, inyx] [, iphs] [, iskip]
Xamp e xcps são a amplitude e frequência, em seguida temos iwave, que
define a forma da onda de acordo com os índices: 1 gera uma onda em forma de rampa, 2
gera uma onda quadrada, 3 uma onda triangular. Kpw depende de iwave, e define a
declividade se iwave =3, ou a largura do pulso se iwave = 2. Usaremos kpw = 1 para
obter uma onda triangular perfeita quando iwave é 3.
Os parâmetros ifn, imaxd, ileak, inyx, iphs, iskip são opcionais e não serão
usados.
Em nosso segundo instrumento usaremos três opcodes vco com a frequência
levemente alterada e iremos mixá-los, como fizemos com buzz no primeiro instrumento,
para alcançar o efeito de chorus.
<CsoundSynthesizer>
<CsOptions>
-o chorus.wav
</CsOptions>
<CsInstruments>
; Inicializa as variáveis globais.
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
; Instrumento #1, três buzz para gerar chorus
instr 1
  
  ; Gera o envelope com amplitude 5000, duração de p3 segundos,
  ; sendo p3/5 segundos de ataque, p3*2/5 de sustentação e p3*2/5 de 
  ; decaimento, 0.1 é usado pois 0 é ilegal em exponenciais
  iamp = 5000
  irise = p3/5
  isus = p3*2/5
  idec = p3*2/5
  kenv expseg 0.1, irise, iamp, isus, iamp, idec, 0.1
  ; Cria o envelope de alteração de frequência
  kfreq linseg 0, p3, 0.01
  ; Toca com amplitude variável de envelope kenv, a partir da 
  ; frequência fundamental de 440 Hz, a onda dos 5 primeiros 
  ; harmônicos em 3 frequências ligeiramente diferentes
  ; Aqui há uma transformação de 440Hz +- 1% em 440 Hz novamente. 
  
  ; Frequência fundamental
  kcps = 440
  ; Número de harmônicos
  knh = 5
  ; Número da f-table do seno.
  ifn = 1
  a1 buzz kenv, kcps, knh, ifn
  a2 buzz kenv, kcps*(0.99+kfreq), knh, ifn
  a3 buzz kenv, kcps*(1.01-kfreq), knh, ifn
  
  ; Dá um leve atraso entre as três ondas
  adel1 = a1
  adel2 delayr 0.1
  delayw a2
  adel3 delayr 0.05
  delayw a3
  ; soma as três ondas na resultante
  asig = adel1 + adel2 +adel3
  ; Manda o som armazenado em asig para o arquivo de saída, 
  ; chorus.wav 
  out asig
endin
; Instrumento #2, três vco para gerar chorus
instr 2
  ; Gera o envelope com amplitude 5000, duração de p3 segundos,
  ; sendo p3/5 segundos de ataque, p3*2/5 de sustentação e p3*2/5 de 
  ; decaimento, 0.1 é usado pois 0 é ilegal em exponenciais
  iamp = 5000
  irise = p3/5
  isus = p3*2/5
  idec = p3*2/5
  kenv expseg 0.1, irise, iamp, isus, iamp, idec, 0.1
  ; Toca com amplitude variável de envelope kenv, a partir da 
  ; frequência fundamental de 440 Hz, a onda em 3 frequências
  ; levemente diferentes, com 3 formas de onda possíveis.
  
  ; Frequência fundamental
  kcps = 440
  ; Forma de onda
  iwave = p4
  ; Alterador de declividade do vco
  kpw = 1
  a1 vco kenv, kcps, iwave, kpw
  a2 vco kenv, kcps*0.99, iwave, kpw
  a3 vco kenv, kcps*1.01, iwave, kpw
  ; Dá um leve atraso entre as três ondas
  adel1 = a1
  adel2 delayr 0.1
  delayw a2
  adel3 delayr 0.05
  delayw a3
  ; soma as três ondas na resultante
  asig = adel1 + adel2 +adel3
  ; Manda o som armazenado em asig para o arquivo de saída, 
  ; chorus.wav 
  out asig
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 20 segundos, começando em 0 segundos
 
i 1 0 20
; Toca o instrumento #2 por 5 segundos, começando em 21 segundos
; com forma de onda 1, rampa.
i 2 21 5 1
; com forma de onda 2, quadrado.
i 2 27 5 2
; com forma de onda 3, triângulo.
i 2 33 5 3
e
</CsScore>
</CsSynhesizer>
Fig.1: chorus.csd
No instrumento 1 nós usamos um envelope kfreq para alterar dinamicamente a
frequência dos opcodes buzz, começando com frequências bem acima e abaixo de 440
Hz e caminhando para o uníssono. Nesse exemplo vimos as três ondas combinadas, assim
como as ondas produzidas pelo instrumento 2 com os opcodes vco. Em nossa seção
CsScore houve mais tempo para a primeira nota, para observarmos todas as nuances na
alteração das frequências por kfreq, e então tocamos mais três notas consecutivas, cada
uma com uma forma de onda diferente, todas com o efeito chorus. 
Nesse exemplo usamos o opcode expseg, criado por Gabriel Maldonado, que tem
exatamente a mesma sintaxe de linseg que já vimos, apenas traçando dessa vez
segmentos exponenciais.
O efeito vibrato
O efeito vibrato são leves e rápidas alterações em torno de uma frequência
fundamental, como se tensionássemos rapidamente várias vezes uma corda, sem que a
frequência percebida se altere drasticamente. É exatamente isso que faremos na orchestra
a seguir, modularemos a frequência de buzz com um sinal oscilatório que alterará a
frequência em torno das notas dadas pelo score.
Aqui usaremos o opcode linen como gerador de envelope. A sintaxe de linen é:
kres linen kamp, irise, idur, idec
Onde kamp é a amplitude, irise o tempo de ataque, idur a duração total do
envelope, e idec o tempo de decaimento.
<CsoundSynthesizer>
<CsOptions>
-o vibrato.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
instr 1
  ; A frequência é dada pelo quarto parâmetro no score
  kcps = cpspch(p4)
  ; envelope de amplitude
  kamp = 5000
  idur = p3
  iatk = p3/5
  idec = p3*2/5
  kenv linen kamp, iatk, idur, idec
  
  ; a variação máxima da frequência será de um centésimo
  kdepth = kcps/100
  ; velocidade de oscilação da frequência
  kfreq = 4
  ; envelope do vibrato
  ifn = 1
  kvib oscil kdepth, kfreq, ifn  
 
  knh = 5
  a1 buzz kenv, kcps+kvib, knh, ifn
   
  out a1
endin
</CsInstruments>
<CsScore>
f 1 0 16384 10 1
i  1  0   1  6.04
i  1  1   1  6.04
i  1  2   1  6.05
i  1  3   1  6.07
i  1  4   1  6.07
i  1  5   1  6.05
i  1  6   1  6.04
i  1  7   1  6.02
i  1  8   1  6.00
i  1  9   1  6.00
i  1  10  1  6.02
i  1  11  1  6.04
i  1  12  2  6.04
i  1  14  2  6.02
e
</CsScore>
</CsoundSynthesizer>
Fig.2: vibrato.csd
Uma técnica de síntese com efeito interessante é a onda modulada por
frequência, ou FM (frequency modulated), em que temos dois osciladores, onde a saída
de um modula a frequência do outro. Felizmente em Csound não precisaremos usar dois
osciladores, pois um único opcode faz todo o trabalho, foscil.  A sintaxe de foscil é:
ares foscil xamp, kcps, xcar, xmod, kndx, ifn [, iphs]
Onde os parâmetros são:
. xamp é a amplitude.
. kcps é uma frequência de base, que será o denominador comum entre os
parâmetros xcar e xmod.
. xcar é o valor pelo qual se multiplica kcps para se obter a frequência da onda
portadora (carrier)
. xmod é o valor pelo qual se multiplica kcps para obter a frequência da onda
moduladora. A frequência percebida por nós é dada pela frequência da portadora, quando
esta é menor que a moduladora.
. kndx é o índice de modulação, que determina a distribuição de amplitude para
cada harmônico gerado na modulação, e normalmente varia no tempo entre os valores 0 e
4.
. ifn é o índice da f-table que conterá uma senóide
. iphs é opcional, com valor default 0, e define a fase inicial da onda em ifn,
podendo conter valores entre 0 e 1.
Veremos agora um exemplo em que usamos apenas a modulação por frequência
para gerar a onda de saída.
<CsoundSynthesizer>
<CsOptions>
-o foscil.wav
</CsOptions>
<CsInstruments>
; Inicializa as variáveis globais
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
; Instrumento #1 - uma forma de onda FM variável
instr 1
  ; cria o envelope de amplitude
  iamp = 10000
  iatk = p3/3
  idur = p3
  idec = p3/3
  kenv
linen
iamp, iatk, idur, idec
  
  ; define o índice de modulação variável
  ibegin = p5
  iend = p6
  kndx
expon
ibegin, idur, iend
  ; gera a onda a partir do oscilador FM
  icps = cpspch(p4)
  icar = 1
  imod = 1
  ifn = 1
  a1   foscil 
kenv, icps, icar, imod, kndx, ifn
  out a1
endin
</CsInstruments>
<CsScore>
f 1  0 4096 10   1    
i 1
0
4
7.09
 
30
i 1
4
6.09
60
i 1
10
9
5.09
 
60 
1
e
</CsScore>
</CsoundSynthesizer>
Fig. 3: foscil.csd, um oscilador FM de índice de modulação variável
Aqui a onda portadora e a moduladora tem a mesma frequência, dada pelo
quarto parâmetro do score, mas o índice de modulação varia entre valores dados pelos
dois últimos parâmetros.
Originalmente o efeito de flanger era obtido através de vários delays variáveis
colocados em cascata. Csound tem um opcode específico para esse efeito, flanger, criado
por Gabriel Maldonado, e sua sintaxe é:
ares flanger asig, adel, kfeedback [, imaxd]
Os parâmetros de flanger são asig, que é o sinal de entrada em que será
aplicado o flanger, adel, que é o delay variável que controla o flanger e não pode exceder
imaxd, e kfeedback, que é a quantidade de feedback desejada, e deve estar entre 0 e 1.
O único parâmetro opcional é imaxd, e diz o delay máximo em segundos, e
esse parâmetro é usado para que o opcode saiba a quantidade de memória necessária na
inicialização.
Como fonte de som inicial usaremos o opcode pluck, visto no capítulo 4, que
simula uma corda vibrante com decaimento natural.
Abaixo temos três efeitos de flanger diferentes obtidos através da variação dos
parâmetros de entrada do opcode flanger, dando uma perspectiva do que pode ser
alcançado com esse opcode.
As alterações dos parâmetros fôram reproduzidas e destacadas dentro de cada
instrumento, ao contrário de serem passadas pelo score, para que a compreensão seja
mais direta.
<CsoundSynthesizer>
<CsOptions>
-o flanger.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
instr 1
  iamp = 10000
  ifqc = cpspch(p4)
  ifn = 0
  imeth = 1
  asig pluck iamp, ifqc, ifqc, ifn, imeth
  adel line 0, p3, 0.01
  kfeedback = 0.7
  aflang flanger asig, adel, kfeedback
  a1 clip aflang, 1, 30000
  out a1
endin
instr 2
  iamp = 10000
  ifqc = cpspch(p4)
  ifn = 0
  imeth = 1
  asig pluck iamp, ifqc, ifqc, ifn, imeth
  adel line 0, p3, 0.01
  kfeedback = 0.85
  aflang flanger asig, adel, kfeedback
  a1 clip aflang, 1, 30000
  out a1
endin
instr 3
  iamp = 10000
  ifqc = cpspch(p4)
  ifn = 0
  imeth = 1
  asig pluck iamp, ifqc, ifqc, ifn, imeth
  adel line 0, p3, 0.05
  kfeedback = 0.7
  aflang flanger asig, adel, kfeedback
  a1 clip aflang, 1, 30000
  out a1
endin
</CsInstruments>
<CsScore>
i 1 0 1 8.05 
i 1 1 1 8.02 
i 1 2 1 8.05 
i 1 3 1 8.04 
i 1 4 1 8.05 
i 1 5 1 8.07 
i 1 6 1 8.05 
i 1 7 1 8.07 
i 1 8 1 8.04 
i 1 9 1 8.09
i 1 10 1 8.04
i 1 11 1 8.02
s
i 2 0 1 8.05 
i 2 1 1 8.02 
i 2 2 1 8.05 
i 2 3 1 8.04 
i 2 4 1 8.05 
i 2 5 1 8.07 
i 2 6 1 8.05 
i 2 7 1 8.07 
i 2 8 1 8.04 
i 2 9 1 8.09
i 2 10 1 8.04
i 2 11 1 8.02
s
i 3 0 1 8.05 
i 3 1 1 8.02 
i 3 2 1 8.05 
i 3 3 1 8.04 
i 3 4 1 8.05 
i 3 5 1 8.07 
i 3 6 1 8.05 
i 3 7 1 8.07 
i 3 8 1 8.04 
i 3 9 1 8.09
i 3 10 1 8.04
i 3 11 1 8.02
e
</CsScore>
</CsoundSynthesizer>
Fig.4: flanger.csd
 
Em Csound existe uma série de opcodes que dão eco ou delay a uma onda de
entrada. Quando esse atraso é perceptível, podemos distinguir o efeito de delay, e quando
esse atraso é pequeno e se torna imperceptível ao ouvido humano, alcançamos o efeito de
reverb.
Vamos começar pelo opcode reverb, criado por William “Pete” Moss, por se
tratar do mais simples e direto opcode de reverberação. Como veremos depois, existem
vários parâmetros envolvidos no processo do efeito de reverb, entretanto esses
parâmetros são pré-configurados em reverb para dar uma resposta de reverberações
comuns à uma sala média. Isso se nota pela pouca quantidade de parâmetros de reverb:
ares reverb asig, krvt [, iskip]
Asig é o sinal de entrada e krvt é o tempo pelo qual cada sample será reverberado.
O parâmetro iskip é opcional e diz se será aproveitada a última reverberação
dada por outro instrumento no início desta nota. O default é 0, isto é, o som começa
apenas com o sinal original, sem aproveitar reverberações anteriores. Tecnicamente, isso
diz se o buffer usado para a reverberação é esvaziado no início da execução do opcode ou
é mantido com o sinal que estava anteriormente.
Precisamos antes fazer algumas considerações em como implementar o reverb
em uma orchestra. A solução imediata e intuitiva usando reverb seria implementar toda a
geração do sinal e do reverb dentro do mesmo instrumento, como abaixo:
instr 1 
  krvt = 1.5
; tempo enquanto vai haver reverberação
  a1 oscil 30000, 440, 1 
; sinal de entrada
  arev reverb a1, krvt 
; sinal reverberado
  out arev 
endin
Entretanto essa implementação tem um problema grave, pois assim que a nota
que ativou o instrumento termina, no mesmo instante a reverberação cessa. Se nossa nota
fôr durar, por exemplo, um décimo de segundo, não poderemos perceber o eco pois assim
que esse décimo passar não haverá mais reverberação, isto é, precisamos que o reverb
esteja ativado mesmo quando o instrumento não está mais sendo executado.
Para alcançar esse objetivo, vamos implementar um instrumento separado
apenas para o reverb, que fique ativo durante toda a duração do score. Nessa nova
implementação usaríamos uma variável global gamix para passar o sinal dos
instrumentos para o reverb, e ficaria algo como:
gamix init 0
instr 1 
  a1 oscil 30000, 440, 1
  out a1  
  gamix = gamix + a1 
endin
instr 99 
  krvt = 1
  arev reverb gamix, krvt
  out arev 
  gamix = 0 
endin
Note que no primeiro instrumento gamix é somada ao sinal do instrumento.
Apesar de no exemplo haver apenas um instrumento antes do reverb por simplicidade, em
outros códigos isso garantiria que o sinal de todos os instrumentos antes do reverb
estariam em gamix, para esse sinal ser então reverberado no último instrumento.
Aqui quando o primeiro instrumento pára, o sinal de entrada gamix cessa mas
continua sendo reverberado pelo segundo instrumento. No instante em que instr 1 é
desativado, o sinal de entrada gamix também deve se igualar a zero, caso contrário
gamix geraria um sinal de entrada eterno mesmo quando instr 1 foi desligado, e você
obteria um sinal com amplitude tendendo a infinito, obtendo na mensagem samples out of
range um número muito grande de amostras que ultrapassaram a amplitude limite. Temos
apenas de lembrar de numerar os instrumentos de reverb com a maior numeração da
orchestra, para garantir que eles sempre sejam executados por último. 
Em síntese, essa abordagem de instrumentos distintos, reinicializando sempre
gamix para zero, garante que haverá a reverberação necessária e não além. Esse modelo
de programação será usado em todos os opcodes de eco que usaremos daqui em diante.
Para tornar nosso leque mais variado, podemos aplicar o reverb sobre um
sample de áudio. Para isso usamos o opcode loscil, que aplica uma frequência escolhida
sobre um sample, depois que lhe informamos em que frequência base o sample está. A
sintaxe de loscil que usaremos é:
ares loscil xamp, kcps, ifn [, ibas]
onde xamp é a amplitude, kcps a frequência desejada, ifn a f-table que contém o arquivo
de áudio, e ibas a frequência fundamental da onda contida no arquivo, que será
modificada para chegar a kcps. Abaixo vem um trecho de código, aplicando o reverb
sobre uma onda com loscil:
instr 2
  kamp = 10000 
  kcps = 1
  ifn = 2
  ibas = 1
  a1 loscil kamp, kcps, ifn, ibas
  out a1
  gamix = gamix + a1 
endin
instr 99 
  krvt = p4
  a99 reverb gamix, krvt
  out a99 
  gamix = 0 
endin
 
E finalmente temos o programa completo, usando um mesmo reverb, que fica ativo
durante todo o score, para os dois instrumentos. 
<CsoundSynthesizer>
<CsOptions>
-o reverb.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
gamix init 0 
instr 1
  kamp = 10000 
  kcps = cpspch(p4)
  ifn = 1
  a1 oscil kamp, kcps, ifn
  out a1
  gamix = gamix + a1 
endin
instr 2
  kamp = 10000 
  kcps = 1
  ifn = 2
  ibas = 1
  a1 loscil kamp, kcps, ifn, ibas
  out a1
  gamix = gamix + a1 
endin
instr 99 
  krvt = p4
  a99 reverb gamix, krvt
  out a99 
  gamix = 0 
endin
</CsInstruments>
<CsScore>
f 1 0 16384 10 1
f 2 0 524288 1 "female.aif" 0 4 0
i 1 0 .1 8.05 
i 1 1 .1 8.02 
i 1 2 .1 8.05 
i 1 3 .1 8.04 
i 1 4 .1 8.05 
i 1 5 .1 8.07 
i 1 6 .1 8.05 
i 1 7 .1 8.07 
i 1 8 .1 8.04 
i 1 9 .1 8.09
i 99 0  10  1 
i 2  10 6
i 99 10 10  1
i 2  20 6
 
i 99 20 10  3 
i 2  30 6
i 99 30 10  10 
e
</CsScore>
</CsoundSynthesizer>
Fig.4: reverb.csd
Tradicionalmente a codificação de reverbs em Csound era feita através de
opcodes combs em paralelo e filtros all-pass, que adicionavam um atraso ao sinal.Vamos
ver o opcode comb, que dá vários atrasos a uma onda inicial diminuindo sua amplitude.
Ele proporciona o efeito de um delay colocado em loopback, causando a realimentação
do sistema e proporcionando o efeito de reverb . A sintaxe de comb que usaremos é:
ares comb asig, krvt, ilpt
O
novo parâmetro de inicialização que não havia em reverb é ilpt, que é o
tempo de loopback ou atraso entre um ciclo e outro dado pelo reverb, i.e., o tempo que o
sinal leva para começar a ser reverberado. Os parâmetros de performance são:
. asig é o sinal de entrada.
. krvt ou reverb time é o tempo em que o sinal se mantém ecoando enquanto
gradativament desaparece, e diz indiretamente quantas vezes o som sofrerá loopback até
desaparecer completamente.
O segundo opcode da família de comb, que usaremos em nosso segundo
instrumento, é o vcomb,  criado por William “Pete” Moss, que tem como característica
um tempo de atraso no loopback variável, e cuja sintaxe é:
ares vcomb asig, krvt, xlpt, imaxlpt [, iskip] [, insmps]
Os parâmetros novos aqui são xlpt e imaxlpt. Este último, imaxlpt, é de
inicialização e nos diz qual o máximo atraso que o sinal pode assumir durante a
execução, i.e., o tempo máximo de loopback.
Este parâmetro é necessário exatamente porque o parâmetro de performance
anterior xlpt é variável, dizendo a cada instante qual o tempo de atraso que o sinal deve
ter, e o fato dele ser variável é o que diferencia vcomb de comb.
Veremos agora o código equivalente de reverb usando comb e vcomb,
especificando vários valores para ilpt diferentes para comb, que será implementado no
instr 98.
No caso de vcomb, que será implementado no instr 99, usaremos três
parâmetros adicionais para o reverb de loopback variável: p5 será o valor inicial de
loopback, p6 será o valor final, e p7 será o loopback máximo.
<CsoundSynthesizer>
<CsOptions>
-o combs.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
gamix init 0 
instr 1
  kamp = 10000 
  kcps = cpspch(p4)
  ifn = 1
  a1 oscil kamp, kcps, ifn
  out a1
  gamix = gamix + a1 
endin
instr 2
  kamp = 10000 
  kcps = 1
  ifn = 2
  ibas = 1
  a1 loscil kamp, kcps, ifn, ibas
  out a1
  gamix = gamix + a1 
endin
instr 98 
  krvt = p4
  ilpt = p5
  a99 comb gamix, krvt, ilpt
  out a99 
  gamix = 0 
endin
instr 99 
  krvt = p4
  klpt line p5, p3, p6
  imaxlpt = p7
  a99 vcomb gamix, krvt, klpt, imaxlpt
  out a99 
  gamix = 0 
endin
</CsInstruments>
<CsScore>
f 1 0 16384 10 1
f 2 0 524288 1 "female.aif" 0 4 0
; reverbs usando comb
i 1 0 .1 8.05 
i 1 1 .1 8.02 
i 1 2 .1 8.05 
i 1 3 .1 8.04 
i 1 4 .1 8.05 
i 1 5 .1 8.07 
i 1 6 .1 8.05 
i 1 7 .1 8.07 
i 1 8 .1 8.04 
i 1 9 .1 8.09
i 98 0  10  1   0.1 
s
i 2  0 6
i 98 0 10  1  0.1 
i 2  10 6
i 98 10 10 3  0.3 
i 2  20 6
i 98 20 10 10 1
s
; reverbs usando vcomb
i 1 0 .1 8.05 
i 1 1 .1 8.02 
i 1 2 .1 8.05 
i 1 3 .1 8.04 
i 1 4 .1 8.05 
i 1 5 .1 8.07 
i 1 6 .1 8.05 
i 1 7 .1 8.07 
i 1 8 .1 8.04 
i 1 9 .1 8.09
i 99 0 10  1  0.05 0.5 0.5
s
i 2  0 6
i 99 0 10  1  0.1 0.3 0.3
i 2  10 6
i 99 10 10 3  0.1 0.6 0.6 
i 2  20 6
i 99 20 10 10 0.1 1.2 1.2
s
e
</CsScore>
</CsoundSynthesizer>
Fig. 5: combs.csd
Descoberto por acidente na década de 50, um dos efeitos mais usados é a
distorção, ou overdrive, obtido originalmente quando se coloca amplificadores de tubo
em seu volume máximo. Ao contrário de manter o som original aumentando apenas sua
amplitude, os amplificadores causavam uma alteração não-linear no som, causando
clipping no sinal e criando novos harmônicos. 
No Csound temos o opcode distort1, criado por Hans Mikelson, que simula a
distorção através de wave shaping, ou alteração da forma de onda original. Apesar de não
simular exatamente o overdrive, ele é o primeiro passo do processo em que obteremos
uma distorção semelhante a dos amplificadores de tubo. A sintaxe de distort1 é:
ares distort1 asig, kpregain, kpostgain, kshape1, kshape2
Todos os parâmetros são de tempo de performance. Asig é o sinal de entrada,
kpregain e kpostgain são os valores de pré-amplificação e ganho de saída, e kshape1 e
kshape2 são os valores que determinarão a quantidade de clipping do sinal,
respectivamente na parte positiva e negativa. O valor 0 resulta em um clipping drástico
do sinal, e para valores positivos pequenos há menos clipping e uma inclinação maior na
crista da onda.
A distorção obtida com distort1 ainda não é suficiente para alcançarmos o
efeito de um verdadeiro tube amp em volume máximo. Para isso devemos fazer com que
a variação positiva da onda sofra um atraso maior do que o restante, e podemos obter esse
delay variável através de deltap.
Já vimos anteriormente que pode ser obtido o delay de um sinal usando o par
delayr e delayw. Entretanto entre esses dois opcodes podemos variar o atraso que será
usado na saída usando o opcode deltap. A sintaxe de deltap é simplesmente:
ares deltap kdlt
Onde kdlt é um sinal de controle que diz o tempo de atraso que será submetido
o sinal de saída a cada instante. 
Quando especificamos um tempo de delay em delayr, podemos imaginar que
estabelecemos uma linha de condução do sinal mais lenta que seu tempo normal. Imagine
um sinal viajando por um fio e de repente entrando numa linha de condução mais lenta,
de modo que ao sair do outro lado dessa linha tenha sofrido um atraso especificado em
delayr. Podemos entender o funcionamento de deltap como uma segunda linha
desviando o sinal no meio da linha de atraso, fazendo com que ele chegue mais rápido à
saída. O que deltap especifica é em que ponto do atraso esse sinal será desviado ao longo
da duração do sinal, fazendo com que ele chegue à saída mais rápido ou mais tarde,
variando com diferentes atrasos o sinal de entrada. 
A especificação do tempo kdlt em deltap pode variar desde um ciclo de
controle apenas (k-pass) até o tempo de atraso máximo especificado por delayr. É
importante lembrar que quando declaramos deltap, o sinal ainda não é modificado.
Apenas quando escrevemos o sinal com delayw é que ele é submetido às variações de
atraso especificadas por deltap.
O exemplo a seguir de distorção nos dá um efeito extremamente semelhante à
distorção de um tube amp, e foi implementado por Hans Mikelson, e é exposto aqui com
leves alterações sintáticas.
No score abaixo usaremos a função GEN05, que constrói ondas a partir de
segmentos de curvas exponenciais. Sua sintaxe é:
f # time size 5 a n1 b n2 c ...
A sintaxe é idêntica a de GEN07, ou seja, a, b, c são os valores
que a onda deve assumir após n1, n2, etc pontos. A única diferença é
que os valores da onda a, b, c, (...) não podem ser zero, por ser uma
função baseada na exponencial.
<CsoundSynthesizer>
<CsOptions>
-o distort1.wav
</CsOptions>
<CsInstruments>
; Initialize the global variables.
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
gadist init 0
  
instr 1
  iamp = 1000
  ifqc = cpspch(p4)
  asig pluck iamp, ifqc, ifqc, 0, 1
  gadist = gadist + asig
endin
  
instr 98
  ipregain   init p4
  ipostgain  init p5
  ishape1 init 0
  ishape2 init 0
  aout distort1 gadist, ipregain, ipostgain, ishape1, ishape2
  out aout
  gadist = 0
endin
instr 99
  ipregain  init p4
  ipostgain init p5
  ishape1  init
0
  ishape2  init
0
  asign   init
0
  adist distort1 gadist, ipregain, ipostgain, ishape1, ishape2
  aold    =       asign          ; Salva o último sinal
  asign   = gadist/30000   
; Normaliza o sinal atual
  atemp   delayr  .1
 
  ; Atraso baseado na amplitude e declividade do sinal.
  ; (Quanta menor a amplitude com sinal, 
  ; e maior a diferença entre a amplitude atual e a amplitude anterior,
  ; maior será o atraso.)
  ; Você pode imaginar que ele “esticaria” a parte negativa,
  ; acentuando os picos da parte positiva 
  ; e aumentando o efeito de distorção
 
  aout    deltapi (2-asign)/1500 + (asign-aold)/300
  delayw  adist
  out aout
  gadist = 0
endin
</CsInstruments>
<CsScore>
f 5 0   8192    8   -.8 336 -.78 800 -.7 5920 .7 800 .78 336 .8
i 1  0.0  1.6  6.04
i 1  0.2  1.4  6.09
i 1  0.4  1.2  7.02
i 1  0.6  1.0  7.07
i 1  0.8  0.8  7.11
i 1  1.0  0.6  8.04
i 98 0    1.6  2       1     
s
i 1  0.0  1.6  6.04
i 1  0.2  1.4  6.09
i 1  0.4  1.2  7.02
i 1  0.6  1.0  7.07
i 1  0.8  0.8  7.11
i 1  1.0  0.6  8.04
i 99 0    1.6  4       1      
s
i 1  0.0  0.2  7.00
i 1  0.1  0.2  7.02
i 1  0.2  0.2  7.04
i 1  0.3  0.2  7.05
i 1  0.4  0.2  7.07
i 1  0.5  0.2  7.09
i 1  0.6  0.2  7.11
i 1  0.7  0.2  8.00
i 1  0.8  0.2  8.02
i 1  0.9  0.2  8.04
i 1  1.0  0.2  8.05
i 1  1.1  0.2  8.07
i 1  1.2  0.2  8.11
i 1  1.3  0.2  9.00
i 1  1.4  0.2  9.02
i 1  1.5  0.2  9.04
i 99 0    1.6  4       1      
s
e
</CsScore>
</CsoundSynthesizer>
Fig. 6: distort1.csd
Em distort1.csd usamos a mesma estrutura das orchestras de reverb, com
instrumentos separados, um para a geração do som e outro para o efeito em si. No instr
98 isso não seria necessário a princípio, pois usamos a distorção simplesmente com o
opcode distort1, mas preferimos essa estrutura por ser mais coerente e legível na
implementação dos dois efeitos de distorção, já que o segundo efeito instr 99 usa delay e
por isso precisa dessa separação. Além disso, essa estrutura simula melhor um efeito de
pedal ou stomp box, podendo ser ligado ou desligado a qualquer momento, independente
do que está sendo tocado.