Skip to content

Cyletix/automakeosufile

Repository files navigation

AUTO MAKE OSU FILE

当前仓库正在做一次主流程收口。

当前推荐入口

  • main.py:新的薄入口,默认走单曲检查流程
  • automakeosufile/tools/inspect_sample.py:检查一首 osu!mania 样本的音频、谱面和基础特征

当前推荐主流程目录

  • automakeosufile/dataset/:歌曲与谱面索引
  • automakeosufile/parsers/.osu 解析
  • automakeosufile/features/:统一特征提取
  • automakeosufile/evaluation/:指标计算与特征叠绘图
  • automakeosufile/tools/:调试与检查工具

当前推荐的单曲质检命令

python -m automakeosufile.tools.inspect_sample --osu "D:\osu!\Songs\...\sample.osu"

这条命令会输出:

  • Onset 对齐指标(Precision / Recall / F1)
  • GT Note 的节拍网格吸附误差
  • Lane 分布、和弦规模、Hold 比例与时长指标
  • onset_overlay.png(固定 10 秒一段的纵向长图)
  • chroma_overlay.png(固定 10 秒一段的纵向长图)
  • click_track_gt.wav
  • click_track_pred.wav
  • metrics.json

高密度歌曲推荐参数

对于 Aragami 这类高密度样本,可以直接加:

python -m automakeosufile.tools.inspect_sample --osu "D:\osu!\Songs\...\sample.osu" --dense-onset

默认输出目录统一为:

  • output/inspect/:单曲质检图、点击音轨与 metrics.json
  • output/optimize/:自动调参结果
  • output/beatmaps/current/:当前默认生成的 .osu 谱面
  • output/beatmaps/archive/:历史测试谱面归档

当前内置的高密度 preset 会:

  • 把 onset 聚合从 median 改为 mean
  • 降低 delta
  • 缩小 peak-picking 窗口

在当前 Aragami 样本上,这一预设把 onset F1 从约 0.305 提升到了约 0.502

旧代码状态

  • 根目录和 algorithm/fileprocess/密度修正专项/ 下保留了大量历史实验脚本
  • 这些文件暂时不删除,但不再视为主流程入口
  • fileprocess/osu_file_parse.pyfileprocess/osu_file_make.py 已明确退役,避免继续和新主流程混用
  • 整理目标是逐步把可保留能力迁移进 automakeosufile/ 新骨架

osu自动做谱程序, 对音频文件进行分析后, 自动生成铺面, 由于谱面的数据可以分为时间维度和轨道维度, 我们可以用时频变换得到的频谱图与之对应, 广义来说, 一个频谱图就可以对应一个osu谱面, 只不过想要得到具有可玩性的谱面需要额外一些处理. 整个流程大致分为4步

  1. 对MP3音频文件先转为WAV格式
  2. 进行时频变换
  3. 对变换结果进行处理
  4. 根据官网给的osu谱面格式制作.osu谱面文件

preview

preview


1.转为WAV格式

比较简单, 对应代码在 mp3_to_wav.py

2.时频变换

可选的方法如下:

  • 直接进行STFT得到spectrogram, 保留最全的信息
  • 转换为DB的spectrogram, 仍然没有信息损失,或许会方便DB筛选
  • mel power spectrogram
  • Constant-Q Transform(CQT)
  • Chroma_CQT 损失部分信息, 但可以看到转换成八度后的频谱, 类似钢琴谱

说实话我没有完全搞明白它们之间的关系, 也没有想好用哪个, 但是目前看来chroma稍微方便点

3.结果处理

由步骤2得到的数据通常是很复杂的频谱图, 还不能直接用, 我选择先对chroma频谱做二值化

接下来还没有完成, 我的想法是想办法对二值化后的数据降维, 这个降维应该是两个维度的:

  • 对于轨道维度, 应该降维成想玩的k数, 比如想得到6k谱就从chroma的八度谱共12个音符降到6个轨道
  • 对于时间维度, 由于音频成分复杂, 得到的谱面密度很高, 其中一些是无效的音, 可以尝试用能量密度来判断这个音是否有效, 具体方法我还没想好

4.写入osu文件

处理步骤在 osu_file_make.py中, 具体规则可以参考osu官网

OSU 谱面结构

x,y,time,type,hitSound,addition

- x: note的横向位置,范围为0~512,其中0表示最左侧,512表示最右侧。 - y: note的纵向位置,范围为0~192,其中0表示最上方,192表示最下方。 - time: note的出现时间,以毫秒为单位,表示自谱面开始时间点的偏移量。 - type: note的类型,表示该note需要击打的方式。该参数是一个二进制数,其中1表示需要击打,0表示不需要击打。四种类型分别对应二进制数的四个位数,分别为:1、2、4、8。例如,如果type值为6,则表示该note需要使用键盘上的2和3键击打。 - hitSound: note的击打声音,表示播放的音效文件。该参数是一个二进制数,其中1表示需要播放,0表示不需要播放。四种声音分别对应二进制数的四个位数,分别为:1、2、4、8。例如,如果hitSound值为3,则表示播放第一个和第二个声音文件。 - addition: 额外参数,表示note的其他属性,如颜色、表现等。该参数的具体含义取决于谱面文件的作者和编辑器。

关于BPM

bpm_calculate.py 这个文件主要用于计算bpm, 第一个和最后一个note的时间

为什么要计算这些? 当然是为了给对音做个参考, 不过如果能够完全从频谱图中抽象出这些对音的时间戳且精度不错的话, 这个步骤就不用了

对音频做完时频变换后得到的时间戳单位unit是ms

一拍的间隔=bpm/60*1000, 则x分音的公式如下:

cent4_interval=bpm/60*1000/4

cent8_interval=bpm/60*1000/8

cent16_interval=bpm/60*1000/16

cent32_interval=bpm/60*1000/16

我测试了一下, 龙少女BPM=164的情况下, 16分音的间隔是88ms, 根据以上公式验证结果, 差不多正确

在高难的音游曲目中,每分钟的BPM可以超过180,有些高难曲目的BPM甚至在200到300以上

以BPM为300为例,计算16分音符的时间间隔:

时间间隔 = (1 / (300 / 60)) * 0.25 * 1000 ≈ 50 毫秒

运行环境

由于cv2目前不支持python11, 所以用python10比较稳

现在好像没用到cv2, 应该没有啥限制

生成代码输出

& pwsh -NoProfile -ExecutionPolicy Bypass -File "docs\export_outputcode_utf8.ps1"

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors