Obrigado a Julio Marchi pelo espaço cedido na MSX All
 

MSX Digitized Sound Generator

  Ferramenta para conversão de sons do PC (samples) para rodar no PSG do MSX. Digitalize vozes e coloque no seu programa!
Descrição dos players - formatos PCM 1 bit e 4 bits   Esta página tem como objetivo explicar como o MSX é capaz de reproduzir sons (samples) através dos chips PPI e do PSG, além de apresentar o código fonte explicado dos players criados para a reprodução dos samples.
  A leitura dos dados envolve uma alta freqüência, o que impossibilita a tarefa de leitura em Basic. Assim, os códigos dos players descritos nessa seção serão feitos em Assembly.
Move Data - Movendo o arquivo de som para as páginas 0 e 1 da RAM   Devido ao fato dos arquivos de som serem grandes demais, a solução adotada pelos programas Video Hits e Digivoix é colocar o arquivo de som na página 0 e/ou 1. Para isso, devemos chavear os slots das páginas 0 e 1, pois estão setadas em Basic para o uso da ROM. Isto só é possível através da linguagem Assembly.
  No caso do Video Hits, ele coloca dois blocos de 16 KB nas páginas 0 e 1. Esse programa adota uma solução inteligente, pois carrega cada bloco da música em formato binário no endereço de &H9000 a &HCFFF (como o programa dele em Basic é pequeno, esta área está livre) e depois move os dados para página 0 ou 1 com um pequeno programa em Assembly.
  O Digivoix, entretanto, utiliza um arquivo no formato texto, onde carrega pequenos blocos na memória e transfere esses blocos de modo semelhante ao Video Hits. Essa combinação de procedimentos resulta, para um arquivo de 16 KB, de cerca de 30 minutos de carregamento, enquanto que o Video Hits leva poucos segundos para carregar e mover os dados de cada bloco.

  O programa em Assembly a seguir move um bloco carregado no endereço de &H9000 a &HCFFF para a página 0 da memória RAM. Esse código permite a troca de slots em qualquer MSX que possua a RAM em um slot primário e a ROM na página 0.
End  Cód máquina  Linha         Mnemônicos        Comentários
-------------------------------------------------------------------------------------
D100  		   10 		ORG  &HD100	; Endereço inicial do programa
D100  F3	   20 		DI 		; Desabilita interrupções
D101  DB A8	   30 		IN   A,(&HA8)	; Lê configuração de slots
D103  5F	   40 		LD   E,A	; Salva em E
D104  06 04	   50 		LD   B,4	; 
D106  CB 3F	   60 ROT1:	SRL  A		; Faz A >> 4
D108  10 FC	   70 		DJNZ ROT1	;
D10A  83	   80 		ADD  A,E	; Junta A com E
D10B  D3 A8	   90 		OUT  (&HA8),A	; Configura RAM em todos os slots
D10D  21 00 90	  100 		LD   HL,&H9000	; Origem
D110  11 00 00	  110 		LD   DE,&H0000	; Destino
D113  01 00 40	  120 		LD   BC,&H4000	; Comprimento
D116  ED B0	  130 		LDIR 		; Move bloco de dados na RAM
D118  DB A8	  140 		IN   A,(&HA8)	; Lê a configuração de slots
D11A  E6 F0	  150 		AND  &HF0	; Faz páginas 0 e 1 como ROM
D11C  D3 A8	  160 		OUT  (&HA8),A	; Envia dados e efetua troca
D11E  FB	  170 		EI 		; Habilita interrupções
D11F  C9	  180 		RET 		; Retorna ao Basic

  Para mover um bloco para a página 1, basta alterar a posição &HD112 de 0 para &H40. O programa em Basic a seguir ilustra como carregar um bloco na página 0 e outro na página 1.
10 BLOAD"MVDATA.BIN"
20 DEFUSR=&HD100
30 BLOAD"BLOCO1.SND"
40 X=USR(0)
50 BLOAD"BLOCO2.SND"
60 POKE &HD112,&H40
70 X=USR(0)
MarMSX SND (1 bit) - som através do click de teclado do chip PPI   A porta C da PPI nos permite habilitar o click das teclas do teclado, através do bit 7 [1]. Veja o esquema abaixo [1].
PPI Port C (I/O Port AAH)

   7     6     5     4     3     2     1     0
