定时同步

时间:2014-12-02 23:03:03

标签: algorithm lua timing

我尝试将音符定时同步到此网格:(放大以正确查看网格)

(请注意其中2行不对齐)但我尝试的所有内容似乎都无法正常工作。我的主要问题是必须实时完成,我无法对其进行预处理。 (它已经足够慢了)

解释图像:

图像的第一行是音符播放的最大速度。这是20 NPS(每秒注释)。第二行没有与网格对齐,它是13.25 NPS。 3月10日NPS。第四名是6.25 NPS。所有其他的都是20 / n,n为3到20。

如果我们将网格的每个部分称为" frame",并考虑20 NPS与帧匹配,我们有20 FPS。我在这里唯一能做的就是选择在哪个框架中播放音符。也就是说,对于20 NPS,我在每个帧上都会播放一个音符,但对于10 NPS,我会在每个音符上跳过1帧,依此类推......

我尝试做的是提出一种跳过帧的算法,这样即使我必须将音符与20 NPS / FPS网格匹配/对齐,13.25 NPS的歌曲仍然会听起来不错。

关于我如何做到这一点的任何想法?

您可以看到我在此处尝试的所有内容:https://github.com/SoniEx2/NBSPlayer/commits/eef9ad465a1e337b17ad4e27e9a22d8a9dddfe4d/ats

2 个答案:

答案 0 :(得分:1)

我认为如果不对更高的费率进行抽样,任何改变都不会有任何好处。

  • 声音很棘手
    1. 如果您要添加可变时间跳过以匹配20 nps网格中的13.25 nps
      • 将以20 nps
      • 创建几乎所有其他音符的​​跳过
      • 但不是全部,并且在声音中显而易见,如毛刺或错过节奏
      • 由于我们如何通过Brain进行perciewe和解码声音的方式。
    2. 如果您将13.25nps对齐为10 nps
      • 那么粗糙你无论如何都会在时间上不同步。出于想要的节奏

所以我认为使用更高采样率的唯一方法

  • LCM最小公倍乘或高足以降低定时误差,因此不明显
  • 例如使用grid:2000 nps +变量跳过,这将导致最多1ms的同步错误
  • 只有非常好的音乐听众才会注意到这一点

如何实施变量跳过

  • 与绘制2D线
  • 相同
  • 所以请使用Bresenham,DDA,(子)部门或任何
  • 只交换轴x =采样率网格,y =目标费率网格
  • 例如类似的东西(在C ++中):

    int f0=200000,f1=1325,f2=2000,cnt1=f1,cnt2=f2; // rates are *100 to avoid use of floats
    for (ix=0;ix<???;ix++) sample[ix]=0;             // erase all samples before so you can add more then one sample in single pass later
    for (ix=0;ix<???;ix++)                             // loop to handle your samples ...
     {
     cnt1-=f1; if (cnt1<=0) { cnt1+=f0; sample[ix]+=???; /*/ here add samples for tempo 1 /*/ }
     cnt2-=f2; if (cnt2<=0) { cnt2+=f0; sample[ix]+=???; /*/ here add samples for tempo 2 /*/ }
     }
    
  • 粗略的
  • 我假设你的笔记定义了长度,所以你需要为每个笔记设置更多的样本,然后设置样本ix,ix+1,ix+2,...

  • 你可以看到你可以根据需要添加任意数量的节奏,每个节目都有cnt?,f?个变量
  • 您可以使用条件(cnt?<0)或使用framerates-1来实现不同的对齐/锯齿样式......

答案 1 :(得分:1)

链接的代码永远不会起作用,因为有bug的sleep()使其睡眠时间过长。但这是一个解决方法:

不要直接调用sleep(),而应该像这样调用它:

local function sleep_workaround(d)
    local t = d * 20
    for i=1,math.floor(t) do
        sleep(0.05) -- 0.05s sleeps don't trigger the bug
    end
end

这是由于错误的ComputerCraft代码执行每个tick x -= 0.05,导致浮点错误,而不是将输入转换为整数并且每个tick都执行x -= 1。由于ComputerCraft使用Java,这是一些显示错误的简单Java代码:

for (double d : new double[]{0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0}) {
    int i;
    double in = d;
    for (i = 0; d > 0.0; i++, d -= 0.05) {}
    System.out.println(in + " " + i);
}