Correctly changing the envelope frequency in Pro Tracker 3
ZXNet echo conference «music.zx»
From Ivan Roshin → To All 7 December 2000
Hello, All!
═══════════════════ env_freq.1 ══════════════════
(c) Ivan Roshchin, Moscow
Fido: 2:5020/689.53
ZXNet: 500:95/462.53
E-mail: asder_ffc@softhome.net
WWW: http://www.zx.ru/echo/roschin
Correctly changing the envelope frequency in Pro Tracker 3
─────────────────────────── ───────────────────────────
("Radio Amateur. Your Computer" 10/2000, 11/2000)
Here I want to talk about the disadvantage of the music editor
Pro Tracker 3 and how to overcome it.
Let's say the melody uses sample, in which for
only the envelope (sample) is used to form the sound
stuck on position 00):
┌──────────────────── ────────────────────┐
│ EDIT SAMPLE 01 │
│ ▒00 000 -0000 00 --E ............... 0 │
When such a sample sounds, if register R13 is set
envelope shape #E, signal at the output of the music coprocessor
will look like this (provided graph
corresponds to the AY coprocessor, which when used
the envelope generates 16 signal levels; on the YM coprocessor
32 levels are formed):
A┼
│
│ ▄██▄ ▄██▄
│ ▄██████▄ ▄██████▄
│ ▄██████████▄ ▄██████████▄
│ ▄██████████████▄ ▄██████████████▄│ ▄██████████████████▄ ▄██████████████████▄
│ ▄██████████████████████▄ ▄██████████████████████▄
│ ▄██████████████████████████▄ ▄█████████████████████████
0└─▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀──▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀─>
<─────────── period ───────────> t
In one of the melody channels (let it be channel A)
let's put a sequence of notes using the discussed
sample and with different values of the envelope frequency divider.
We get a pattern something like this:
│00│003F│..│E-5 1E..│
│01│....│..│--- ....│
│02│....│..│--- ....│
...................
│15│....│..│--- ....│
│16│003C│..│F-5 .E..│
│17│....│..│--- ....│
...................
│31│....│..│--- ....│
│32│0033│..│G-5 .E..│
│33│....│..│--- ....│
...................
│47│....│..│--- ....│
│48│0030│..│A-5 .E..│
│49│....│..│--- ....│
...................
When playing this pattern we will hear in channel A
four different sounds successively replacing each other
frequencies.
This is where the trouble begins: in moments when one soundreplaced by another, a crash is clearly heard. Let's try to figure it out
why is this happening. To do this, consider the signal shape at
output of the music coprocessor when changing sounds:
A┼
│
│ ▄██▄ ▄██▄ ▄██▄
│ ▄█████ ▄████▄ ▄████▄
│ ▄███████ ▄██████▄ ▄██████▄ ▄
│ ▄█████████ ▄████████▄ ▄████████▄ ▄█
│ ▄███████████ ▄██████████▄ ▄██████████▄ ▄██
│ ▄█████████████ ▄████████████▄ ▄████████████▄ ▄███
│ ▄███████████████ ▄██████████████▄ ▄██████████████▄ ▄████
0└─▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀─▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀──▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀──▀▀▀▀▀─>
│t
moment of sound change
It can be seen that at the moment of changing two sounds (namely, at the moment
when the number #E is written to the envelope shape register R13)
the music coprocessor begins a new envelope cycle, despite
that the old cycle has not yet ended. This is the peculiarity
coprocessor - it reacts to the very fact of writing to register R13,
even if the same number is written there that is already there
it was. The graph clearly shows a sharp drop in amplitudes during this
moment, which is perceived by ear as a click.
At the same time, if you change only the frequency of the envelope, there is no
touching R13, the result will be exactly as it should:
A┼
││ ▄██▄ ▄██▄ ▄██▄
│ ▄█████▄ ▄████▄ ▄████▄
│ ▄████████▄ ▄██████▄ ▄██████▄
│ ▄███████████▄ ▄████████▄ ▄████████▄
│ ▄██████████████▄ ▄██████████▄ ▄██████████▄
│ ▄█████████████████▄ ▄████████████▄ ▄████████████▄
│ ▄████████████████████▄ ▄██████████████▄ ▄██████████████▄
0└─▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀──▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀──▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀─>
│ t
момент смены звуков
════════════════════════════════════════════════
С уважением, Иван Рощин.
[ZX] [BestView 3.0 - 26%]
From Ivan Roshin → To All 7 December 2000
Hello, All!
═══════════════════ env_freq.2 ══════════════════
Well, here's the problem - Pro Tracker does not allow you to install new
envelope frequency value without writing the value to the form register
envelope. If we try to write it as shown
below, Pro Tracker will not "understand" this entry and will not change
envelope frequency:
│00│003F│..│E-5 1E..│
│01│....│..│--- ....│
│02│....│..│--- ....│
...................
│15│....│..│--- ....│
│16│003C│..│--- ....│
│17│....│..│--- ....│
...................
│31│....│..│--- ....│
│32│0033│..│--- ....│
│33│....│..│--- ....│
...................
│47│....│..│--- ....│
│48│0030│..│--- ....│
│49│....│..│--- ....│
...................
Other music editors may allow this
do it, but I just don’t want to switch anywhere from Pro Tracker,
because its interface seems to me (and not only me) the most
convenient.
I listened to a lot of what was written in Pro Tracker
melodies and came to the conclusion that their authors came to terms with this, as
with something inevitable. At the same time, there is a way to overcome thisproblems that do not require switching to another editor.
Let's take advantage of the fact that Pro Tracker has commands
increasing and decreasing the value of the envelope frequency divider:
9 - Enable portamento up
A - Enable portamento down
In position 2 for these commands the delay value is indicated
(number of interruptions between two changes), and in positions
3 and 4 indicate the change step.
Here is an example of the action of the "9810" command for the case when
The initial value of the frequency divider was #0050:
divisor ┼
frequencies │
#80 │ ▒▒▒▒▒▒▒▒
#70 │ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
#60 │ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
#50 │█████████████▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
#40 │█████████████▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
#30 │█████████████▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
#20 │█████████████▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
#10 │█████████████▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
0 └─────────────┼───────┼─ ──────┼────────┼───────>
x x+8 x+16 x+24 t
│
└─the moment the command starts
As you can see, after these commands the value of the frequency divider is
will change all the time. And we need to adapt these commands
to solve the following problem: at the moment of the beginning of a note with an ordinalnumber n change the value of the frequency divider from p1 to p2 if
the speed of the melody is s.
This can be done as follows: on a note with an ordinal
number n-1 we put command 9 if p2>p1, and command A if
p1>p2. Command parameters: in the second position we indicate s, and in
in positions 3 and 4 we indicate │p2-p1│. Then at the moment when the note with
serial number n-1 will end and note n will begin, meaning
The frequency divider will change from p1 to p2. In order to
stop further changes in the frequency divider to note n
set the command 9s00 or As00 (i.e. change in steps of 0).
If we apply this method to the example discussed earlier
(assuming the melody speed is four), then we
we get the following (commands for convenience are given on the right
column, in fact, when working in the editor they are not visible):
│00│003F│..│E-5 1E..│ │
│01│....│..│--- ....│ │
│02│....│..│--- ....│ │
...................
│15│....│..│---▒....│A403│ (#3F-#3C=3)
│16│003C│..│---▒....│9400│
│17│....│..│--- ....│ │
...................
│31│....│..│---▒....│A409│ (#3C-#33=9)
│32│0033│..│---▒....│9400│
│33│....│..│--- ....│ │
...................│47│....│..│---▒....│A403│ (#33-#30=3)
│48│0030│..│---▒....│9400│
│49│....│..│--- ....│ │
...................
I recommend downloading Pro Tracker and testing it in practice,
how much better the sound became.
Now let's look at the case when a melody consisting of
of the same single pattern, looped back to the beginning. Please pay
pay attention to the fact that for the correct sound you will have to change
the above pattern and add another one. After all, if
use only the above pattern, then when transitioning
to its beginning #E will be written in R13, which means there will be
a click is heard.
════════════════════════ ════════════════════════
Best regards, Ivan Roshchin.
[ZX] [BestView 3.0 - 26%]
From Ivan Roshin → To All 7 December 2000
Hello, All!
═══════════════════ env_freq.3 ══════════════════
So, we get this (the melody should be looped on
pattern 1):
Pattern 0: │00│003F│..│E-5 1E..│ │
│01│....│..│--- ....│ │
│02│....│..│--- ....│ │
...................
│15│....│..│---▒....│A403│ (#3F-#3C=3)
│16│....│..│---▒....│9400│
│17│....│..│--- ....│ │
...................
│31│....│..│---▒....│A409│ (#3C-#33=9)
│32│....│..│---▒....│9400│
│33│....│..│--- ....│ │
...................
│47│....│..│---▒....│A403│ (#33-#30=3)
│48│....│..│---▒....│9400│
│49│....│..│--- ....│ │
...................
│62│....│..│--- ....│ │
│63│....│..│---▒....│940F│ (#3F-#30=#F)
Pattern 1: │00│....│..│---▒....│9400│
│01│....│..│--- ....│ │
│02│....│..│--- ....│ │
...................
│15│....│..│---▒....│A403│ (#3F-#3C=3)
│16│....│..│---▒....│9400│
│17│....│..│--- ....│ │
...................│31│....│..│---▒....│A409│ (#3C-#33=9)
│32│....│..│---▒....│9400│
│33│....│..│--- ....│ │
...................
│47│....│..│---▒....│A403│ (#33-#30=3)
│48│....│..│---▒....│9400│
│49│....│..│--- ....│ │
...................
│62│....│..│--- ....│ │
│63│....│..│---▒....│940F│ (#3F-#30=#F)
As we can see, when using this method the number of patterns
in the melody may increase. Yes, and with the calculation of differences and with
You'll have to tinker with installing commands, but the sound quality will be
it will get much better! I recommend writing the melody first "like
usually", not paying attention to the clicks during playback, and then
already convert it to the “correct” form.
And a few more words: as you may have noticed,
the considered sample sounds the same as when used
envelope shape #E, as well as when using envelope shape #A.
But in the melody it is recommended to use the #E form - as
can be seen from the graph when using the #A form at the beginning of the melody
a click will be heard due to a sharp change in amplitude:
A┼
│
│ █▄ ▄██▄
│ ███▄ ▄██████▄
│ █████▄ ▄██████████▄│ ███████▄ ▄██████████████▄
│ █████████▄ ▄██████████████████▄
│ ███████████▄ ▄██████████████████████▄
│ █████████████▄ ▄██████████████████████████▄
0└─────────────▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀── ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀─>
<─────────── period ───────────> t
│
beginning of the melody
Well, how can you listen to already written PT3 modules without crashing?
without changing anything about them? This can be done using my
BestView 2.9 program, turning on the envelope filter (a sign of its
activity - '√' icon in the lower right corner of the screen, enable/
switch off - using the "V" key). In version 2.9 the filter
only works when playing PT3 modules, so if you
want to get rid of the crackling sound when playing modules written
in Sound Tracker, S.T.Pro, Pro Tracker 2, then you need them
convert to PT3 format (which is successfully done using
PT3 itself). In subsequent versions of BestView all these formats
will be supported directly.
Using this feature, many PT modules began to sound
in a new way - for example, the music album "Explosion" by
ViSuAl^Extreme.
Perhaps some of the readers of this article would like
write your own music player, or just add it to your
program the ability to play PT3 modules (say, inas background music). In this case, the following
The information will certainly be useful. So how does it work
this same envelope filter in BestView 2.9?
First, let's define the variables used. ENV_FIL (byte)
shows whether the filter is enabled (1 - yes, 0 - no). This variable
can be changed by the user directly during playback.
The Z_FIRST (byte) variable indicates whether a write was made to
R13 at least once from the beginning of the melody (1 - yes, 0 - no). She needs it
reset before initializing the module.
Let's look at a fragment of a standard player of PT3 modules, in
in which new values are written to the music registers
coprocessor:
...... .......
#C73C: LD B,D
#C73D: OUT (C),L
#C73F: LD B,E
#C740: OUTI
#C742: LD A,0
#C744: OR A
#C745: JR Z,#C751
#C747: LD B,D ;!
#C748: OUT (C),L ;!
#C74A: LD B,E ;!
#C74B: OUT (C),A ;!
#C74D: XOR A
#C74E: LD (#C743),A
#C751: LD LY,#3A
...... .......
Marked with '!' commands directly record newvalue in R13. Before their execution, the battery contains
written value, D=#FF, E=#BF, L=13.
Let's put the CALL PATCH command at address #C747. Then how
as soon as the player wants to record something in R13, it will be called
our PATCH routine. And she will already decide: to record in
R13 or not, and if produced, then what exactly should be written there.
════════════════════════ ════════════════════════
Best regards, Ivan Roshchin.
[ZX] [BestView 3.0 - 26%]
From Ivan Roshin → To All 7 December 2000
Hello, All!
═══════════════════ env_freq.4 ══════════════════
Here is her text with detailed comments:
PATCH LD B, D ; these are the same two commands instead of which
OUT (C),L ;the player now has CALL PATCH
;If the filter is turned off - write to R13
;should be (and set Z_FIRST
;in 1):
LD B,A
LD A,(ENV_FIL)
AND A
JR Z,SET_ZFS
;Filter is enabled.
;Replacement of envelope shape #A with #E
;(but only if the period is less than #200):
LD A,(#C30C)
CP 2
JR NC,ENV_NEA
LD A,B
CP#A
JR NZ,ENV_NEA
LD B,#E
ENV_NEA
;If the call is the first after INIT -
;the entry in R13 should be:
LD A,0
Z_FIRST EQU $-1
AND A
SET_ZFS LD A,1
LD(Z_FIRST),A
LD A,B
RET Z
;If the same is not written in R13
;the value that was there - record
;should be:
LD B,D
IN B,(C)
CP B
RET NZ
;If the envelope was previously turned off,
;the entry should be:
PUSH AF ;These commands need some
LD B,#7F ;explanation. BestView has
LD A,SS_BANK ;special variable EN_USED,
OUT (C),A ;which changes after eachLD A,(EN_USED) ;calling the PLAY procedure. This re-
AND A ;variable is set to 1 if
LD A,#10 ;used on any channel
OUT (C),A ;envelope, and to 0 if envelope
JR NZ,PR_PERI ;not used. At the moment of execution
;the meaning of these commands is therefore
;EN_USED indicates whether it was used
;whether the envelope is before the current call
;PLAY procedures.
POP AF
RET
;If period >=#200 - the entry should be:
PR_PERI LD A,(#C30C)
CP 2
JR C,NEN_WKL
POP AF
RET
;Cancel the entry in R13:
NEN_WKL POP AF
;increase the return address by 3
;(to skip LD B,E: OUT (C),A
;in the player):
EX (SP),HL
INC HL
INC HL
INC HL
EX (SP),HL
RET
When playing PT3 modules compiled with the player,
I recommend taking the frequency table directly from the module
(as is done in BestView). First, the frequency tables in
different versions of Pro Tracker 3 are slightly different, and secondly,
it is worth considering the possibility that the author of the melody
used my own frequency table, not matching
with none of the standard ones (for example, I used naturalscale, not tempered).
When playing modules compiled without a player,
I recommend using frequency tables from Pro Tracker 3.4
final, since it is in this version of the editor that they are calculated with
maximum accuracy. It is enough to store in the program only
the first 24 bytes of each table, which corresponds to twelve
notes of the first octave. For each subsequent octave the frequencies will be
twice as much - well, the values in the table are, accordingly, twice
less. Considering that there are four tables in total, and each contains values
for eight octaves, this will save 4*7*24=672 bytes!
This is a lot - especially considering that such tables
practically not packed.
I also recommend fixing the one in the standard player
error processing the vibrato command (see my article "Error in
player Pro Tracker 3 and its correction" in the 8th issue of the magazine).
To do this, you need to place byte #1D at offset #A34 from
start of the player.
There is another error in the PT3 player:
mixing up the parameters of the vibrato command. Those who want to fix it
I recommend reading the article ((c) Max/CBX/BDA) in the ninth issue
electronic magazine DEJA VU.
════════════════════════ ════════════════════════
Best regards, Ivan Roshchin.
[ZX] [BestView 3.0 - 26%]