|
|
|
©1985 / Charles A. Measday
If you're looking for information about the Commodore VIC-20 and C64, visit the famed Toronto PET Users Group; its links page will lead you to more resources on these classic computers.
It was an exciting moment when I first ran Donald J. Eddington's MozartMachine (COMPUTE!, January 1984) and heard my VIC-20 playing real music!
Eddington published a number of articles in various Commodore magazines. See this YouTube video of Eddington's The Grand Improvisor on a Commodore 64.
Reading the article inspired me to write a BluesBand program and examining the Mozart program in more detail suggested some techniques of implementation. After a little work, I had my VIC-20 playing a somewhat random bass pattern, following a standard blues chord progression, and I was the featured soloist "tickling the ivories" on the top row of the keyboard. Wow! Too bad it sounded awful!
My initial endeavor at computer music was disappointing and discouraging.
Taking a last, "I-give-up" look at the VIC-20 Programmer's Reference
Manual, I suddenly noticed that the sound register POKE
values given for different notes were not in an orderly sequence.
Discussion of the problem with a classical guitarist of local fame, Don Sauter, yielded the following facts. First, to go up an octave, you must double the frequency; i.e., the next octave above a 440-Hz A is an 880-Hz A. Second, the twelve half-steps in an octave are equally-spaced with regard to their tone. Mathematically, this means that you must multiply the frequency of a note by the 12-th root of 2 in order to move up one half-step. Because of these facts, the linear sequence of tones you perceive as you plunk your way up the piano keyboard is actually caused by increasing frequency differences between successive half-steps and octaves.
The table of musical notes found on
page
97 of the
VIC-20
Programmer's Reference Manual shows a similar, but inverse,
relationship: the differences in POKE
values between
successive octaves are halved. For example, the note C has
POKE
values of 135, 195, 225, and 250; the differences between
octaves, 60, 30, and 15, are progressively halved. Therefore, you might
expect the POKE
values for successive half-steps to be
characterized by decreasing increments. Good guess, but you're wrong! The
first octave (C, C#, D, D#, E, etc., with POKE
values 135,
143, 147, 151, 159, etc.) has the sequence of differences 8, 4, 4, 8, 4, 4,
8, 4, 4, 4, 4, and 4 - clearly not the continually decreasing increments we
expected.
How did Commodore get the POKE
values they got and what are
the correct values? The answer to the first question is "I have no idea!".
The answer to the second question can be found buried in the information
about the VIC-20's video interface chip
(pp.
216-217 of the VIC-20 Programmer's Reference Manual).
The video interface chip uses four registers to turn on or off and set the
frequency of the VIC's bass, alto, soprano, and noise voices. Setting the
most significant, eighth bit (OR
'ing the POKE
value with 128) of a register turns that voice on; clearing the most
significant bit (AND'ing the POKE
value with 127) turns
the voice off. The count, X
, in the least significant
seven bits generates a particular frequency and is calculated as follows:
frequency = clock / (127 - X)
And then solving for the count, X
:
X = 127 - (clock / frequency)
(Again, once calculated, X
has to be OR'ed with 128
or AND'ed with 127 to turn the voice on or off, respectively,
when POKE
d into the voice's register.)
Knowing this formula and our little bit of music theory, we can construct
a new musical note/POKE
value table for the VIC-20. To begin,
we choose a clock value of 3995 for the bass voice (see the NTSC table on
page
217 in the VIC-20 Programmer's Reference Manual). The
POKE
values we will compute, when POKE
'd into the
other voices' registers, give notes shifted up one octave for each voice. A
standard frequency is the 440-hz A; dropping it down four octaves (440
-> 220 -> 110 -> 55 -> 27.5
) and multiplying it three times
by the 12-th root of 2 (A -> A# -> B -> C
) brings us to
the same C note that the VIC-20 Programmer's Reference Manual
starts its table with. The following BASIC
subroutine, used in
the BluesBand program, sets up the voice parameters and builds
the new table in array N
:
9500 REM MUSIC SETUP 9502 V = 36878 : S1 = 36874 : S2 = 36875 : S3 = 36876 : S4 = 36877 9504 NN = 66 : DIM N(NN) : S = 2^(1/12) : C = 3995 : F = (440/16)*S*S*S 9506 FOR I=1 TO NN : N(I) = 128 OR INT(127-(C/F)+.5) : F = F*S : NEXT I 9508 RETURN