The ZX Spectrum Beepquencer
Those of you who own a Spectrum will no doubt be quite familiar with the BEEP command by now. The BEEP being a square wave tone of specified pitch and duration produced from the Spectrum's internal speaker.
The duration is set in seconds, and the pitch in positive whole numbers for each semitone above middle C or negative numbers below e.g. BEEP 1, 0 produces a one second tone at middle C whereas BEEP 1,12 produces a one second tone at C one octave above.
The Spectrum can therefore be used to create simple tunes by stringing together BEEPS of appropriate frequency and length. However, this is a tedious way to enter in a melody.
To store values for note and duration, and be able to recall these to be 'played' with the BEEP we need a more complex programme, see Figure 1.
This is a sequencer programme which allows you to compose up to 16 repeating melodies, 32 notes in length over a span of 4 octaves. Each note can have a length of 1 to 8 intervals. A length of 1 being the smallest interval. Consider this to be a demi-semi quaver, 2 would represent a semi-quaver, 4 would represent a quaver and therefore 8 a crotchet.
The programme allows each sequence to be written, played or listed and allows complete sets of 16 sequences to be loaded from or dumped to cassette.
The easiest way to understand how the programme works is to split it into separate sections or routines.
To allow the sequences to be stored and loaded on cassette at any time the note values and lengths are placed in memory above the User Defined Graphics. To do this the CLEAR command is used to provide 1040 bytes after 'Ramtop'. Each sequence requires 1 byte for the number of notes in the sequence, 32 bytes for the note values and 32 bytes for the lengths i.e. (1+32+32)*16 =1040.
The tempo variable 't' is set to 5 at the beginning of the programme but can be varied during the Play Mode.
The title and options are printed on the screen after which input variable Y is checked to make sure that it is within the set range. If Save or Load has been selected a jump is made to the relevant line number. However, if Write, Play or List has been selected, the sequence number, variable 'y', is input. This number is used to provide the base address, variable 's', of the appropriate sequence. The variable 'length' is then set to 4 (quaver) and the appropriate jump made.
The titles are printed and the number of notes required, variable 'b', input and checked. If 'b' is 0 then the programme returns to the menu, if not, the loop counter variable 'step', is set to zero and the value of 'b' is stored at the base address, 's', of the sequence. A For-Next loop is then used to store the notes and lengths. Firstly, the two flags 'sharp' and 'rest' are set to 0 then the sub-routine for Note Entry is called (Line 1550).
This reads in a character string, n$, used to represent the Octave, Note and Length required. The characters are stripped, checked for errors and the appropriate values for 'rest', 'sharp', c2 (ASCII for note), c1 (offset for octave) and 'length' returned.
If a rest is entered (R), the value of 'note' is set to 100 and the following conversion omitted. Lines 1120-1180 are used to convert the ASCII to a 'note' value. The offsets for 'sharp' and octave (c1) are then added with an extra 24 (since the minimum value for note is -24, 24 has to be added to allow it to be stored in memory). The values for note and length are then stored.
Another subroutine is called (line 3170) which converts the stored values back into a form which can be displayed. The programme then returns for the next note, continuing in this fashion until the required number of notes have been stored. Afterthis the option to Play or return to the Menu is offered.
The titles are displayed and the options listed. The base address, variable 's', is calculated using the sequence number 'y'. The number of notes in this sequence, 'b', is read from the base address, and the 'tempo', initially set to 5, is displayed. The Play For-Next loop is entered and the appropriate note and length read from memory. If the note read is a rest, i.e. has the value 100, the programme waits for (length*t/2 - 0.037) seconds (line 2100). If not a rest, the BEEP (at long last!) is set up for the equivalent time. The -0.037 seconds is to allow for a 37mS delay produced while the Spectrum Basic is read and disassembled before the next note is played. This value was chosen to give the most accurate results on our machine but you may have to make slight adjustments to obtain correct timing on your own. The keyboard is then scanned for interrupt options before returning for the next run through the loop. When the required number of steps has been made the For-Next loop is initialised again. (Which will repeat until the ram's come home!)
The titles are printed on the screen, the base address calculated from the sequence number, and the required number of steps read from this address. The List For-Next loop is set up with this limit, the note and length values read and the List routine used earlier is called (Line 3170).
The first stage in this routine is to increment the loop counter'step'. If the note read is a rest, i.e. value 100, the note character string, r$, is 'Rest' and the octave, 'o' set to 0. Otherwise, the octave is calculated from the offset and the note converted to a character string. Once the step, octave, note value and length have been printed the values for the next note and length are read and processed. When the whole sequence has been listed it can be played, a new sequence entered or the menu displayed.
Line 4010 allows 1040 bytes from address 31559 to be stored on tape. When this is complete the menu is displayed. Line 5010 allows the 16 sequences to be loaded before returning to the menu.
To write a sequence, enter option 1 on the menu and specify the sequence number. The Write Mode will now request the number of notes required. If you no longer wish to continue enter 0, which returns you to the menu, otherwise enter the required number from 1 to 32.
The notes are entered in the form Octave (1-4), Note (C-B) and Length (1-8) i.e. for middle C, a quaver in length enter 3C, for C# two octaves below, a crotchet in length enter 1C#8. When a new length has been entered this is held and used until respecified. To enter a rest, input'R' with the length required i.e. R4. If at any time you wish to start again enter 'X'. When all the notes have been entered you have the option to Play or return to Menu.
To play a sequence enteroption 2 on the menu and sequence number. The sequence can be stopped at any time, a new Tempo entered (1 to 10), a new sequence selected or return to the menu.
To list a sequence enter option 3 on the menu and sequence number. After listing you have the option of playing this sequence, listing another or back to the old menu (board of chips please!)