↑ Writing ↑


You've Got a Tin Ear!

Incomplete and Unpublished!

©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 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 POKE value, X, used to generate a particular frequency is calculated as follows:

frequency = clock / (127 - X)

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/4)*S*S*S
    9506  FOR I=1 TO NN : N(I) = 128+INT(127-(C/F)+.5) : F = F*S : NEXT I
    9508  RETURN

Alex Measday  /  E-mail