VIC MUSICIAN
Blake Wilson
You can have your VIC playing a song in the background while some other BASIC program is RUNning. It will even play while you're programming. This article will also show you how to take music from a printed score and enter it into your VIC.
I have always believed that music in any form was above my head. I own a computer retail store, and several customers have asked how they could produce music that would run continuously, without delays, during a program. My wife helped me to understand just what all those incomprehensible symbols on a piece of sheet music actually mean. I wanted the explanation in terms that I (and VIC) could understand. The only musical instrument that I can play is the VIC. Here's her response:
Don't be concerned that some shafts go up and some down, or that notes may be joined with arcs or bar-like flags. These exist only to confuse computer people. You need be concerned only with the duration of a note (filled in or open, whether it has a shaft or not, and the number of bars or flags. By the way, a dot after a note increases its duration by 50 percent) and its pitch (as determined by its altitude on the staff). Any pitch of less than 128 is a rest or silence.
If notes are stacked, just take the highest one. There are generally two staffs (groups of lines). The lower set is often for harmony; usually we can ignore them.
Compare the data at line 190 with the musical score above. Notice that the first item is duration. The first note is filled in and has a shaft and one flag. That means that it is an eighth note and will be played for 15 jiffies. The next data item represents the pitch — it is 201 because the note is tangent to the lowest line. The next two notes are the same. The fourth note is open and has a shaft. So it is a half note and gets 60 jiffies. Since that note is on the third line, its pitch is 'G' = 215. See how it works?
Inspect a musical score and write data for each note, first duration and then pitch. Place the data in the program to replace lines 190 through 260. The actual line numbers mean nothing, but the first 71 data items representing the program must come first.
The program is limited to 61 notes due to the size of the cassette buffer. In practice, the 61 notes should be enough for most programs. I use only 37 notes in the sample program. If your creation uses fewer than 61 notes, end your data with 1, 1. This instructs the computer to replay from the first.
Once the data has been POKEd into the buffer and you've done a SYS to 830, the music plays continuously even if you execute NEW or write another program. The music will continue until:
- You type a RUN/STOP RESTORE
- Attempt to use the cassette
- Or get so tired of it that you shut off the VIC.
The program is driven by the hardware interrupt. Each jiffy (1/60 of a second), a counter ($033D = 829) is reduced by one. If this decrement results in a value of zero, the next duration is placed in the counter, the next note is placed in the sound generator ($900C = 36876), and the note count is increased by two and stored at ($033C = 828). The computer then goes on its way, updating the realtime clock and scanning its keyboard.
The computer is not slowed appreciably. Most of the time, unless the note is to be changed, the time wasted is 120 microseconds per second or 120 parts per million. If the note must be changed, then the time lost is a few thousandths of a second.
Note: A complete listing of musical pitch values, including sharps and flats, is in the VIC-20 Programmer's Reference Guide.
Program 1 : VIC Musician
10 REM ******* VIC MUSICIAN ********** 30 REM *** CONTINUOUSLY PLAYS ******* 40 REM ** TUNE FROM STAR WARS ****** 60 POKE 36878,15 : REM SET VOLUME TO MAX 70 FOR I = 830 TO 976 : READC : POKEI, C : NEXT 80 SYS 830 : REM STARTS MUSIC 90 REM ******* SET-UP FOLLOWS ******* 100 DATA 120, 169, 5, 141, 60, 3, 169, 6, 141, 61, 3, 169 110 DATA 133, 133, 0, 169, 3, 133, 1, 169, 93, 141 120 DATA 20, 3, 169, 3, 141, 21, 3, 88, 96 130 REM **** MUSIC PGM FOLLOWS ****** 140 DATA 206, 61, 3, 208, 28, 72, 152, 72, 172, 60 150 DATA 3, 200, 177, 0, 141, 61, 3, 200, 177, 0, 201 160 DATA 1, 240, 12, 141, 12, 144, 140, 60, 3, 104 170 DATA 168, 104, 76, 191, 234, 160, 255, 208, 243 180 REM *** MUSIC DATA FOLLOWS ****** 190 DATA 15, 201, 15, 201, 15, 201, 60, 215, 60, 228, 15 200 DATA 225, 15, 223, 15, 219, 60, 235, 35, 228, 15 210 DATA 225, 15, 223, 15, 219, 60, 235, 35, 228, 15 220 DATA 225, 15, 223, 15, 225, 60, 219, 35, 201, 15 230 DATA 201, 60, 215, 60, 228, 15, 225, 15, 223, 15 240 DATA 219, 60, 235, 35, 228, 15, 225, 15, 223, 15 250 DATA 219, 60, 235, 35, 228, 15, 225, 15, 223, 15 260 DATA 219, 60, 235, 1, 1
Program 2: Disassembled Machine Language For VIC Musician 033E 78 SEI ;PROHIBIT INTERRUPTS (DON'T BOTHER ME) 033F A9 05 LDA #$05 ;FIRST NOTE IS SILENCE 0341 8D 3C 03 STA $033C ;STORE NOTE 0344 A9 06 LDA #$06 ;WAIT 6 JIFFIES 0346 8D 3D 03 STA $033D ;STORE DELAY 0349 A9 85 LDA #$85 ;ADDRESS LOW OF START OF MUSIC DATA 034B 85 00 STA $00 ;ZERO PAGE POINTER 034D A9 03 LDA #$03 ;ADDRESS HI START OF MUSIC DATA 034F 85 01 STA $01 ;ZERO PAGE POINTER 0351 A9 5D LDA #$5D ;ADDRESS LOW OF MUSIC PROGRAM 0353 8D 14 03 STA $0314 ;VECTOR INTERRUPT TO MUSIC PGM 0356 A9 03 LDA #$03 ;ADDRESS HI OF MUSIC PROGRAM 0358 8D 15 03 STA $0315 ;VECTOR INTERRUPT TO MUSIC PGM 035B 58 CLI ;OK TO INTERRUPT AGAIN 035C 60 RTS ;BACK TO BASICS 035D CE 3D 03 DEC $033D ;REDUCE DELAY COUNTER 0360 D0 1C BNE $037E ;UMLESS DELAY IS FINISHED, EXIT 0362 48 PHA ;SAVE ACCUMULATOR ON STACK 0363 98 TYA ;TRANSFER Y TO ACCUMULATOR 0364 48 PHA ;SAVE IT TOO 0365 AC 3C 03 LDY $033C ;GET POINTER TO LAST NOTE FREQUENCY 0368 C8 INY ;MOVE POINTER TO NEXT DELAY 0369 Bl 00 LDA ($00) ,Y ;GET NEXT DELAY 036B 8D 3D 03 STA $033D ;SET DELAY DURATION 036E C8 INY ;MOVE POINTER TO NOTE FREQUENCY 036F Bl 00 LDA ($00) ,Y ;GET NOTE FREQUENCY OR TONE 0371 C9 01 CMP #$01 ;IS FREQUENCY = 1 (START OVER FLAG) 0373 F0 0C BEQ $0381 ;IF SO, PLAY IT AGAIN SAM 0375 8D 0C 90 STA $900C ;START NOTE PLAYING 0378 8C 3C 03 STY $033C ;STORE NOTE FREQUENCY POINTER 037B 68 PLA ;RETRIEVE Y FROM STACK 037C A8 TAY ;PUT Y BACK IN Y 037D 68 PLA ;RETRIEVE ACCUMULATOR 037E 4C BF EA JMP $EABF ;GO ON ABOUT YOUR BUSINESS 0381 A0 FF LDY #$FF ;SET NOTE POINTER TO START -1 0383 D0 F3 BNE $0378 ;BRANCH ALWAYS TO STORE POINTER |