Capítulo 8
Síntese Imitativa
Ao implementar um programa no Csound, não há limitação para algoritmos
mais complexos simularem sintetizadores comerciais ou instrumentos eletro-acústicos.
Nesse capítulo, o primeiro som característico de sintetizadores a  ser emulado será o
efeito de cordas, disponível em vários teclados comerciais. Usaremos o opcode
especializado oscbnk, que contém embutido um número ilimitado de osciladores
controlados por lfo’s e um equalizador paramétrico.
O opcode oscbnk foi criado por Istvan Varga especialmente para emular cordas
sintetizadas, e para isso, nele é declarado um grande número de osciladores com
frequências, amplitudes e fases variando levemente entre si, e tendo um equalizador
paramétrico na saída para melhorar a qualidade do som, isso tudo em um único opcode.
A sintaxe de oscbnk é extensa e podemos declará-la como:
ares oscbnk  kcps, kamd, kfmd, kpmd, iovrlap, iseed, kl1minf, \ 
kl1maxf,kl2minf, kl2maxf, ilfomode, keqminf, keqmaxf, \ 
keqminl, keqmaxl, keqminq, keqmaxq, ieqmode, kfn \
[, il1fn] [, il2fn] [, ieqffn] [, ieqlfn] [, ieqqfn]\ 
[, itabl] [, ioutfn]
Vamos primeiro entender como funciona os parâmetros mais importantes, e no
caminho iremos entender como funciona oscbnk. Iremos então descrevê-los na ordem
que mais facilita o entendimento.
. iovrlap nos diz quantos osciladores estarão sendo executados simultaneamente
para a produção do som.
. kcps é a frequência fundamental dos osciladores.
. kfn é a forma de onda dos osciladores.
. kamd, kfmd, kpmd são respectivamente as variações máximas na amplitude,
frequência e fase dos osciladores. 
. ilfomode é o modo como os osciladores serão controlados. Cada oscilador tem
dois LFOs (osciladores de baixa frequência) controlando sua frequência, fase, amplitude
e equalização. De que maneira esse controle é feito é definido através do parâmetro 
ilfomode, que é a soma dos seguintes valores: 
*128 para o LFO1 controlar a frequência
* 64 para ele controlar a amplitude
* 32 ele controla a fase
* 16 ele controla a equalização
* 8 para o LFO2 controlar a frequência
* 4 para ele controlar a amplitude
* 2 ele controla a fase
* 1 ele controla a equalização.
Muitos dos aspectos da saída de oscbnk variam aleatoriamente, mas dentro de
uma faixa definida. Se definirmos em ilfomode que o primeiro LFO controlará a
amplitude, a frequência e a fase dos osciladores, devemos definir os valores máximos
dessa variação em kamd, kfmd e kpmd. O LFO, nesse sentido, age como um vibrato de
baixa frequência alterando a amplitude, frequência e fase. Como essa variação é aleatória
pra cada oscilador, cada oscilador terá uma variação diferente, mas sempre dentro dessa
faixa. Se queremos que até num mesmo oscilador dois desses aspectos variem
separadamente, devemos associar a um aspecto o LFO1 e ao outro o LFO2, através de
ilfomode.
. iseed é a semente do gerador de números randômicos. Para o valor 0, ele
tomará o tempo corrente.
.kl1minf, kl1maxf, kl2minf, kl2maxf são as frequências mínimas e máximas
que o LFO1 e o LFO2 assumirão, variando dentro desses valores. Não confundir com
kfmd, que é a variação da frequência do sinal. Aqui há a variação do tempo em que um
novo ciclo de mudanças nos parâmetros ocorrerá, e é muitíssimo mais lento que as altas
frequências de kcps+-kfmd
. keqminf, keqmaxf, keqminl, keqmaxl, keqminq, keqmaxq são os mínimos
e máximos para frequência, nível e “Q” do equalizador. Novamente os assuntos
relacionados a equalização serão vistos em detalhe a seguir.
Os parâmetros a seguir são opcionais:
. il1fn, il2fn são as formas de onda do primeiro e do segundo LFO.
. ieqffn é a forma de onda da frequência do equalizador, onde a frequência será
redimensionada para variar entre keqminf e keqmaxf, sendo então lida pelos LFOs.
. ieqlfn é a forma de onda para o nível do equalizador, que é então
redimensionadas para valores entre keqminl e keqmaxl.
. ieqqfn é a forma de onda para o “Q” do equalizador (cujo significado será
explicado logo abaixo após ieqmode), e essa forma de onda é então redimensionada para
valores entre keqminq e keqmaxq.
. ieqmode nos diz qual será o modelo de equalização usado pelos equalizadores,
seguindo o código: 
* -1 desabilita o equalizador
* 0 a equalização é no modelo peak
* 1 para low shelf
* 2 para high shelf
* Os valores 3, 4, 5 repete a mesma sequência mas para valores
interpolados. 
Se faz necessário agora explicar o que é modelo de equalização peak, low shelf
e high shelf. O padrão de equalização do equalizador paramétrico é atribuir a todas as
frequências uma amplitude de 0 dB. 
No modelo peak, todas as frequências tem uma resposta de 0 dB com exceção
de um pico central na frequência que está sendo lida em ieqffn com a amplitude que está
sendo lida em ieqlfn. Vale lembrar que a frequência ieqffn está devidamente
desnormalizada para valores entre keqminf e keqmaxf e a amplitude ieqlfn para valores
entre keqminl e keqmaxl
A declividade desse pico é mapeada pelo Q em ieqqfn, que é lida pelo LFO e
novamente desnormalizada para valores entre keqminq e keqmaxq. Quanto maior o
valor de Q maior a declividade do pico central de frequência.
No modelo low shelf, novamente a resposta padrão do equalizador é de 0 dB
para todas as frequências, mas abaixo da frequência lida naquele momento em ieqffn as
frequências sofrem uma modificação de amplitude dada naquele momento por ieqlfn, e a
declividade em ieqffn novamente é proporcional ao valor de Q em ieqqfn.
O modelo high shelf é similar ao low shelf, com exceção que agora
modificamos o nível de amplitude de frequências acima de ieqffn.
. itabl é uma tabela opcional, para inicialização dos osciladores
. iotfn é uma tabela opcional, para escrita de valores de saída
Ambas não serão usadas
Nós veremos dois programas. O segundo é onde nós veremos realmente como
programar oscbnk.  
O primeiro programa, logo abaixo, é apenas para ser executado, sem a
necessidade de ser lido, e servirá para entendermos visualmente os conceitos de
frequência central, nível, Q e modelo de equalização. Para manipular graficamente esses
parâmetros em tempo de execução, usaremos instruções gráficas de FLTK, que só serão
vistas no próximo capítulo, e por isso mesmo não nos ateremos a elas agora. Execute-o e
altere os knobs para ver como o espectro do equalizador se modifica:
<CsoundSynthesizer>
<CsOptions>
--displays -+rtaudio=null -o dac -b 1024 -B 2048
</CsOptions>
<CsInstruments>
sr
=  48000
ksmps
=  32
nchnls
=  1
0dbfs
=  1
FLpanel "pareq", 360, 120
ih1
FLvalue " ", 50, 22, 20, 90
gkfco, ih1v
FLknob "Freq", 500, 10000, -1, 1, ih1, 60, 15, 10
FLsetVal_i 5000, ih1v
ih2
FLvalue " ", 50, 22, 120, 90
gklvl, ih2v
FLknob "Level", 0.01, 3, -1, 1, ih2, 60, 115, 10
FLsetVal_i 3, ih2v
ih3
FLvalue " ", 50, 22, 220, 90
gkQ, ih3v
FLknob "Q", 0.1, 3, -1, 1, ih3, 60, 215, 10
FLsetVal_i 3, ih3v
ih4
FLvalue " ", 40, 22, 310, 90
gkmode, ih4v
FLroller "Mode", 0, 2, 1, 0, 2, ih4, 20, 60, 320, 10
FLsetVal_i 2, ih4v
FLpanelEnd
FLrun
opcode pulse, a, ki
setksmps 1
kprd, iphs
xin
kcnt
init iphs
aout
=  0
kcnt
=  kcnt + 1
if (kcnt < kprd) kgoto cont1
kcnt
=  0
aout
=  1
cont1:
xout aout
endop
instr 1
gkmode_old
init -1
a1
pulse 4096, 2048
kc
port gkfco, 0.04
kv
port gklvl, 0.04
kq
port gkQ, 0.04
modeChange:
a2
pareq a1, kc, kv, kq, round(i(gkmode))
if (gkmode == gkmode_old) kgoto noChange
reinit modeChange
rireturn
noChange:
gkmode_old
=  gkmode
dispfft a2, 4096.01 / sr, 4096, 1
endin
</CsInstruments>
<CsScore>
i 1 0 3600
e
</CsScore>
</CsoundSynthesizer>
Fig1.: equalizer.csd
A seguir temos um exemplo de como usar oscbnk para gerar sons semelhantes
a cordas sintetizadas. Nele temos o trecho de código:
kcps = cpspch(p4)
kamd = 0.0
kfmd = 0.02 * kcps
kpmd = 0.0
iovrlap = 80
iseed = 200
kl1minf = 0.1
kl1maxf = 0.2
kl2minf = 0
kl2maxf = 0
ilfomode = 144
keqminf = 0.0
keqmaxf = 6000
keqminl = 0.0
keqmaxl = 0.0
keqminq = 1
keqmaxq = 1
ieqmode = 2
kfn = 1
il1fn = 3
il2fn = 0
ieqffn = 5
ieqlfn = 5
ieqqfn = 5
ares oscbnk  kcps, kamd, kfmd, kpmd, iovrlap, iseed, kl1minf, kl1maxf, \
kl2minf, kl2maxf, ilfomode, keqminf, keqmaxf, keqminl, \
keqmaxl, keqminq, keqmaxq, ieqmode, kfn, il1fn, il2fn, \
ieqffn, ieqlfn, ieqqfn
A frequência da nota kcps é obtida a partir de p4, e a quantidade de osciladores
simultâneos iovrlap é de 80 osciladores. 
O controle dos LFOs é dado por ilfomode com o valor de 144, i.e., o LFO1
controla a frequência e a equalização dos osciladores, e nenhum LFO controla a
amplitude e a fase, que tem variação 0 em kamd e kpmd
A variação máxima de frequência kfmd dada pelo LFO1 é de 0.02*kcps, 2% da
frequência total.
A frequência do LFO1 em si varia entre kl1minf e kl2maxf, que é entre 0.1 e
0.2 Hertz. Como o LFO2 não controla nenhum aspecto dos osciladores, suas frequências
mínimas e máximas são zero. 
O método de equalização ieqmode é 2, high shelf, ou seja, as frequências baixas
ficam inalteradas em 0 dB e as frequências altas são alteradas pelos parâmetros do
equalizador. 
As frequências mínima keqminf e máxima keqmaxf do equalizador são 0 e
6000 Hertz. Os níveis keqminl e keqmaxl são ambos zero e portanto atenuarão até
anularem todas as frequências acima da máxima, e a declividade mínima keqminq e
máxima keqmaxq é de 1. Com esses parâmetros o equalizador se torna quase um filtro
passa-baixa, mantendo frequências abaixo da central audíveis em 0 dB, e acima tornando-
as inaudíveis. O programa completo está a seguir:
<CsoundSynthesizer>
<CsOptions>
-o oscbnk.wav
</CsOptions>
<CsInstruments>
sr
=  48000
kr
=  750
ksmps
=  64
nchnls
=  1
ga01
init 0
ga02
init 0
i_
ftgen 1, 0, 16384, 7, 1, 16384, -1
i_
ftgen 3, 0, 4096, 7, 0, 512, 0.25, 512, 1, 512, 0.25, 512,
\
0, 512, -0.25, 512, -1, 512, -0.25, 512, 0
i_
ftgen 5, 0, 1024, 5, 1, 512, 32, 512, 1
instr 1
  p3 = p3 + 0.4
  kcps = cpspch(p4)
  kamd = 0.0
  kfmd = 0.02 * kcps
  kpmd = 0.0
  iovrlap = 80
  iseed = 200
  kl1minf = 0.1
  kl1maxf = 0.2
  kl2minf = 0
  kl2maxf = 0
  ilfomode = 144
  keqminf = 0.0
  keqmaxf = 6000
  keqminl = 0.0
  keqmaxl = 0.0
  keqminq = 1
  keqmaxq = 1
  ieqmode = 2
  kfn = 1
  il1fn = 3
  il2fn = 0
  ieqffn = 5
  ieqlfn = 5
  ieqqfn = 5
  ares oscbnk  kcps, kamd, kfmd, kpmd, iovrlap, iseed, kl1minf, kl1maxf,