┌─────┬─────┬─────┬─────┬───────────────────────┐
│ Key │ Cap │ Cas │ Cas │  Keyboard Row Select  │
│Click│ LED │ Out │Motor│                       │
└─────┴─────┴─────┴─────┴───────────────────────┘
  Conforme indica o Livro Vermelho do MSX [1], o som gerado pelo click é atenuado e misturado com a saída do chip de som do PSG. Além disso, é necessário ligar e desligar esse bit de forma a gerar um som.
  Na realidade, um click somente é produzido quando se altera o estado do bit 7. Caso se altere de 0 para 1, um click forte é gerado e seu valor é atenuado até o silêncio, caso não haja a alteração de seu valor. Quando a alteração é feita de 1 para 0, um click fraco é gerado e atenuado até o silêncio, caso o estado do bit 7 não seja alterado. A freqüência de ambos os eventos é de cerca de 100 Hz.
  A imagem a seguir ilustra isso. Observe os valores do bit 7 ao longo do tempo. Quando há transições entre 0 e 1, há a geração de um pulso (um para cima, outro para baixo).   Com base nos players do programa Video Hits e Digivoix, propomos a criação do player a seguir. Esse player contém melhorias significativas, pois permite a troca de slots em qualquer MSX, bem como toma cuidado na hora de setar o bit 7 da PPI, preservando o estado dos demais bits.
End  Cód máquina  Linha         Mnemônicos        Comentários
-------------------------------------------------------------------------------------
D000  		   10 		ORG  &HD000	; Endereço inicial de execução
D000  F3	   20 		DI 		; Desabilita interrupção
D001  DB A8	   30 		IN   A,(&HA8)	; Obtém configuração dos slots
D003  5F	   40 		LD   E,A	; Salva no reg. E
D004  06 04	   50 		LD   B,4	; 
D006  CB 3F	   60 ROT:	SRL  A		; Desloca o valor de A 4 vezes
D008  10 FC	   70 		DJNZ ROT	;
D00A  83	   80 		ADD  A,E	; Soma A com E
D00B  D3 A8	   90 		OUT  (&HA8),A	; Configura todas as páginas como RAM
D00D  21 00 00	  100 		LD   HL,0	; Endereço inicial do PCM
D010  4E	  110 LOOP:	LD   C,(HL)	; Lê próximo octeto (8 amostras)
D011  06 08	  120 		LD   B,8	; Repete 8x
D013  CB 11	  130 LPI:	RL   C		; Desloca 1 bit para a esquerda
D015  DB AA	  140 		IN   A,(&HAA)	; Lê o estado da porta C da PPI
D017  38 04	  150 		JR   C,TONE	; Verifica de CY=1
D019  E6 7F	  160 		AND  &H7F	; Se não, click=0
D01B  18 02	  170 		JR   CHTONE	; Salta para CHtone
D01D  F6 80	  180 TONE:	OR   &H80	; Se sim, click=1
D01F  D3 AA	  190 CHTONE:	OUT  (&HAA),A	; Envia resultado para PPI
D021  1E 0E	  200 		LD   E,14	; Define um delay de 14
D023  1D	  210 DELAY:	DEC  E		;
D024  20 FD	  220 		JR   NZ,DELAY	; Delay
D026  10 EB	  230 		DJNZ LPI	;
D028  23	  240 		INC  HL		; Passa para o próximo octeto
D029  7C	  250 		LD   A,H	;
D02A  FE 40	  260 		CP   &H40	; Verifica de HL=&H4000
D02C  20 E2	  270 		JR   NZ,LOOP	; Se não for, repete LOOP
D02E  DB A8	  280 		IN   A,(&HA8)	; Obtém configuração dos SLOTS
D030  E6 F0	  290 		AND  &HF0	; Seta páginas 0 e 1 como ROM
D032  D3 A8	  300 		OUT  (&HA8),A	; Troca
D034  FB	  310 		EI 		; Habilita interrupções
D035  C9	  320 		RET		; Retorna ao Basic
  O primeiro passo é setar as 4 páginas de memória como sendo RAM (linhas 30-90), para podermos utilizar as páginas 0 ou 1. Os arquivos de som são grandes e deverão fazer uso dessa parte da RAM não utilizada pelo Basic.
  Em seguida, apontamos para o endereço inicial do arquivo de som e lemos o primeiro byte. Como esse formato é de 1 bit, devemos ler os 8 bits desse byte. A instrução de deslocamento RL desloca 1 bit à esquerda e coloca o bit 7 no flag de carry. Assim, o resultado contido no flag de carry irá indicar o estado do click.
  O programa Digivoix faz um brincadeira com esse deslocamento para causar um efeito no som. Ele altera a rotação à esquerda dos bits para a rotação à direita.
  A cada bit lido e executado, faz-se uma pausa. Essa pausa (delay) é utilizada para sincronizar a freqüência de execução do programa com a freqüencia do arquivo de som PCM. Por exemplo, no Video Hits o delay de 14 corresponde a uma freqüência de 11.131 Hz.
  Após a leitura dos 8 bits, é verificado se o final do arquivo de som foi atingido. Caso não tenha, repete-se a operação de leitura e execução de som.
  Quando a leitura termina, devolvemos o estado inicial dos slots, com as páginas 0 e 1 na ROM.

  Programa em Basic para carregar um bloco de som, mover e depois tocá-lo.
