-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Here the basics of how to use Flizzer tracker are collected. Note that some things related to trackers in general will be omitted, so if you are new to the tracker things, consider digging into basics first somewhere else.
Note: Flizzer tracker possesses a lot of similarities with klystrack, because I have been developing a fork of it for more than a year now, so some pieces of code are copy-pasted there...
This is a pretty much generic (not including instrument program, because most chiptune trackers go "macros" way) 4-channel chiptune tracker with basic waveforms and effects. It's capabilities are on par with SID chip, although it has one more channel and independent filter on each channel... Okay I am carried away a bit. So it is a real tracker where you can do real multi-channel chiptune-like songs, as opposed to Zero Tracker and Music Beeper. The goal was to make a feature-rich program and fit it on crappy 128x64 pixels display and make the controls using 6 buttons (lol LSDJ moment). Well, it kinda works...
Hold Back to go to the menu where you can exit, load/save song, access settings and show help (actually a QR code lol). To exit the menu or help, press back once. You can't exit saving/loading keyboards without typing at least one character and pressing SAVE
(they are from flipper firmware and I can't tell them to exit when you press Back, sadly, so the only way is to type some garbage there).
In settings you can change the audio ouput -- internal means that it plays through internal piezo speaker, external means that the signal is on PA6 pin (to record it, connect it directly to LINE IN on your soundcard (better for me, less noise) or to mic input but through ~400 kOhm resistance).
The main screen consists of pattern editor (lower half), sequence editor (top left) and song info (top right). Using these, you edit the song parameters, the patterns, and tewll the tracker in which order you want to play the patterns.
Your current position is indicated by tiny frame with curved borders. To actually edit something, press Ok briefly to switch into editing mode, where the frame is replaced by a box that inverts the color of any text that is inside. To exit edit mode, press Ok again.
To switch between editors, press Back briefly while not in editing mode.
To switch to instrument editor, press Back twice.
To play/stop the song, hold Ok.
Patterns are arranged side by side, and you can move your cursor using the arrow buttons across the patterns. Long press Up lets you jump to the beginning of the pattern, long press Down -- to the end of it. If you press Down on the bottommost pattern row, it will jump to the next pattern in sequence (if present), if you press Up on topmost -- to the previous pattern (if present). Note that the same pattern can be placed on several channels, so if you edit it in one channel it will update on other channels as well.
In editing mode you can edit the contents of pattern rows using Up and Down buttons for increasing/decreasing the value of selected parameter, which are grouped as follows:
Note that volume row volume values are relative to instrument volume.
Pressing Back deletes the contents of selected parameter. Long press Ok on note or octave columns to enter release note (triggers ADSR release; looks like long horizontal rectangle). You can press Down to change it to OFF
note (triggers release + immediately cuts the channel, setting the volume to zero).
Tracker remembers the last note, instrument and volume you placed, so if you placed G-4
and after that press Up on some row with empty note parameter, it will place G#4
, if you are on octave parameter -- G-5
. The same applies for instrument and volume, although it would not allow to place an instrument that does not exist.
Long press Left on any channel mutes or unmutes it (see the tiny icons on top of the pattern editor).
This is where you place patterns in a sort of matrix structure. When the tracker ends playing the pattern, it jumps to the next position of this matrix and starts playing patterns that are there.
The controls are the same, except deleting means placing 00
pattern index in current cell.
There is also looping available: long press Right to place start and end points, long press Left to clear them. The loop is labeled as square bracket:
Displays various parameters related to song. Editing works as in other places, although there is no deleting function.
Pattern position: displays the current pattern position. The second number is total pattern length and is changeable in 00-FF
range. Note: shrinking and then expanding the pattern again will erase all data beyond the pattern end after shrinking.
Sequence position: displays the current sequence matrix position. The second number is total sequence length and is changeable in 00-FF
range. Note: shrinking and then expanding the pattern again will NOT erase any data beyond the pattern end after shrinking.
Speed: displays (and allows to change) song speed (how many ticks it takes to advance one pattern row).
Rate: displays (and allows to change) song rate (how many ticks are there in one second). Default is 0x32
which is 50 in decimal, so tracker engine runs at 50 Hz.
Volume: displays (and allows to change) tracker master volume. Treat it as simply a volume slider. Large values will lead to clipping and signal inversion (since there is no clipping handling and the value is just overflowing).
Song: this field lets you edit the song name.
Inst: this field lets you edit the current instrument name and number.
Tune:
and Free:
: let you see how much RAM is occupied by the song and how much is free. Do not recommend to go as far as less than 30 kB of free memory since flipper may crash when connected to a PC or smartphone while the tracker is running. You use more memory by adding patterns and instruments or making the patterns longer. And also yeah, nod to first Amiga trackers.
This is where the infamous chiptune magic happens. Here you make the instruments using the controls on the left side and the program on the right side.
Inst: the same as in song info above.
Note: sets the base note. How it works: the base note determines divergence from C-4
. So if base note is C-5
and you place C-4
in the pattern, the actual note will be C-5
. If base note is C-3
and you place C-4
in the pattern, the actual note will be C-3
.
Finetune: Lets you detune the actual frequency. Ranges from -128 to 127 which covers base - 0.5 semitones to base + 0.5 semitones. The frequency between adjacent notes is linearly interpolated.
Slide speed: How many 1/64th of a semitone the note is changed when slide (auto portamento) is used. The larger the value, the faster the slide.
Set PW: set pulse width on keydown. To the right is initial PW value (00-FF covers 100% to 0% range).
Set cutoff: set filter cutoff and resonance on keydown, also resets the filter.
Below are the waveforms from left to right.
Noise: C64-like noise. Pulse: pulse wave with variable pulse width. Triangle: triangle wave. Saw: sawtooth wave. Metal: metallic noise, can be used with or without the noise enabled. Basically loops over the same repeating part of the noise, thus producing somewhat tonal sound. Can detune on high notes. Sine: 256-step sine wave from a LUT. Has some aliasing because of that on low notes.
If you enable multiple waves at once, the result will be the wave of bitwise ANDed basic waves. This can lead to many new and interesting sounds, e.g. triangle + sawtooth produce an interesting fractal-shaped wave which sounds kinda like C64 tripulse wave.
Attack: envelope attack period. The higher the number, the longer the attack.
Decay: envelope decay period.
Sustain: envelope sustain level. FF
means max level (the peak between attack and decay phases).
Release: envelope release period.
Volume: instrument envelope volume.
If you have series of notes which are just placed one after another without gaps of silence between them, set attack and decay to 00
, sustain to FF
, and manipulate the volume with pattern effects or volume column (Amiga MOD style).
Filter: enables filter at instrument trigger.
Cutoff: filter cutoff. The filter is not stable and may output cracks and overflow at high cutoff values. This can kinda be fixed by cranking up the resonance but it would change sound texture, so experiment.
Resonance: filter resonance (additional amplification of cutoff frequency).
Type: NONE
means filter is initialized but not enabled. There are also lowpass, highpass, bandpass and all their possible combinations (as in SID chip).
Ring: enable ring modulation Source: ring modulation source channel (F = self).
Hard: enable oscillators' hard sync between channels. Source: hard sync source channel (F = self).
Slide retrig: retrigger on slide command. Restarts the instrument even if the note has slide command next to it.
Key sync: sync oscillator on keypress. Not recommended if you have series of notes which are just placed one after another without gaps of silence between them. This also enables keypress sync for vibrato and PWM LFOs.
Vibrato: enables vibrato.
Vibrato speed: speed of the vibrato.
Vibrato depth: depth of the vibrato. FF
means swing between -1
semitone and +1
semitone.
Vibrato delay: how many tracker engine ticks to wait from instrument trigger. After this number of ticks passes, the vibrato is enabled.
PWM: enables PWM (pulse width modification).
PWM speed: speed of the PWM.
PWM depth: depth of the PWM. FF
means swing between 0
semitone and FFF
pulse widths (0-100% range).
PWM delay: how many tracker engine ticks to wait from instrument trigger. After this number of ticks passes, the PWM is enabled.
No program restart: do not restart instrument program on instrument trigger.
Program period: How many ticks does it take to advance one program step.
Basically a stolen klystrack program, no more, no less.
Program is executed step by step. There are 16 steps in the program. If no special commands are placed, it just loops through its contents infinitely.
You can create loops, use jump command and a special HALT
-like command (see effects list below; they are entered by pressing Down on the lefmost digit of instrument program step):
Unknown commands are displayed as ?xx
. If you keep pressing Up after Zxx
command you will encounter such commands. Just delete it or go back to valid commands.
You can use a bunch of effects in pattern and instrument program, most of them are interchangeable between them (unless stated otherwise).
Some of the commands loosely follow klystrack and original Amiga tracker "standards".
xx
, yy
= parameter to command
Command | Description |
---|---|
0xx |
set arpeggio note (final played note = played note + arpeggio note + vibrato etc.). 0F0 enables first external note, 0F1 sets second external note. Used as 0xy in pattern to set external arpeggio notes (x = 1st note, y = 2nd, so 047 with appropriate commands in instrument program makes a classic major chord arpeggio). |
1xx |
portamento up, xx/64th of a semitone per tick |
2xx |
portamento down, xx/64th of a semitone per tick |
3xx |
slide to a note with speed of xx/64th of a semitone per tick |
4xy |
vibrato with speed x and depth y |
5xy |
PWM with speed x and depth y |
6xx |
set pulse width |
7xx |
pulse width down |
8xx |
pulse width up |
9xx |
set filter cutoff |
axy |
Fade volume x steps up and y steps down, axx obviously does nothing (fade up and fade down cancel each out if x = y). Note that it caps volume at 0x80 even if before the volume was higher. |
bxx |
Set waveform. xx is a binary number where LSB is for noise, the next bit is for pulse etc. So b03 = pulse + noise. |
cxx |
Set channel volume. |
dxx |
Skip to next pattern, parameter is discarded |
e0x |
e00 disables filter, e0x where x is 1-F enables filter |
e1x |
fine portamento up (x/256th of a semitone, runs only in the first tick of program or pattern step, as all other exy effects where applicable) |
e2x |
fine portamento down |
e3x |
set filter mode |
e6x |
Works only in pattern! e60 marks loop begin, e6x where x is 1-F marks loop end. Loop runs x times. |
e9x |
Retrigger instrument at tick x-1 , so e90 does not work |
eax |
Fine volume down fade |
ebx |
Fine volume up fade |
ecx |
Cut note at tick x, same as OFF note but with optional tick offset |
edx |
Delay the note trigger for x ticks, x should be lower than (song_speed - 1) |
efx |
Phase rest on tick x (reset oscillator) |
fxx |
In pattern sets song speed, in instrument program sets its program period |
gxx |
Filter cutoff up |
hxx |
Filter cutoff down |
ixx |
Set filter resonance |
jxx |
Filter resonance up |
kxx |
Filter resonance down |
lxx |
Set envelope attack period. If envelope is in attack phase, its speed changes immediately |
mxx |
Set envelope decay period. If envelope is in decay phase, its speed changes immediately |
nxx |
Set envelope sustain level |
oxx |
Set envelope release period. If envelope is in release phase, its speed changes immediately |
pxx |
Works only in pattern! Restart instrument program |
rxx |
Set ring modulation source channel (FF = self) |
sxx |
Set hard sync source channel (FF = self) |
txx |
Portamento up xx semitones per tick |
uxx |
Portamento down xx semitones per tick |
Xxx |
Legato (like slide: to instrument retrigger but note changes immediately rather than smoothly) |
yxx |
Works only in instrument program! Set absolute arpeggio note (does not depend on what is base note, note in pattern etc.) |
zxx |
Trigger release (works like release note) |
The following commands work only in instrument program! | |
<00 |
Loop begin, the parameter is discarded |
>xx |
Loop end, loop xx times |
^xx |
Go to (jump to) step xx |
:FF |
Program end. Its execution is stopped until it is restarted by command or new note trigger. |
But how does it work? Well, like flipper wav player! There is an array in RAM used as double buffer. DMA in circular buffer mode loops through the buffer and puts samples into TIM16 compare register which in turn generates a 60 kHz 10-bit PWM signal which is then routed either to internal shitty buzzer or on "3" (aka A6 aka PA6) pin you can find amongst GPIO pins. Connect it to your PC microphone input through a ~400kOhm resistance to have clean sound. Don't plug in any usb cable while listening to/recording this sound, because the common ground or whatever introduces audible noise.
So, let's continue with hardware abuse. Obviously, I want to adjust sample rate of sound engine independently from PWM frequency, so for that I am using TIM1. It is the timer that triggers DMA transfers.
So, are we OK with that? Well, not quite... Because we also have a tracker engine running on its own rate! (typically 50-60 Hz) I could just approximate the rate through sound engine sample rate, but why would I go this miserable silly way, if I can... Yes, abuse third timer!
TIM2 is a unique one in Flipper ARM Cortex M4 main core because it has a 32-bit counter, so without any prescaler fuckery you have a 1-255 Hz range with quite a precision (ofc the master clock (64 MHz) is not itself so precise, but comparing wav recordings playback with my PC ones it's close enough for you to not notice until you launch playback on these two simultaneously). It's interrupt priority is one level higher than sound engine DMA interrupt, so effects timings precision is within one sample duration (and by default you have 44100 Hz sample rate, is it enough precision?).
So these three timers are working together to provide a smooth tracker operation. I am surprized it still has time to update the screen: even when I enable filters on all 4 channels, it still manages to have like 0.5 FPS.