Skip to content

关于MCM导出/导入maidata时,某个33.33ms的延迟的问题。 #40

@Starrah

Description

@Starrah

导出时

当把歌曲导出为maidata时,在MusicTransferController.ExportAsMaidata中,回为导出的maidata.txt设置一个固定的&first=0.0333的延迟:

var simaiFile = new StringBuilder();
simaiFile.AppendLine($"&title={music.Name}");
simaiFile.AppendLine($"&artist={music.Artist}");
simaiFile.AppendLine($"&wholebpm={music.Bpm}");
simaiFile.AppendLine("&first=0.0333");

我听说的说法是(我不知道这种说法对不对),这是因为majdataplay内置2帧延迟;所以如果一首歌是按照HDD里的acb对音是准确的话,那对应到majdataplay里就要加上这个0.0333的修正。

导入时

先说结论:导入时,并不会减去这个0.0333s的延迟。而是按照谱面中实际声明的&first=值进行音频裁剪。

这行代码事实上并不生效?

注:这是导入过程中,唯一一处与0.0333有关的代码。
该代码此前仅在ImportChart正式导入的过程中存在。其他的地方,如ImportChartCheck中等处,都是找不到这样的-0.033代码的。
后来009d965中被我原样重构移动到MaidataImportService里去,我可以保证我重构的等价性,下面所说的问题不是我重构引入的,而是此前一直存在的。

尽管看起来ImportChartController.ImportChart里是有这样的代码的,第247行看起来是在抵消上面说的那个0.033:

float.TryParse(maiData.GetValueOrDefault("first"), out var first);
// Mai 的歌曲是从两帧后开始播放的
first -= 1 / 30f;
var paddings = allCharts.Values.Select(chart => CalcMusicPadding(chart.simaiSharpChart, first)).ToList();
// 音频前面被增加了多少
var audioPadding = paddings.Max(); // bar - firstTiming = bar - 谱面前面休止符的时间 - &first
var shouldAddBar = false;
float chartPadding;
switch (shift)
{
case ShiftMethod.Legacy:
chartPadding = audioPadding + first;
break;
case ShiftMethod.Bar when audioPadding + first > 0.1:
shouldAddBar = true;
chartPadding = 0f;
break;
default:
chartPadding = 0f;
break;
}

然而,进一步分析可以发现:245行定义局部变量并在247行减去0.033后,它的用法只有三处:249、257、259行。

  1. 249行是CalcMusicPadding(chart.simaiSharpChart, first)

    public static float CalcMusicPadding(MaiChart chart, float first)
    {
    // TimingChanges 对应的是所有的 {int}
    var bpm = chart.TimingChanges[0].tempo;
    // 一小节多长
    var bar = 60 / bpm * 4;
    // 第一押什么时候出来
    var firstTiming = chart.NoteCollections[0].time + first;
    return bar - firstTiming;
    }

    注意到这个audioPadding变量的计算结果是bar - chart.NoteCollections[0].time - first。(注意这里所说的first是已经被247行减法后的值,它和下面两行使用的值是相等的)

  2. 257、259行在使用first时,无论是用于计算chartPadding还是用于比较,都是audioPadding + first这样使用的。
    于是,这个值其实是bar - chart.NoteCollections[0].time - first + first=bar - chart.NoteCollections[0].time,注意这个值是与first无关的!
    所以,247行的first不管减多少加多少,都是没有用的,这行代码事实上不起任何作用。

正在调查

起因是有人和我反应,疑似MCM导入的谱面会有33ms的延迟。

目前我正在做各种调查,包括但不限于反复把歌曲导出又导入、查看wav文件的变化,等等。试图找到这个0.033的原因。
但至少上面第一步的分析已经证明了,确实存在着“导出时引入的&first=0.033在导入时不会被考虑”的情况,然后导入时看似-0.033的代码实则完全不生效。

发这个issue主要是想询问0.033和这段代码的来龙去脉,这里似乎存在着一些我不了解的东西,因此十分渴望给予一些点拨。

Update

Update 1: 已实验确认,把上面247行的first -= 0.033删掉,甚至哪怕把它改为一个特别离谱的数比如10,都是不改变导入谱面的结果的。所以这行确实是无用的。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions