with a pattern length of 48 with each beat being 4 lines
set the speeds both to 2: 09-02, and 0F-02 to align with 8th note quarter notes
Monday, March 9, 2026
deflemask triplets in 12 lines instead of 8
deflemask triplets using speed commands
in 2 columns set 09 01 and 0f 01
then to reset back 09 03 0f 03
that lets you sequence like regular quarter notes across 8 lines
Thursday, March 5, 2026
Timing Systems in the History of Music Trackers
In the history of music trackers (especially on early computers like the Commodore 64 and Commodore Amiga), timing systems evolved because different hardware offered different ways to measure time. Terms like PPQN, CIA, VBlank, NTSC, PAL, and LPB refer to how trackers scheduled musical events such as notes and effects.
1. VBlank Timing (Early Trackers)
VBlank = Vertical Blank interrupt
Early trackers synchronized playback with the screen refresh interrupt.
- The video chip triggers an interrupt every frame.
- The music routine runs once per frame.
Frame rates depended on TV standards
- PAL: 50 Hz (50 interrupts per second)
- NTSC: ~60 Hz (59.94 interrupts per second)
These standards come from analog television systems used by machines like the Commodore 64 and early Amiga 500.
Effect on tracker timing
A tracker row advanced every N frames.
Example (classic Amiga trackers):
Speed = 6
PAL 50 Hz
Row duration:
6 frames / 50 Hz = 120 ms per row
Pros
- Simple
- Stable with graphics
Cons
- Different speed on PAL vs NTSC
- Limited timing resolution
This system was used in early trackers such as Soundtracker (1987).
2. CIA Timer Timing (Amiga Precision Timing)
The Commodore Amiga had CIA chips (Complex Interface Adapters) with programmable timers.
Later trackers used CIA Timer A instead of VBlank interrupts.
Why?
CIA timers allow arbitrary interrupt rates, independent of video refresh.
Example:
Timer frequency ≈ 709379 Hz / divider
This allowed:
- More precise BPM
- Same playback speed on PAL and NTSC
Trackers such as ProTracker used this technique.
Pros
- Hardware accurate timing
- Independent from video
- Higher precision
Cons
- Slight CPU overhead
- Required careful hardware programming
3. LPB (Lines Per Beat)
LPB = Lines Per Beat
This concept appeared in later trackers during the PC era.
Trackers such as FastTracker II and Impulse Tracker separated:
- tempo (BPM)
- pattern resolution
LPB defines how many rows equal one beat.
Example:
BPM = 125
LPB = 4
Meaning:
- 4 rows per beat
- 16 rows per bar (4/4)
This makes timing more musical and flexible.
4. PPQN (Pulses Per Quarter Note)
PPQN = Pulses Per Quarter Note
This timing concept comes from MIDI sequencing rather than trackers.
Common MIDI timing resolutions:
24 PPQN
96 PPQN
480 PPQN
960 PPQN
Higher PPQN values give finer timing resolution.
Later tracker-inspired software and modern trackers adopted similar high-resolution internal clocks.
Examples include modern trackers and DAWs such as Renoise and OpenMPT.
5. Relationship Between These Systems
| System | Used In | Resolution | Hardware Dependence |
|---|---|---|---|
| VBlank | early Amiga / C64 trackers | low | tied to video |
| PAL / NTSC | video standards | defines frame rate | hardware |
| CIA timer | later Amiga trackers | medium | hardware timer |
| LPB | PC trackers | high | software |
| PPQN | MIDI / DAWs | very high | software |
6. Typical Classic Tracker Timing Formula
For ProTracker-style trackers:
row_time = speed × tick_time
Where:
tick_time = 2.5 / BPM seconds
Example:
speed = 6
BPM = 125
Tick time:
2.5 / 125 = 0.02 s
Row time:
6 × 0.02 = 0.12 s
This produces the famous 125 BPM / speed 6 groove used in many Amiga modules.
7. Historical Timeline
1980s
- VBlank timing
- PAL/NTSC differences
- Soundtracker era
Early 1990s
- CIA timer timing
- ProTracker era
Mid 1990s
- PC trackers adopt BPM + speed system
Late 1990s
- LPB introduced
2000s+
- PPQN-style internal clocks
Summary
- PAL / NTSC → video refresh standards
- VBlank → music tick tied to screen frame
- CIA timer → programmable hardware timer interrupts
- LPB → musical resolution (rows per beat)
- PPQN → MIDI timing resolution
understaning clock speeds in sunvox and deflemask
deflemask default is ntsc basetime 1 = 150bpm
sunvox default is 125 6tpl
- to match deflemask to sunvox:
set to pal, increase basetime from 1 to 2
- to match sunvox to defle:
lower tpl from 6 to 3 and increase bpm to 150
for quarter note (8 lines) to be equivalent
sunvox at 6tpl is half the speed of deflemask pal basetime 1.
increasing basetime lowers the speed
while decreasing the tpl increases the speed
triplet tuplets in trackers
-
32 lines
half note triplet
00, 11, 21 -
16 lines
quarter note triplet
00, 05, 11 -
8 lines
eighth note triplet
00, 03, 05 -
4 lines
sixteenth note triplet
00, 01, 03 -
64 lines
1 bar triplet
00, 21, 43
1/16 note | 4 lines | 00 01 03
1/8 note | 8 lines | 00 03 05
1/4 note | 16 lines | 00 05 11
1/2 note | 32 lines | 00 11 21
1 bar | 64 lines | 00 21 43
Monday, March 2, 2026
converting long samples to 16bit 8000khz for deflemask using sox
for f in *.wav; do sox "$f" -r 8000 -e signed-integer -b 16 "${f%.wav}_16bit.wav"; done
Wednesday, February 25, 2026
.bashrc function to toggle function keys from being media keys to being regular fn keys on linux mint
fnkeys() {
FN="/sys/module/hid_apple/parameters/fnmode"
if [ ! -f "$FN" ]; then
echo "Fn control not available."
return 1
fi
current=$(cat "$FN")
if [ "$current" -eq 2 ]; then
sudo sh -c "echo 1 > $FN"
echo "Switched to media keys (fnmode=1)"
else
sudo sh -c "echo 2 > $FN"
echo "Switched to F1–F12 keys (fnmode=2)"
fi
}
Saturday, February 21, 2026
fasttracker2 on ipad
under:
- quickmenu
- core options
- general
force output fps set to 60 stopped the stuttering
Thursday, February 19, 2026
Tuesday, February 17, 2026
reaper midi looping custom action
combine these 7 actions into a macro you can trigger with a shortcut or add to a toolbar
- Transport: Record
- Take: Switch items to previous take
- Take: Crop to active take in items
- Track: Duplicate tracks
- Item: Select all items in track
- Item: Remove items
- Transport: Record
Monday, February 16, 2026
you can toggle between mt32 and soundfonts using sysex in mt32-pi
to find ports use aplaymidi or aconnect then use this as the info for the -p option
aplaymidi -l
-g to change to soundfont
mt32-pi-ctl -p 128:0 -g
-s to change --soundfont specify the number
mt32-pi-ctl -p 128:0 -s 1
-m to change to mt32
mt32-pi-ctl -p 128:0 -m
-b to change romset: old, new, cm32l
mt32-pi-ctl -p 128:0 -b cm32l
Saturday, February 14, 2026
making midis in reaper and playing them over udp
#!/usr/bin/env python3
import time
from socket import AF_INET, SOCK_DGRAM, socket
import mido
import threading
import signal
import sys
# MT32-Pi UDP target
UDP_HOST = "192.168.0.100"
UDP_PORT = 1999
sock = socket(AF_INET, SOCK_DGRAM)
# MIDI file path
midi_file = "/home/bweew/Desktop/midi_export.mid"
# Shared variable for dynamic CC91
dynamic_cc91 = [64] * 16 # default reverb level per channel
# Track currently sounding notes per channel
active_notes = {ch: set() for ch in range(16)}
def cc91_input():
global dynamic_cc91
while True:
try:
raw = input("Set CC91 (format: channel,value e.g., 0,80): ")
ch, val = map(int, raw.split(','))
if 0 <= ch < 16 and 0 <= val <= 127:
dynamic_cc91[ch] = val
sock.sendto(bytes([0xB0 | ch, 91, val]), (UDP_HOST, UDP_PORT))
except Exception:
print("Invalid input. Format: channel,value")
def send_note_offs():
for ch, notes in active_notes.items():
for note in notes:
sock.sendto(bytes([0x80 | ch, note, 0]), (UDP_HOST, UDP_PORT))
for ch in range(16):
sock.sendto(bytes([0xB0 | ch, 123, 0]), (UDP_HOST, UDP_PORT))
def signal_handler(sig, frame):
print("\nAborting playback, sending note-offs...")
send_note_offs()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
# start thread for dynamic CC91 input
threading.Thread(target=cc91_input, daemon=True).start()
print(f"Playing {midi_file} to {UDP_HOST}:{UDP_PORT}... (Ctrl-C to stop)")
while True:
mid = mido.MidiFile(midi_file)
active_notes = {ch: set() for ch in range(16)} # reset notes
for msg in mid:
time.sleep(msg.time)
if msg.type == 'note_on':
sock.sendto(bytes([0x90 | msg.channel, msg.note, msg.velocity]), (UDP_HOST, UDP_PORT))
if msg.velocity > 0:
active_notes[msg.channel].add(msg.note)
else:
active_notes[msg.channel].discard(msg.note)
elif msg.type == 'note_off':
sock.sendto(bytes([0x80 | msg.channel, msg.note, msg.velocity]), (UDP_HOST, UDP_PORT))
active_notes[msg.channel].discard(msg.note)
elif msg.type == 'program_change':
sock.sendto(bytes([0xC0 | msg.channel, msg.program]), (UDP_HOST, UDP_PORT))
elif msg.type == 'control_change':
val = dynamic_cc91[msg.channel] if msg.control == 91 else msg.value
sock.sendto(bytes([0xB0 | msg.channel, msg.control, val]), (UDP_HOST, UDP_PORT))
send_note_offs()
print("Looping playback...")
Friday, February 13, 2026
playing soundfonts on mt32-pi over udp
my udp.py
#in the config disabled dhcp and set fixed ip
cranked the gain from 0.2 to 0.8, disabled reverb and chorus
(you need to edit the .cfg files for individual soundfonts because those will overide the main config
didn't get rtp working but udp works pretty ok.
midi over wifi can sometimes be a bit wonky but the latency isnt bad.
was hoping to make use of my other midi keyboard in my closet but the notes would get stuck
#!/usr/bin/env python3
from signal import SIGINT, signal
from socket import AF_INET, SOCK_DGRAM, socket
from threading import Event
from rtmidi import MidiIn
UDP_HOST = "192.168.0.100"
UDP_PORT = 1999
MIDI_PORT_NAME = "mt32-pi UDP socket"
sock = socket(AF_INET, SOCK_DGRAM)
midiin = MidiIn()
midiin.open_virtual_port(MIDI_PORT_NAME)
signal(SIGINT, lambda *_: exit(1))
print(
f"Listening for MIDI on port '{MIDI_PORT_NAME}' and sending to"
f" {UDP_HOST}:{UDP_PORT} (Ctrl-C to exit)..."
)
midiin.ignore_types(False, False, False)
midiin.set_callback(lambda msg, _: sock.sendto(bytes(msg[0]), (UDP_HOST, UDP_PORT)))
Event().wait()
Sunday, February 8, 2026
fluidsynth for octamed
you can make midi templates for sunvox and fl studio also
here i use linux mint autostart to run the bash script
and run the render command
- path must be like /home/user/Desktop/ not
~/Desktop/
also drag and drop wont work
it will try to open in celluloid so you must type it out.
#fluidsynth from terminal
fluidsynth -is -p "FluidSynth-GS" -g 0.7 ~/Documents/sf2/GeneralUser-GS.sf2
#bash for autostart
#!/bin/bash
gnome-terminal -- bash -c 'fluidsynth -is -p "FluidSynth-GS" -g 0.7 ~/Documents/sf2/GeneralUser-GS.sf2; exec bash'
#rendering
read -e -p "MIDI file path: " f; f=${f%\"}; f=${f#\"}; fluidsynth -is -p "FluidSynth-GS" -g 0.7 -R 0 -C 0 -F ~/Desktop/"$(basename "$f" .mid)".wav ~/Documents/sf2/GeneralUser-GS.sf2 "$f"; echo "Rendered ~/Desktop/$(basename "$f" .mid).wav"
# using jack instead for cadence to record in audacity
#!/bin/bash
gnome-terminal -- bash -c 'fluidsynth -a jack -m alsa_seq -is -p "FluidSynth-GS" -g 0.7 ~/Documents/sf2/GeneralUser-GS.sf2; exec bash'
# optional monitoring to find port use jack_lsp
jack_connect "FluidSynth-GS:audio_L" "system:playback_1"
jack_connect "FluidSynth-GS:audio_R" "system:playback_2"
# jack and monitoring
#!/bin/bash
gnome-terminal -- bash -c '
fluidsynth -a jack -m alsa_seq -is -p "FluidSynth-GS" -g 0.7 ~/Documents/sf2/GeneralUser-GS.sf2 &
until jack_lsp | grep -q "fluidsynth:left"; do sleep 0.5; done
jack_connect fluidsynth:left system:playback_1
jack_connect fluidsynth:right system:playback_2
wait
exec bash'
Wednesday, February 4, 2026
Tuesday, February 3, 2026
samplerbox raspberry pi
program your own screenless rompler. write is disabled on the os making it safe for the sd to be undamaged by unplugging. (idk about the usb with the sounds though? I guess its fine as long as your not in the middle of transferring files)
defle distilled
made a cheatsheet for learning deflemask.
- distilled 53 pages down to 1 front and back.
Monday, February 2, 2026
deflemask
running deflemask on ipad with a logitech k480
the keyboard os modes matter bigtime!
the 2 modes: pc, i.
in I (ios mode)
- cmd h for home, cmd tab for switching apps
in pc mode
- fn left / right = home / end
- fn up / down = pgup pgdown
turn off follow
in the right panel so you can use f7 to play from line
otherwise it keeps going. ESSENTIAL!
- ctrl 123456789 mute channels
- ctrl left / right switch tracks
- ctrl w/e shrink expand
- ctr b = paste and mix (ctrl v is regular paste)
- switching octave is done on screen because /* is numpad only
- note off is tab
- interpolate = ctrl i
- transposing = ctrl f1/f2,f3/f4
work from the top
instead of working from 0-64 top down work horizontally in 16 line chunks to make use of the f5 playback and f7 playbacks for the best of both worlds. copy and paste each 1/4 pattern horizontally and ctrl 123456789 to mute the previous until you complete all four quarters of a pattern to re assemble them.