Beep Tracker by alone coder

Beep Tracker v1.0fix6

The player used is 5-channel Tim Follin-like impulse player with sampled drums added
(not pausing the song).
Impulse widths in channels may be varied independently.
Impulse width affects volume and timbre.
If an impulse in one of channels concurs in time with some impulse in another channel,
these impulses are genereted consequently. Thus, every channel (even if its output is off) affects
other channels. Average period of a channel does not depend on others.
Although, the note we hear is not average period. I suppose, we hear the most usual period.
This means higher notes might play slightly higher than they should do
(for around 1/50 of frequency for each channel lower than this note).
To compensate this, use shift command.

You can set for every channel (incl. drums) what device it is played to: speaker or tape out,
or both, or nowhere. Last option is used to shut down channels while editing music.
Key T toggles tape, and Y toggles speaker.
Speaker may be toggled while playing too: keys D,1,2,3,4,5.
When channels are off their impulses are still generated.
This must be done or the frequences will go wrong.
If the volume is 0 (as in pause) then some 4th octave frequency is used
(each channel has its own). This is to remove the parasite tone from paused channels.

Some of editor's fields are decimal (instead of hexadecimal). They are marked with small "10".

A song is made of positions (max 255). Each position has its own length (max 64 lines)
and a set of track numbers for tempo, drums, channel 1, channel 2, channel 3, channel 4, channel 5.
Position list is also called order. It is shown on screen above the pattern area.
Use "o" to switch between pattern and order.

All the tracks (three types: tempo, drums, tone; although tempo and tone have the same inner format)
are using common numeration: 00..FF. Order will not allow you to insert
track number of wrong type into any field.

Key "k" in order sets loop position of the song.

Every track has 64 lines even if the order contains another length.
For example, you may use the same track as 64-line track in some place and as 32-line track in another.

Keys to navigate in order are PageUp (CS/3) (position up)
and PageDown (CS/4) (position down using loop). Keys "up" and "down" in order mode
do the same.

Keys Home (SS/Q) and End (SS/E) do what are they intended to do - they move cursor
to the beginning and to the end. Double Home in pattern mode moves to the middle of the pattern.

Order allows entering track numbers with numeric keys and A..F. It requires
two hexadecimal digits. If your second key is not a hexadecimal digit then
the input is cancelled. Position length is entered the same way but it is decimal.

You can obtain the first free track number if you press Del (CS/9).
You can obtain it and copy the current track into it if you press "v".

Pattern and order both have BackSpace (CS/0) key to delete line and scroll the following text up.
It moves the whole table in order, but it affects only the current track in pattern.
Pattern and order both have Ins (SS/W) key to insert line and scroll the following text down.
In order, it clones the current line, but in pattern it adds free space and affects only
the current track.

In every field of a pattern (including tempo)
"." (key "0") means the old value of this parameter is used.

8 sampled drums are used, 4096 bytes each with sampling period around 22 kHz,
all stored as one 4096 bytes block (bit per drum).
Drum numbers are 1..8. Value 9 in drum column means pause.

Every pattern line plays for integer number of pseudo-frames. One pseudo-frame is
256 bytes of drum that is around 46500 t-states (1/75 of a second).
Tempo in tempo column is shown in pseudo-frames.
Volumes (impulse widths) and frequencies
are re-counted once per pseudo-frame.

Volume depends on first 4 parameters of a note:
1. TL (Total Level) - volume (at start).
If this field contains 1 or 2, then the current volume is used,
and it will fall (if 1) or rise (if 2).
If this field contains 3, the volume will rise from zero.
2. DR (Decay Rate) - speed of volume falling (or rising, see TL).
3. SL (Sustain Level) - volume level where the speed changes to SR (see below).
4. SR (Sustain Rate) - speed of volume falling (falling mode is set automatically!)
after the volume reaches SL.

Changing these numbers you can obtain envelopes like |\, like /\,
like |`- etc.

Speed of "1" is zero speed. 2..F is logarithmic scale:
"D" speed is twice the "B" speed, which is twice the "9" speed etc.
Volume scale is also logarithmic.

Frequency depends on last 2 parameters of a note:
5. GM (Gliss Mode) - referred to as a command, selects the mode how the frequency is changed.
Commands 1/2 - slide (smooth glissando, portamento) down/up.
Commands 3/4 - shift frequency (from a given note) down/up.
Values of 5..F are vibrate half-period.
6. GR (Gliss Rate) - slide/vibrate speed, or frequency shift value.
The scale is logarithmic. Value of "1" means zero speed or no shift.

Memory for tracks is allocated dynamically. They are stored packed.
Tracks are written into memory when you navigate order, or press play,
or go to file dialogue and in some other cases.
"Free" at the top of screen shows free room in memory.

The following keys are notes:
 s d   g h j
z x c v b n m
If a note is pressed with CS, it is entered octave higher, and if it is with SS, then octave below.
Select current octave in note field by means of keys 1..4.
Delete current note - Del (CS/9).
Delete current note and its parameters - "=" (SS/L).
Pause - "r".

Auto scroll after note/parameter input (as well as after deleting and inserting lines)
is changed by SS/0..SS/8.

Press and hold Enter to play from cursor.
Speaker may be toggled while playing: use keys D,1,2,3,4,5.
Turbo mode is switched off for playing (OUT #EFF7,#10).

Break (CS/Space) key moves to file dialog.
You are asked there to enter "s" (to save song) or "l" (to load song),
or anything else (to resume editing).
Then enter the file name.
File dialog is written in BASIC, feel free to crack and adapt ;)
Song module is generated at 24576. When you are about to enter
the file dialog, compilation occurs: data used for editing are moved
(not copied!) into fields of module and recalculated into displacements instead of addresses.
When you quit the file dialog, decompilation occurs: data are moved
back and recalculated back.
This frees RAM.
The program itself resides at the end of memory.

Editor uses the same player as you are supposed to use in your code.
For this, when you press a note, a 1-line pattern is generated.
When you press Enter, notes above cursor are parsed.

Beep Tracker module format

All displacements are counted from the start address of module.
Asterisk marks field not used in player.

+0  4 "BEEP" (*)
+4  1 version number (this version has 1)
+5  2 drum samples displacement
+7  1 samples length/256
+8  2 order displacement
+10 2 order length in bytes (*)
+12 1 loop position
+13 2 track descriptors displacement
+15 2 track descriptors length in bytes (*)
+17 2 tracks displacement (*)
+19 2 tracks overall length in bytes (*)
+21 6 values for port #FE for channels D,1,2,3,4,5

++0 1 pattern length (0=end of order)
++1 1 tempo track number
++2 1 drums track number
++3 1 channel 1 track number
++4 1 channel 2 track number
++5 1 channel 3 track number
++6 1 channel 4 track number
++7 1 channel 5 track number

track descriptors:
++0 2 track displacement+#6000 (version 0 had #6204)

tempo/drums track:
0..63 - skip 64..1 + end line
64 - end of track
65.. - data (0..)

tone channel track:
0..25 - skip 26..1 + end line
26 - end of track
27..116 - command + end line (used when no note)
117..206 - command
207 - R + end line
208..255 - note + end line
0..14: GR 1..F
15..29: GM 1..F
30..44: SR 1..F
45..59: SL 1..F
60..74: DR 1..F
75..89: TL 1..F

From the first #XX00 address after this: drum samples