home *** CD-ROM | disk | FTP | other *** search
- MUSIC IN THE KEY OF C
-
- By Mark Lewis Baldwin
-
- *****************************************************************************
- NOTICE
-
- This article and the attached program and code are Copyright (c) 1986 by
- Mark Lewis Baldwin. It is realeased as shareware. It may be copied and
- distributed freely so long as this notice and the copyright remain
- intact.
-
- If you feel that the article/program is of value, please send me a
- pricely sum of $1 for its use. If the code (or a substatial part
- thereof) is used in a commercial product, I ask that a sum of $100 be
- sent to me for licensed use of the code. My mailing address is:
-
- Mark Baldwin
- Beacon Technical Services
- 7711 S Curtice Way, #E
- Littleton, CO 80120
-
- I can also be reached through GEnie at M.L.BALDWIN and through
- Compuserve at 73637,3032.
-
- I hope that you find the article of value. Enjoy.
-
- Mark Baldwin
-
- *****************************************************************************
-
- Over the past months, there have been many articles about using the
- MIDI for music on the Atari ST. But the ST has an internal sound chip
- as well capable of a wide range of sound and music. Lets have a look at
- this sound chip and figure out how to make beautiful music with it.
- What I'm going to do is describe the sound chip and how to talk to it.
- Then we'll look at a program I wrote for the chip which allows us to use
- three independent voices and even describe instrument ADSR envelopes.
- Before I talk about the program, let us look at the sound chip itself.
-
- The Chip and Its Registers
-
- The ST sound chip is a General Instruments AY-3-8910 programmable
- sound generator. It has three tone generators and a noise generator
- which can be mixed and matched on three output channels (or voices). It
- communicates with 16 registers, each an 8 bit word in length, from which
- the user can communicate with the chip. These registers are numbered 0
- through 15. We are actually only interested in the first 14 registers
- (0-13) since the last two are used to communicate with the I/O port.
- Each of the first 14 registers has a specific purpose which are
- described below:
-
- Register 0 and 1 - These registers control the frequency (or tone) of
- the first voice (Channel A) of the sound chip. A 12 bit word is
- necessary to define the frequency, therefore the lower 8 bits of the
- word are stored in register 0 and the upper 4 bits of the word are
- stored in the lower half of register 1. See the next section to find
- out how to convert musical notes to the proper frequency.
-
- Register 2 and 3 - These registers control the frequency of the second
- voice (Channel B).
-
- Register 4 and 5 - These registers control the frequency of the third
- voice (Channel C).
-
- Register 6 - The frequency of the noise generator is controlled through
- this register. Only the first 5 bits are used so acceptable values are
- between 0 and 31.
-
- Register 7 - This register is actually 8 on/off flags used to control
- mixing of the tone and noise generator plus control of the I/O ports
- (registers 14 and 15). Bits 0 through 2 control mixing the tone signals
- for channels A, B and C respectively. A 1 in the bit position will turn
- the tone for that channel off while a 0 will turn it on. Bits 3 through
- 5 do the same thing for the noise generator. Note that by turning on
- both tone and noise, you can mix both signals together. This may be a
- little confusing, so let's try an example. Lets say we want to turn the
- tone on for Channel A and B plus merge the noise signal as well on
- Channel B and leave Channel C off. As a result, we need bits 0, 1, and
- 4 to be 0 while 2, 3 and 5 should be set to 1. Or in binary it looks
- like this 101100 (the right most bit is bit 0). 101100 in binary
- converts to 44 decimal which we would place in register 7.
-
- Register 8 through 10 - These registers control the volume for channels
- A, B and C after mixing. Values of 0 through 15 are acceptable with 0
- being no sound and 15 being the loudest. However, if bit 4 is set (i.e.
- a value of 16), the volume is calculated from the sound envelope data
- described in registers 11 through 13.
-
- Register 11 through 13 - These registers describe a wave form that can
- be used to control the volume of a voice should the voices respective
- volume register be set to 16. Registers 11 and 12 contain a two byte
- word (lower byte in register 11) describing the length of the wave form.
- This is calculated by taking the incoming clock frequency (2 Megahertz),
- dividing by 256, and then dividing that result by the contents in
- registers 11 and 12. Register 13 describes the shape of the wave form
- as shown in Figure 1.
-
- Register 14 and 15 - As mention before, these registers have nothing to
- do with producing sound but are used for the I/O ports of the ST so let
- us leave them alone.
-
- Converting Musical Notes For The Registers
-
- Any musical note can be calculated as follows:
-
- period = 284.0909091 * ( 1.059462 ** index )
-
- After rounding 'period' to an integer, the lower byte would be
- stored in the first register (i.e. registers 0, 2, or 4) while the
- upper byte would be stored in the second register (i.e. 1, 3, or 5).
- The value of index is determined by counting the number of notes there
- are between the desired note and a 440hz "A". When counting, higher
- notes are negative. Remember that there are 12 notes to an octave, not
- 7 because of the sharps. Therefore a "C" in the same octave as "A"
- would have an index of 9 (with register values of 222 and 1) while a "B"
- would be -2 (with register values of 253 and 1). If you look in the
- attached program listing, the note_f and note_c arrays contain register
- data for 5 octaves around middle "A".
-
- Talking to the Sound Chip
-
- Now that we know what makes our chip sing (or at least croak), how
- do we get the data into the chip registers. Atari has solve that for us
- by giving us two routines to communicate with the sound chip.
- The simpler of the two routines is 'Giaccess'. The C form is
-
- char Giaccess( data, register )
- char data
- int register
-
- This routine allows us to read or write to any single register in the
- sound chip. If you wish to write to a register (like putting in the
- volume for a channel), 'data' would contain the value you wish to write
- and 'register' would contain the register number plus 128. The added
- 128 (which turns on bit 7) tells the routine that this is a write and
- not a read action. If you wish to read a register, just use the
- register number itself, and the value will be returned.
- The second routine for accessing the sound chip is 'Dosound'. This
- routine actually allows you to send an array of byte commands to the
- chip and then forget about it. Therefore, it is a little more complex.
- The C call is of the form:
-
- Dosound( ptr )
- char *ptr
-
- where *ptr points to a byte array containing the sound commands. The
- following commands are allowed for the byte array:
-
- Commands 0 - 15 ($00-$0F): These commands are perceived as register
- numbers in which the next byte will be inserted as data. Therefore the
- sequence 8 10 would put the value 10 in register 8.
-
- Command 128 ($80): This command loads the next byte into a temporary
- register.
-
- Command 129 ($81): This command uses the next three bytes as data. The
- first byte is the number of the register in which the contents of the
- temporary register will be loaded. The second byte is a 2's compliment
- value to be added to the temporary register. The third byte is the
- termination value. The sound register will be loaded once each cycle
- until the temporary register equals the termination value.
-
- Command 130-255 ($82-$FF): The byte following this command either
- terminates the byte array (with a 0) or defines the number of 50HZ
- cycles before the next update.
-
- The example program includes an example of using 'Dosound'.
-
- Entering the Score
-
- Now that we know how to produce sound out of the sound chip, how can
- we turn that into music. That's what the attached example program is
- for. I designed this program to play a three voice score using multiply
- designed instruments. You can use the program just as it is or include
- it in you own programming projects. Let's go through it step by step
- and see how we use it to make the sound chip sing.
- Since we want to be able to include music easily, I had to invent a
- simple language to describe the musical score. Two scores are included
- named 'interstel' and 'spake'. 'interstel' is the theme for software
- produced by The Interstel Company while 'spake' is "Thus Spake
- Zarathustra" by Richard Strauss. I used these two songs because I
- previously used them in Star Fleet I for the ST and had the scores lying
- around. Note that although the Interstel Theme is copyright, you are
- welcome to use it for your personal use with this program. Each song is
- an integer array where each value has a meaning to the score processor.
- To make things simple, I've defined all of the parameters we need to
- construct the score at the start of the program. The following score
- instructions are available:
-
- SPEED n, - Change the song speed to n. The larger the number, the
- slower the song. Start the score with a SPEED value, and insert it
- again if you need to change speed part way through the song. Remember
- to put a comma after the number n.
-
- <instrument> - There are three instruments defined in the program being
- ORGAN, HORN and SNARE. They indicate that all note entries following
- will be played with that instrument until a new instrument is used. A
- little later I'll show you how to define your own instrument.
-
- <note duration> - The following durations are available, WH, HF, QU, EI,
- SX and TH representing WHole, HalF, QUarter, EIghth, SiXteenth and
- THirty second. They indicate that all note entries following will be of
- the designated length until a new length is defined. The length values
- can be modified for dotted and tripleted notes by adding a D or T to the
- end of the duration (i.e. EID means eighth note dotted).
-
- <note> - Five octaves have been defined. Two above and two below the
- middle octave. A note is designated by the note (C,D,E,F,G,A or B), a
- optional S for sharp, and the octave (2-6) where 4 is the middle octave.
- Therefore FS3 would be F sharp below middle C. The note will use the
- currently active instrument for the currently active note duration.
-
- REST - Rest (no sound) for the current note duration.
-
- P - Play the current notes you've defined since the last P.
-
- VU - Increase the volume of all following notes by one.
-
- VD - Decrease the volume of all following notes by one.
-
- VN - Return the notes to normal volume.
-
- DO n, - Repeat the following music until the ENDDO n times.
- Remember to put a comma after the n.
-
- END - Terminate the music.
-
- All you have to do to create a score is to build a data array using the
- above defined parameters.
-
- The Instruments
-
- We also have a capability of defining instruments to a limited
- extent in the program. We can define the ADSR envelope for each
- instrument. ADSR stand for Attack, Decay, Sustain and Release and are a
- means of defining a sound envelope for the instrument. See figure 2.
- The magnitude of each phase of the envelope is contained in the array
- 'inst_mag'. Values of 0 to 15 are allowable. These correspond to the
- volume levels allowed on the sound chip. The array 'inst_tim' describes
- the time allowed for each phase. Values of 1 to 15 are allowed here
- with one exception. If a value of 16 is used for the sustain phase (3rd
- value), the program will calculate the length of the sustain based on
- the length of the note being played. Therefore, long notes will be
- drawn out while short notes will be cut short. Go ahead and play with
- the values or add as many more instruments as you wish.
- Since we can also mix the noise generator with the tone generator,
- two more arrays have been defined. The first is 'inst_tone'. A value
- of TRUE mixes in the tone generator. Secondly, we have 'inst_noise'
- which will mix in the noise generator if TRUE. Note that either one can
- be turned on or even both of them at once as I did for the SNARE
- instrument.
-
- The Code
-
- The program first calls 'init_music' to initialize some
- precalculations and clear the sound chip. It then starts a song by
- entering 'play_music' passing a pointer to the song array. 'play_music'
- actually processes the song array separating out the notes, durations,
- instruments, etc. When it's ready to play some notes, it calls
- 'inst_sound' with arrays containing the note(s) it wishes to play, the
- instrument assigned to each note, the duration of each note, and the
- time 'inst_sound' should play until returning to 'play_music'. Note
- that if less than three notes are passed and 'inst_sound' still has some
- of a note left over from a previous call, it will continue to play the
- old note as well as the new ones.
- 'inst_sound' actually builds the data array that we are going to
- pass to the sound chip through 'Dosound'. The function 'sound_build'
- takes the register and value data and places them in 's_array' which is
- our data array. The function 'calc_s_vol' used toward the bottom of
- 'inst_sound' is the routine which actually calculates where we are in
- the ADSR envelope for each of our voices, and returns a volume level.
- Finally, 'sound_go' takes the sound array and passes it to 'Dosound'.
-
- Play It Again, Sam
-
- I hope that now that you've been exposed to the Atari sound chip,
- you'll see that there are a great deal of possibilities for it. The
- program will play it's two songs as much as you wish, but I hope you dig
- into the program yourself and add more songs or instruments. Or even
- improved on the processing code itself. I can already think of half a
- dozen ways to improve upon the program. If you come up with any
- improvements, I'd love to see them, so drop me a line. Until then,
- happy sounds to you.
-
-