Skip to content
LTVA1 edited this page Apr 20, 2024 · 20 revisions

Flizzer tracker wiki

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...

Flizzer tracker

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...

Tracker files (modules and settings config file) are in apps_data/flizzer_tracker folder on SD card.

Main screen

https://github.com/LTVA1/flizzer_tracker/blob/main/wiki_images/main_screen.png

Hold Back to go to the menu where you can exit, load/save song, access settings and show help (actually a QR code lol). When in pattern editing mode, the pattern editor occupies all screen and holding Back brings you to pretty self-explanatory copypaste stuff menu. It treats pattern your cursor is on as current pattern. 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 tell 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.

Pattern editor

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:

https://github.com/LTVA1/flizzer_tracker/blob/main/wiki_images/pattern_row.png

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).

Sequence 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:

https://github.com/LTVA1/flizzer_tracker/blob/main/wiki_images/sequence_loop.png

Song info

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 sequence 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. Press Up when in editing mode to open the keyboard.

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.

Instrument editor

https://github.com/LTVA1/flizzer_tracker/blob/main/wiki_images/instrument_editor.png

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.

Hold Back to enter the menu where you can load and save instruments in separate .fzi files.

Controls

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.

Sample: enable DPCM sample playback. Sample signal is added to channel signal. OENV: override volume envelope. This means that sample will always play at max volume regardless of volume settings and ADSR envelope. It will, however, stop, if it ends (if not looped) or if your ADSR finishes its release phase. L: lock to base note. This means sample pitch will not change, so no matter what vibrato/portamento you use or what note you trigger the instrument with, it will always play at maximum sample rate.

Program period: How many ticks does it take to advance one program step.

Instrument program

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):

https://github.com/LTVA1/flizzer_tracker/blob/main/wiki_images/instrument_program.png

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.

Sample editor

Sample editor is incomplete and is in dev version only.

Here you can import samples from wav files and adjust their settings.

Samples are NES-style DPCM samples so expect that they will sound much much worse than original files. DPCM samples are used because there is too little RAM space available.

Maximum sample rate is 44100 Hz, but sample can play at lower pitch. Max sample rate is at instrument base note, if note is lower sample will play slower. Sample obeys all vibrato/slide/portamento stuff (unless lock to base note flag is set in instrument editor). If note goes higher than instrument base note, sample plays at max sample rate.

Sample can be looped. Start and end points are available. If start point is not at the very beginning, then sample will play this part only once and then loop through the part between loop start and loop end points.

If your sample is large and you set loop start point relatively far from beginning, there will be some freeze time. It is because Flipper needs to calculate delta counter position on loop start point, which means it needs to "play" the sample from the very beginning to the loop start point (because that's how DPCM works: you need to go through all previous steps to know current delta counter value) which it tries to do as fast as it can (not bound by sample rate, obviously), but is still can take several seconds.

Speaking of slow things: wav import is very slow (12 seconds long sample (nearly the longest sample you can use) import takes 1+ minute) because it reads wav file 1 sample at a time which is very slow (see 1st line of SD card benchmark).

While I coded it so you can't import sample which wouldn't fit in RAM, you still may see Flipper crashing when trying to import long sample. This is probably because of fragmentation and I have no power here, so it is as it is. Pay attention to FREE: thing on main screen and use samples in such a way that you have at least 20 KiB of RAM free.

So I suggest using samples for drums, short looped synth sounds or very short vocal things. You may layer samples with Flizzer Tracker synth sound, e.g. play snare sample and noise at the same channel so noise would make for lacking high frequencies in the sample (classic NES DPCM sample snare trick).

Controls

Wave: select current sample. Up to 32 samples can be used. To the right you can write sample name. Loop: make sample loop. Start: loop start point End: loop end point

You may notice that length is exactly 8 times larger than sample size in bytes. That's because 1 byte codes 8 consecutive steps of the sample, and start and end loop points are set relatively to steps, not the size in bytes.

Effect list

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
qxx Set tracker engine rate (in Hz)
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
vxx Set detune. v80 is no detune. v00 is minus one semitone. vff is just shy plus one semitone.
Xxx Legato (like slide: no 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). xx is the tick when release is triggered (can't be larger than song_speed - 1)
The following commands work only in instrument program!
<xx 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.

Technicalities

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 (or to line in without any resistors) 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.