10 BLOAD"SOUND.SND"
20 BLOAD"MVDATA.BIN"
30 DEFUSR=&HD100
40 X=USR(0)
50 BLOAD"SND.BIN"
60 DEFUSR=&HD000
70 X=USR(0)
MarMSX S4b (4 bits) - som através do chip de som PSG   Esse formato irá modular o volume de um dos canais do PSG do MSX.
  Cada canal de som do MSX é capaz de discriminar 16 níveis de volume, o que nos permite descrever a onda sonora com até 4 bits. Isso nos permite modelar a onda original de uma forma mais precisa do que o formato de 1 bit. Entretanto, isso tem um preço alto: o arquivo de 4 bits terá quatro vezes o tamanho de um arquivo de 1 bit.
  Utilizaremos um sinal com a máxima freqüência possível, pois não é possível gerar um tom com intensidade máxima como na PPI, e somente podemos gerar um envelope sobre o sinal do PSG.
  Utilizaremos o canal A e ajustaremos o período para 0. Então, lemos o arquivo e alteramos o volume do canal A ao longo do tempo, de acordo com o formato da onda de som.

  O programa em Assembly para gerar sons em 4 bits é apresentado a seguir.
End  Cód máquina  Linha         Mnemônicos        Comentários
-------------------------------------------------------------------------------------
D000  		   10 		ORG  &HD000	; Endereço inicial do programa
D000  F3	   20 		DI 		; Desabilita interrupções
D001  3E 07	   30 		LD   A,7	; Escolhe registrador 7 (mixer)
D003  D3 A0	   40 		OUT  (&HA0),A	;
D005  3E BE	   50 		LD   A,190	; Valor do Mixer - habilita canal A
D007  D3 A1	   60 		OUT  (&HA1),A	;
D009  AF	   70 		XOR  A		; Escolhe registrador 0
D00A  D3 A0	   80 		OUT  (&HA0),A	;
D00C  3E 00	   90 		LD   A,0	; Período fino = 0
D00E  D3 A1	  100 		OUT  (&HA1),A	;
D010  3E 01	  110 		LD   A,1	; Registrador 1
D012  D3 A0	  120 		OUT  (&HA0),A	;
D014  AF	  130 		XOR  A		; Período grosso = 0
D015  D3 A1	  140 		OUT  (&HA1),A	;
D017  DB A8	  150 		IN   A,(&HA8)	; Lê conf. slots
D019  5F	  160 		LD   E,A	; Salva em E
D01A  06 04	  170 		LD   B,4	;
D01C  CB 3F	  180 ROT:	SRL  A		; Faz A >> 4
D01E  10 FC	  190 		DJNZ ROT	;
D020  83	  200 		ADD  A,E	; Junta valores
D021  D3 A8	  210 		OUT  (&HA8),A	; Seta páginas como RAM
D023  21 00 00	  220 		LD   HL,0	; Endereço inicial do som
D026  06 02	  230 LOOP:	LD   B,2	; Lê 2 nibbles
D028  1E 00	  240 		LD   E,0	; E armazena valor de A
D02A  3E 08	  250 LPI:	LD   A,8	; Seleciona registro 8
D02C  D3 A0	  260 		OUT  (&HA0),A	;
D02E  7B	  270 		LD   A,E	; Recupera valor salvo
D02F  ED 6F	  280 		RLD 		; Rotaciona A com (HL)
D031  D3 A1	  290 		OUT  (&HA1),A	; Altera volume
D033  5F	  300 		LD   E,A	; Salva valor em E
D034  16 0E	  310 		LD   D,14	;
D036  15	  320 DELAY:	DEC  D		; Delay de 14
D037  20 FD	  330 		JR   NZ,DELAY	;
D039  10 F4	  340 		DJNZ LPI	; Next B
D03B  ED 6F	  350 		RLD 		; Rotaciona para recuperar (HL)
D03D  23	  360 		INC  HL		; Próximo byte do som
D03E  7C	  370 		LD   A,H	; 
D03F  FE 40	  380 		CP   &H40	; Verifica se HL=fim
D041  20 E3	  390 		JR   NZ,LOOP	; Senão, loop
D043  3E 08	  400 		LD   A,8	; Registrador 8
D045  D3 A0	  410 		OUT  (&HA0),A	;
D047  AF	  420 		XOR  A		; Volume 0
D048  D3 A1	  430 		OUT  (&HA1),A	;
D04A  DB A8	  440 		IN   A,(&HA8)	; Lê slots
D04C  E6 F0	  450 		AND  &HF0	; Faz RAM RAM ROM ROM
D04E  D3 A8	  460 		OUT  (&HA8),A	;
D050  FB	  470 		EI 		; Habilita interrupções
D051  C9	  480 		RET 		; Retorna ao Basic
  Nota importante: segundo o Livro Vermelho do MSX [1], devemos alterar o registro 7 do PSG sempre como os bits 7 e 6 da seguinte forma: &b10xxxxxx, ou seja, o bit 7 deve ser 1 e o bit 6 deve ser 0. Caso contrário, poderá danificar o PSG.

  Programa em Basic para carregar um bloco de som, mover e depois tocá-lo.
