2パス符号化を試す。
- MS変換 + 最適プリエンファシス x2 + PARCOR(4) + CDF42を1段 + 各帯域でSS(4): 56.1%
からスタート。単純にブロックサイズ8192, サブブロックサイズ2048とする
- MS変換 + 最適プリエンファシス x2 + PARCOR(4), サブブロックでPARCOR(4) + CDF42を1段 + 低域でSS(4), 高域でSS(4): 55.0%
- 薬効あり。1.1%減った。
- MS変換 + 最適プリエンファシス x2 + PARCOR(4), サブブロックでCDF42を1段 + 低域でSS(4), 高域でSS(4): 56.2%
- MS変換 + 最適プリエンファシス x2, サブブロックでPARCOR(4) + CDF42を1段 + 低域でSS(4), 高域でSS(4): 56.0%
- 0.1%改善。
- これもわかる。プリエンファシスはより正確な相関でやるべきでより長い区間を見れているから正確にプリエンファシスできている。
- MS変換 + PARCOR(4), サブブロックで最適プリエンファシス x2 + PARCOR(4) + CDF42を1段 + 低域でSS(4), 高域でSS(4): 55.1%
- ブロック単位で最適プリエンファシスを行ったほうが0.1%減る。
プリエンファシスの観察からわかるように、圧縮は、大域的(定常的)なものからだんだん細かく(パラメータが大きいモデルを使う)していくのがミソでは。
(ブロックサイズ, サブブロックサイズ)をいじって様子を見よう。以下のモデルを使用。
- MS変換 + 最適プリエンファシス x2 + PARCOR(4), サブブロックでPARCOR(4) + CDF42を1段 + 低域でSS(4), 高域でSS(4)
- ( 4096, 512): 55.0%
- ( 4096, 1024): 55.0%
- ( 4096, 2048): 55.0%
- ( 4096, 4098): 55.2%
- ( 8192, 512): 55.0% (1024より微妙に減った)
- ( 8192, 1024): 55.0% (2048より微妙に減った)
- ( 8192, 2048): 55.0%
- ( 8192, 4096): 55.1%
- ( 8192, 8192): 55.2% <- PARCOR(4)の2段適用で減るということ
- (16384, 512): 54.9%
- (16384, 1024): 54.9%
- (16384, 2048): 55.0%
- (16384, 4096): 55.1%
- (16384, 8192): 55.2%
- (16384, 16384): 55.2%
細かく分けたほうが0.1%単位で得のようだ。一応(8192, 2048)で話をすすめる。
次気になるのが、LPCの次数。予測としては、ブロック単位のLPC次数は小さくしたほうが良いと思っている。(ブロック次数, サブブロック次数)で考えよう
- ( 0, 4): 56.0% <- !!!
- ( 0, 8): 54.8% <- !!!
- ( 0, 16): 54.2% <- !!!
- ( 0, 32): 53.5% <- !!!
- ( 0, 64): 52.9% <- !!!
- ( 0,128): 52.4% <- !!!
- ( 2, 4): 55.3%
- ( 2, 16): 54.0%
- ( 2, 32): 53.4%
- ( 2, 64): 52.7% <-
- ( 2,128): 52.1% <-
- ( 4, 4): 55.0%
- ( 4, 8): 54.7%
- ( 4, 12): 54.3%
- ( 4, 16): 54.1%
- ( 4, 20): 53.9%
- ( 4, 32): 53.4% <- !!!
- ( 4, 64): 52.7% <- !!!
- ( 4,128): 52.1% <- !!!
- ( 8, 8): 54.8%
- ( 8, 12): 54.5%
- ( 8, 16): 54.2%
- ( 8, 20): 54.0%
- ( 8, 4): 55.0% ((4,4)よりは微妙に減る)
- (12, 4): 54.8%
- (16, 4): 54.7%
- (20, 4): 54.6%
これも予測通りというか、大ブロック単位では次数を小さく、サブブロックは次数を大きくした方が改善度合いが大きい。 大ブロックでは適用しなくても良い結果。 しかもサブブロックは増やし続けても悪化しない。スケールする。 ひとまず(4,4)を使い続ける。現在のベースラインは以下:
- MS変換 + 最適プリエンファシス x2 + PARCOR(4), サブブロックでPARCOR(4) + CDF42を1段 + 低域でSS(4), 高域でSS(4): 55.0% - ブロックサイズ8192, サブブロックサイズ2048
次は、Sign-Signアルゴリズムの出力をフィードバックして効果を確かめたい。 「情報源符号化 歪みのあるデータ圧縮」(大名著)で触れられていて思い出した。次数を(履歴次数, 出力次数)で変えてみた結果は以下:
- (4, 0): 55.0% (ベースライン)
- (4, 2): 54.89%
- (4, 4): 54.87%
- (4, 6): 54.82%
かつてのワン・ツー・スゥイーツ突っ込んだら微妙な結果を出していた。とくに出力次数をいじるとボロボロ(使わない方が10%低かった)。特にダイナミックな音源で、極型フィルタにしてしまうと発散する危険があると見て良いと思う。海苔音源は多いと思うので 不採用とする。
FLACの係数の扱い
おそらくLPCをやることになる。今のうちFLACのソースガン見して係数の扱いをよく見ておく。
- LPC係数の計算はここ 。結果は2次元配列で、最大次数を与えると0次から最大次数までのLPC係数を求める。
- LPC係数の量子化 量子化。予め決めたビット幅precisionに収めるように丸め込む。同時にシフト幅も計算。 FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN bit(=5bit)で表現できる範囲で計算している。5bitは大きすぎないか。 frexp で指数部を取り出して計算してるのはスマート。
- 予測 。マジで1サンプルごとにLPC予測を実行。ただし積和した結果を lp_quantization だけ右シフト。
- シフト幅は エンコーダ側の呼び出し を見るに、量子化で得られたシフト幅をそのまま入力している。
- ビット幅はここ で定めている。サンプルあたりのビット幅とブロックサイズに応じて決めている。最大は FLAC__MAX_QLP_COEFF_PRECISION =15。そういやあTAKは14と言ってたな。
- 今まで自分は固定シフトでやってきたので新鮮。こっちのほうが有効に使えるビット幅が広くて良いかもしれない。
- 24bitのために関数は分けてなくて、係数ビット幅と次数によって64bit整数を使うか呼び分けている。
- 合成 。予測の逆。特に難しいことはないはず。