源码来自工程『少女终末旅行』
InheritExpression.SetCompareLists(System.Windows.Forms.Application.StartupPath + "\\test"); //生成TimeLine(时间序列) var a = new TimeLine().Serialize(MidiPath.Text, WavePath.Text, 0, 10, 10, 4); a.Sound_InheritExpression("%p");//设置子表达式 //设定音轨及其音色 a.Sound_StopSound(true);//启用/stopsound a.Sound_ExtraDelay(3);//所有音轨的发生发声延长3tick a.Sound_SoundName("9", "9");//用法:timeLine.Sound_SoundName("音色名称","音轨名称","乐器名称") a.Sound_SoundName("33c", "33"); a.Sound_ExtraDelay(4, "33");//用法:timeLine.Sound_SoundName(延长时间[刻],"音轨名称","乐器名称") a.Sound_SoundName("39", "39"); a.Sound_SoundName("51c", "51"); a.Sound_SoundName("7", "7"); a.Sound_StopSound(false, "7"); a.Sound_SoundName("1", "1"); a.Sound_PercVolume(110, "1"); a.Sound_StopSound(false, "1");//对"1"(钢琴)禁用/stopsound a.Sound_SoundName("5c", "5"); a.Sound_ExtraDelay(4, "5"); a.Sound_SoundName("8", "8"); a.Sound_SoundName("26c", "26"); a.Sound_SoundName("0.44", "Pedal Hi-Hat"); a.Sound_SoundName("0.36", "Bass Drum1"); a.Sound_SoundName("0.47", "Low-Mid Tom"); a.Sound_SoundName("0.59", "Ride Cymbal2"); a.Sound_SoundName("0.58", "Vibra-slap"); a.Sound_ExtraDelay(10, "Vibra-slap"); //禁用&启用特定的音轨 a.EnableMidi(false);//Midi序列全部禁用 a.EnableWave(false, -1, "Right");//Wave序列的右声道全部禁用 a.EnableMidi(true, "", "", -1, "PlaySound");//启用Midi序列的/playsound a.EnableMidi(false, "D", "", -1, "PlaySound");//禁用下列音轨的/playsound a.EnableMidi(false, "X", "", -1, "PlaySound"); a.EnableMidi(false, "R", "", -1, "PlaySound"); a.EnableMidi(false, "F", "", -1, "PlaySound"); a.EnableMidi(true, "D", "", -1, "Pitch"); a.EnableMidi(true, "X", "", -1, "Pitch"); a.EnableMidi(true, "R", "", -1, "Pitch"); a.EnableMidi(true, "F", "", -1, "Pitch");//这些音轨用于输出它们音高值到计分板 a.EnableMidi(true, "Low-Mid Tom", "", -1, "Velocity"); a.EnableMidi(true, "Pedal Hi-Hat", "", -1, "Velocity"); a.EnableMidi(true, "Ride Cymbal2", "", -1, "Velocity"); a.EnableMidi(true, "Vibra-slap", "", -1, "Velocity");//这些音轨除了用于/playsound还将输出它们速率(力度)到计分板 //生成CommnandLine(命令序列) var b = new CommandLine().Serialize(a); //读取AMLrc(命令序列)嵌入命令序列 var lrc = new AMLrc().Serialize(LrcPath.Text).AMLrcLine; b = b.Combine(b, lrc); //生成schematic文件 new Schematic().ExportSchematic(b, new ExportSetting() { AlwaysActive = true, AlwaysLoadEntities = false, Direction = 0, Width = 5 }, "E:\\time.schematic");
a.EnableMidi(false, "D", "", -1, "PlaySound"); a.EnableMidi(true, "D", "", -1, "Pitch");
音轨"D"是我们为了计分板输出而专门设定的一条的音轨。
(上面两行代码即禁用该音轨/playsound的同时输出音轨中键的音高。)
接下来我们进入Minecraft内查看A2M留下的计分板接口。(可从命令流开头的初始化命令中查看,即下图最左侧)
计分板接口的命名规则如下:
计分板接口首先需要用于储存实体分数的计分板。
Midi文件格式
Midi音轨总数
Midi¼音符占刻
BPM
Wav文件格式
总刻数
键的计分板有以下几个:
键起始时间
键起始刻数
键持续时间
键持续刻数
小节索引
小节长度
频道
音高
力度
波形的计分板有以下几个:
采样频率
采样振幅
计分板接口还需要储存分数的实体对象。你可以通过实体标签选中它们。
实体对象的共有标签为AudioRiptideNode
。
储存键信息的实体有三个标签,分别是特有标签、音轨标签和乐器标签
[track](5)_[instrument](5)_[index]
由[track]
(音轨名)的前五个字符、[instrument]
(乐器名)的前五个字符与[index]
(键按照出现顺序的索引)组成
例如表示音轨名"Track"、乐器名"Instrument"、出现的第3个键,则特有标签如下:
Track_Instr_3
t_[track]
[track]
(音轨名)前加上"t_"即可。
i_[instrument]
[instrument]
(乐器名)前加上"i_"即可。
储存波形采样信息的实体命名规则很简单:
wave_[index]_r 或 wave_[index]_rl
[index]
(采样信息索引)与采样数有关,后面的r或l代表右声道或左声道。
为使实体标签合法,实体标签中出现的空格或其他特殊字符(包括汉字),将由下划线替代。
fill -20 6 17 -20 13 17 air 0 replace minecraft:stained_glass execute @e[tag=wave0_l_0,score_Fre_min=18] ~ ~ ~ setblock -20 6 17 minecraft:stained_glass 14 execute @e[tag=wave0_l_0,score_Fre_min=36] ~ ~ ~ setblock -20 7 17 minecraft:stained_glass 14 execute @e[tag=wave0_l_0,score_Fre_min=54] ~ ~ ~ setblock -20 8 17 minecraft:stained_glass 14 execute @e[tag=wave0_l_0,score_Fre_min=72] ~ ~ ~ setblock -20 9 17 minecraft:stained_glass 14 execute @e[tag=wave0_l_0,score_Fre_min=90] ~ ~ ~ setblock -20 10 17 minecraft:stained_glass 14 execute @e[tag=wave0_l_0,score_Fre_min=108] ~ ~ ~ setblock -20 11 17 minecraft:stained_glass 14 execute @e[tag=wave0_l_0,score_Fre_min=126] ~ ~ ~ setblock -20 12 17 minecraft:stained_glass 14
这是对波形频率可视化的一段Function,基本思路就是穷举。通过对计分板接口的值进行遍历,穷举所有可能出现的事件,以实现可视化的效果。如果利用方块作为可视化对象,别忘了重置更新。