时序同步

我要 masochistically 同步音符来对齐这个网格: (放大图片看网格正常)

(注意到2行没有对齐) 但是我尝试的所有方法似乎都不起作用。我的主要问题是这必须是实时完成,我不能预处理它。(因为它已经足够慢了)

为了解释图片: 图片的第一行是音符播放的最大速度。它是20 NPS(每秒音符数)。第二行不对齐到网格,它是13.25 NPS,第3行是10 NPS,第4行是6.25 NPS。所有其他行都是20/n(n从3到20)。

如果我们把网格的每个部分称为“帧”,并且考虑20 NPS与帧匹配,我们有20 FPS。我能做的唯一的事情就是选择在哪个帧中播放一个音符。也就是说,对于20 NPS,我在每个帧上播放一个音符,但对于10 NPS,我每个音符跳过1个帧,以此类推...

我要做的是想出一种算法,跳过帧,以便13.25 NPS的歌曲即使必须与20 NPS / FPS网格匹配/对齐,仍然听起来不错。

有什么想法吗?

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

点赞
用户2521214
用户2521214

我认为,如果没有高采样率的采样,任何改变都没有用。

  • 例如,声音很棘手
    1. 如果您将变量时间跳跃以匹配20nps网格中的13.25nps
    • 这将在20nps中几乎每两个音符中都创建跳跃
    • 但不是所有的,这在声音中会产生故障或失去节奏感
    • 因为我们通过大脑感知和解码声音的方式。
    1. 如果您将13.25nps对齐到10 nps,那么当然您在时间上失去了同步或想要的节奏

因此,我认为使用更高的采样率是唯一的方法

  • 最小公倍数或足够高,以降低时间误差,使其不明显
  • 例如使用网格:2000 nps + 可变跳跃,这将创建同步错误,最多只会达到1毫秒
  • 并且只有很好的音乐听觉人才能注意到

如何实现可变跳跃

  • 它与绘制2D线相同
  • 因此使用Bresenham、DDA、(sub)division或其他方法
  • 只是交换轴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)或使用帧速率-1来实现不同的对齐/混叠样式...

2014-12-03 08:42:06
用户3691554
用户3691554

链接的代码永远无法运行,因为 sleep() 有一个 bug 使它休眠的时间太长了。但是这里有一个解决办法:

不要直接调用 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 代码每个周期执行 x -= 0.05,导致浮点数错误,而不是将输入转换成整数并且每个周期执行 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);
}
2015-05-12 13:51:32