pygame.mixer.music.play() 无法识别 Fast Tracker(.xm 音乐格式)重复位置

pygame.mixer.music.play() doesn't recognize Fast Tracker (.xm music format) repeat position

问题是:

我尝试无限循环播放 Fast Tracker 模块,但这样做只是从头开始重播音乐,而不是跟随重复位置。

示例: (这里是模块 https://api.modarchive.org/downloads.php?moduleid=153915#zeta_force_level_2.xm 的来源)

import pygame

pygame.mixer.init()
pygame.mixer.music.load('/path/to/zeta_force_level_2.xm')
pygame.mixer.music.play(-1)

我要实现的目标: 循环播放模块音乐,每次都在重复位置而不是曲目开始处循环。使用 pygame 不是必需的:我使用它是因为我没有找到任何适合播放跟踪器音乐的东西

提前致谢。

更新:我用 cython 写了一个简单的演示,成功播放了链接的 .xm 文件。它基本上是 this c demo code. My code for it can be found on this github page 的 t运行 版本。为了让它在 Ubuntu 中工作,我必须安装 libxmp-dev 包。请注意,目前所有内容都是硬编码的,因此需要重构才能更直接地在您的项目中使用。


这绝不是一个决定性的答案。我 运行 遇到了许多潜在的陷阱,这让我怀疑 pygame 是否适合这里的工作,但我将介绍到目前为止我发现的内容以及一些建议。

看起来 .xm Fast Tracker MODule 格式与典型的 wav/ogg/mp3 文件不同之处在于它不仅仅是播放一组样本数据,您可以将不同的 MIDI 乐器和样本组合在一起来创作音乐,例如问题中链接的(甜蜜的)芯片音乐。

事实证明 SDL/pygame 可以播放此类文件,但方式相当有限。查看pygame的music module, there is a set_pos function. However, trying to use that gave me a pygame.error: set_pos unsupported for this codec. Interestingly however, I was able to work around this by using pygame.mixer.music.play with the optional start keyword. While start on most file formats is simply the offset in seconds before starting the file (only on the first playthrough of the song), it has a different meaning for MOD files like the .xm file in the question. Apparently,它对应MOD文件中的一个pattern号。因此,根据每个模式在文件中的起始位置,pygame 中可以使用的潜在起始点数量非常有限。

如果您心中有一个特定的模式编号,那么下面的代码就足以循环。请注意,我使用 pygame 的事件系统来查看声音何时完成到 "loop" 具有适当 "pattern offset":

的声音文件
import pygame

pygame.init()
pygame.mixer.music.load('zeta_force_level_2.xm')
pattern = 10
loop_event = pygame.USEREVENT + 1
pygame.mixer.music.set_endevent(loop_event)
pygame.mixer.music.play(start=pattern)

while True:
    for event in pygame.event.get():
        if event.type == loop_event:
            pygame.mixer.music.play(start=pattern)

此时,您可能想知道这些 patterns 到底是什么?如果您的系统上安装了 ffmpeg,您可以 运行 ffprobe 在您的文件上并获得以下输出:

Input #0, libmodplug, from 'zeta_force_level_2.xm':
  Metadata:
    name            : zeta force level 2
    instrument      : by zabutom --
                    : bye bye computer..
                    : see you in a week
    sample          : zeta force level 2
    extra info      : 20 patterns, 10 channels, 3/14 instruments, 1/14 sample
  Duration: 00:01:01.00, bitrate: 3 kb/s
    Stream #0:0: Audio: pcm_s16le, 44100 Hz, 2 channels, s16, 1411 kb/s

该文件中似乎有 20 个模式,您可以从中选择作为循环的起始位置。要获取有关您的特定文件的更多信息,您可以在 MilkyTracker 等工具中打开(并编辑!)您的文件并获得如下输出:

youtube 上有一些关于 MilkyTracker 的在线教程,但它看起来是一个相当复杂的软件。

似乎还有一个名为 libxmp and its corresponding python binding 的图书馆。这应该处理将 "render" MOD 文件数据转换为简单的 PCM 数组,该数组可以在 pyaudio 或任何 python 绑定到 OpenAL 的库中播放。无论哪种方式,看起来您的工作都已完成!