AviUtl 拡張編集の加減速移動について考える

# 加減速移動とは
AviUtl の拡張編集におけるトラックバーの変化方法の一つで，変化の初めと終わりの変化速度が 0 で，比較的なめらかに変化する変化方法．なのだが，デフォルトの加減速移動はバグがあるようで，中間点を使うと吹っ飛ぶことがある．そのため自作しようということになるのだが，この種の変化を実現できる関数は無数にある．この記事では，それらのうち，簡単なものをいくつか紹介する．

## 加減速移動の条件
「なめらかな加減速移動」の条件を考えてみよう．簡単のため，時間もトラックバーの値も 0 から 1 に変化するものとし，時刻 $t$ におけるトラックバーの値を $f(t)$ と表示することにしよう．最低限の条件は，以下の 4 つとなる

```math
\begin{cases}
f(0)=0 \\
f(1)=1 \\
f'(0)=0 \\
f'(1)=0
\end{cases}
```

さらに，$0\leq t\leq 1$ において単調増加であり，$f(t)$ や $f'(t)$ が連続などが条件となる．この条件を満たす関数の形状を，横軸を $t$，縦軸を $f(t)$ としてプロットすると，
![関数形状例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/2f6c164e-ba60-81c7-6ef6-b1416dd05e46.png)
のような S 字型の関数となる．また，「加減速移動」前後が移動なしと考えると，$t<0$ において $f(t)=0$，$1<t$ において $f(t)=1$ となる区分的関数としたときにも導関数等が連続となるとより良いだろうと考えられる．

##スクリプトでの実装
スクリプトでは，

```lua
local i, t = math.modf(obj.getpoint("index")) -- i: 現在の直前の中間点は何番目か，t: 区間中の相対時刻(=f(t)のt)
local a = obj.getpoint(i) -- 開始時のトラックバー値
local b = obj.getpoint(i+1) -- 終了時のトラックバー値
return a+(b-a)*f(t)
```

のようにすればよい．以下で述べる関数はすべて [KSAの加減速移動スクリプト](https://github.com/cycloawaodorin/ksa/blob/master/USAGE.md#%E5%8A%A0%E6%B8%9B%E9%80%9F%E7%A7%BB%E5%8B%95)[^1] で実装している．

[^1]: 将来別のスクリプトを同じファイルで実装する可能性があるので，ソースコードではなくドキュメントへのリンクとした．

# 関数の例
## 多項式
$f$ 自体やその(高階)導関数が連続という条件を必ず満たすのが多項式である．最低限の条件は上記の4つなので，これらを満たす最も簡単な多項式は，次の3次多項式である．

```math
f_\mathrm{p3}(t) = t^2(3-2t)
```

$f'(0)=f'(1)=0$ を満たしているので，速度も連続となるが，加速度は不連続となる．そのため，$f''(0)=f''(1)=0$ の 2 条件を追加すると，次の 5 次多項式が条件を満たす．

```math
f_\mathrm{p5}(t) = t^3(10+3t(-5+2t))
```

さらに，躍度が連続となるように $f'''(0)=f'''(1)=0$ の 2 条件を追加すると，

```math
f_\mathrm{p7}(t) = t^4(35-2t(42+5t(-7+2t)))
```

が得られる．これらの 3 つの変位，速度，加速度の関数形状をプロットすると，以下のようになる．
![多項式関数の形状](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/c0f61be4-ac55-d727-3f5e-6d7631a05527.png)
![多項式関数の速度(1階導関数)の形状](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/84cc5bb9-2426-da4c-3404-6a74a57c794d.png)
![多項式関数の加速度(2階導関数)の形状](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/2aba4d3f-af24-7512-4b48-2ec0a2bdc4d4.png)
それぞれ，青が $f_\mathrm{p3}$，オレンジが $f_\mathrm{p5}$，緑が $f_\mathrm{p7}$ である．最大加速度が $f_\mathrm{p5}<f_\mathrm{p3}$ となっている点が少し面白い．

$f_\mathrm{p3}$ 型の変化を物理的に解釈すると，突然大きな力が加わったら，時間とともに力のかかる方向が逆転していき，静止した瞬間に力が突然抜けるという動きであると言える．加速度を連続にした $f_\mathrm{p5}$，躍度も連続である $f_\mathrm{p7}$ は，加わる力の変化がよりなめらかで，自然な動きであるといえる．

## 三角関数
この手のなめらかな S 字型の関数の代表例として，三角関数を挙げることもできるだろう．速度までが連続なものと，加速度までが連続なもの，躍度までが連続なものとして，次の例が挙げられる．

```math
f_\mathrm{t}(t) = \big(1-\cos(\pi t)\big)/2 = \big(\!\sin(\pi t/2)\big)^2 \\
f_\mathrm{tv}(t) = t-\frac{\sin(2\pi t)}{2\pi} \\
f_\mathrm{ta}(t) = \big(2+\cos(\pi t)\big)\big(\!\sin(\pi t/2)\big)^4
```

変位，速度，加速度までをプロットすると，
![三角関数の形状](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/8bf3ec5f-a601-3a33-ba2b-8825547df4ef.png)
![三角関数の速度](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/cd48f83d-8032-6fd4-a78c-fd882ceab463.png)
![三角関数の加速度](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/0250d8b9-9b40-7c65-0449-974d537c7a4e.png)
となる．それぞれ青が $f_\mathrm{t}$，オレンジが $f_\mathrm{tv}$，緑が $f_\mathrm{ta}$ である．条件が同等であるため，多項式の場合とよく似た形状をしていることがわかる．

## さつき氏のスクリプト
[さつき氏のスクリプト](https://dic.nicovideo.jp/u/2787743#script) にも独自の加減速移動スクリプトが含まれている．氏のスクリプトは，区分関数とすることで単純に実装しているが，その分滑らかさの観点では劣る．具体的な関数は，パラメータ $p$ を使って[^2]次のように表される．

[^2]: パラメータはオブジェクトごとに指定できる．

```math
f_\mathrm{s}(t;p) = \begin{cases}
2^{p-1}t^p & 0\leq t\leq 1/2 \\
1-2^{p-1}(1-t)^p & 1/2 < t \leq 1 
\end{cases}
```

$p=2,3$ の場合の変位，速度，加速度をプロットすると，次のようになる．
![さつき氏関数の変位](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/4e5d732c-bc9e-4235-0526-14c7d63aadc1.png)
![さつき氏関数の速度](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/92dd7f2f-1762-e8eb-d7d4-77fbef858e26.png)
![さつき氏関数の加速度](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483881/248f1291-00bd-d2f0-bc1c-7de42eeaf562.png)
青が $p=2$，オレンジが $p=3$ の場合である．多項式，三角関数の場合は $f''(1/2)=0$ であるのに対し，この関数の場合は $t=1/2$ において $f''(t)$ が不連続であり，$f''(1/2)$ が定義されないのが特徴である．$p$ を指定できるように作られているが，$p=2$ 以外を選択する意義はよくわからない．

# あとがき
いろいろ例を上げたが，結局の所なにがいいのかと思っている読者もいるだろう．正解はなく，動画にしてしまうと違いを知覚するのはなかなか困難だ．個人的には最もなめらかだと思われる $f_\mathrm{ta}$ がよいと思うが，単純な $f_\mathrm{p3}$ などでもそこまで見た目に違いはない．

また，今回は $f(x+1/2)-1/2$ が奇関数となる単調関数だけを取り上げたが，加速と減速が非対称な関数や，単調ではなく，オーバーシュートを起こすような関数を使うというのもアリだと思う．どういう動きをさせたいのかを考え，関数を作り込むとよいだろう．