.XM

来自音MAD维基
这是一个文件格式介绍页面
library_books
本站收录音MAD相关的各种术语,欢迎您进行补充。

XM即“扩展模块”(Extended Module),是FastTracker 2的一种模块音乐格式。

编辑与播放

XM文件可以使用OpenMPT进行编辑与播放。安卓系统上可以使用Xmp Mod Player进行播放。

文件结构

以下内容参考了MilkyTracker的文档[1]和OpenMPT的相关代码[2],并根据实际情况进行了修正。

总体结构

一个XM文件通常为以下结构:

  • XM文件头
    • "Extended Module: " 0x1a 模块名称 Tracker名称 XM版本号 文件头长度
    • Channel总数 Pattern总数 Instrument总数 频率表类型 默认BPM 默认Tempo Pattern顺序
  • 各Pattern
    • 头部长度 压缩类型 行数
    • (压缩过的)音符数据
  • 各Instrument
    • 头部信息
      • 头部长度 名称 类型 Sample总数
      • (若Sample总数大于0则有额外头部数据)
    • 各Sample的头部信息
      • 头部长度 循环起点 循环终点 音量 音调微调 类型 声像 相关音符编号 保留位 名称
    • 各Sample的采样数据(使用了差分编码)

音符数据

各Pattern的音符数据按照各Channel从左到右再按各行从上至下存放(含空音符)。下表给出了一个音符的各项属性:

大小 数据类型 属性名称
1 Byte 音符(1~96对应C1~B8,97为终止符,0为空音符)
1 Byte 使用的Instrument编号(1~128,注意是从1开始)
1 Byte 音量(可以为音量效果)
1 Byte 效果类型
1 Byte 效果参数

在多数情况下,音符数据会进行压缩以减小文件体积。下面是一段读取一个音符的伪代码[3]

    dbyt = getbyte();
    if (dbyt AND 0x80) {
        if (dbyt AND 0x01) c_note = getbyte();
        if (dbyt AND 0x02) c_inst = getbyte();
        if (dbyt AND 0x04) c_vol = getbyte();
        if (dbyt AND 0x08) c_effect = getbyte();
        if (dbyt AND 0x10) c_param = getbyte();
    } else {
        c_note = dbyt;
        current_row++;
    }

采样数据

采样数据使用了差分编码以在压缩时(如使用pkzip)获得更高压缩比。采样每个点的值的数据类型由Sample类型决定,0~3为 char 类型,4为 signed int 类型。下面是一段读取采样数据的伪代码[4]

    signed byte old, new;
    old = 0;
    for i = 0 to data_len {
        new = sample[i] + old;
        sample[i] = new;
        old = new;
    }

下面是使用Python 3实现的一段代码:

class XMSample:
    def doParseSampleFromBytes(self, data):
        self.sample = list(data)
        typeMax = 0x80
        if self.type == 4: # 16-bit signed int
            typeMax *= 0x100
        old = 0
        for i in range(self.length):
            old = self.sample[i] = (self.sample[i] + old + typeMax) % (typeMax * 2) - typeMax