Renoise version tested: 3.5.4 (macOS)
Component: Impulse Tracker (.it) file import
Severity: Medium — silent data corruption on import (wrong playback + wrong pattern data)
Summary
When Renoise imports an .it module, set-volume values in the IT volume column are
imported correctly, and volume-column slide commands are silently dropped — but volume-column
set-panning, tone-portamento (Gx), and vibrato (Hx) are imported as meaningless
volume-column slide commands. The value written is a raw-byte artifact that is unrelated to
the original command, so the song plays incorrectly and the pattern data is corrupted on those
cells.
IT volume-column commands and how each is imported
The IT volume column stores one command per cell as a single byte (per the IT format spec):
| IT volume-column command | byte range | Renoise 3.5.4 import |
|---|---|---|
| set volume | 0–64 | |
fine volume slide up/down (a/b) |
65–84 | |
volume slide up/down (c/d) |
85–104 | |
pitch slide down/up (e/f) |
105–124 | |
set panning (p) |
128–192 | |
tone portamento (Gx) |
193–202 | |
vibrato (Hx) |
203–212 |
Actual behavior
For the corrupted ranges, Renoise writes a volume-column command (shown/saved as Ixx/Oxx)
whose value is independent of which effect it was. The value is exactly:
renoise_volume_value = (raw_IT_volume_column_byte − 159) mod 32
i.e. the raw IT byte is passed straight through without being decoded. The tell-tale sign is
that tone-portamento and vibrato — two completely unrelated effects — produce one continuous
value sequence as the underlying byte increments:
| IT vol-col command | raw byte | Renoise <Volume> (saved .xrns) |
|---|---|---|
G0 tone-portamento |
193 | I2 |
G9 |
202 | IB |
H0 vibrato |
203 | IC |
H9 |
212 | O5 |
p set-pan, byte 160 |
160 | I1 |
p set-pan, byte 192 |
192 | I1 (wraps mod 32) |
p set-pan, bytes 128–159 |
128–159 | (dropped, empty) |
The continuous byte→value mapping regardless of command meaning indicates the IT volume-column
byte is being copied into Renoise’s volume column for these byte ranges instead of being
decoded into the corresponding command.
Expected behavior
- Volume-column set-panning (
p) → the note’s panning column. - Volume-column tone-portamento (
Gx) / vibrato (Hx) → the corresponding effect-column
command (Renoise’s glide0G/ vibrato0V), since Renoise’s volume column has no native
representation for them.
(At minimum, these should never produce values unrelated to the source command.)
Steps to reproduce
- Open an
.itmodule that uses the volume column for panning, tone-portamento, or
vibrato. A minimal purpose-built test module is available:voltest.it— 98 rows, one IT
volume-column command per row, sweeping every command (set-vol,a/b/c/d/e/f
slides, pan, porta, vibrato) across its parameter range, each on a held note so the result is
isolated per row. - In Renoise: File → Open →
voltest.it. - Inspect the volume column of rows ~60–88 in the pattern editor (or Save Song As
.xrns
and inspect the<Volume>entries inSong.xml).
Rows 0–59 (the slide commands) come in empty; rows 60–88 (pan/porta/vibrato) come in as the
incorrect I/O values described above; rows 89–97 (set-volume) are correct.
Impact
- Panning, tone-portamento, and vibrato authored in the IT volume column are lost and replaced
with incorrect volume slides → audible playback differences and corrupted pattern data, with
no warning to the user. - Affects both classic Impulse Tracker
.itfiles and OpenMPT/ModPlug-saved.itfiles, since the issue is inherent to decoding the IT volume-column format.
Notes
The set-volume and slide handling are fine (the latter merely unsupported/dropped, which is at
least not wrong). Only the pan/portamento/vibrato volume-column ranges are corrupted.