Programming 64 Sound
Part 2
John Michael Lane
Last month in Part 1, we discussed sound and music in general. This month we examine some techniques for programming more complicated music using the 64's SID chip.
The control register is the most complex register in the chip. Each of the eight bits in this register has a different function. Dealing with individual bits within a one-byte register is often a problem for BASIC programmers. One very easy way to approach the problem is to use the following:
170 B(0)=1 180 B(1)=0 190 B(2)=l 200 B(3)=0 210 B(4)=0 220 B(5)=0 230 B(6)=0 240 B(7)=l 250 FOR 1=0 TO 7 260 Q=Q+B(I)*2↑I 270 NEXT I:POKE S+4,Q
This is not efficient programming, but by defining the bits we want (that is, B(I) where 1= the bit number) in terms of a 1 and those we don't want in terms of a 0, this segment will work. It will be somewhat slow and cannot be used in a loop that must execute quickly, which is usually the case when doing musical programming.
A quicker method is to think of the bits in terms of their value in an eight-bit binary number. Bit 0 has a value of 1, bit 1 = 2, bit 2 = 4, bit 3 = 8, bit 4 = 16, bit 5 = 32, bit 6 = 64, and bit 7=128. In the case above, we want to set bits 0, 2, and 7 on, so we simply add their values: 1+4 + 128 = 133. Simply POKE 133 into the register to set those bits. It's much simpler, but requires you to add up the bit values before writing the program, so when you look back on the program one month later you may not have the slightest idea why you chose 133.
The first bit of the control register, bit 0, acts as the gate to turn the sound on and off. Remember that when the gate is opened (when bit 0 is set to 1), the attack phase of the volume envelope begins. When the gate is closed (bit 0 is set to 0), the release phase of the volume envelope is triggered. If the gate is closed prematurely, the sustain, decay, and even a portion of the attack phase may be omitted. Opening and closing the gate is actually very easy. Just remember that POKEing an odd value in register 4 turns the gate on and that POKEing an even value into the register turns the gate off.
Watch The Timing
Be careful of turning the gate off by POKEing zero into the register. That will also clear the waveform bits (which we'll discuss in a second) and will result in your volume envelope having no release phase.
The next bit, bit 1, is the sync bit. If this bit is on, the output from voice 1 will be synchronized with the output from voice 3. Sync in this case means that the output of voice 1 will be replaced with a logical AND of the output of voice 1 and voice 3. Another way to think of it is that voice 1 is turned on and off with the frequency of voice 3. In order for this bit to have any effect, oscillator three (voice 3) must be set to some frequency less than voice 1. The best way to understand this effect is to listen to it. "Laser" (Program 4) contains a demonstration using the sync bit. When using sync, the lower frequency will predominate. The effect works best when the lower frequency is 1/10 to 1/2 of the higher.
The sync bit has a slightly different effect in the other two voices. In voice 2 it produces a sync of voice 2 with voice 1, and in voice 3 it produces a sync of voice 3 with voice 2.
The next bit, bit 2, is the ring modulation bit. When this bit is set on, it produces nonharmonic overtones that sound like a bell. In order for this effect to take place, the triangular waveform must be selected for voice 1, and voice 3 must have a frequency other than zero.
Ring modulation in the other voices works like the sync bit; that is, for voice 2 to be ring modulated, voice 1 must have a nonzero frequency. For voice 3, voice 2 must be nonzero. In all cases the triangular waveform must be selected for the affected voice.
Bit 3 in the control register is the test bit. Setting the test bit to one will turn off the sound generator. This technique will generally be used only by machine language programmers.
Bits 4-7 are the waveform bits. Turning on bit 4 will select the triangular waveform; bit 5 will select the sawtooth; bit 6, the rectangular pulse; and bit 7, white noise (the hissing sound that you hear between stations on a radio).
At this point you must be asking yourself "What happens if more than one bit is selected?" The answer is that the two (or more) waveforms will be ANDed together (a logical AND will be done on the waveforms). Commodore cautions that selecting more than one waveform while using the white noise waveform could cause the oscillator to go silent, so don't combine waveforms using the white noise waveform. Even while avoiding the white noise waveform, it is still possible to generate four more waveform shapes using combinations of the sawtooth, triangular, and rectangular pulse waveforms. However, the volume declines significantly when combining waveforms.
Register 5 contains the attack and decay values for the sound envelope. The four-bit attack value is held in bits 7-4. The four-bit decay value is held in bits 3-0. The values can be loaded like this:
300 A=13sD=5: REM ATTACK=13, DECAY=5 310 POKE S+5, 16*A+D
Register 6 contains the sustain level and the release value. As above, the sustain level is held in bits 7-4, and the release value in bits 3-0. Program them in the following manner:
320 SU=13:R=4s REM SUSTAIN=13,RELEASE-4 330 POKE S+6, 16*SU+R
Now we've completely covered the seven register groups and shown how to load them. "Twiddle" (Program 1) allows you to explore all possible combinations using these seven registers. The program allows you to set and change any of the values and then listen to an eight-note scale governed by those values. If you can sit down and play with the program for a couple of hours, you'll gain a good understanding of how changing SID parameters affects a sound. The program is also useful for demonstrating how to play a tune within a basic program.
From Sound To Music
To play actual music, you generally write a program which will load all the parameters except the waveform and the frequency. At this point you select the note to be played and POKE the appropriate values into the frequency registers. Then you POKE the waveform value plus one (16 + 1 = 17 for triangular, 33 for sawtooth, 65 for the rectangular pulse, and 129 for white noise) into register 4 (the control register). Adding a 1 causes the gate bit (bit 0) to be turned on and the tone begins. The program waits a certain period of time and then POKEs the waveform value (16, 32, 64, or 128) into register 4. By POKEing an even number into the register we turn the gate off, and the note begins its release phase and gradually dies out (according to the release value that you've set).
A simple way to time the note is to use a delay loop. An empty loop (like the one below) will execute 1000 cycles in just about one second.
400 FOR 1=1 TO 1000:NEXT I
Therefore, each cycle is just about 1/1000 second (or a millisecond). To turn the note on and off, the program line will look like this:
400 POKE S+4,17:FOR 1=1 TO 250: NEXT.POKES+4,16
The above program line will play a note for about one quarter of a second.
This technique works well for a single voice, but it may not work at all for more than one voice. The problem is that while the computer is timing the duration of one note, it cannot be separately timing voices 2 and 3. We could fill the empty loop with timing routines for voices 2 and 3, but that would change the execution time for the loop and throw the timing off.
A second technique is to use the internal timer of the Commodore 64 through the use of the variable TI. The variable TI is updated automatically on the Commodore 64 and increases by a value of one every l/6o second. We can use this timer to time the duration of our notes:
500 T0=TI: REM INITIALIZE THE VARIABLE "T0" 510 T0=T0+D: REM INCREASE "T0" BY DURATION OF THE PIRST NOTE - D 520 IP T0<=TI THEN GOSUB 1100: REM CHECK{SPACE}IP THE TIME IS UP 525 REM IP SO SUBROUTINE 1100 WILL CHANGE NOTES 530 GOTO 520: REM IF NOT CHECK TIME AGAIN
The key to using this routine is to make sure that the subroutine executes quickly, at least while using multiple voices. "Tune" (Program 2) illustrates this technique using all three voices. But this method isn't problem-free either. We want to reproduce the rhythm of the original tune as accurately as possible. It's physically impossible to change the frequency of all three voices at once. Using BASIC, it's somewhat difficult to change all three voices in less than 1/6 second. For that reason, we split all the frequencies into the higher and lower order bytes before the tune begins. We can then change the frequency of all three voices in about 1/10 second. For most tunes that will be satisfactory. However, for a fast tempo, you might have to omit the second or third voice in order to maintain the rapid changes of the first voice.
Sound Effects
Now, let's briefly explore the sound of a laser firing, or an explosion, siren, or any other sound we need. How can we accomplish it?
There is no direct way. The best approach is trial and error. Listen to the sound carefully. Most sounds in nature cannot be duplicated simply by selecting the right waveform and envelope. Generally, the frequency is also actively changing during the sound's life. While you listen to (or think about) the sound you want, consider what is happening to the frequency. Is it rising or falling? How quickly?
Also consider the volume. Many volume envelopes cannot be duplicated using the attack/decay/sustain/release envelope on the Commodore SID. You will often have to change the volume level through program control, using the volume register (register 24) on the SID.
Programs 3 and 4, "Blast-off" and "Laser," illustrate one approach. In Blast-off, both the frequency and volume are modulated by the program. Laser demonstrates the sync feature and modulates the frequency to produce the laser sound. Both programs were written after much trial and error.
Many authors, when converting programs to the 64, simply drop the sound effects or stop at a sound which is only vaguely like the one they want. Be persistent; the 64 can accurately produce almost any sound. As you gain experience, you will find that the trial and error phase will decrease significantly.
Twiddle illustrates the basic methods of loading the SID registers and lets you experiment by changing the waveform and ADSR envelope while listening to the musical scale.
Tune uses the three voices to play an English folk tune. Don't be discouraged by the long list of DATA statements. Voice 1 repeats the same statements four times, and there is consid-erable repetition in voices 2 and 3. Once you've typed in the few basic lines, you can simply change the line numbers with the screen editor to produce the remainder of the data statements. Tune can be used to produce any melody by changing the values in the DATA statements. Each note is represented by a pair of values. The first represents the duration of the note (in sixtieths of a second). A value of 30-40 is appropriate for a quarter note. The second value is the frequency of the note. Appendix E in the Commodore 64 Programmer's Reference Guide offers a good, simple frequency table. Below are the values for the 12-semitone scale starting at middle C.
C - 4291 C# - 4547 D - 4817 D# - 5103 E - 5407 F - 5728 F# - 6069 G - 6430 G# - 6812 A - 7217 A# - 7647 B - 8101
Notes for other octaves can be calculated by doubling or halving these values, depending upon whether you're going one octave up (doubling) or one octave down (halving).
It is useful to convert one measure of music to one DATA statement if you can. This makes it easier to match the voices.
Voice 1 is the sound of a flute, voice 2 is a mandolin, and voice 3 is a guitar. Blast-off and Laser are supposed to produce the sound of their titles. They are pretty straightforward.