10 BLOAD"SOUND.S4B"
20 BLOAD"MVDATA.BIN"
30 DEFUSR=&HD100
40 X=USR(0)
50 BLOAD"S4B.BIN"
60 DEFUSR=&HD000
70 X=USR(0)
MarMSX S4b Plus (4 bits) - utiliza os três canais do PSG   Em janeiro de 2022 foi lançada a versão plus do S4b, onde em vez de tocar apenas 1 canal de som do PSG, toca os três aos mesmo tempo.

  O programa em Assembly para gerar sons em 4 bits com os três canais é apresentado a seguir.
End  Cód máquina  Linha         Mnemônicos              Comentários
-------------------------------------------------------------------------------------
D000  		   10 		ORG  &HD000		; Endereço inicial do programa
D000  F3	   20 		DI 			; Desabilita interrupções
D001  3E 07	   30 		LD   A,7		; Escolhe registrador 7 (mixer)
D003  D3 A0	   40 		OUT  (&HA0),A		;
D005  3E B8	   50 		LD   A,&B10111000	; Valor do Mixer
D007  D3 A1	   60 		OUT  (&HA1),A		;  habilita canais A,B,C
D009  06 07	   70 		LD   B,7		;
D00B  78   	   80 LPSG:	LD   A,B		;
D00C  3D   	   90 		DEC  A			; Ajusta todos os periodos
D00D  D3 A0	  100 		OUT  (&HA0),A		; 
D00F  AF   	  110 		XOR  A			; para o valor zero
D010  D3 A1	  120 		OUT  (&HA1),A		;
D012  10 F7	  130 		DJNZ LPSG		;
D014  DB A8	  140 		IN   A,(&HA8)		; Lê conf. slots
D016  5F	  150 		LD   E,A		; Salva em E
D017  06 04	  160 		LD   B,4		;
D019  CB 3F	  170 ROT:	SRL  A			; Faz A >> 4
D01B  10 FC	  180 		DJNZ ROT		;
D01D  83	  190 		ADD  A,E		; Junta valores
D01E  D3 A8	  200 		OUT  (&HA8),A		; Seta páginas como RAM
D020  21 00 00	  210 		LD   HL,0		; Endereço inicial do som
D023  06 02	  220 LOOP:	LD   B,2		; Lê 2 nibbles
D025  1E 00	  230 		LD   E,0		; E armazena valor de A
D027  7B	  240 LPI:	LD   A,E		; Recupera valor salvo
D028  ED 6F	  250 		RLD 			; Rotaciona A com (HL)
D02A  4F   	  260 		LD   C,A 		; Salva em C
D02B  3E 08	  270 		LD   A,8		; Seleciona registro 8 (ch. A)
D02D  D3 A0	  280 		OUT  (&HA0),A		;
D02F  79   	  290 		LD   A,C 		; Recupera A
D030  D3 A1	  300 		OUT  (&HA1),A		; Altera volume
D032  3E 09	  310 		LD   A,9		; Seleciona registro 9 (ch. B)
D034  D3 A0	  320 		OUT  (&HA0),A		;
D036  79   	  330 		LD   A,C 		; Recupera A
D037  D3 A1	  340 		OUT  (&HA1),A		; Altera volume
D039  3E 0A	  350 		LD   A,10		; Seleciona registro 10 (ch. C)
D03B  D3 A0	  360 		OUT  (&HA0),A		;
D03D  79   	  370 		LD   A,C 		; Recupera A
D03E  D3 A1	  380 		OUT  (&HA1),A		; Altera volume
D040  5F	  390 		LD   E,A		; Salva valor em E
D041  16 0E	  400 		LD   D,14		;
D043  15	  410 DELAY:	DEC  D			; Delay de 14
D044  20 FD	  420 		JR   NZ,DELAY		;
D046  10 DF	  430 		DJNZ LPI		; Next B
D048  ED 6F	  440 		RLD 			; Rotaciona para recuperar (HL)
D04A  23	  450 		INC  HL			; Próximo byte do som
D04B  7C	  460 		LD   A,H		; 
D04C  FE 40	  470 		CP   &H40		; Verifica se HL=fim
D04E  20 D3	  480 		JR   NZ,LOOP		; Senão, loop
D050  DB A8	  490 		IN   A,(&HA8)		; Lê slots
D052  E6 F0	  500 		AND  &HF0		; Faz RAM RAM ROM ROM
D054  D3 A8	  510 		OUT  (&HA8),A		;
D056  FB	  520 		EI 			; Habilita interrupções
D057  CD 90 00	  530 		CALL &H90		; Inicia PSG (zera volumes)
D05A  C9	  540 		RET 			; Retorna ao Basic
  A forma de carregamento, bem como o formato do arquivo de som s4b são os mesmos da versão normal do Sb4. Entretanto, a relação entre frequência e delay mudou. Dessa forma, confira o arquivo conv_table.txt que acompanha o programa.

  Os players MarMSX SND, MarMSX S4b e MarMSX S4b Plus mais o Move Data são de autoria de Marcelo Silveira e estão sob licença GNU-GPL v. 3.x - http://www.gnu.org/licenses/gpl-3.0.txt.



  Referências:

  1. O Livro Vermelho do MSX, Avalon Software, editora McGraw Hill.
  2. Video Hits, Produzido pelo grupo CPM.
  3. Digivoix, Produzido por Hartard Frederic e publicado na revista francesa Hebdogiciel,
números 164 a 168, 1986.


Marcelo Silveira
Engenheiro de Sistemas e Computação
Especialista em Processamento de Imagens e Inteligência Artificial
© MarMSX 1999-2025