Curso de Jogos em Basic
Criando sons
Você está em: MarMSX >> Cursos >> Jogos em Basic
Nesse capítulo extra veremos como podemos utilizar o comando SOUND do Basic para gerar efeitos sonoros para um jogo.
O comando SOUND do MSX
O comando SOUND do Basic do MSX é capaz de modificar os registros do PSG, o chip de som do MSX. Neste artigo, faremos uma breve descrição desse comando. Caso o leitor deseje maiores informações sobre o comando SOUND, sugerimos uma leitura no capítulo 11 do curso de Basic dessa homepage.
A sintaxe do comando SOUND é:
SOUND número_do_registro, valor
Os registros que usaremos são:
0/1 - Período do canal A (forma de onda mais interna)
7 - Seleção para canal e ruído
8 - Volume do canal A (0-15. 16=envelope)
11/12 - Peíodo do envelope (forma de onda mais externa)
13 - Forma do envelope
Formato do envelope (registro 13):
0-3 / 9 | ◺
4-7 / 15 | ◿
8 | ◺◺◺◺◺◺◺
10 | ◺△△△△△△
11 | ◺|▔▔▔▔▔
12 | ◿◿◿◿◿◿◿
13 | /▔▔▔▔▔▔
14 | △△△△△△△
Analisando um sinal sonoro
Podemos reproduzir um determinado tipo de sinal sonoro através da análise da sua forma de onda. Essa tarefa se torna mais fácil, quando a frequência do sinal não varia (muito) com o tempo. Um bom exemplo disso é o som de um apito.
A seguir, iremos analisar o espectro do som de um apito para podermos entender os conceitos de período, frequencia e envelope.
O envelope é a variação de volume de um sinal ao longo do tempo (registradores 11 e 12 do PSG). Conforme podemos observar na imagem acima, o som do apito aumenta e abaixa de volume diversas vezes ao longo do tempo. Vejamos a ampliação do espectro para observar melhor o envelope.
No gráfico anterior, observamos duas formas de onda principais: o sinal mais externo e com menor freqüência é o envelope. O sinal mais interno e de maior freqüência é o sinal sonoro.
Apesar dos períodos do envelope variar um pouco, vamos considerá-los constantes. Ao observarmos a figura acima, constatamos que o a parte superior da forma de onda do envelope é parecido com o seguinte formato:
-------- -------- --------
/ \/ \/ \ ...
|--------|
Período do
Envelope
Iremos a seguir selecionar um período do envelope para medir sua duração e depois sua frequência. Observe na figura abaixo a presença de uma régua no topo da figura, contendo a medição de tempo decorrido do sinal em segundos. Os intervalos de tempo nessa régua são de 0,0005 segundos.
O período do envelope selecionado varia de 0,4275 a 0,4495 segundos. Dessa forma, sua duração é de 0,022 segundos. Como a freqüência é o inverso do período, temos que F=1/T ou Fenv=45,45 Hz.
Ao ampliarmos mais o sinal, podemos medir a freqüência interna dele (registrador 0 e 1 do PSG).
O sinal varia de 0,43895 a 0,43930. Assim T=0,00035 segundos e F=2857,14 Hz.
No capítulo 11 do curso de Basic, tem um programa que gera um som a partir das freqüências do sinal e do envelope. Iremos utilizá-lo para gerar o som do apito.
10 ' Determina a freqüência em A
20 F=freq_sinal
30 A=3575611#/8192/F
40 SOUND 1, INT(A)
50 SOUND 0, INT(0.5+256*(A-INT(A)))
60 ' Mixer - seleciona som em A
70 SOUND 7,255-1
80 ' Envelope
90 SOUND 8,16
100 FE=freq_envelope
110 A=3575611#/131072!/FE
120 SOUND 12, INT(A)
130 SOUND 11, INT(0.5+256*(A-INT(A)))
140 SOUND 13,forma_envelope
A forma de envelope do PSG mais parecida com a forma de envelope do apito apresentada mais acima é a 14. Assim, já temos as informações necessárias para preencher os dados assinalados em vermelho no código Basic anterior.
Som: apito
Sinal
T = 0,00035 segundos
F = 2857,14 Hz
Envelope
T = 0,022 segundos
F = 45,45 Hz
Tipo = 14
O programa em Basic para gerar um som de apito é:
10 ' Determina a freqüência em A
20 F=2857.14
30 A=3575611#/8192/F
40 SOUND 1, INT(A)
50 SOUND 0, INT(0.5+256*(A-INT(A)))
60 ' Mixer - seleciona som em A
70 SOUND 7,255-1
80 ' Envelope
90 SOUND 8,16
100 FE=45.45
110 A=3575611#/131072!/FE
120 SOUND 12, INT(A)
130 SOUND 11, INT(0.5+256*(A-INT(A)))
140 SOUND 13,14
Podemos estabelecer um intervalo para o apito soar e depois interrompê-lo.
150 FOR T=1 TO 500 : NEXT T
160 SOUND 8,0 ' Pára o apito
Nota:
- Podemos também realizar ajustes finos no som, variando a freqüência do sinal, a freqüencia do envelope e a forma do envelope até encontrarmos os valores ideais.
- De forma a simplificar o processamento do programa, podemos calcular os valores passados para SOUND 0,1 e 11,12 apenas uma vez e inseri-los diretamente no código (linhas 40, 50, 120 e 130).
Para inserir diretamente os valores no SOUND, utilizamos as seguintes fórmulas:
FC FC
T = ------ T = ---------
16 X F 256 x Fenv
Onde: FC = clock_z80 / 2 = 1787805
Para obter a frequência a partir do MSB (período grosso) e LSB (período fino):
FC FC
F = ------ Fenv = ---------
16 X T 256 x Tenv
Onde:
1. FC = clock_z80 / 2 = 1787805
2. T = MSB x 256 + LSB
A frequência do sinal é variante
Há determinados sons emitidos em que a frequência do sinal varia ao longo do tempo. Podemos citar como exemplos um assobio, o motor de um carro e um telefone.
Motor
Vamos reproduzir o som de um motor. A frequencia dele varia de acordo com a potência aplicada. O volume é mantido constante, ou seja, não há qualquer forma de envelope aplicada ao sinal.
10 ' Determina a freqüência inicial em A
20 T1=255:T2=52
30 ' Mixer - seleciona som em A
40 SOUND 7,255-1
50 SOUND 8,13
60 ' Varia frequencia do sinal para cima - acelera
70 FOR T=0 TO 256
80 SOUND 0,T1 : SOUND 1,T2
90 T1=T1-2 : IF T1<0 THEN T1=255 : T2=T2-1
100 NEXT T
110 ' Varia frequencia do sinal para baixo - desacelera
120 FOR T=0 TO 256
130 SOUND 0,T1 : SOUND 1,T2
140 T1=T1+2 : IF T1>255 THEN T1=0 : T2=T2+1
150 NEXT T
160 SOUND 8,0
Assobio
No próximo exemplo, vamos reproduzir o som de um assobio. Diferente do apito, o som começa com uma frequência alta, diminui, e logo aumenta.
Para reproduzi-lo, vamos manter o volume constante e variar a freqüência.
10 ' Determina a freqüência em A
20 SOUND 0,40
30 SOUND 1,0
40 ' Mixer - seleciona som em A
50 SOUND 7,255-1
60 SOUND 8,13
70 FOR F=40 TO 50 STEP .1 : SOUND 0,F: NEXT
80 FOR F=50 TO 30 STEP -.3 : SOUND 0,F: NEXT
90 FOR T=1 TO 25:NEXT T
100 SOUND 0,0
Nota: para encontrar o período inicial de 40 para o assobio, fui variando o valor de SOUND 0,<n> até encontrar a mesma freqüência do meu assobio.
Telefone
O som de um telefone tocando pode ser simulado da seguinte maneira: alternamos duas frequências de som de forma abrupta por algumas vezes, fazendo então uma pausa. Veja o programa a seguir.
10 SOUND 1,0
20 SOUND 7,255-1
30 SOUND 8,15
40 FOR G=1 TO 12 ' Numero de toques alternados antes da pausa
50 SOUND 0,200
60 FOR F=0 TO 32 : NEXT F
70 SOUND 0,255
80 FOR F=0 TO 32 : NEXT F
90 NEXT G
100 SOUND 8,0 ' Silencio
110 FOR F=0 TO 1100 : NEXT F
120 GOTO 30
Fonte: Revista MSX Micro [4].
Sirenes
Vamos reproduzir os sons da sirene de uma ambulância e da polícia, que também variam a frequência do sinal.
Som: Ambulância
Sinal (valores aproximados)
T = 0,00065 segundos
F = 1538,46 Hz
TMSX = 73
MBS = TMSX \ 256 = 0
LSB = TMSX MOD 256 = 73
Programa em Basic da sirene da ambulância.
10 ' Determina a freqüência em A
15 T=73 : P=0.05
20 SOUND 0,T
30 SOUND 1,0
40 ' Mixer - seleciona som em A
50 SOUND 7,255-1
60 SOUND 8,13
70 FOR F=T-10 TO T+10 STEP P : SOUND 0,F: NEXT
80 FOR F=T+10 TO T-10 STEP -P : SOUND 0,F: NEXT
90 GOTO 70
A variável "P" controla o tempo de variação da freqüência.
Som: Sirene da polícia
Sinal (valores aproximados)
T = 0,000705 segundos
F = 1418,44 Hz
TMSX = 79
MBS = TMSX \ 256 = 0
LSB = TMSX MOD 256 = 79
Programa em Basic da sirene da polícia.
10 ' Determina a freqüência em A
15 T=79 : P=0.3
20 SOUND 0,T
30 SOUND 1,0
40 ' Mixer - seleciona som em A
50 SOUND 7,255-1
60 SOUND 8,13
70 FOR F=T-10 TO T+10 STEP P : SOUND 0,F: NEXT
80 FOR F=T+10 TO T-10 STEP -P*3 : SOUND 0,F: NEXT
90 A = STICK(0)
100 IF A=1 THEN P=P+.05 : IF P>0.5 THEN P=.5
110 IF A=5 THEN P=P-.05 : IF P<0.05 THEN P=.05
120 GOTO 70
Deixe a sirene mais rápida ou mais lenta usando as teclas do cursor para cima e para baixo. Observe que a "subida" de freqüência da polícia é 3 vezes mais rápida que a descida (linha 80).
No próximo exemplo, vamos simular o Efeito Doppler para a sirene da polícia. Quando ela se aproxima, sua freqüência é alta, vai diminuindo e o volume aumenta. Quando se afasta, o volume cai e a freqüência continua diminuindo. No instante que a polícia passa por você, possui a freqüência normal e volume máximo.
10 ' Determina a freqüência em A
15 T=79 : P=0.3 : V=10
20 SOUND 0,T
30 SOUND 1,0
40 ' Mixer - seleciona som em A
50 SOUND 7,255-1
60 SOUND 8,V : T=T+20 : M=1
70 FOR F=T-10 TO T+10 STEP P : SOUND 0,F: NEXT
80 FOR F=T+10 TO T-10 STEP -3*P : SOUND 0,F: NEXT
90 IF M=1 THEN T=T+2:V=V+.5 ELSE T=T+2:V=V-.5
100 IF V=15 THEN M=2
110 SOUND 8,V
120 IF V=5 THEN END
130 GOTO 70
Ruídos e envelope
O MSX é capaz de gerar ruídos através do registrador 6. O ruído é um som com frequências pseudo-aleatórias que é gerado pelo PSG, de forma que a frequência resultante é formada pela informação do clock de entrada mais o valor de período fornecido para o registrador 6.
O motor de um avião pode ser simulado através do uso de um ruído mais um envelope (envoltória) periódica. Veja a figura a seguir.
O primeiro sinal da figura anterior é o ruído. Já o segundo sinal mais abaixo, é o envelope aplicado ao ruído.
No exemplo a seguir, apresentamos o som do motor de uma avião, onde ainda modificamos a frequência do envelope de forma a parecer que o motor do avião está ligando.
10 SOUND 6,20 ' Freq. ruido
20 SOUND 7,&B10110111
30 SOUND 8,16
40 SOUND 11,255
50 SOUND 12,0
60 SOUND 13,14 ' Envelope periodico
70 FOR I=255 TO 50 STEP -.1
80 SOUND 11,I ' Freq. Envelope
90 NEXT I
Cuidados com sons repetidos e seqüenciais
Vimos que os processadores Z80 e PSG trabalham de forma independente. Dessa forma, quando enviamos um determinado som para o PSG com um envelope de "fábrica", ele irá trabalhar de forma independente do Z80 para produzir aquele som por determinado período (tempo).
Quando criamos uma seqüência de sons (ou repetimos o mesmo som) com um determinado envelope habilitado, devemos incluir uma pausa para que o PSG tenha tempo de gerar corretamente o som. Caso contrário, o som seguinte "atropela" o som corrente, de forma que este não seja percebido.
No jogo Alcatraz, a fuga impossível, uma seqüência de tiros é disparada na tela de abertura, a partir do mesmo som. Um intervalo é feito, para que o som de cada tiro possa soar antes que outro tiro soe.
Veja o programa a seguir.
10 FOR N=0 TO 9
20 SOUND 7,7:SOUND 8,16:SOUND 6,25:SOUND 13,0:SOUND 12,20
30 FOR M=0 TO 100:NEXT M
40 NEXT N
Experimente comentar a linha 30 (coloque REM ou ' no inicio da linha). Apenas um tiro é percebido.
Ao aumentar o diminuir o intervalo da linha 30, modificamos o tempo de disparo entre as balas.
Sons de programas e jogos
Nesta seção veremos alguns exemplos de sons publicados em livros e jogos.
Utilize as seguintes funções em Python para calcular as frequências e períodos para os programas em Basic:
# Envoltoria
def freq_env(msb, lsb):
f = 1787805 / (256.0 * (msb*256.0 + lsb))
print("Freq.: {:.2f} Hz.".format(f))
print("Per.: {:.2f} Seg.".format(1/f))
# Sinal e ruido
def freq_sr(msb, lsb):
f = 1787805 / (16.0 * (msb*256.0 + lsb))
print("Freq.: {:.2f} Hz.".format(f))
print("Per.: {:.2f} Seg.".format(1/f))
Convenções do sinal e envelope:
MSB LSB (MSB*256 + LSB)
Livro Dominando o Expert
Som de helicóptero
Sinal: 0 24 (24) F = 4655,74 Hz
Canal C V = Envelope
Ruído: 22 F = 5078,99 Hz
Envelope: 2 90 F = 11,60 Hz
(602) T = 0,086 seg.
Tipo envelope: 12
10 FOR I=0 TO 13
20 READ S
30 SOUND I,S
40 NEXT I
50 DATA 0,0,0,0,24,0,22,3,2,2,16,90,2,12
60 DATA 0,0,0,0,0,0,21,247,16,0,0,100,60,0
Notas:
♬ - A linha 60 não é lida por esse programa. Ela reproduz o som de tiro (mais adiante), se comentada a linha 50.
♬ - O volume dos canais A e B controla o nível de ruído.
Som de mar
Sinal: Não usa.
Ruído: 5 F = 22347,56 Hz
Envelope: 180 0 F = 0,15 Hz
(46080) T = 6,67 seg.
Tipo envelope: 10
10 SOUND 8,16 ' Habilita envelope
20 SOUND 7,(1+2+4+16+32) ' Mixer
30 SOUND 6,5 ' Freq. ruído
40 SOUND 13,10 ' Tipo envelope
50 SOUND 12,180 ' Freq. envelope
60 SOUND 11,0 ' Freq. envelope
Nota:
♬ - O som leva 6,67 para aumentar de 0 a 15 e voltar a 0 (ciclo).
Som de tiro
Sinal: Não usa.
Ruído: 20 F = 5586,89 Hz
Envelope: 60 100 F = 0,45 Hz
(15460) T = 2,22 seg.
Tipo envelope: 0
10 FOR A=0 TO 13
20 READ B
30 SOUND A,B
40 NEXT
50 DATA 0,0,0,0,0,0,20,247,16,0,0,100,60,0
Nota:
♬ - O tempo de duração do tiro é de 2,2 segundos.
Livro Coleção de Programas para MSX - Vol 1
Aterrissagem de Espaçonave
-= Nave =-
Sinal: 0 a 511 (559) F = 111737.81 a 199,89 Hz
L a L+50 STEP 8 T = 8,95 x 10-6 a 0,005 seg.
-= Pouso =-
Ruído: Não usa
Envelope: 0 12 F = 1,24 Hz
(3072) T = 0,81 seg.
Tipo envelope: 15
10 SOUND 7,56 : SOUND 8,15 : SOUND 9,0 : SOUND 10,0
20 FOR L=0 TO 511 : FOR M=L TO L+50 STEP 8
30 SOUND 0,M MOD 256 : SOUND 1,M\256
40 NEXT M,L
50 SOUND 7,7 : SOUND 8,16 : SOUND 12,32
60 SOUND 6,0 : SOUND 13,15
70 FOR I=1 TO 500 : NEXT I
80 SOUND 13,0
Notas:
♬ - Valores do sinal: 0 0 a 2 47 (0 a 559)
♬ - O período do som varia em cada iteração assim:
[0, 8, 16, 24, 32, 40, 48]
[1, 9, 17, 25, 33, 41, 49]
[2, 10, 18, 26, 34, 42, 50]
...
[511, 519, 527, 535, 543, 551, 559]
Campainha
Sinais: 0 100 F = 1117.38 Hz
0 112 F = 997.66 Hz
0 125 F = 893.90 Hz
0 170 F = 657.28 Hz
Ruído: -
Envelope: -
Tipo envelope: -
10 DATA 100,125,112,170,170,112,100,125
20 RESTORE
30 SOUND 7,56 : SOUND 8,16 : SOUND 1,0 : SOUND 12,36
40 FOR I=1 TO 8 : READ A : SOUND 0,A : SOUND 13,0
50 FOR L=1 TO 400 : NEXT L
60 IF I = 4 THEN FOR L=1 TO 400 : NEXT L
70 NEXT I
Alarme 1
Sinais: 0 100 F = 1117.38 Hz
0 50 F = 2234.76 Hz
Ruído: -
Envelope: -
Tipo envelope: -
10 SOUND 7,56 : SOUND 8,15 : SOUND 1,0
20 SOUND 0,50
30 FOR I=1 TO 200 : NEXT I
40 SOUND 0,100
50 FOR I=1 TO 200 : NEXT I
60 GOTO 20
Alarme 2
Sinais: 0 230 F = 485.82 Hz
0 100 F = 1117.38 Hz
Ruído: -
Envelope: -
Tipo envelope: -
10 SOUND 7,56 : SOUND 8,15 : SOUND 1,0
20 FOR L=230 TO 100 STEP -.5
30 SOUND 0,L
40 NEXT L
50 SOUND 0,0
60 FOR I=1 TO 150 : NEXT I
70 GOTO 20
Sirene
Sinais: A 0 190 F = 588.09 Hz
B 0 192 F = 581.97 Hz
A 0 250 F = 446.95 Hz
B 0 253 F = 441.65 Hz
Ruído: -
Envelope: -
Tipo envelope: -
10 SOUND 7,56 : SOUND 8,15 : SOUND 1,0
20 SOUND 9,15 : SOUND 3,0
30 SOUND 0,190 : SOUND 2,192
40 FOR I=1 TO 400 : NEXT I
50 SOUND 0,250 : SOUND 2,253
60 FOR I=1 TO 400 : NEXT I
70 GOTO 30
Notas:
♬ - Assim como o alerme 1, possui 2 frequências alternadas.
♬ - Porém, cada vez, 2 canais tocam frequências levemente diferentes.
Decolagem
Sinais: A 0 100 F = 1117.38 Hz
A 0 30 F = 3724.59 Hz
Ruído: C 2 a 31 F = 55868.91 a 3604.45 Hz
Envelope: 255 0 F = 2.27 Hz
Tipo envelope: 0
10 SOUND 7,28 : SOUND 1,0 : SOUND 3,0
20 SOUND 6,0 : SOUND 0,100 : SOUND 8,13
30 SOUND 9,0 : SOUND 10,15 : SOUND 12,255
40 FOR L=1 TO 2000 : NEXT L
50 FOR L=100 TO 30 STEP -.04
60 SOUND 0,L
70 NEXT L
80 SOUND 8,0
90 FOR L=2 TO 31 STEP .01
100 SOUND 6,L
110 NEXT L
120 SOUND 10,16
130 SOUND 13,0
Notas:
♬ - Qual o efeito de se alterar a linha 40 de 2000 para 1000?
R: Diminui o intervalo para o foguete começar a decolar.
♬ - E na linha 90, o valor do step de .01 para .1?
R: O efeito da explosão é mais rápido.
Jogo Alcatraz, a Fuga Impossível
Jogar água no fogo
Sinal: Não usa.
Ruído: 0 F = 111737,81 Hz
Envelope: 50 0 F = 0,55 Hz
(15460) T = 1,82 seg.
Tipo envelope: 0
10 SOUND 7,7:SOUND 8,16:SOUND 6,0:SOUND 13,0:SOUND 12,50
Desativar o alarme
Sinal: 5 Q (1280 + Q) F = 22347,56 Hz
Canal A V = 14
Ruído: Não usa.
Envelope: Não usa.
10 SOUND 7,56:SOUND 8,14:SOUND 1,5:FORQ=0TO255:SOUND 0,Q:
20 NEXT:SOUND 8,0
Nota:
♬ - Varia a freqüência na parte LSB do canal A.
Serra ligada
Sinal: 15 0 (3840) F = 29,10 Hz
Canal A V = envelope
Ruído: Não usa.
Envelope: 10 0 F = 2,72 Hz
(2560) T = 0,37 seg.
Tipo envelope: 14
10 SOUND 7,56:SOUND 1,15:SOUND 8,16:SOUND 13,14:SOUND 12,10
Cortar a porta com serra
Sinais: 1 255 (511) F = 218,67 Hz
Canal A V = 15
7 255 (2047) F = 54,58 Hz
Canal B V = 15
Ruído: Não usa.
Envelope: Não usa.
10 SOUND 7,56:SOUND 8,15:SOUND 9,15:SOUND 1,2:SOUND 3,7:
20 SOUND 0,255:SOUND 2,255:FORQ=1TO500:NEXT:
30 SOUND 1,0:SOUND 3,5 ' Muda ambas freq
40 FOR Q=1 TO 1000:NEXT:BEEP
Notas:
♬ - A um final de um tempo, os dois sinais variam a freqüência.
♬ - O BEEP finaliza o som.
Pá cavando
Sinal: Não usa.
Ruído: 6 F = 18622,97 Hz
Envelope: 10 0 F = 2,72 Hz
(2560) T = 0,37 seg.
Tipo envelope: 12
10 SOUND 7,7:SOUND 6,10:SOUND 8,16:SOUND 13,12:SOUND 12,10:
20 FOR Q=0 TO 2500:NEXT:SOUND 8,0
Queimar
Sinal: Não usa.
Ruído: 30 F = 3724,59 Hz
Envelope: 30 0 F = 0,91 Hz
(7680) T = 1,10 seg.
Tipo envelope: 5
10 SOUND 7,7:SOUND 6,30:SOUND 8,16:SOUND 13,5:SOUND 12,30
Disparo arma de fogo
Sinal: Não usa.
Ruído: 26 F = 4297,61 Hz
Envelope: 20 0 F = 1,36 Hz
(5120) T = 0,74 seg.
Tipo envelope: 0
10 SOUND 7,7:SOUND 8,16:SOUND 13,0:SOUND 6,28:SOUND 12,20
Vários tiros na abertura
Sinal: Não usa.
Ruído: 25 F = 4469,51 Hz
Envelope: 20 0 F = 1,36 Hz
(5120) T = 0,74 seg.
Tipo envelope: 0
10 FOR N=0 TO 9
20 SOUND 7,7:SOUND 8,16:SOUND 6,25:SOUND 13,0:SOUND 12,20
30 FOR M=0 TO 100:NEXT M
40 NEXT N
Referências:
[1] - Livro Dominando o Expert, editora Aleph, 5a. Edição, 1987.
[2] - Livro Linguagem Basic MSX, editora Aleph, 5a. Edição, 1987.
[3] - Livro Coleção de Programas para MSX - Volume 1, editora Aleph, 3a. Edição, 1986.
[4] - Revista MSX Micro 16. Editora Fonte Editorial, Julho 1988.