kl2minf, kl2maxf, ilfomode, \
keqminf, keqmaxf, keqminl, keqmaxl, keqminq, keqmaxq, ieqmode,
\
kfn, il1fn, il2fn, ieqffn, ieqlfn, ieqqfn
  out ares*1000
endin
</CsInstruments>
<CsScore>
t 0 60
i 1 0 4 6.05
i 1 0 4 8.00
i 1 0 4 8.05
i 1 0 4 8.09
e
</CsScore>
</CsoundSynthesizer>
Fig.2: oscbnk.csd
A f-table 1 é uma onda de dente de serra e é a forma dos osciladores de oscbnk,
a f-table 3 é a onda do LFO1 e se assemelha a uma senóide, e a f-table 5 é a onda
mapeada para as frequências centrais do equalizador.
Os sintetizadores analógicos criados por Robert Moog revolucionaram o
mercado da década de 70, e se tornou referência para os sintetizadores atuais. 
Existem atualmente três opcodes que emulam partes do sintetizador Mini-
Moog, são eles moog, moogvcf e moogladder, sendo que os dois últimos emulam o
cerne do Mini-Moog, que é o filtro ladder. 
Veremos mais especificamente o moogladder, criado por Victor Lazzarini. A
sintaxe de moogladder que usaremos é:
asig moogladder ain, kcf, kres
Temos em ain o sinal de entrada, em kcf a frequência de corte, e em  kres o
índice de ressonância. O filtro ladder do Mini-Moog é um tipo de filtro passa-baixa
ressonante, isto é, acima de uma determinada frequência de corte o sinal é atenuado.
Entretanto ao invés de apenas agir como um filtro passa-baixa comum, a ressonância
causa também o efeito de corner peaking, isto é, as frequências próximas da frequência
de corte são extremamente acentuadas, como um pico para em seguida as sequências
superiores serem drasticamente atenuadas. Isso faz com que se acentue o espectro mais
agudo das frequências imediatamente próximas a frequência de corte, e acima dela as
frequências chegem próximo de se anular, como uma escalada íngreme e logo depois um
vale. 
Em nosso exemplo iremos variar a frequência de corte kcf de moogladder, e
você poderá apreciar o efeito que ela causa. Usaremos dois instrumentos, no primeiro a
onda de entrada é uma onda dente-de-serra e a frequência de corte aumenta ao longo do
tempo, no segundo a entrada é uma senóide e a frequência de corte começa alta para ir
diminuindo.
Apesar de variarmos completamente os sinais de entrada, a ação de
moogladder é drástica no sentido que diminui as diferenças das ondas que entram. Se
usássemos um sample de vocal a saída ainda seria semelhante à que obtemos. Na
verdade, o que influi principalmente é quais frequências de corte usaremos.
No código abaixo usaremos como gerador de sinal do primeiro instrumento, o
oscilador vco, visto no início do capítulo 5.
<CsoundSynthesizer>
<CsOptions>
-o moogladder.wav
</CsOptions>
<CsInstruments>
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1
instr 1
  iamp = 30000
  icps = cpspch(p4)
  isaw = 1
  asig vco iamp, icps, isaw
  kcf linseg icps, p3/2, icps*5, p3/2, icps
  kres init 1
  a1 moogladder asig, kcf, kres
  out a1
endin
instr 2
  iamp = 30000
  icps = cpspch(p4)
  ifn = 1
  kenv linseg 0, p3*.2, 1, p3*.8, 1
  asig oscil iamp, icps, ifn
  kcf line icps*10, p3, icps
  kres init 1
  a1 moogladder asig, kcf, kres
  out a1*kenv        
endin        
</CsInstruments>
<CsScore>
f1 0 8192 10 1 
     
i1 0   20 8.04  
i2 10  10 8.00
i2 10  10 7.09
e
</CsScore>
</CsoundSynthesizer>
Fig.3: moogladder.csd