Thanks to Julio Marchi for this space in MSX All |
||
A nice tool to convert PC sounds (samples) to run on MSX PSG. Digitize voices and insert into your app!
Data reading involves a high frequency which make it impossible to run in Basic. So, all players were developed in Assembly. Video Hits program is able to move up to two blocks of 16 KB each to pages 0 and 1. This program performs an intelligent way to load sound files, once it loads a binary file on RAM addresses from &H9000 to &HCFFF (as Video Hits code in Basic is short, this area is free) and then moves the data to RAM page 0 or 1 using a simple Assembly program. Nevertheless, Digivoix makes use of a text file for sound data. It loads small blocks of data and then copies them to page 1 in a quite similar way to Video Hits. This combination of data reading results on about 30 minutes to finish for a 16 KB data file. In contrast, Video Hits takes only a few seconds to load and move the same amount of data to page 0 or 1. The next program in Assembly moves a block from &H9000-&HCFFF to RAM page 0. This code is compatible with any MSX with RAM on page 0 and RAM in any primary slot. Add Machine code Line Mnemonics Comments ------------------------------------------------------------------------------------- D100 10 ORG &HD100 ; Program initial address D100 F3 20 DI ; Disable interruptions D101 DB A8 30 IN A,(&HA8) ; Read slots configuration D103 5F 40 LD E,A ; Save in E D104 06 04 50 LD B,4 ; D106 CB 3F 60 ROT1: SRL A ; Do A >> 4 D108 10 FC 70 DJNZ ROT1 ; D10A 83 80 ADD A,E ; Join A and E D10B D3 A8 90 OUT (&HA8),A ; Configure RAM in all slots D10D 21 00 90 100 LD HL,&H9000 ; Source D110 11 00 00 110 LD DE,&H0000 ; Destiny D113 01 00 40 120 LD BC,&H4000 ; Length D116 ED B0 130 LDIR ; Move a block D118 DB A8 140 IN A,(&HA8) ; Read slots configuration D11A E6 F0 150 AND &HF0 ; Filter to enable ROM D11C D3 A8 160 OUT (&HA8),A ; Change to RAM RAM ROM ROM D11E FB 170 EI ; Enable interruptions D11F C9 180 RET ; Return to Basic If you want to move data to page 1, change address &HD112 value to &H40. The next program in Basic shows how to move a block to pages 0 and 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) 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│ │ └─────┴─────┴─────┴─────┴───────────────────────┘As the MSX Red Book [1] indicates, the key click output is attenuated and mixed with the audio output from the Programmable Sound Generator. To actually generate a sound this bit should be flipped on and off. In fact, a click sound is only generated when the register bit 7 state is changed. If we change this bit from 0 to 1, a strong click is produced and its value is attenuated until silence, except if the bit state is changed. When the state is changed from 1 to 0, a weak click is produced and attenuated until silence, also except for state changing. For each event, the frequency is about 100 Hz. The next picture illustrates that. Take a look on bit 7 value trough time line. When a state changes (transition between 0-1), there is a pulse generation (one up, other down). Based on Video Hits and Digivoix players, we propose the player presented below. This player has some important improvements like slot changing on any MSX, as well as the correct PPI bit setting, preserving original data on it. Add Machine code Line Mnemonics Comments ------------------------------------------------------------------------------------- D000 10 ORG &HD000 ; Starting address D000 F3 20 DI ; Disable interruption D001 DB A8 30 IN A,(&HA8) ; Read slots configuration D003 5F 40 LD E,A ; Save on register E D004 06 04 50 LD B,4 ; D006 CB 3F 60 ROT: SRL A ; Shift left A 4 times D008 10 FC 70 DJNZ ROT ; D00A 83 80 ADD A,E ; Add A to E D00B D3 A8 90 OUT (&HA8),A ; Set all slots as RAM D00D 21 00 00 100 LD HL,0 ; PCM initial data D010 4E 110 LOOP: LD C,(HL) ; Read the next octet (8 samples) D011 06 08 120 LD B,8 ; Repeat 8x D013 CB 11 130 LPI: RL C ; Shift 1 bit to left D015 DB AA 140 IN A,(&HAA) ; Read PPI port C state D017 38 04 150 JR C,TONE ; Check if CY=1 D019 E6 7F 160 AND &H7F ; If not, click=0 D01B 18 02 170 JR CHTONE ; Jumps to CHtone D01D F6 80 180 TONE: OR &H80 ; If yes, click=1 D01F D3 AA 190 CHTONE: OUT (&HAA),A ; Sen result to PPI D021 1E 0E 200 LD E,14 ; Create a delay of 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 ; Next octet (data) D029 7C 250 LD A,H ; D02A FE 40 260 CP &H40 ; Check if HL=&H4000 D02C 20 E2 270 JR NZ,LOOP ; If not, go to LOOP D02E DB A8 280 IN A,(&HA8) ; Read slots configuration D030 E6 F0 290 AND &HF0 ; Filter to set ROM on pgs 0 and 1 D032 D3 A8 300 OUT (&HA8),A ; Change D034 FB 310 EI ; Enable interruptions D035 C9 320 RET ; Return to BasicThe first step is to set all pages to RAM (lines 30-90) in order to use page 0 or 1. The sound files are quite large and we recommend to make use of this RAM place not used by Basic. Then, we point to initial data address and read the first byte. Once this format is 1 bit, we must read all the 8 bits from this byte. The shift instruction RL shifts left one bit and move the bit 7 to the carry flag. So, the carry flag value indicates the click state. Digivoix has an option to make fun on sound (change voice), by replacing this left shift to a corresponding right shift. For each bit read and executed, we make a pause. The delay is used to synchronize the execution frequency with PCM sound frequency. For example, Video Hits delay of 14 corresponds to a frequency of 11,131 Hz. After reading the byte, we check if the end of data was reached. If not, repeat sound reading and execution operation. When the reading ends, we return slots to the original state with ROM on pages 0 and 1. Program in Basic to load a sound file, move data and play. 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) Each PSG sound channel is able to discriminate 16 volume levels, which allow us to represent a wave sound using 4 bits. Now, the original wave can be modeled more precisely than the 1-bit format. Nevertheless, this format has a high cost: the file size is 4 times greater than the 1-bit format. For generating a sound, we will set the highest possible frequency, once PSG do not generate clicks like PPI. In this case, we will create an envelope over the tone signal. We will use the PSG channel A and set its frequency to 0. The program will then read data and change channel A volume, according to the values read. An Assembly program to play 4-bit sounds is presented below. Add Machine code Line Mnemonics Comments ------------------------------------------------------------------------------------- D000 10 ORG &HD000 ; Initial address D000 F3 20 DI ; Disable interruptions D001 3E 07 30 LD A,7 ; Set register 7 (mixer) D003 D3 A0 40 OUT (&HA0),A ; D005 3E BE 50 LD A,190 ; Mixer value - enable channel A D007 D3 A1 60 OUT (&HA1),A ; D009 AF 70 XOR A ; Register 0 D00A D3 A0 80 OUT (&HA0),A ; D00C 3E 00 90 LD A,0 ; LO period in A = 0 D00E D3 A1 100 OUT (&HA1),A ; D010 3E 01 110 LD A,1 ; Register 1 D012 D3 A0 120 OUT (&HA0),A ; D014 AF 130 XOR A ; HI period in A = 0 D015 D3 A1 140 OUT (&HA1),A ; D017 DB A8 150 IN A,(&HA8) ; Read slots configuration D019 5F 160 LD E,A ; Save in E D01A 06 04 170 LD B,4 ; D01C CB 3F 180 ROT: SRL A ; Do A >> 4 D01E 10 FC 190 DJNZ ROT ; D020 83 200 ADD A,E ; Join values D021 D3 A8 210 OUT (&HA8),A ; Set all slots as RAM D023 21 00 00 220 LD HL,0 ; Data initial address D026 06 02 230 LOOP: LD B,2 ; Read 2 nibbles D028 1E 00 240 LD E,0 ; E stores A D02A 3E 08 250 LPI: LD A,8 ; Selects register 8 D02C D3 A0 260 OUT (&HA0),A ; D02E 7B 270 LD A,E ; Recover saved value D02F ED 6F 280 RLD ; Rotates A with (HL) D031 D3 A1 290 OUT (&HA1),A ; Change volume D033 5F 300 LD E,A ; Save A in E D034 16 0E 310 LD D,14 ; D036 15 320 DELAY: DEC D ; Delay of 14 D037 20 FD 330 JR NZ,DELAY ; D039 10 F4 340 DJNZ LPI ; Next B D03B ED 6F 350 RLD ; Additional to recover (HL) D03D 23 360 INC HL ; Next sound data D03E 7C 370 LD A,H ; D03F FE 40 380 CP &H40 ; Check if HL=end D041 20 E3 390 JR NZ,LOOP ; If not, LOOP D043 3E 08 400 LD A,8 ; Register 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) ; Read slots D04C E6 F0 450 AND &HF0 ; Do RAM RAM ROM ROM D04E D3 A8 460 OUT (&HA8),A ; D050 FB 470 EI ; Enable interruptions D051 C9 480 RET ; Return to BasicImportant note: according to the MSX Red Book [1], PSG register 7 must always contain 10xxxxxx or possible damage could result to the PSG. In this case, bit 6 is always 0 and bit 7 is always 1. Program in Basic to load a sound file, move data and play. 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) The program in Assembly to play 4-bit sounds with three channels is presented below. Add Machine code Line Mnemonics Comments ------------------------------------------------------------------------------------- D000 10 ORG &HD000 ; Initial address D000 F3 20 DI ; Disable interruptions D001 3E 07 30 LD A,7 ; Set register 7 (mixer) D003 D3 A0 40 OUT (&HA0),A ; D005 3E B8 50 LD A,&B10111000 ; Mix value D007 D3 A1 60 OUT (&HA1),A ; set channels A,B,C D009 06 07 70 LD B,7 ; D00B 78 80 LPSG: LD A,B ; D00C 3D 90 DEC A ; Set all periods D00D D3 A0 100 OUT (&HA0),A ; D00F AF 110 XOR A ; to value zero D010 D3 A1 120 OUT (&HA1),A ; D012 10 F7 130 DJNZ LPSG ; D014 DB A8 140 IN A,(&HA8) ; Read slot conf. D016 5F 150 LD E,A ; Save in E D017 06 04 160 LD B,4 ; D019 CB 3F 170 ROT: SRL A ; Do A >> 4 D01B 10 FC 180 DJNZ ROT ; D01D 83 190 ADD A,E ; Join values D01E D3 A8 200 OUT (&HA8),A ; Set all slots as RAM D020 21 00 00 210 LD HL,0 ; Data initial address D023 06 02 220 LOOP: LD B,2 ; Read 2 nibbles D025 1E 00 230 LD E,0 ; E stores A D027 7B 240 LPI: LD A,E ; Recover saved value D028 ED 6F 250 RLD ; Rotates A with (HL) D02A 4F 260 LD C,A ; Save in C D02B 3E 08 270 LD A,8 ; Select register 8 (ch. A) D02D D3 A0 280 OUT (&HA0),A ; D02F 79 290 LD A,C ; Recover A D030 D3 A1 300 OUT (&HA1),A ; Change volume D032 3E 09 310 LD A,9 ; Select register 9 (ch. B) D034 D3 A0 320 OUT (&HA0),A ; D036 79 330 LD A,C ; Recover A D037 D3 A1 340 OUT (&HA1),A ; Change volume D039 3E 0A 350 LD A,10 ; Select register 10 (ch. C) D03B D3 A0 360 OUT (&HA0),A ; D03D 79 370 LD A,C ; Recover A D03E D3 A1 380 OUT (&HA1),A ; Change volume D040 5F 390 LD E,A ; Save A in E D041 16 0E 400 LD D,14 ; D043 15 410 DELAY: DEC D ; Delay of 14 D044 20 FD 420 JR NZ,DELAY ; D046 10 DF 430 DJNZ LPI ; Next B D048 ED 6F 440 RLD ; Rotate to recover (HL) D04A 23 450 INC HL ; Next sound data D04B 7C 460 LD A,H ; D04C FE 40 470 CP &H40 ; Check if HL=end D04E 20 D3 480 JR NZ,LOOP ; If not, LOOP D050 DB A8 490 IN A,(&HA8) ; Read slots D052 E6 F0 500 AND &HF0 ; Do RAM RAM ROM ROM D054 D3 A8 510 OUT (&HA8),A ; D056 FB 520 EI ; Enable interruptions D057 CD 90 00 530 CALL &H90 ; Reset PSG (clear volumes) D05A C9 540 RET ; Return to BasicBoth loading procedure and file format are the same of S4b normal version. Nevertheless, the delay and frequency relationship is different. Check out the conv_table.txt file which follows the program. The players MarMSX SND, MarMSX S4b and MarMSX S4b Plus and the Move Data program were created by Marcelo Silveira and they are under GNU-GPL v. 3.x license - http://www.gnu.org/licenses/gpl-3.0.txt. References: 1. The MSX Red Book, Avalon Software. McGraw Hill. 2. Video Hits, produced by Grupo CPM, Brazil. 3. Digivoix, produced by Hartard Frederic and publish on frech magazine Hebdogiciel, numbers 164 to 168, 1986. |
||