gt2fork
- Editor by Lasse Öörni and Jan Wassermann.
- Music playroutines by Lasse Öörni.
- Uses reSID engine by Dag Lem and Leandro Nini.
- Uses reSIDfp distortion / nonlinearity by Antti Lankila and Leandro Nini.
- Uses 6510 crossassembler from Exomizer2 beta by Magnus Lind.
- Uses the SDL2 library.
- Uses the RtMidi library.
- Uses parts of the GoatTracker icon by Antonio Vera.
- Command quick reference by Simon Bennett.
- Patches and further development by Stefan A. Haubenthal, Valerio Cannone,
Raine M. Ekman, Tero Lindeman, Henrik Paulini and Groepaz. - Microtonal support by Birgit Jauernig.
Distributed under GNU General Public License 2.0 (see the file LICENSE for details).
Table of contents
Command line options
-Axx Set ADSR parameter for hardrestart in hex.
DEFAULT=0F00
-Bxx Set sound buffer length in milliseconds
DEFAULT=100
-Dxx Pattern row display
(0 = decimal, 1 = hexadecimal)
-Exx Set emulated SID model
(0 = 6581 1 = 8580)
DEFAULT=8580
-Fxx Set custom SID clock cycles per second
(0 = use PAL/NTSC default)
-Gxx Set pitch of A-4 in Hz
(0 = use default frequencytable, close to 440Hz)
-Ixx Set reSID/-FP settings
(0 = reSID Fast Resample,
1 = reSID Resample,
2 = reSID-FP Interpolate,
3 = reSID-FP Interpolate Resample)
DEFAULT = reSID Resample
-Jxx Set special note names
(2 chars for every note in an octave/cycle, e.g. C-DbD-EbE-F-GbG-AbA-BbB-)
-Kxx Note-entry mode
(0 = Protracker, 1 = DMC, 2 = Janko)
DEFAULT=Protracker
-Lxx SID memory location in hex.
DEFAULT=D400
-Mxx Set sound mixing rate
DEFAULT=48000
-Oxx Set pulseoptimization/skipping
(0 = off, 1 = on)
DEFAULT=on
-Qxx Set equal divisions per octave
(12 = default, 8.2019143 = Bohlen-Pierce)
-Rxx Set realtime-effect optimization/skipping
(0 = off, 1 = on)
DEFAULT=on
-Sxx Set speed multiplier
(0 for 25Hz, 1 for 1x, 2 for 2x etc.)
-Vxx Set finevibrato conversion
(0 = off, 1 = on)
DEFAULT=on
-Xxx Set window type
(0 = window, 1 = fullscreen)
DEFAULT=window
-Yxx Path to a Scala tuning file .scl
-Zxx Set random reSID write delay in cycles
(0 = off)
DEFAULT=off
-N Use NTSC timing
-P Use PAL timing (DEFAULT)
-W Write sound output to a file SIDAUDIO.RAW
-? Show command line options info
-?? Standalone online help window
Keyboard commands
- General Keys
- Pattern edit mode
- Song edit mode
- Instrument edit mode
- Table edit mode
- Songname edit mode
General Keys
| F1 | Play from beginning |
| F2 | Play from current pos. |
| F3 | Play one pattern from current pos. |
| F4 | Stop playing & silence all sounds |
| F5 | Go to pattern editor |
| F6 | Go to song editor |
| F7 | Go to instrument/table editor |
| F8 | Go to songname editor |
| F9 | Pack, relocate & save PRG,SID etc. |
| F10 | Load song (Pattern/Song/Songname mode) or instrument (Instrument mode) |
| F11 | Save song (Pattern/Song/Songname mode) or instrument (Instrument mode) |
| F12 | Online help screen. Press F12 again to toggle context mode |
| SHIFT+F1 | Play from beginning /w follow play |
| SHIFT+F2 | Play from current pos. /w follow play |
| SHIFT+F3 | Play one pattern from current pos. /w follow play |
| SHIFT+F4 | Mute current channel |
| SHIFT+F5 | Decrease speed multiplier |
| SHIFT+F6 | Increase speed multiplier |
| SHIFT+F7 | Edit hardrestart ADSR parameter |
| SHIFT+F8 | Switch between 6581 and 8580 SID models |
| SHIFT+F10 | Merge-load song |
| SHIFT+,. | Move song startposition on all channels and restart last playmode |
| TAB | Cycle between editing modes (forwards) |
| SHIFT+TAB | Cycle between editing modes (backwards) |
| INS | Insert row (Press INS/DEL on endmark to change pattern/song length) |
| DEL | Delete row |
| SHIFT+ESC | Optimize musicdata, or clear musicdata & set default pattern length |
| ALT+D | Select MIDI input device |
| ALT+M | Switch between mono and stereo mode |
| ALT+T | Switch between black and blue theme |
| ESC | Exit program |
Pattern edit mode
| - + | Select instrument |
| / * | Select octave |
| < > | Select pattern |
| BACKQUOTE | Select channel |
| 0-9 & A-F | Enter parameters |
| SPACE | Switch between jam/editmode |
| RETURN (or CAPSLOCK) |
Insert keyoff Enter table (when cursor is over a table-utilizing command) Enter instrument (when cursor is over a nonzero instrument number) |
| SHIFT+RETURN | Insert keyon Convert portamento/vibrato/funktempo old style parameter to a speedtable entry (when cursor is over the command) Go into an empty table entry (when parameter is zero on a table-utilizing command) |
| BACKSPACE | Insert rest |
| SHIFT+BACKSPACE | Insert rest and clear commands |
| SHIFT+SPACE | Play from cursor position |
| SHIFT+Q | Transpose halfstep up |
| SHIFT+A | Transpose halfstep down |
| SHIFT+W | Transpose octave up |
| SHIFT+S | Transpose octave down |
| SHIFT+O | Shrink pattern (divide size by 2) |
| SHIFT+P | Expand pattern (multiply size by 2) |
| SHIFT+J | Join pattern with next pattern in orderlist |
| SHIFT+K | Split pattern from edit position |
| SHIFT+H | Calculate "hifi" left/right shifted speedtable entry for portamento or vibrato |
| SHIFT+I | Invert selection / whole pattern if no selection |
| SHIFT+CRSR UP SHIFT+CRSR DOWN |
Mark pattern |
| SHIFT+CRSR LEFT SHIFT+CRSR RIGHT |
Select pattern |
| SHIFT+L | Mark/unmark entire pattern |
| SHIFT+M SHIFT+N |
Choose highlighting step size |
| SHIFT+X SHIFT+C SHIFT+V |
Cut, copy, paste pattern |
| SHIFT+E SHIFT+R |
Copy, paste commands |
| SHIFT+Z | Cycle autoadvance-mode |
For pattern joining to work properly, select the pattern you want to join with the next from the orderlist first (by pressing RETURN on it). Both joining and splitting will rearrange pattern numbers (for example if you split pattern 00, pattern 01 will be created and old patterns 01-xx will be shifted forward in the pattern order).
SHIFT+SPACE will play from the pattern onwards if playback was previously stopped, but if it is pressed while in pattern play mode, it will stay in the current pattern.
Entering notes
There are two rows of a piano keyboard:
23 567 90 Higher octave QWERTYUIOP SD GHJ L Lower octave ZXCVBNM,.
Song edit mode
| < > | Select subtune |
| - + | Insert Transpose down/up command (shown as -/+ in the orderlist) |
| 0-9 & A-F | Enter pattern numbers |
| SPACE | Set start position for F2 key |
| BACKSPACE | Set end position for F2 key |
| RETURN | Go to pattern |
| SHIFT+R | Insert Repeat command (shown as "R" in the order-list) |
| SHIFT+CRSR LEFT SHIFT+CRSR RIGHT |
Mark orderlist |
| SHIFT+1 SHIFT+2 SHIFT+3 |
Swap current channel orderlist with channel 1, 2, 3 |
| SHIFT+X SHIFT+C SHIFT+V |
Cut, copy, paste channel orderlist |
| SHIFT+L | Mark/unmark entire orderlist |
| SHIFT+SPACE | Set start position on all channels |
| SHIFT+RETURN | Go to pattern on all channels |
SHIFT+SPACE or SHIFT+BACKSPACE set the start/end mark on all channels to the same position. To clear the endmark, press BACKSPACE again on it or at/before the startmark.
Instrument edit mode
| < > | Select instrument |
| - + | Select instrument |
| / * | Select octave |
| F7 | Go to table editor |
| 0-9 & A-F | Enter parameters |
| SPACE | Play test note |
| SHIFT+SPACE | Silence test note |
| RETURN | Go to table position indicated by wave/pulse/filter/vibratoposition |
| SHIFT+N | Edit instrument name |
| SHIFT+S | Smart paste an instrument |
| SHIFT+U | Unlock/lock table scrolling |
| SHIFT+X SHIFT+C SHIFT+V |
Cut, copy, paste instrument |
| SHIFT+DEL SHIFT+BACKSPACE |
Delete instrument & tabledata |
| SHIFT+RETURN | Set tablepointer to empty position or convert old style vibrato parameter |
The test note will be played on the channel you last were on in the pattern editor. To hear filtering as intended, be sure to play it on a channel that has been selected for filtering in the filter parameters.
Note that cut,copy,paste instrument do not touch the tabledata, just for the case you need it in another instrument. If you want to completely get rid of an instrument + its associated tabledata, press SHIFT+DEL.
If wave/pulse/filter/vibrato param. is zero and you press RETURN over it, you will move to the first free location in the corresponding table. If you press SHIFT+RETURN, also the instrument parameter will be set accordingly.
If vibrato parameter is nonzero and you press SHIFT+RETURN over it, it will be interpreted as an old style vibrato parameter (left nybble speed, right nybble depth) and converted to a speedtable entry.
"Smart paste" will convert instrument numbers in all patterns if you "move" an instrument by cut/pasting it.
Table edit mode
| < > | Select instrument |
| - + | Select instrument |
| / * | Select octave |
| BACKQUOTE | Select table |
| F7 | Go to instrument editor |
| 0-9 & A-F | Enter parameters |
| SPACE | Play test note |
| SHIFT+SPACE | Silence test note |
| RETURN | Go back to wave/pulse/filterposition parameter |
| SHIFT+Q SHIFT+A |
Transpose speedtable portamento speed halfstep up/down |
| SHIFT+W SHIFT+S |
Transpose speedtable portamento speed octave up/down, or multiply/divide pulse/filterspeed by 2 |
| SHIFT+L | Convert <limit,speed> modulation step to <time,speed> |
| SHIFT+N | Negate speed parameter (pulse/filtertable) or relative note (wavetable) |
| SHIFT+O | Optimize current table (remove unused entries) |
| SHIFT+R | Convert note between absolute/relative in wavetable |
| SHIFT+U | Unlock/lock table scrolling |
If you need to insert rows in the beginning of an instrument's wave/pulse/ filtertable, press SHIFT+INS instead of just INS: this way table pointers pointing to the table first row will not move.
For easier programming of negative modulation speeds in pulse/filtertables, you can first enter a positive speed positive value ($00-$7F) and then press SHIFT+N to negate it.
Conversion between relative and absolute notes will use the basenote C-0 if octave is 0, C-1 if octave is 1 and so on.
When table scrolling is unlocked, each table maintains its separate view position. To indicate this mode, a "U" letter is visible in the bottom right part of the screen. By default table scrolling is locked.
Songname edit mode
Use CRSR UP/CRSR DOWN to move between song, author & copyright strings, and other keys to edit them.
Mouse control
By clicking with the left mouse button, you can select the data to edit.
By dragging with middle or right mouse button, you can mark orderlist/pattern/tabledata.
Some values like octave or subtune/pattern numbers can be incremented with the left mouse button and decremented with the right.
By holding the middle/right mouse button in the status bar, a menu becomes active. Continue to hold and click with left button to select options.
In the fileselector, confirm loading or entering a directory by double-clicking. Doubleclick outside the selector to cancel.
Song data
Orderlist data
A song can consist of up to 32 subtunes. For each subtune's each channel, there is an orderlist which determines in what order patterns are to be played. In addition to pattern numbers, there can be TRANSPOSE & REPEAT commands and finally there is a RST (RESTART) endmark followed by restart position. The maximum length of an orderlist is 254 pattern numbers/commands + the endmark.
TRANSPOSE is measured in halftones. Transpose up (shown as +X) can be 0-14 halftones and transpose down (shown as -X) can be 1-15. Transpose is automatically reset only when starting the song, not when looping.
A REPEAT command (shown as RX) will repeat the pattern following it 1-16 times. "Repeat 16 times" is displayed as R0.
There are some rules for orderlist command order:
- If there are both TRANSPOSE and REPEAT commands before a pattern number, TRANSPOSE must come first.
- The last thing before the RST-endmark must be a pattern number. If you need to reset transpose on song repeat, do it in the beginning of the repeat loop.
In case of wrong order, the editor will halt playback. This tells that the resulting packed/relocated song would play incorrectly.
Pattern data
Patterns are single-channel only for flexibility & low memory use. They contain the actual notes, instrument changes & sound commands. A pattern can have variable length, up to 128 rows. There can be 208 different patterns in a song.
The explanation of a pattern row:
Note name
|
| Octave
| |
| | Instrument number ($01 - $3F, or $00 for no change)
| | |
| | | Command ($0 - $F)
| | | |
| | | | Databyte
| | | | |
C-1 00 0 00
The highest note available in a pattern is G#7. To reach the top three notes (A-7 to B-7), you can use transpose.
In place of a normal note, there can also be one of these special "notes":
... Rest
--- Key off (clear gatebit mask)
+++ Key on (set gatebit mask)
The actual state of the gatebit will be the gatebit mask ANDed with data from the wavetable. A key on cannot set the gatebit if it was explicitly cleared at the wavetable.
Commands:
Commands 1XY-4XY and FXY bear some resemblance to Soundtracker/Protracker/Fasttracker effect commands. However, they are different in some ways, so read their descriptions! Note that there is no "databyte $00 uses the last databyte"-action in the commands.
| Command: | Description: |
|---|---|
0XY |
Do nothing. Databyte will always be $00. |
1XY |
Portamento up. XY is an index to a 16-bit speed value in the speedtable. |
2XY |
Portamento down. XY is an index to a 16-bit speed value in the speedtable. |
3XY |
Toneportamento. Raise or lower pitch until target note has been reached. XY is an index to a 16-bit speed value in the speedtable, or $00 for "tie-note" effect (move pitch instantly to target note) |
4XY |
Vibrato. XY is an index to the speed table, where left side determines how long until the direction changes (speed) and right side determines the amount of pitch change on each tick (depth). |
5XY |
Set attack/decay register to value XY. |
6XY |
Set sustain/release register to value XY. |
7XY |
Set waveform register to value XY. If a wavetable is actively changing the channel's waveform at the same time, will be ineffective. |
8XY |
Set wavetable pointer. $00 stops wavetable execution. |
9XY |
Set pulsetable pointer. $00 stops pulsetable execution. |
AXY |
Set filtertable pointer. $00 stops filtertable execution. |
BXY |
Set filter control. X is resonance and Y is channel bitmask. $00 turns filter off and also stops filtertable execution. |
CXY |
Set filter cutoff to XY. Can be ineffective if the filtertable is active and also changing the cutoff. |
DXY |
Set mastervolume to Y, if X is $0. If X is not $0, value XY is copied to the timing mark location, which is playeraddress+$3F. |
EXY |
Funktempo. XY is an index to the speedtable, tempo will alternate between left side value and right side value on subsequent pattern steps. Sets the funktempo active on all channels, but you can use the next command to override this per-channel. |
FXY |
Set tempo. Values $03-$7F set tempo on all channels, values $83-$FF only on current channel (subtract $80 to get actual tempo). Tempos $00-$01 recall the funktempo values set by EXY command. |
Master volume is by default the maximum ($F), but it is only reset when loading a new song or clearing songdata in the editor, not every time playback starts. If you change mastervolume, you have to reset it manually in the beginning of your song.
If the command is not 1XY-4XY, instrument vibrato will be active.
Note that the one-shot commands 5XY-FXY allow the previous 1XY-4XY command or instrument vibrato to continue "underneath" them. In section 3.6 (hints & tips) there is an example of this.
Instrument data
You can use up to 63 different instruments in a song. Each instrument is defined by 9 parameters:
| Attack/Decay | $0 is fastest attack or decay, $F is slowest |
|---|---|
| Sustain/Release | Sustain level $0 is silent and $F is the loudest. Release behaves like Attack & Decay (F slowest). |
| Wavetable Pos | Wavetable startposition. Value $00 stops the wavetable execution and is not very useful. |
| Pulsetable Pos | Pulsetable startposition. Value $00 will leave pulse execution untouched. |
| Filtertable Pos | Filtertable startposition. Value $00 will leave filter execution untouched. In most cases it makes sense to have a filter-controlling instrument only on one channel at a time. |
| Vibrato Param | Instrument vibrato parameter. An index to the speedtable, see command 4XY. |
| Vibrato Delay | How many ticks until instrument vibrato starts. Value $00 turns instrument vibrato off. |
| HR/Gate Timer | How many ticks before note start note fetch, gateoff and hard restart happen. Can be at most tempo-1. So on tempo 4 highest acceptable value is 3. Bitvalue $80 disables hard restart and bitvalue $40 disables gateoff. |
| 1stFrame Wave | Waveform used on init frame of the note, usually $09 (gate + testbit). Values $00, $FE and $FF have special meaning: leave waveform unchanged and additionally set gate off ($FE), gate on ($FF), or gate unchanged ($00). |
In case of illegal (too high) gateoff timer values, the song playback is stopped.
ADSR settings are crucial to getting any sound at all. If all of them are zero just a very short "click" will be heard. Here is a diagram to help you visualize the Attack, Decay, Sustain & Release phases:
V /\ |<- gatebit reset (key-off) at this point
O / \ |
L / \__________|
U / |\
M / | \
E / | \
TIME ---------------------------->
A D S R
Some ADSR examples:
A/D 09 |
Will produce a sound that starts from full volume right away and fades to silence automatically. By increasing the Decay value, the fade will last longer. |
A/D 00 |
A sound that goes very fast from full volume to sustain level 8. If you increase the Decay value, it will go to the sustain level slower. After key-off, starts fading out with speed A. |
A/D CC |
A sound that rises slowly to maximum volume, then decays slowly to the sustain level A and after key-off, fades out to silence very slowly. |
Instrument legato works as following: When HR/Gate Timer parameter has bit $40 set, no hard restart or gateoff will be performed. When 1st Frame Wave is also $00, no 1st frame waveform will be set and gate flag is untouched. However wave/pulse/filterpointers and ADSR are initialized normally. You can also use this in conjunction with command 8XY to set another wavetable pointer for the note.
Table data
Tables control the execution of instruments' waveform/arpeggio changes, pulse modulation, and filter modulation. All the tables are controlled by the left side bytes, while the right side byte specifies additional parameters.
Note that you should never jump directly onto a table jump command (FF) either with instrument parameters or pattern commands 8XY, 9XY, AXY. Otherwise, results are undefined.
Wavetable
| Wavetable left side: | Wavetable right side: | ||
|---|---|---|---|
00 |
Leave waveform unchanged | 00-5F |
Relative notes |
01-0F |
Delay this step by 1-15 frames | 60-7F |
Negative relative notes (lower pitch) |
10-DF |
Waveform values | 80 |
Keep frequency unchanged |
E0-EF |
Inaudible waveform values $00 - $0F |
81-DF |
Absolute notes C#0 - B-7 |
F0-FE |
Execute command 0XY-EXY. Right side is parameter. |
||
FF |
Jump. Right side tells position ($00 = stop) |
||
Short explanation of waveform bitvalues:
01 |
Gatebit. When on, initiates attack/decay/sustain phase. When off, initiates the release phase. |
02 |
Synchronize. Creates weird effects using output of another channel. |
04 |
Ring modulation. Creates weird effects using output of another channel. Most effective with the triangle waveform. |
08 |
Testbit. Silences sound and resets the oscillator. |
10 |
Triangle waveform. |
20 |
Sawtooth waveform. |
40 |
Pulse waveform. |
80 |
Noise waveform. |
All waveforms except noise can be combined (for example triangle + pulse), but the effect will be different on 6581 and 8580 SID chips, so use with caution.
On many 6581 SID chips only 50 (triangle + pulse) will be audible. On 8580 it is usually safe to use all of the mixed waveforms: 30 (triangle + saw), 50 (triangle + pulse), 60 (saw + pulse).
The way how the channels work with synchronize/ringmod:
- When used on channel 1, channel 3's output modulates the sound.
- When used on channel 2, channel 1's output modulates the sound.
- When used on channel 3, channel 2's output modulates the sound.
Wavetable delay or no wavechange should not be used in the first step of instrument wavetable. Otherwise, missing notes may be caused. On the other hand, if you use 8XY command to jump into a wavetable program, those are allowed.
Using wavetable delay or a wavetable step with no frequency change allows realtime commands & instrument vibrato to be executed together with wave-table. Be warned that this has the potential for large rastertime usage!
You can execute pattern commands from the wavetable. Right side is the command parameter. Note that commands 0XY (do nothing), 8XY (set wavetable pointer) and EXY (funktempo) are illegal and should not be used. When executing a command, no wave/note will be changed on the same frame.
Some examples of wave tables (all examples start on table step 1):
01: 21 00 02: FF 00 |
Sawtooth waveform on note's original pitch. |
01: 41 00 02: 11 00 03: FF 00 |
A flute sound with pulse on the first tick and triangle on all the rest. |
01: 41 01 02: 40 00 03: FF 00 |
A "koto" sound that is one halfstep higher on the first tick and on original pitch the next. Gatebit is also cleared on the second tick. |
01: 81 D0 02: 41 AA 03: 41 A4 04: 80 D4 05: 80 D1 06: FF 00 |
A snaredrum sound, using all absolute notes so it does not depend on which note it's played. Use pulsewidth 800 for best result. |
01: 81 DF 02: 41 00 03: FF 00 |
A pulse sound on original pitch, preceded with a short noise (like a hi-hat or something) that has always an absolute pitch of B-7. |
01: 41 00 02: 00 04 03: 00 07 04: 00 0C 05: 00 00 06: FF 02 |
A 4-note looping arpeggio sound with pulse waveform. Note that waveform does not change in the looping part. |
01: 21 00 02: 02 03 03: 02 07 04: 02 00 05: FF 02 |
A delayed minor chord arpeggio with sawtooth waveform. Each step takes 3 ticks. |
01: 41 00 02: 03 80 03: 11 80 04: 03 80 05: 41 80 06: FF 02 |
Use pulse first, but then switch between pulse & triangle every 5 ticks while frequency remains unchanged (allowing for vibrato & slides). |
01: 81 CF 02: 21 00 03: 08 00 04: F6 2A 05: FF 00 |
Short noise in the beginning, sawtooth, after a short delay change sustain/release (via pattern command 6XY) to $2A. |
Pulsetable
Pulsetable left side:
01-7F |
Pulse modulation step. Left side indicates time and right side the speed (signed 8-bit value). |
8X-FX |
Set pulse width. X is the high 4 bits, right side tells the 8 low bits. |
FF |
Jump. Right side tells position ($00 = stop). |
Some examples of pulse tables (all examples start on table step 1):
01: 88 00 02: FF 00 |
01: Set pulse value $800 (middle) 02: Stop pulse execution |
01: 80 10 02: 20 40 03: 40 E0 04: 40 20 05: FF 03 |
01: Set pulse value $010 (very thin) 02: For 32 ticks, increase pulse with speed $0040 (64) 03: For 64 ticks, decrease pulse with speed $FFE0 (-32) 04: For 64 ticks, increase pulse with speed $0020 (32) 05: Jump back to step 03 for a nice loop |
Filtertable
Filtertable left side:
00 |
Set cutoff, indicated by right side. |
01-7F |
Filter modulation step. Left side indicates time and right side the speed (signed 8-bit value). |
80-F0 |
Set filter parameters. Left side high nybble tells the passband ($90 = lowpass, $A0 = bandpass etc.) and right side tells resonance/channel bitmask, as in command BXY. |
FF |
Jump. Right side tells position ($00 = stop). |
If "Set filter parameters" is followed by "Set cutoff" directly below, both will be executed on the same frame.
Some examples of filter tables (all examples start on table step 1):
01: 90 F1 02: 00 40 03: FF 00 |
01: Set lowpass, resonance F, channel bitmask 1 (filter channel 1 only) 02: Set cutoff to $40 03: Stop filter execution |
01: 80 00 02: FF 00 |
01: No passband selected, resonance 0, bitmask 0 (no filtered channels) 02: Stop filter execution |
01: A0 87 02: 00 00 03: 7F 01 04: 7F 01 05: 7F FF 06: 7F FF 07: FF 03 |
01: Set bandpass, resonance 8, channel bitmask 7 (filter all channels) 02: Set cutoff to $00 03: Increase cutoff with speed $01 for 127 ticks 04: Continue cutoff increase 05: Then decrease back to starting position (speed $FF = -1) 06: ... 07: ...and loop back to step 03 |
01: C0 F2 02: 00 F0 03: 90 F2 04: 00 50 05: FF 00 |
01: Set highpass, resonance F, channel bitmask 2 (filter channel 2) 02: Set cutoff to $F0 03: On the next frame, change to lowpass... 04: ...and set cutoff $50 05: Stop filter execution |
Note that the second example could also be achieved simply with pattern command B00 (set filter control, and stop filter execution, because parameter was $00).
Speedtable
The speedtable is shared by vibrato, portamento and funktempo. No jump commands exist.
| For vibrato: | XX YY |
Left side tells how long until vibrato direction changes (speed), right side is the value added to pitch each tick (depth). |
|---|---|---|
| For portamento: | XX YY |
A 16-bit value added to pitch each tick. Left side is the MSB and the right side the LSB. |
| For funktempo: | XX YY |
Two 8-bit tempo values that are alternated on each pattern row, starting from the left side. |
For both vibrato and portamento, if XX has the high bit ($80) set, note independent vibrato depth / portamento speed calculation is enabled, and YY specifies the divisor (higher value -> lower result and more rastertime taken).
Vibrato examples:
01: 03 40 |
Vibrato with speed $03 and depth $40. Corresponds to old vibrato parameter $34 |
01: 05 04 |
Speed $05 and depth $04. Slow shallow vibrato, suitable for bass notes. Not possible to achieve with old parameters. |
01: 83 04 |
Speed $03, note-independent depth enabled, depth divisor 4 right-shifts (division by 16). |
Portamento examples:
01: 00 20 |
Portamento with speed $0020, corresponds to old parameter $08 (4 * $08 = $0020). |
01: 01 00 |
Portamento with speed $0100, corresponds to old parameter $40 (4 * $40 = $0100). |
01: 4F FF |
Portamento with speed $4fff, loops the pitch highbyte very fast so that a SEUCK-like "space" effect is heard. Not possible to achieve with old parameters. |
01: 80 01 |
Note-independent speed enabled, speed divisor 1 rightshift (division by 2). |
Funktempo examples:
01: 09 06 |
Play tempo $09 on even pattern steps and $06 on odd steps, corresponds to old parameter $96. |
01: 24 18 |
The same funktempo adjusted for 4x-multispeed. Not possible to achieve with old parameters. |
Note that you can enter old style vibrato parameters, portamento speeds and funktempo to patterns & instruments, and when cursor is over the parameter, press SHIFT+RETURN to create a new speedtable entry corresponding to that parameter. The parameter will now be overwritten by a speedtable pointer.
Playback details
Each pattern row is divided into as many 50Hz/60Hz "ticks" as the tempo indicates. Some ticks are reserved for special actions, and to conserve rastertime, certain realtime effects/commands (pulse, vibrato, portamento) are skipped at the same time. Let's assume a tempo of 6 and gateoff timer value 2 and look at what happens on each tick:
| Tick: | Actions: |
|---|---|
0 |
|
1 |
|
2,3 |
|
4 |
|
5 |
|
Filtertable is executed on each tick regardless of what the channels are doing. Wavetable is never skipped, so arpeggios/drumsounds should always play OK.
With the commandline parameter /O0 (or by clicking the "PO" text on the statusbar) you can disable pulse skipping. This leads to increased rastertime use but can be good for example with tempo 3 tunes.
Likewise, with the commandline parameter /R0 (or by clicking the "RO" text on the status bar) you can disable realtime pattern command skipping on tick 0.
Miscellaneous tips
- Patterns will take less memory the less there are command changes. When the song is packed/relocated, for example a long vibrato or portamento command needs to be stored only once as long as the parameter stays the same on subsequent pattern rows.
- Using instrument vibrato can make 4XY commands unnecessary and save even more memory. Use realtime calculated note-independent speed (see speedtable section) if you want the vibrato to have the same magnitude regardless of the note.
- In the instrument parameters, there is no option to stop pulse execution directly. So if you have for example a sawtooth instrument, there might be an "unnecessary" pulsemodulation going on underneath and wasting rastertime.
There are two ways you can stop this:
- Make a short pulseprogram like this and use it in the instrument:
01: 80 00
Set pulse $00002: FF 00
Stop pulse execution - Use pattern command 900 to stop pulse execution
- Make a short pulseprogram like this and use it in the instrument:
- If you have a realtime command (vibrato/portamento), you can put "one-shot" commands 5XY-FXY inbetween and the realtime command will be unaffected.
An example:
C-4 01000 --- 00401 Begin vibrato with speedtable index $01 --- 00401 --- 00401 --- 0065A Set sustain/release to $5A. Vibrato executes also on this step! --- 00401 Continue vibrato normally --- 00401
However, the vibrato would stop immediately if command 0 was encountered. - Normally tempo 3 is the fastest you can use. However, by using the funktempo command you can get tempo 2. To do this, create a following speedtable entry: 02 02, and point your funktempo command to it. You also need to use gateoff timer 1 in all instruments and disable the pulse-optimization skipping.
- For very optimized songdata & player you can refrain from using any pattern commands and rely on the instruments' step-programming. Even in this case, you can set song startup default tempo with the Attack/Decay parameter of the last instrument (63), if you otherwise leave this instrument unused.
Limit-based modulation steps
You can enter pulse/filter modulation steps in limit-based format, and convert them to time-based with SHIFT+L. For example, you could enter the following in the pulsetable:
01: 84 00 Set initial pulse to $400 02: C0 10 Modulate pulse to $C00 with speed $0010 03: 40 10 Modulate pulse back to $400 with speed $0010
Now position the cursor on step 02 and press SHIFT+L twice, to convert both of the modulation steps to usual time-based steps. If necessary, the steps will be expanded to several (if the resulting time parameter is over $7F).
Remember that the player only understands time-based steps and you always have to convert limit-based steps before they play correctly!
Precalculated note-independent "hifi player" portamento/vibrato
From v2.62 onwards, GoatTracker actually supports realtime calculated note independent portamento and vibrato speeds, see speedtable section for this. However, this makes the player bigger and much slower. You can still also use the old method of manually precalculating needed note-independent speeds with the SHIFT+H function, which this section is about.
The idea is to take the frequency difference between 2 adjacent notes in the frequency table and manipulate it by bit shifting left (multiply) or right (divide).
To use, you need a portamento or vibrato command in the pattern, and the note you wish to base the calculation on on the current pattern step or before it (before it only for toneportamento) The amount of shift is determined by the command parameter. A number in the left nybble means shift left and right nybble right shift. When you press Shift+H while the cursor is on the command, a speedtable entry is created, and the parameter is replaced with a speedtable index.
Some examples:
C-3 00110 |
Take the frequency difference between C-3 & C#3 and shift it left 1 times (multiply by 2.) |
E-4 00000 |
Take the frequency difference between E-4 & F-4 and shift it right 2 times (divide by 4.) |
Multispeed tips
- When making multispeed songs, remember to multiply your tempos and also the gateoff timer values! For example, gateoff timer is normally 2, but in a 2X- speed tune the same gateoff length would be achieved with value 4.
- If you want to keep vibrato the same compared to 1X-speed, you must multiply vibrato speed by the speed multiplier, and divide vibrato depth by the multiplier. Remember also to divide portamento and pulse/filter modulation speeds as necessary.
- When importing a v1.xx multispeed song, you also need to multiply the gateoff timers.
- In the instruments, using Attack 0 might result in a very silent first row of the wavetable. You could try increasing the attack, or adding one or more rows of E9 00 (testbit+gate) to the beginning of the wavetable.
Using the songs outside the editor
Press F9 in the editor to enter the packer/relocator. Choose playroutine options, startaddress, zeropage address (need 2 consecutive locations) and file format (PRG/BIN/SID), then type the filename.
If you use patterns longer than 64 rows, there is the possibility that relocation fails because of too complex patterns. Each pattern row can be 0-4 bytes packed, and the total amount of bytes per one pattern may not exceed 256.
#If wave/pulse/filtertables overflow past row 255 without a jump command or there are other serious errors, you get a warning screen and have to fix the error.
Look at /examples/example1.prg - example4.prg to get an idea how much these playroutines take rastertime. No promises!
The basic functions independent of playroutine options are:
Init music:
LDA #subtunenumber ;Starting from 0
JSR startaddress
Play one frame of music:
JSR startaddress+3
Playroutine options
BUFFERED SID-WRITES - Instead of writing each SID value as soon as possible, waits for the end of the channel's execution on each frame and then writes the registers in one go. Improves sound stability but takes more memory & raster- time.
SOUND EFFECT SUPPORT - Adds a sound effect engine for use in games. Implies buffered writes. To use, call in the following way:
LDA #<effect ;Start address of sound effect data
LDY #>effect
LDX #channel ;0, 7 or 14 for channels 1-3
JSR startaddress+6
The sound effects have a hardcoded priority system based on their start addresses. A sound higher up in memory (bigger address) will never be interrupted with a sound lower in memory.
VOLUME CHANGE SUPPORT - Adds a routine in the player's jumptable to change the master volume level. To use, call in the following way:
LDA #volume ;0-15
JSR startaddress+6 ;(startaddress+9 with sound effect support)
Note that the master volume command (DXY) also modifies this same location, so it will clash if you also change the volume manually.
STORE AUTHOR-INFO - Writes the "AUTHOR" string from songname editor to the location range (startaddress+$20 - startaddress+$3F). Also enables timing mark support. A timing mark is a mastervolume command (DXY) with parameter $10-$FF. This parameter will be copied into startaddress+$3F when the command is encountered in playback.
USE ZEROPAGE GHOSTREGS - Instead of writing to the SID, a memory range in the zeropage is used for holding the SID register data. This can then be copied in the main program to the SID, for example to enable the playroutine & music data to reside under the I/O area. Implies buffered writes. A reverse copy loop should be used after each call to the playroutine:
LDX #$18
copy: LDA ghostregs,x
STA $D400,x
DEX
BPL copy
The copy loop can also be unrolled for more speed.
Note that when you use the alternative hardrestart method & playroutine (hard- restart attack parameter F) the copy loop should not be in reverse order but should be for each channel: wave, frequency, pulsewidth, and ADSR last.
If you are using both sound effect support and ghostregisters, there exists a possibility of sound errors in the case that a sound effect has finished, and the same channel starts a new pulse-waveform note without setting an initial pulsewidth value (for example, like in the beginning of Sanxion loader tune). This is because the ghostregisters are shared between music & sound effect playback, and the sound effect has already overwritten the previous pulse width.
DISABLE OPTIMIZATIONS - The relocator removes saved playroutine code based on what effects & commands the song uses, resulting in a smaller playroutine accordingly. If you encounter anomalies in the sound (such as ADSR bugs caused by unpredictable timing variation) you can try disabling the optimizations. Normally this is not necessary, but is included just in case.
FULL BUFFERING - in some cases, especially with multispeeds, the "standard" or per-channel buffering is not enough and will still produce ADSR errors. This enables a functionality similar to the ZP ghost regs, where the previous frame's SID data is copied to the SID at the beginning of the play call for maximum stability. Will use more rastertime and imply the same problems with sound effect playback as the ZP ghost regs, so use only when necessary.